private void addOperator(Operator operator) { Section section = stack.peek(); Tree tree = section.unwind(operator); Tree tree1 = Tree.of(operator, tree.getRight(), Atom.NIL); Tree.forceSetRight(tree, tree1); section.push(tree1); }
private class Section { private char kind; private Deque<Tree> list = new ArrayDeque<>(Arrays.asList(Tree.of(null, null, Atom.NIL))); private boolean isDanglingRight = true; public Section(char kind) { this.kind = kind; } private Tree unwind(Operator operator) { int prec0 = operator != null ? operator.getPrecedence() : -1; Operator op; Tree tree; while ((op = (tree = list.getLast()).getOperator()) != null) { int prec1 = op.getPrecedence(); if (prec0 < prec1 || operator.getAssoc() == Assoc.LEFT && prec0 == prec1) pop(); else break; } return tree; } private void push(Tree tree) { list.addLast(tree); isDanglingRight = true; } private Tree pop() { return list.removeLast(); } }
private Node parse() { Lexer lex = new Lexer(operators, in); stack.push(new Section(' ')); Token token; while ((token = lex.lex()) != null) { Operator operator = token.operator; String data = token.getData(); char ch = data.charAt(0); if (operator != null) { addOperator(operator); if (operator == TermOp.BRACES) stack.push(new Section('{')); } else if (ch == '(' || ch == '[' || ch == '{') stack.push(new Section(ch)); else if (ch == ')' || ch == ']' || ch == '}') { Section section = stack.pop(); if (section.kind == '(' && ch == ')' // || section.kind == '[' && ch == ']' // || section.kind == '{' && ch == '}') { Node node = section.unwind(null).getRight(); if (ch == ']') node = Tree.of(TermOp.TUPLE_, Atom.of("["), node); add(node); } else throw new RuntimeException("Cannot parse " + in); } else if (ch == '`') if (stack.peek().kind == ch) { Node node = stack.pop().unwind(null).getRight(); node = Tree.of(TermOp.TUPLE_, Atom.of("`"), node); add(node); } else stack.push(new Section(ch)); else if (Util.isNotBlank(data)) add(terminalParser.parseTerminal(data)); } if (stack.size() == 1) return stack.pop().unwind(null).getRight(); else throw new RuntimeException("Cannot parse " + in); }
private void add(Node node) { Section section = stack.peek(); if (!section.isDanglingRight) addOperator(TermOp.TUPLE_); Tree.forceSetRight(section.list.getLast(), node); section.isDanglingRight = false; }