// preprocessor: func(S -> O) // returns func(S -> E) static O makeGrabber(OccTree2 tree, final O preprocessor) { final new StrictTreeMap strictMap; // TODO: maybe use hashmap strictMap.detailedExceptions = true; for (OccTree2 node : tree.allNodes()) { if (node.e.a() && node.parent != null && node.parent.e.q()) { S in = node.parent.e.text(), out = node.e.text(); O preprocessed; try { preprocessed = callFunction(preprocessor, in); // may throw exception, then we just skip } catch { continue; } if (preprocessed != null) strictMap.put(preprocessed, out); } } ret func(S in) { O preprocessed = callF(preprocessor, in); if (preprocessed == null) null; ret E.a(strictMap.get(preprocessed)); }; }