static new AtomicInteger nlParse_count; // how often did we parse something? static Lisp nlParse(S s) { ret nlParse(s, true); } static Lisp nlParse(S s, boolean unbracket) { ret nlParse(codeTokens(snlTok(s)), unbracket, false, null); } static Lisp nlParse(S s, boolean unbracket, boolean explicitBrackets) { ret nlParse(codeTokens(snlTok(s)), unbracket, explicitBrackets, null); } static Lisp nlParse(L tok) { ret nlParse(tok, true, false, null); } // unbracket refers to outermost brackets // explicitBrackets refers to inner brackets static Lisp nlParse(L tok, boolean unbracket, final boolean explicitBrackets, L warnings) { nlParse_count.incrementAndGet(); class Entry { int i; Lisp tree; S wrapper; *(int *i) { tree = lisp("[]"); } *(int *i, S bracket) { tree = lisp("[]"); wrapper = bracket; } Lisp wrapped() { Lisp t = explicitBrackets ? tree : nlUnbracket(tree); ret wrapper == null ? t : lisp(wrapper, t); } } new L stack; stack.add(new Entry(0)); for (int i = 0; i < l(tok); i++) { S t = tok.get(i); if (eq(t, "[") || eq(t, "(")) { stack.add(new Entry(i, eq(t, "(") ? "()" : null)); } else if (eq(t, "]") || eq(t, ")")) { if (l(stack) == 1) warn("too many closing brackets", warnings); else { Entry e = popLast(stack); /*if (!bracketsMatch(tok.get(e.i), t)) warn("non-matching brackets");*/ last(stack).tree.add(e.wrapped()); } } else last(stack).tree.add(t); } while (l(stack) > 1) { warn("too many opening brackets", warnings); Entry e = popLast(stack); last(stack).tree.add(e.wrapped()); } Lisp result = last(stack).wrapped(); ret unbracket ? nlUnbracket(result) : result; }