package slangc.parser; public class Parse { private int maxRecursion = 1000; public String nodeTypesAsString(NodeType[] types) { if (types.length == 0) { return "Nothing?"; } else if (types.length == 1) { return types[0].name(); } else { String result = ""; for (int i = 0; i < types.length; i++) { if (i != 0) { if (i == types.length - 1) { result += " or "; } else { result += ", "; } } result += types[i].name(); } return result; } } public Node expectAny(ScanWalker walker, int recursion, NodeType... types) { return expectAnyArray(walker, recursion, types); } public Node expectAnyArray(ScanWalker walker, int recursion, NodeType[] types) { Node result = parseAnyArray(walker, recursion + 1, types); if (result == null) { result = new Branch(NodeType.ERROR_ONLY).annotate(ErrorType.EXPECTING, "Expecting " + nodeTypesAsString(types) + " (got " + walker.peek().getType().name() + ")"); } return result; } public Node parseAny(ScanWalker walker, int recursion, NodeType... types) { return parseAnyArray(walker, recursion, types); } public Node parseAnyArray(ScanWalker walker, int recursion, NodeType[] types) { for (int i = 0; i < types.length; i++) { ScanWalker w = walker.clone(); Node result = parseInner(w, recursion + 1, types[i]); if (result != null) { walker.reset(w); ScanWalker.recycle(w); return result; } ScanWalker.recycle(w); } return null; } public Node parseList(ScanWalker walker, int recursion, NodeType listType, NodeType separator, boolean consumeTailSeparator, NodeType... types) { return parseListArray(walker, recursion, listType, separator, consumeTailSeparator, types); } public Node parseListArray(ScanWalker walker, int recursion, NodeType listType, NodeType separator, boolean consumeTailSeparator, NodeType[] types) { checkRecursion(walker, recursion); Branch result = new Branch(listType); Node n; boolean first = true; do { ScanWalker w = walker.clone(); if (first || separator == null) { n = parseAnyArray(w, recursion + 1, types); first = false; } else { ScanWalker w2 = w.clone(); Node sep = parseInner(w2, recursion + 1, separator); if (sep == null) { n = null; } else { n = parseAnyArray(w2, recursion + 1, types); //System.out.println("Got a "+ n); if (n != null || consumeTailSeparator) { result.append(sep); w.reset(w2); } } ScanWalker.recycle(w2); } if (n != null) { result.append(n); walker.reset(w); } else if (consumeTailSeparator) { walker.reset(w); } ScanWalker.recycle(w); } while (n != null); return result; } public Node parseGenericOnlyList(ScanWalker walker, int recursion, NodeType listType, NodeType separator, boolean consumeTailSeparator, NodeType gentype, NodeType middletype) { checkRecursion(walker, recursion); Branch result = new Branch(listType); Node n; boolean first = true; Node lastGenType = null; ScanWalker lastGenWalker = null; ScanWalker ogWalker = walker.clone(); int iter = 0; do { //System.out.println("XXXXXX" + iter); iter++; ScanWalker w = walker.clone(); if (first || separator == null) { n = parseAny(w, recursion + 1, gentype, middletype); if (n != null && n.getNodeType() == gentype) { lastGenType = n; lastGenWalker = w.clone(); } first = false; } else { ScanWalker w2 = w.clone(); Node sep = parseInner(w2, recursion + 1, separator); if (sep == null) { n = null; } else { n = parseAny(w2, recursion + 1, gentype, middletype); if (n != null && n.getNodeType() == gentype) { lastGenType = n; lastGenWalker = w2.clone(); } //System.out.println("Got a "+ n); if (n != null || consumeTailSeparator) { result.append(sep); w.reset(w2); } } ScanWalker.recycle(w2); } if (n != null) { result.append(n); walker.reset(w); } else if (consumeTailSeparator) { walker.reset(w); } ScanWalker.recycle(w); } while (n != null); if (lastGenWalker == null) { walker.reset(ogWalker); return null; } else { walker.reset(lastGenWalker); Branch realResult = new Branch(listType); for (int i = 0; i < result.countSubnodes(); i++) { realResult.append(result.getSubnode(i)); if (result.getSubnode(i) == lastGenType) { return realResult; } } throw new Error("Internal error (this should be unreachable)"); } } public Token parseToken(ScanWalker walker, int recursion, TokenType type) { //checkRecursion(walker, recursion); if (walker.isAtEnd()) { //System.out.println("AT END"); return null; } if (walker.peek().is(type)) { //System.out.println("Got a match to " + type); Token result = walker.peek(); walker.advance(); return result; } else { //System.out.println("Not a " + type + " but a " + walker.peek()); return null; } } public Token parseToken(ScanWalker walker, int recursion, TokenType type, String value) { //checkRecursion(walker, recursion); if (walker.isAtEnd()) { return null; } if (walker.peek().is(type, value)) { Token result = walker.peek(); walker.advance(); return result; } else { return null; } } public Token parseToken(ScanWalker walker, int recursion, Language.Key key) { //checkRecursion(walker, recursion); if (walker.isAtEnd()) { return null; } String val = walker.peek().getSnippet().getSource(); if (walker.peek().is(TokenType.KEYWORD) && walker.getScan().getLanguage().matches(key, val)) { Token result = walker.peek(); walker.advance(); return result; } else { return null; } } public Token parseToken(ScanWalker walker, int recursion, String value) { // Can skip recursion check since we know we won't recurse from here! checkRecursion(walker, recursion); if (walker.isAtEnd()) { return null; } if (walker.peek().is(value)) { Token result = walker.peek(); walker.advance(); return result; } else { return null; } } public Branch parseTokenBranch(ScanWalker walker, int recursion, NodeType n, TokenType type) { Token t = parseToken(walker, recursion, type); //System.out.println("Got " + t); if (t == null) { return null; } else { return new Branch(n, t); } } public Branch parseTokenBranch(ScanWalker walker, int recursion, NodeType n, Language.Key key) { Token t = parseToken(walker, recursion, key); //System.out.println("Got " + t); if (t == null) { return null; } else { return new Branch(n, t); } } public Branch parseTokenBranch(ScanWalker walker, int recursion, NodeType n, TokenType type, String value) { Token t = parseToken(walker, recursion, type, value); if (t == null) { return null; } else { return new Branch(n, t); } } /** This one is used for the special >> and >>> operators (which are actually parsed as a sequence of > operators, to avoid * conflict with nested template sizeExpression (e.g. Map>). */ public Branch parseSpecialTokenBranch(ScanWalker walker, int recursion, NodeType n, TokenType type, String value, int number) { ScanWalker pos = walker.clone(); switch (number) { case 2: case 3: break; default: throw new Error("Internal error: Bad number " + number); } Token t = parseToken(walker, recursion, type, value); if (t == null) { walker.reset(pos); ScanWalker.recycle(pos); return null; } else { Token t2 = parseToken(walker, recursion, type, value); if (t2 == null) { walker.reset(pos); ScanWalker.recycle(pos); return null; } else if (number == 2) { ScanWalker.recycle(pos); return new Branch(n, t, t2); } else { // number == 3 Token t3 = parseToken(walker, recursion, type, value); if (t3 == null) { walker.reset(pos); ScanWalker.recycle(pos); return null; } else { ScanWalker.recycle(pos); return new Branch(n, t, t2, t3); } } } } public Branch parseTokenBranch(ScanWalker walker, int recursion, NodeType n, String value) { Token t = parseToken(walker, recursion, value); if (t == null) { return null; } else { return new Branch(n, t); } } public Node parseSimpleBinop(ScanWalker walker, int recursion, NodeType result, NodeType operator, NodeType inner) { Node lhs = parseInner(walker, recursion + 1, inner); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseInner(walker, recursion, operator); if (op == null) { done = true; } else { lhs = new Branch(result, lhs, op, expectAny(walker, recursion + 1, inner)); } } return lhs; } public Node parseInner(ScanWalker walker, int recursion, NodeType type) { checkRecursion(walker, recursion); if (walker.isAtEnd()) { return null; } switch (type) { case NodeType.EOF: return parseTokenBranch(walker, recursion + 1, NodeType.EOF, TokenType.END_OF_FILE); case NodeType.TOKEN: if (walker.isAtEnd()) { return null; } else { Token t = walker.peek(); walker.advance(); return t; } case NodeType.NAME: //System.out.println("Parsing name..."); return parseTokenBranch(walker, recursion + 1, NodeType.NAME, TokenType.NAME); case NodeType.INDEXED_NAME: { Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { Node o = parseInner(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE); if (o == null) { return n; } else { while (o != null) { Node c = expectAny(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE); n = new Branch(NodeType.INDEXED_NAME, n, o, c); // Check for next set of braces o = parseInner(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE); } return n; } } } case NodeType.GENERIC_NAME: { Node n = parseTokenBranch(walker, recursion + 1, NodeType.NAME, TokenType.NAME); if (n != null) { if (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, "<")) { Node genargs = parseAny(walker, recursion + 1, NodeType.GENERIC_ARGUMENTS); if (genargs == null) { return null; } return new Branch(NodeType.GENERIC_NAME, n, genargs); } else { return null; } } return null; } case NodeType.DOT: return parseTokenBranch(walker, recursion + 1, NodeType.DOT, TokenType.OPERATOR, "."); case NodeType.WILDCARD: return parseTokenBranch(walker, recursion + 1, NodeType.WILDCARD, TokenType.OPERATOR, "*"); case NodeType.COMMA: return parseTokenBranch(walker, recursion + 1, NodeType.COMMA, TokenType.OPERATOR, ","); case NodeType.SEMICOLON: return parseTokenBranch(walker, recursion + 1, NodeType.SEMICOLON, TokenType.OPERATOR, ";"); case NodeType.COLON: return parseTokenBranch(walker, recursion + 1, NodeType.COLON, TokenType.OPERATOR, ":"); case NodeType.DOUBLECOLON: return parseTokenBranch(walker, recursion + 1, NodeType.DOUBLECOLON, TokenType.OPERATOR, "::"); case NodeType.QUESTIONMARK: return parseTokenBranch(walker, recursion + 1, NodeType.QUESTIONMARK, TokenType.OPERATOR, "?"); case NodeType.OPEN_ROUND_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE, TokenType.OPERATOR, "("); case NodeType.CLOSE_ROUND_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE, TokenType.OPERATOR, ")"); case NodeType.OPEN_CURLY_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE, TokenType.OPERATOR, "{"); case NodeType.CLOSE_CURLY_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE, TokenType.OPERATOR, "}"); case NodeType.OPEN_SQUARE_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE, TokenType.OPERATOR, "["); case NodeType.CLOSE_SQUARE_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE, TokenType.OPERATOR, "]"); case NodeType.OPEN_ANGLE_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.OPEN_ANGLE_BRACE, TokenType.OPERATOR, "<"); case NodeType.CLOSE_ANGLE_BRACE: return parseTokenBranch(walker, recursion + 1, NodeType.CLOSE_ANGLE_BRACE, TokenType.OPERATOR, ">"); case NodeType.PACKAGE_NAME: return parseList(walker, recursion + 1, NodeType.PACKAGE_NAME, NodeType.DOT, false, NodeType.NAME); case NodeType.PACKAGE_DECLARATION: { Token t = parseToken(walker, recursion + 1, Language.Key.MODULE); //TokenType.KEYWORD, "package"); if (t == null) { return null; } else { return new Branch(NodeType.PACKAGE_DECLARATION, t, expectAny(walker, recursion + 1, NodeType.PACKAGE_NAME), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } } case NodeType.IMPORTED_PACKAGE: { Node n = parseInner(walker, recursion + 1, NodeType.PACKAGE_NAME); if (n != null) { Node dot = parseInner(walker, recursion + 1, NodeType.DOT); if (dot != null) { return new Branch(NodeType.IMPORTED_PACKAGE, n, dot, expectAny(walker, recursion + 1, NodeType.WILDCARD)); } } return null; } case NodeType.IMPORTED_TYPE: return parseList(walker, recursion + 1, NodeType.IMPORTED_TYPE, NodeType.DOT, false, NodeType.NAME); case NodeType.IMPORT_DECLARATION: { Token t = parseToken(walker, recursion + 1, Language.Key.IMPORT); //TokenType.KEYWORD, "import"); if (t == null) { return null; } else { Token stat = parseToken(walker, recursion + 1, Language.Key.STATIC); //TokenType.KEYWORD, "static"); if (stat == null) { return new Branch(NodeType.IMPORT_DECLARATION, t, expectAny(walker, recursion + 1, NodeType.IMPORTED_PACKAGE, NodeType.IMPORTED_TYPE), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } else { return new Branch(NodeType.IMPORT_STATIC_DECLARATION, t, stat, expectAny(walker, recursion + 1, NodeType.IMPORTED_PACKAGE, NodeType.IMPORTED_TYPE), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } } } case NodeType.TYPE_DECLARATIONS: return parseList(walker, recursion + 1, NodeType.TYPE_DECLARATIONS, null, false, NodeType.CLASS_DECLARATION, NodeType.INTERFACE_DECLARATION, NodeType.ENUM_DECLARATION, NodeType.ATTRIBUTE_DECLARATION, NodeType.SEMICOLON); case NodeType.INTERFACE_BASES: { Node keyword = parseToken(walker, recursion + 1, Language.Key.EXTENDS); //TokenType.KEYWORD, "extends"); if (keyword == null) { return new Branch(NodeType.NO_INTERFACE_BASES); } else { return new Branch(NodeType.INTERFACE_BASES, keyword, parseInner(walker, recursion + 1, NodeType.TYPE_REFERENCES)); } } case NodeType.CLASS_BASE: { Node keyword = parseToken(walker, recursion + 1, Language.Key.EXTENDS); //TokenType.KEYWORD, "extends"); if (keyword == null) { return new Branch(NodeType.NO_CLASS_BASE); } else { return new Branch(NodeType.CLASS_BASE, keyword, expectAny(walker, recursion + 1, NodeType.TYPE_REFERENCE)); } } case NodeType.CLASS_IMPLEMENTS: { Node keyword = parseToken(walker, recursion + 1, Language.Key.IMPLEMENTS); //TokenType.KEYWORD, "implements"); if (keyword == null) { return new Branch(NodeType.NO_CLASS_IMPLEMENTS); } else { return new Branch(NodeType.CLASS_IMPLEMENTS, keyword, parseInner(walker, recursion + 1, NodeType.TYPE_REFERENCES)); } } case NodeType.TYPE_REFERENCES: return parseList(walker, recursion + 1, NodeType.TYPE_REFERENCES, NodeType.COMMA, false, NodeType.TYPE_REFERENCE); case NodeType.TYPE_REFERENCE: if (!walker.isAtEnd() && walker.peek().is(TokenType.NAME)) { return parseList(walker, recursion + 1, NodeType.TYPE_REFERENCE, NodeType.DOT, false, NodeType.GENERIC_NAME, NodeType.NAME); } else { return null; } case NodeType.GENERIC_ONLY_TYPE_REFERENCE: if (!walker.isAtEnd() && walker.peek().is(TokenType.NAME)) { return parseGenericOnlyList(walker, recursion + 1, NodeType.TYPE_REFERENCE, NodeType.DOT, false, NodeType.GENERIC_NAME, NodeType.NAME); } else { return null; } case NodeType.TYPE: { Node result = null; result = result != null ? result : parseInner(walker, recursion + 1, NodeType.SIMPLE_TYPE); result = result != null ? result : parseInner(walker, recursion + 1, NodeType.TYPE_REFERENCE); while (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, "[") && walker.peekOffset(1) != null && walker.peekOffset(1).is(TokenType.OPERATOR, "]")) { result = new Branch(NodeType.ARRAY_TYPE, result, parseInner(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE), parseInner(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE)); } if (result == null) { return null; } else { return new Branch(NodeType.TYPE, result); } } case NodeType.RETURN_TYPE: { Node voidToken = parseToken(walker, recursion + 1, Language.Key.VOID); //TokenType.KEYWORD, "void"); if (voidToken == null) { Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } else { return new Branch(NodeType.RETURN_TYPE, t); } } else { return new Branch(NodeType.NO_RETURN_TYPE, voidToken); } } case NodeType.ENUM_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node keyword = parseToken(walker, recursion + 1, Language.Key.ENUM); //TokenType.KEYWORD, "enum"); if (keyword == null) { return null; } else { return new Branch(NodeType.ENUM_DECLARATION, mods, keyword, expectAny(walker, recursion + 1, NodeType.NAME), parseInner(walker, recursion + 1, NodeType.GENERIC_DECLARATIONS), parseInner(walker, recursion + 1, NodeType.CLASS_BASE), parseInner(walker, recursion + 1, NodeType.CLASS_IMPLEMENTS), expectAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE), parseInner(walker, recursion + 1, NodeType.ENUM_MEMBERS), parseInner(walker, recursion + 1, NodeType.ENUM_CLASS_MEMBERS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } } case NodeType.INTERFACE_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node keyword = parseToken(walker, recursion + 1, Language.Key.INTERFACE); //TokenType.KEYWORD, "interface"); if (keyword == null) { return null; } else { return new Branch(NodeType.INTERFACE_DECLARATION, mods, keyword, expectAny(walker, recursion + 1, NodeType.NAME), parseInner(walker, recursion + 1, NodeType.GENERIC_DECLARATIONS), parseInner(walker, recursion + 1, NodeType.INTERFACE_BASES), expectAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE), parseInner(walker, recursion + 1, NodeType.INTERFACE_MEMBERS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } } case NodeType.CLASS_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node keyword = parseToken(walker, recursion + 1, Language.Key.CLASS);//parseToken(walker, recursion + 1, TokenType.KEYWORD, "class"); if (keyword == null) { return null; } else { return new Branch(NodeType.CLASS_DECLARATION, mods, keyword, expectAny(walker, recursion + 1, NodeType.NAME), parseInner(walker, recursion + 1, NodeType.GENERIC_DECLARATIONS), parseInner(walker, recursion + 1, NodeType.CLASS_BASE), parseInner(walker, recursion + 1, NodeType.CLASS_IMPLEMENTS), expectAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE), parseInner(walker, recursion + 1, NodeType.CLASS_MEMBERS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } } case NodeType.ATTRIBUTE_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node at = parseToken(walker, recursion + 1, TokenType.OPERATOR, "@"); if (at == null) { return null; } Node keyword = parseToken(walker, recursion + 1, Language.Key.INTERFACE); //TokenType.KEYWORD, "interface"); if (keyword == null) { return null; } else { return new Branch(NodeType.ATTRIBUTE_DECLARATION, mods, at, keyword, expectAny(walker, recursion + 1, NodeType.NAME), parseInner(walker, recursion + 1, NodeType.GENERIC_DECLARATIONS), parseInner(walker, recursion + 1, NodeType.INTERFACE_BASES), expectAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE), parseInner(walker, recursion + 1, NodeType.INTERFACE_MEMBERS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } } case NodeType.ENUM_MEMBERS: return parseList(walker, recursion + 1, NodeType.ENUM_MEMBERS, NodeType.COMMA, true, NodeType.SPECIALISED_ENUM_SUBTYPE, NodeType.SPECIALISED_ENUM_MEMBER, NodeType.ENUM_MEMBER); case NodeType.ENUM_MEMBER: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node name = parseToken(walker, recursion + 1, TokenType.NAME); if (name == null) { return null; } else { return new Branch(NodeType.ENUM_MEMBER, mods, name); } } case NodeType.SPECIALISED_ENUM_MEMBER: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node name = parseToken(walker, recursion + 1, TokenType.NAME); if (name == null) { return null; } Node args = parseAny(walker, recursion + 1, NodeType.ARGUMENTS); if (args == null) { return null; } return new Branch(NodeType.SPECIALISED_ENUM_MEMBER, mods, name, args); } case NodeType.SPECIALISED_ENUM_SUBTYPE: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node name = parseToken(walker, recursion + 1, TokenType.NAME); if (name == null) { return null; } Node args = parseAny(walker, recursion + 1, NodeType.ARGUMENTS); //if (args == null) { // return null; //} Node open = parseAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE); if (open == null) { return null; } Node members = expectAny(walker, recursion + 1, NodeType.CLASS_MEMBERS); Node close = expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE); if (args == null) { return new Branch(NodeType.SPECIALISED_ENUM_SUBTYPE, mods, name, open, members, close); } else { return new Branch(NodeType.SPECIALISED_ENUM_SUBTYPE_WITH_ARGS, mods, name, args, open, members, close); } } case NodeType.ENUM_CLASS_MEMBERS: { //System.out.println("Looking for semicolon got " + walker.peek()); Node semi = parseInner(walker, recursion + 1, NodeType.SEMICOLON); if (semi == null) { return new Branch(NodeType.NO_ENUM_CLASS_MEMBERS); } else { return new Branch(NodeType.ENUM_CLASS_MEMBERS, semi, parseInner(walker, recursion + 1, NodeType.CLASS_MEMBERS)); } } case NodeType.CLASS_MEMBERS: { // Workaround because empty {...} seems to cause issues //ScanWalker pos = walker.clone(); //Node emptyEnd = parseAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE); //if (emptyEnd != null) { // walker.reset(pos); // return new Branch(NodeType.CLASS_MEMBERS); //} return parseList(walker, recursion + 1, NodeType.CLASS_MEMBERS, null, false, NodeType.CONSTRUCTOR_DECLARATION, NodeType.STATIC_CONSTRUCTOR_DECLARATION, NodeType.METHOD_DECLARATION, NodeType.FIELD_DECLARATION, NodeType.CLASS_DECLARATION, NodeType.INTERFACE_DECLARATION, NodeType.ENUM_DECLARATION, NodeType.ATTRIBUTE_DECLARATION, NodeType.SEMICOLON); } case NodeType.INTERFACE_MEMBERS: { return parseList(walker, recursion + 1, NodeType.INTERFACE_MEMBERS, null, false, NodeType.STATIC_CONSTRUCTOR_DECLARATION, NodeType.METHOD_DECLARATION, NodeType.FIELD_DECLARATION, NodeType.CLASS_DECLARATION, NodeType.INTERFACE_DECLARATION, NodeType.ENUM_DECLARATION, NodeType.ATTRIBUTE_DECLARATION, NodeType.SEMICOLON); } case NodeType.MODIFIER_LIST: return parseList(walker, recursion + 1, NodeType.MODIFIER_LIST, null, false, NodeType.SIMPLE_MODIFIER, NodeType.COMPLEX_TAGGED_MODIFIER); case NodeType.SIMPLE_MODIFIER: { Node mod = null; mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.PUBLIC);//parseToken(walker, recursion + 1, TokenType.KEYWORD, "public"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.PROTECTED);//TokenType.KEYWORD, "protected"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.PRIVATE);//TokenType.KEYWORD, "private"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.STATIC);//TokenType.KEYWORD, "static"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.FINAL);//TokenType.KEYWORD, "final"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.ABSTRACT);//TokenType.KEYWORD, "abstract"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.SYNCHRONISED);//TokenType.KEYWORD, "synchronized"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.NATIVE);//TokenType.KEYWORD, "native"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.TRANSIENT);//TokenType.KEYWORD, "transient"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.VOLATILE);//TokenType.KEYWORD, "volatile"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.COMPAT_STRICTFP);//TokenType.KEYWORD, "strictfp"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.VOLATILE);//TokenType.KEYWORD, "volatile"); mod = mod != null ? mod : parseToken(walker, recursion + 1, Language.Key.DEFAULT);//TokenType.KEYWORD, "default"); return mod == null ? null : new Branch(NodeType.SIMPLE_MODIFIER, mod); } case NodeType.BREAK_STATEMENT: { Node br = parseToken(walker, recursion + 1, Language.Key.BREAK); //TokenType.KEYWORD, "break"); if (br == null) { return null; } else { Node label = parseAny(walker, recursion + 1, NodeType.NAME); Node semicolon = expectAny(walker, recursion + 1, NodeType.SEMICOLON); if (label == null) { return new Branch(NodeType.BREAK_STATEMENT, br, semicolon); } else { return new Branch(NodeType.BREAK_TO_STATEMENT, br, label, semicolon); } } } case NodeType.CONTINUE_STATEMENT: { Node br = parseToken(walker, recursion + 1, Language.Key.CONTINUE); //TokenType.KEYWORD, "continue"); if (br == null) { return null; } else { Node label = parseAny(walker, recursion + 1, NodeType.NAME); Node semicolon = expectAny(walker, recursion + 1, NodeType.SEMICOLON); if (label == null) { return new Branch(NodeType.CONTINUE_STATEMENT, br, semicolon); } else { return new Branch(NodeType.CONTINUE_TO_STATEMENT, br, label, semicolon); } } } case NodeType.LABEL_STATEMENT: { Node n = parseAny(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } Node s = parseAny(walker, recursion + 1, NodeType.COLON); if (s == null) { return null; } else { return new Branch(NodeType.LABEL_STATEMENT, n, s); } } case NodeType.COMPLEX_TAGGED_MODIFIER: { Node tagsymbol = parseToken(walker, recursion + 1, TokenType.OPERATOR, "@"); boolean noAt = (tagsymbol == null); if (noAt) { tagsymbol = tagsymbol != null ? tagsymbol : parseToken(walker, recursion + 1, TokenType.OPERATOR, "#"); tagsymbol = tagsymbol != null ? tagsymbol : parseToken(walker, recursion + 1, TokenType.OPERATOR, "##"); } if (tagsymbol == null) { return null; } Node tagname; if (noAt) { tagname = parseAny(walker, recursion + 1, NodeType.NAME, NodeType.STRING_LITERAL_EXPRESSION, NodeType.INTEGER_LITERAL_EXPRESSION); } else { tagname = parseAny(walker, recursion + 1, NodeType.TYPE_REFERENCE); } if (tagname == null) { return null; } if (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, "(")) { return new Branch(NodeType.COMPLEX_TAGGED_MODIFIER, tagsymbol, tagname, expectAny(walker, recursion + 1, NodeType.MODIFIER_ARGUMENTS)); } else if (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, ":")) { Node sep = parseToken(walker, recursion + 1, TokenType.OPERATOR, ":"); return new Branch(NodeType.NAME_TAGGED_MODIFIER, tagsymbol, tagname, sep, expectAny(walker, recursion + 1, NodeType.NAME, NodeType.STRING_LITERAL_EXPRESSION, NodeType.INTEGER_LITERAL_EXPRESSION)); } else { return new Branch(NodeType.SIMPLE_TAGGED_MODIFIER, tagsymbol, tagname); } } case NodeType.MODIFIER_ARGUMENTS: { Node open = parseAny(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); if (open == null) { return null; } Node inner = parseAny(walker, recursion + 1, NodeType.MODIFIER_EXPRESSIONS); Node close = expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE); return new Branch(NodeType.MODIFIER_ARGUMENTS, open, inner, close); } case NodeType.SIMPLE_TYPE: { Node result = null; result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.BIT); //TokenType.KEYWORD, "boolean"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.BYTE); //TokenType.KEYWORD, "byte"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.SHORT); //TokenType.KEYWORD, "short"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.COMPAT_CHAR); //TokenType.KEYWORD, "char"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.INT); //TokenType.KEYWORD, "int"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.LONG); //TokenType.KEYWORD, "long"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.FLOAT); //TokenType.KEYWORD, "float"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.DOUBLE); //TokenType.KEYWORD, "double"); //result = result != null ? result : parseToken(walker, recursion + 1, TokenType.KEYWORD, "cpuword"); result = result != null ? result : parseToken(walker, recursion + 1, Language.Key.DUCK); //TokenType.KEYWORD, "duck"); return result; } case NodeType.ARGUMENT_DECLARATIONS: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); if (start == null) { return null; } else { return new Branch(NodeType.ARGUMENT_DECLARATIONS, start, parseList(walker, recursion + 1, NodeType.ARGUMENT_DECLARATION_LIST, NodeType.COMMA, false, NodeType.LAZY_ARGUMENT_DECLARATION, NodeType.VARIABLE_ARGUMENT_DECLARATION, NodeType.SIMPLE_ARGUMENT_DECLARATION), expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE)); } } case NodeType.GENERIC_DECLARATIONS: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_ANGLE_BRACE); if (start == null) { return new Branch(NodeType.NO_GENERIC_DECLARATIONS); } else { return new Branch(NodeType.GENERIC_DECLARATIONS, start, parseList(walker, recursion + 1, NodeType.GENERIC_DECLARATION_LIST, NodeType.COMMA, false, NodeType.VARIABLE_TYPED_GENERIC_DECLARATION, NodeType.VARIABLE_GENERIC_DECLARATION, NodeType.SIMPLE_TYPED_GENERIC_DECLARATION, NodeType.SIMPLE_EXTENDED_GENERIC_DECLARATION, NodeType.SIMPLE_GENERIC_DECLARATION), expectAny(walker, recursion + 1, NodeType.CLOSE_ANGLE_BRACE)); } } case NodeType.METHOD_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node gentype = parseInner(walker, recursion + 1, NodeType.GENERIC_DECLARATIONS); Node t = parseInner(walker, recursion + 1, NodeType.RETURN_TYPE); if (t == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { Node args = parseInner(walker, recursion + 1, NodeType.ARGUMENT_DECLARATIONS); if (args == null) { return null; } else { return new Branch(NodeType.METHOD_DECLARATION, mods, gentype, t, n, args, parseAny(walker, recursion + 1, NodeType.ARRAY_TYPE_TAIL), parseInner(walker, recursion + 1, NodeType.THROWS), expectAny(walker, recursion + 1, NodeType.METHOD_BODY)); } } } } case NodeType.CONSTRUCTOR_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { Node args = parseInner(walker, recursion + 1, NodeType.ARGUMENT_DECLARATIONS); if (args == null) { return null; } else { return new Branch(NodeType.CONSTRUCTOR_DECLARATION, mods, n, args, parseInner(walker, recursion + 1, NodeType.THROWS), expectAny(walker, recursion + 1, NodeType.METHOD_BODY)); } } } case NodeType.STATIC_CONSTRUCTOR_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); if (walker.peek().is(TokenType.OPERATOR, "{")) { Node body = parseInner(walker, recursion + 1, NodeType.METHOD_BODY); return new Branch(NodeType.STATIC_CONSTRUCTOR_DECLARATION, mods, body); } else { return null; } } case NodeType.THROWS: { Token keyword = parseToken(walker, recursion + 1, Language.Key.THROWS); //TokenType.KEYWORD, "throws"); if (keyword == null) { return new Branch(NodeType.NO_THROWS); } else { return new Branch(NodeType.THROWS, parseInner(walker, recursion + 1, NodeType.TYPE_REFERENCES)); } } case NodeType.METHOD_BODY: { Node semi = parseInner(walker, recursion + 1, NodeType.SEMICOLON); if (semi == null) { Node def = parseToken(walker, recursion + 1, Language.Key.DEFAULT); //TokenType.KEYWORD, "default"); if (def != null) { return new Branch(NodeType.DEFAULT_METHOD_BODY, def, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } return new Branch(NodeType.METHOD_BODY, expectAny(walker, recursion + 1, NodeType.BLOCK_STATEMENT)); } else { return new Branch(NodeType.NO_METHOD_BODY, semi); } } case NodeType.BLOCK_STATEMENT: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE); if (start == null) { return null; } else { return new Branch(NodeType.BLOCK_STATEMENT, start, parseInner(walker, recursion + 1, NodeType.STATEMENTS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } } case NodeType.SWITCH_STATEMENT: { Node keyword = parseToken(walker, recursion + 1, Language.Key.SWITCH); //TokenType.KEYWORD, "switch"); if (keyword == null) { return null; } Node cond = expectAny(walker, recursion + 1, NodeType.BRACED_EXPRESSION); Node start = expectAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE); return new Branch(NodeType.SWITCH_STATEMENT, keyword, cond, start, parseInner(walker, recursion + 1, NodeType.SWITCH_MEMBERS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } case NodeType.ASSERT_STATEMENT: { Node keyword = parseToken(walker, recursion + 1, Language.Key.ASSERT); //TokenType.KEYWORD, "assert"); if (keyword == null) { return null; } else { Node expr = expectAny(walker, recursion + 1, NodeType.EXPRESSION); Node colon = parseAny(walker, recursion + 1, NodeType.COLON); if (colon == null) { return new Branch(NodeType.ASSERT_STATEMENT, keyword, expr, expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } else { return new Branch(NodeType.ASSERT_DEBUG_STATEMENT, keyword, expr, colon, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } } } case NodeType.THROW_STATEMENT: { Node keyword = parseToken(walker, recursion + 1, Language.Key.THROW); //TokenType.KEYWORD, "throw"); if (keyword == null) { return null; } else { return new Branch(NodeType.THROW_STATEMENT, keyword, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } } case NodeType.RETURN_EXPRESSION_STATEMENT: { Node keyword = parseToken(walker, recursion + 1, Language.Key.RETURN); //TokenType.KEYWORD, "return"); if (keyword == null) { return null; } else { Node next = expectAny(walker, recursion + 1, NodeType.EXPRESSION, NodeType.SEMICOLON); if (next.getNodeType() == NodeType.SEMICOLON) { return new Branch(NodeType.RETURN_NOTHING_STATEMENT, keyword, next); } else { return new Branch(NodeType.RETURN_EXPRESSION_STATEMENT, keyword, next, expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } } } case NodeType.VARIABLE_STATEMENT: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t != null &&!walker.isAtEnd() && walker.peek().is(TokenType.NAME)) { return new Branch(NodeType.VARIABLE_STATEMENT, mods, t, parseInner(walker, recursion + 1, NodeType.SLOTS), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } else { return null; } } case NodeType.FOR_VARIABLES: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t != null &&!walker.isAtEnd() && walker.peek().is(TokenType.NAME)) { return new Branch(NodeType.FOR_VARIABLES, mods, t, parseInner(walker, recursion + 1, NodeType.SLOTS)); } else { return null; } } case NodeType.IF_STATEMENT: { Token keyword = parseToken(walker, recursion + 1, Language.Key.IF); //TokenType.KEYWORD, "if"); if (keyword == null) { return null; } else { Node cond = expectAny(walker, recursion + 1, NodeType.BRACED_EXPRESSION); // TODO: Change to only bracketed expression Node cons = expectAny(walker, recursion + 1, NodeType.STATEMENT); Node els = parseInner(walker, recursion + 1, NodeType.ELSE_CLAUSE); return new Branch(NodeType.IF_STATEMENT, keyword, cond, cons, els); } } case NodeType.SYNCHRONIZED_STATEMENT: { Token keyword = parseToken(walker, recursion + 1, Language.Key.SYNCHRONISED); //TokenType.KEYWORD, "synchronized"); if (keyword == null) { return null; } else { Node cond = expectAny(walker, recursion + 1, NodeType.BRACED_EXPRESSION); // TODO: Change to only bracketed expression Node cons = expectAny(walker, recursion + 1, NodeType.BLOCK_STATEMENT); return new Branch(NodeType.SYNCHRONIZED_STATEMENT, keyword, cond, cons); } } case NodeType.ELSE_CLAUSE: { Token keyword = parseToken(walker, recursion + 1, Language.Key.ELSE); //TokenType.KEYWORD, "else"); if (keyword == null) { return new Branch(NodeType.NO_ELSE_CLAUSE); } else { return new Branch(NodeType.ELSE_CLAUSE, keyword, expectAny(walker, recursion + 1, NodeType.STATEMENT)); } } case NodeType.WHILE_STATEMENT: { Token keyword = parseToken(walker, recursion + 1, Language.Key.WHILE); //TokenType.KEYWORD, "while"); if (keyword == null) { return null; } else { Node cond = expectAny(walker, recursion + 1, NodeType.BRACED_EXPRESSION); Node cons = expectAny(walker, recursion + 1, NodeType.STATEMENT, NodeType.SEMICOLON); return new Branch(NodeType.WHILE_STATEMENT, keyword, cond, cons); } } case NodeType.FOR_STATEMENT: { Token keyword = parseToken(walker, recursion + 1, Language.Key.FOR); //TokenType.KEYWORD, "for"); if (keyword == null) { return null; } else { Node obr = expectAny(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); Node st1 = expectAny(walker, recursion + 1, NodeType.FOR_VARIABLES, NodeType.EXPRESSIONS); Node firstsep = expectAny(walker, recursion + 1, NodeType.SEMICOLON, NodeType.COLON); if (firstsep.getNodeType() == NodeType.COLON) { // Handle for-each variant Node rangeexpr = parseAny(walker, recursion + 1, NodeType.EXPRESSIONS); Node cbr = expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE); Node cons = expectAny(walker, recursion + 1, NodeType.STATEMENT, NodeType.SEMICOLON); return new Branch(NodeType.FOR_EACH_STATEMENT, keyword, obr, st1, firstsep, rangeexpr, cbr, cons); } else { Node st2 = expectAny(walker, recursion + 1, NodeType.EXPRESSIONS); Node lastsep = expectAny(walker, recursion + 1, NodeType.SEMICOLON); Node st3 = parseAny(walker, recursion + 1, NodeType.EXPRESSIONS); Node cbr = expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE); Node cons = expectAny(walker, recursion + 1, NodeType.STATEMENT, NodeType.SEMICOLON); return new Branch(NodeType.FOR_STATEMENT, keyword, obr, st1, firstsep, st2, lastsep, st3, cbr, cons); } } } case NodeType.DO_WHILE_STATEMENT: { Token keyword = parseToken(walker, recursion + 1, Language.Key.DO); //TokenType.KEYWORD, "do"); if (keyword == null) { return null; } else { Node cons = expectAny(walker, recursion + 1, NodeType.STATEMENT); Node kw2 = parseToken(walker, recursion + 1, Language.Key.WHILE); //TokenType.KEYWORD, "while"); Node cond = expectAny(walker, recursion + 1, NodeType.BRACED_EXPRESSION); Node end = expectAny(walker, recursion + 1, NodeType.SEMICOLON); return new Branch(NodeType.DO_WHILE_STATEMENT, keyword, cons, kw2, cond, end); } } case NodeType.TRY_STATEMENT: { Token keyword = parseToken(walker, recursion + 1, Language.Key.TRY); //TokenType.KEYWORD, "try"); if (keyword == null) { return null; } else { Node vars = parseAny(walker, recursion + 1, NodeType.TRY_RESOURCES); Node tries = expectAny(walker, recursion + 1, NodeType.BLOCK_STATEMENT); Node catches = parseList(walker, recursion + 1, NodeType.CATCH_CLAUSES, null, false, NodeType.CATCH_CLAUSE); Node fin = parseInner(walker, recursion + 1, NodeType.FINALLY_CLAUSE); return new Branch(NodeType.TRY_STATEMENT, keyword, vars, tries, catches, fin); } } case NodeType.TRY_RESOURCES: { Node open = parseAny(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); if (open == null) { return new Branch(NodeType.NO_TRY_RESOURCES); } return new Branch(NodeType.TRY_RESOURCES, open, parseList(walker, recursion + 1, NodeType.TRY_RESOURCE_LIST, NodeType.SEMICOLON, false, NodeType.FOR_VARIABLES), expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE)); } case NodeType.CATCH_CLAUSE: { Token keyword = parseToken(walker, recursion + 1, Language.Key.CATCH); //TokenType.KEYWORD, "catch"); if (keyword == null) { return null; } else { Node cond = expectAny(walker, recursion + 1, NodeType.ARGUMENT_DECLARATIONS); Node cons = expectAny(walker, recursion + 1, NodeType.BLOCK_STATEMENT); return new Branch(NodeType.CATCH_CLAUSE, keyword, cond, cons); } } case NodeType.FINALLY_CLAUSE: { Token keyword = parseToken(walker, recursion + 1, Language.Key.FINALLY); //TokenType.KEYWORD, "finally"); if (keyword == null) { return new Branch(NodeType.NO_FINALLY_CLAUSE); } else { Node cons = expectAny(walker, recursion + 1, NodeType.BLOCK_STATEMENT); return new Branch(NodeType.FINALLY_CLAUSE, keyword, cons); } } case NodeType.EXPRESSION_STATEMENT: { Node expr = parseAny(walker, recursion + 1, NodeType.EXPRESSION); if (expr != null) { /*switch (expr.getNodeType()) { case NodeType.ASSIGNMENT_EXPRESSION: case NodeType.COUNT_EXPRESSION: case NodeType.AUTOMATIC_METHOD_CALL_EXPRESSION: case NodeType.NORMAL_METHOD_CALL_EXPRESSION: case NodeType.SUPER_CONSTRUCTOR_CALL_EXPRESSION: case NodeType.SUPER_METHOD_CALL_EXPRESSION: case NodeType.THIS_CONSTRUCTOR_CALL_EXPRESSION: return new Branch(NodeType.EXPRESSION_STATEMENT, expr, expectAny(walker, recursion + 1, NodeType.SEMICOLON)); default: return null; }*/ return new Branch(NodeType.EXPRESSION_STATEMENT, expr, expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } else { return null; } } case NodeType.STATEMENTS: return parseList(walker, recursion + 1, NodeType.STATEMENTS, null, false, NodeType.STATEMENT); case NodeType.SWITCH_MEMBERS: return parseList(walker, recursion + 1, NodeType.SWITCH_MEMBERS, null, false, NodeType.CASE_LABEL, NodeType.DEFAULT_LABEL, NodeType.STATEMENT); case NodeType.CASE_LABEL: { Node keyword = parseToken(walker, recursion + 1, Language.Key.CASE); //TokenType.KEYWORD, "case"); if (keyword == null) { return null; } else { return new Branch(NodeType.CASE_LABEL, keyword, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.COLON)); } } case NodeType.DEFAULT_LABEL: { Node keyword = parseToken(walker, recursion + 1, Language.Key.DEFAULT); //TokenType.KEYWORD, "default"); if (keyword == null) { return null; } else { return new Branch(NodeType.DEFAULT_LABEL, keyword, expectAny(walker, recursion + 1, NodeType.COLON)); } } case NodeType.STATEMENT: return parseAny(walker, recursion + 1, NodeType.LABEL_STATEMENT, NodeType.IF_STATEMENT, NodeType.WHILE_STATEMENT, NodeType.DO_WHILE_STATEMENT, NodeType.FOR_STATEMENT, NodeType.SWITCH_STATEMENT, NodeType.ASSERT_STATEMENT, NodeType.THROW_STATEMENT, NodeType.RETURN_EXPRESSION_STATEMENT, NodeType.TRY_STATEMENT, NodeType.VARIABLE_STATEMENT, NodeType.BLOCK_STATEMENT, NodeType.EXPRESSION_STATEMENT, NodeType.SYNCHRONIZED_STATEMENT, NodeType.BREAK_STATEMENT, NodeType.CONTINUE_STATEMENT, NodeType.CLASS_DECLARATION, NodeType.INTERFACE_DECLARATION, NodeType.ENUM_DECLARATION, NodeType.ATTRIBUTE_DECLARATION, NodeType.SEMICOLON); case NodeType.FIELD_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t != null &&!walker.isAtEnd() && walker.peek().is(TokenType.NAME)) { return new Branch(NodeType.FIELD_DECLARATION, mods, t, parseInner(walker, recursion + 1, NodeType.SLOTS), expectAny(walker, recursion + 1, NodeType.SEMICOLON)); } else { return null; } } case NodeType.NULL_LITERAL_EXPRESSION: { Token keyword = parseToken(walker, recursion + 1, Language.Key.NULL); //TokenType.KEYWORD, "null"); if (keyword == null) { return null; } else { return new Branch(NodeType.NULL_LITERAL_EXPRESSION, keyword); } } case NodeType.BOOLEAN_LITERAL_EXPRESSION: { Token keyword = parseToken(walker, recursion + 1, Language.Key.FALSE); //TokenType.KEYWORD, "false"); if (keyword == null) { keyword = parseToken(walker, recursion + 1, Language.Key.TRUE); //TokenType.KEYWORD, "true"); } if (keyword == null) { return null; } else { return new Branch(NodeType.BOOLEAN_LITERAL_EXPRESSION, keyword); } } case NodeType.INTEGER_LITERAL_EXPRESSION: { Token num = parseToken(walker, recursion + 1, TokenType.DEC_INTEGER); if (num == null) { num = parseToken(walker, recursion + 1, TokenType.HEX_INTEGER); } if (num == null) { num = parseToken(walker, recursion + 1, TokenType.BIN_INTEGER); } if (num == null) { return null; } else { return new Branch(NodeType.INTEGER_LITERAL_EXPRESSION, num); } } case NodeType.FLOAT_LITERAL_EXPRESSION: { Token num = parseToken(walker, recursion + 1, TokenType.DEC_FLOAT); if (num == null) { num = parseToken(walker, recursion + 1, TokenType.HEX_FLOAT); } if (num == null) { num = parseToken(walker, recursion + 1, TokenType.BIN_FLOAT); } if (num == null) { return null; } else { return new Branch(NodeType.FLOAT_LITERAL_EXPRESSION, num); } } case NodeType.STRING_LITERAL_EXPRESSION: { Token str = parseToken(walker, recursion + 1, TokenType.STRING); if (str == null) { return null; } else { return new Branch(NodeType.STRING_LITERAL_EXPRESSION, str); } } case NodeType.CHAR_LITERAL_EXPRESSION: { Token chr = parseToken(walker, recursion + 1, TokenType.CHAR); if (chr == null) { return null; } else { return new Branch(NodeType.CHAR_LITERAL_EXPRESSION, chr); } } case NodeType.LITERAL_EXPRESSION: return parseAny(walker, recursion + 1, NodeType.NULL_LITERAL_EXPRESSION, NodeType.BOOLEAN_LITERAL_EXPRESSION, NodeType.INTEGER_LITERAL_EXPRESSION, NodeType.FLOAT_LITERAL_EXPRESSION, NodeType.CHAR_LITERAL_EXPRESSION, NodeType.STRING_LITERAL_EXPRESSION); case NodeType.REFERENCE_EXPRESSION: return parseTokenBranch(walker, recursion + 1, NodeType.REFERENCE_EXPRESSION, TokenType.NAME); case NodeType.GENERIC_REFERENCE_EXPRESSION: { Node n = parseAny(walker, recursion + 1, NodeType.GENERIC_ONLY_TYPE_REFERENCE); if (n == null) { return null; } return new Branch(NodeType.GENERIC_REFERENCE_EXPRESSION, n); } case NodeType.GENERIC_REFERENCE_NAME: { Node args = parseAny(walker, recursion + 1, NodeType.GENERIC_ARGUMENTS); if (args == null) { return null; } Node nam = parseAny(walker, recursion + 1, NodeType.NAME); if (nam == null) { return null; } return new Branch(NodeType.GENERIC_NAME, args, nam); } case NodeType.SUPER: return parseTokenBranch(walker, recursion + 1, NodeType.SUPER, Language.Key.SUPER); //TokenType.KEYWORD, "super"); case NodeType.THIS_EXPRESSION: { // TODO: Why'd I put this here? // Node t = parseInner(walker, recursion + 1, NodeType.TYPE_REFERENCE); return parseTokenBranch(walker, recursion + 1, NodeType.THIS_EXPRESSION, Language.Key.THIS); //TokenType.KEYWORD, "this"); } case NodeType.OUTER_THIS_EXPRESSION: { Node t = parseInner(walker, recursion + 1, NodeType.TYPE_REFERENCE); if (t == null) { return null; } Node dot = parseInner(walker, recursion + 1, NodeType.DOT); if (dot == null) { return null; } Node thi = parseTokenBranch(walker, recursion + 1, NodeType.THIS_EXPRESSION, Language.Key.THIS); //TokenType.KEYWORD, "this"); if (thi == null) { return null; } else { return new Branch(NodeType.OUTER_THIS_EXPRESSION, t, dot, thi); } } case NodeType.OUTER_SUPER_CONSTRUCTOR_CALL_EXPRESSION: { Node outerThis = parseAny(walker, recursion + 1, NodeType.OUTER_THIS_EXPRESSION, NodeType.TYPE); if (outerThis == null) { return null; } Node dot = parseInner(walker, recursion + 1, NodeType.DOT); if (dot == null) { return null; } Node sup = parseToken(walker, recursion + 1, Language.Key.SUPER); //TokenType.KEYWORD, "super"); if (sup == null) { return null; } Node argsOrDot = parseAny(walker, recursion + 1, NodeType.DOT, NodeType.ARGUMENTS); if (argsOrDot == null) { return null; } if (argsOrDot.getNodeType() == NodeType.DOT) { Node nam = expectAny(walker, recursion + 1, NodeType.NAME); Node realargs = expectAny(walker, recursion + 1, NodeType.ARGUMENTS); return new Branch(NodeType.OUTER_SUPER_METHOD_CALL_EXPRESSION, outerThis, dot, sup, argsOrDot, nam, realargs); } return new Branch(NodeType.OUTER_THIS_EXPRESSION, outerThis, dot, sup, argsOrDot); } case NodeType.TYPE_EXPRESSION: { Node t = parseAny(walker, recursion + 1, NodeType.TYPE, NodeType.RETURN_TYPE); // RETURN_TYPE handles special case NodeType.of void if (t == null) { return null; } Node dot = parseInner(walker, recursion + 1, NodeType.DOT); if (dot == null) { return null; } Node thi = parseToken(walker, recursion + 1, Language.Key.CLASS);//parseToken(walker, recursion + 1, TokenType.KEYWORD, "class"); if (thi == null) { return null; } else { return new Branch(NodeType.TYPE_EXPRESSION, t, dot, thi); } } /*case NodeType.NAMED_LAMBDA_EXPRESSION: { Node t = parseAny(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } Node dcol = parseAny(walker, recursion + 1, NodeType.DOUBLECOLON); if (dcol == null) { return null; } Node name = parseToken(walker, recursion + 1, Language.Key.NEW); //TokenType.KEYWORD, "new"); if (name == null) { name = expectAny(walker, recursion + 1, TokenType.NAME); } return new Branch(NodeType.NAMED_LAMBDA_EXPRESSION, t, dcol, name); }*/ case NodeType.LAMBDA_ARGS: { Node open = parseAny(walker, recursion + 1, NodeType.NAME, NodeType.OPEN_ROUND_BRACE); if (open == null) { return null; } if (open.getNodeType() == NodeType.NAME) { return new Branch(NodeType.LAMBDA_ARGS, open); } Node inner = parseList(walker, recursion + 1, NodeType.ARGUMENT_DECLARATION_LIST, NodeType.COMMA, false, NodeType.LAZY_ARGUMENT_DECLARATION, NodeType.VARIABLE_ARGUMENT_DECLARATION, NodeType.SIMPLE_ARGUMENT_DECLARATION, NodeType.NAME); Node close = parseAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE); if (close == null) { return null; } return new Branch(NodeType.LAMBDA_ARGS, open, inner, close); } case NodeType.LAMBDA_EXPRESSION: { Node args = parseAny(walker, recursion + 1, NodeType.LAMBDA_ARGS); if (args == null) { return null; } Node op = parseToken(walker, recursion + 1, TokenType.OPERATOR, "->"); if (op == null) { return null; } Node rhs = expectAny(walker, recursion + 1, NodeType.BLOCK_STATEMENT, NodeType.EXPRESSION); return new Branch(NodeType.LAMBDA_EXPRESSION, args, op, rhs); } case NodeType.SIMPLE_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.TYPE_NAMED_LAMBDA_EXPRESSION, NodeType.SUPER, NodeType.THIS_EXPRESSION, NodeType.OUTER_SUPER_CONSTRUCTOR_CALL_EXPRESSION, // A weird edge-case NodeType.OUTER_THIS_EXPRESSION, NodeType.TYPE_EXPRESSION, NodeType.LITERAL_EXPRESSION, NodeType.BRACED_EXPRESSION, NodeType.GENERIC_REFERENCE_EXPRESSION, NodeType.REFERENCE_EXPRESSION, NodeType.NEW_EXPRESSION); boolean done = false; while (lhs != null && !done && !walker.isAtEnd() && (walker.peek().is(TokenType.OPERATOR, "[") || walker.peek().is(TokenType.OPERATOR, ".") || walker.peek().is(TokenType.OPERATOR, "::") || walker.peek().is(TokenType.OPERATOR, "("))) { if ((lhs.getNodeType() == NodeType.REFERENCE_EXPRESSION || lhs.getNodeType() == NodeType.GENERIC_REFERENCE_EXPRESSION) && walker.peek().is(TokenType.OPERATOR, "(")) { lhs = new Branch(NodeType.AUTOMATIC_METHOD_CALL_EXPRESSION, lhs, parseInner(walker, recursion + 1, NodeType.ARGUMENTS)); } else if (lhs.getNodeType() == NodeType.SUPER && walker.peek().is(TokenType.OPERATOR, "(")) { lhs = new Branch(NodeType.SUPER_CONSTRUCTOR_CALL_EXPRESSION, lhs, parseInner(walker, recursion + 1, NodeType.ARGUMENTS)); } else if (lhs.getNodeType() == NodeType.THIS_EXPRESSION && walker.peek().is(TokenType.OPERATOR, "(")) { lhs = new Branch(NodeType.THIS_CONSTRUCTOR_CALL_EXPRESSION, lhs, parseInner(walker, recursion + 1, NodeType.ARGUMENTS)); } else if (walker.peek().is(TokenType.OPERATOR, "::")) { Node dcol = parseInner(walker, recursion + 1, NodeType.DOUBLECOLON); Node nam = parseToken(walker, recursion + 1, Language.Key.NEW); //TokenType.KEYWORD, "new"); if (nam == null) { nam = expectAny(walker, recursion + 1, NodeType.NAME); } lhs = new Branch(NodeType.NAMED_LAMBDA_EXPRESSION, lhs, dcol, nam); } else if (walker.peek().is(TokenType.OPERATOR, ".")) { boolean isThis = lhs.getNodeType() == NodeType.THIS_EXPRESSION; boolean isSuper = lhs.getNodeType() == NodeType.SUPER; Node dot = parseInner(walker, recursion + 1, NodeType.DOT); Node specialNew = parseAny(walker, recursion + 1, NodeType.NEW_EXPRESSION); if (specialNew != null) { lhs = new Branch(NodeType.SPECIAL_NEW_EXPRESSION, lhs, dot, specialNew); } else { Node nam = expectAny(walker, recursion + 1, NodeType.NAME, NodeType.THIS_EXPRESSION, NodeType.GENERIC_REFERENCE_NAME); if (walker.peek().is(TokenType.OPERATOR, "(")) { lhs = new Branch(isThis ? NodeType.THIS_METHOD_CALL_EXPRESSION : (isSuper ? NodeType.SUPER_METHOD_CALL_EXPRESSION : NodeType.NORMAL_METHOD_CALL_EXPRESSION), lhs, dot, nam, parseInner(walker, recursion + 1, NodeType.ARGUMENTS)); } else { lhs = new Branch(/*isThis ? NodeType.THIS_REFERENCE_EXPRESSION : (isSuper ? NodeType.SUPER_REFERENCE_EXPRESSION : */ (NodeType.SUBREFERENCE_EXPRESSION), lhs, dot, nam); } } } else if (lhs.getNodeType() != NodeType.SUPER && lhs.getNodeType() != NodeType.THIS_EXPRESSION && walker.peek().is(TokenType.OPERATOR, "[")) { Node open = parseInner(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE); /*if (walker.peek().is(TokenType.OPERATOR, "]")) { //ScanWalker pos = walker.clone(); Node close = parseInner(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE); lhs = new Branch(NodeType.SPECIAL_ARRAY_TYPE_EXPRESSION, open, close); } else {*/ lhs = new Branch(NodeType.ARRAY_INDEX_EXPRESSION, lhs, open, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE)); //} } else { done = true; } } return lhs; } case NodeType.TYPE_NAMED_LAMBDA_EXPRESSION: { Node typ = parseAny(walker, recursion + 1, NodeType.TYPE); if (typ == null) { return null; } Node dcol = parseAny(walker, recursion + 1, NodeType.DOUBLECOLON); if (dcol == null) { return null; } Node nam = parseToken(walker, recursion + 1, Language.Key.NEW); //TokenType.KEYWORD, "new"); if (nam == null) { nam = expectAny(walker, recursion + 1, NodeType.NAME); } return new Branch(NodeType.TYPE_NAMED_LAMBDA_EXPRESSION, typ, dcol, nam); } case NodeType.NEW_EXPRESSION: { Node keyword = parseToken(walker, recursion + 1, Language.Key.NEW); //TokenType.KEYWORD, "new"); if (keyword == null) { return null; } else { Node typ = expectAny(walker, recursion + 1, NodeType.TYPE); if (typ.getNodeType() == NodeType.TYPE && ((Branch)typ).getSubnode(0).getNodeType() == NodeType.ARRAY_TYPE) { return new Branch(NodeType.NEW_INITIALISED_ARRAY_EXPRESSION, keyword, typ, expectAny(walker, recursion + 1, NodeType.ARRAY_INITIALISER)); } if (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, "[")) { Node opener = parseAny(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE); /*if (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, "]")) { Node closer = parseAny(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE); return new Branch(NodeType.NEW_INITIALISED_ARRAY_EXPRESSION, keyword, typ, opener, closer, expectAny(walker, recursion + 1, NodeType.ARRAY_INITIALISER)); } else*/ { return new Branch(NodeType.NEW_CLEARED_ARRAY_EXPRESSION, keyword, typ, opener, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE), expectAny(walker, recursion + 1, NodeType.ARRAY_TYPE_TAIL)); } } else { Node args = expectAny(walker, recursion + 1, NodeType.ARGUMENTS); if (!walker.isAtEnd() && walker.peek().is(TokenType.OPERATOR, "{")) { return new Branch(NodeType.NEW_CLASS_EXPRESSION, keyword, typ, args, expectAny(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE), parseInner(walker, recursion + 1, NodeType.CLASS_MEMBERS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } else { return new Branch(NodeType.NEW_OBJECT_EXPRESSION, keyword, typ, args); } /* return new Branch(NodeType.NEW_OBJECT_EXPRESSION, keyword, typ, expectAny(walker, recursion + 1, NodeType.ARGUMENTS));*/ } } } case NodeType.ARRAY_TYPE_TAIL: { Node tmp; Branch result = new Branch(NodeType.ARRAY_TYPE_TAIL); while ((tmp = parseAny(walker, recursion + 1, NodeType.ARRAY_TYPE_PART)) != null) { result.append(tmp); } return result; } case NodeType.ARRAY_TYPE_PART: { Node open = parseAny(walker, recursion + 1, NodeType.OPEN_SQUARE_BRACE); if (open == null) { return null; } Node close = parseAny(walker, recursion + 1, NodeType.CLOSE_SQUARE_BRACE); if (close == null) { return null; } return new Branch(NodeType.ARRAY_TYPE_PART, open, close); } case NodeType.UNARY_EXPRESSION: { Node op = parseInner(walker, recursion + 1, NodeType.UNARY_OPERATOR); if (op == null) { Node open = parseInner(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); if (open == null) { return null; } else { Node typ = parseInner(walker, recursion + 1, NodeType.ANDABLE_TYPE); if (typ == null) { return null; } else { Node close = parseInner(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE); if (close == null) { return null; } else { // TODO: Should parsing EXPRESSION here really work? Node expr = parseAny(walker, recursion + 1, NodeType.UNARY_EXPRESSION, NodeType.SIMPLE_EXPRESSION); if (expr == null) { return null; } else { return new Branch(NodeType.CAST_EXPRESSION, open, typ, close, expr); } } } } } else { Node rhs = parseAny(walker, recursion + 1, NodeType.UNARY_EXPRESSION, NodeType.SIMPLE_EXPRESSION); if (rhs.getNodeType() == NodeType.STRING_LITERAL_EXPRESSION) { return null; // XXX This is a bit of a hack to prevent (x) + "str" evaluating as a cast } return new Branch(NodeType.UNARY_EXPRESSION, op, rhs); } } case NodeType.MULTIPLICATIVE_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.UNARY_EXPRESSION, NodeType.COUNT_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseAny(walker, recursion, NodeType.MULTIPLICATIVE_OPERATOR); if (op == null) { done = true; } else { lhs = new Branch(NodeType.MULTIPLICATIVE_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.UNARY_EXPRESSION, NodeType.SIMPLE_EXPRESSION)); } } return lhs; } case NodeType.ADDITIVE_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.MULTIPLICATIVE_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseAny(walker, recursion, NodeType.ADDITIVE_OPERATOR); if (op == null) { done = true; } else { lhs = new Branch(NodeType.ADDITIVE_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.MULTIPLICATIVE_EXPRESSION)); } } return lhs; } case NodeType.SHIFT_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.ADDITIVE_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseAny(walker, recursion, NodeType.SHIFT_OPERATOR); if (op == null) { done = true; } else { lhs = new Branch(NodeType.SHIFT_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.ADDITIVE_EXPRESSION)); } } return lhs; } case NodeType.COMPARISON_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.SHIFT_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseAny(walker, recursion, NodeType.COMPARISON_OPERATOR); if (op == null) { done = true; } else { lhs = new Branch(NodeType.COMPARISON_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.SHIFT_EXPRESSION)); } } return lhs; } case NodeType.INSTANCEOF_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.COMPARISON_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseToken(walker, recursion + 1, Language.Key.INSTANCEOF); //TokenType.KEYWORD, "instanceof"); if (op == null) { done = true; } else { lhs = new Branch(NodeType.INSTANCEOF_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.TYPE)); } } return lhs; } case NodeType.EQUALITY_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.INSTANCEOF_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseAny(walker, recursion, NodeType.EQUALITY_OPERATOR); if (op == null) { done = true; } else { lhs = new Branch(NodeType.EQUALITY_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.INSTANCEOF_EXPRESSION)); } } return lhs; } /*case NodeType.LOGICAL_EXPRESSION: { Node lhs = parseAny(walker, recursion + 1, NodeType.EQUALITY_EXPRESSION); boolean done = false; while (lhs != null && !walker.isAtEnd() && !done) { Node op = parseAny(walker, recursion, NodeType.LOGICAL_OPERATOR); if (op == null) { done = true; } else { lhs = new Branch(NodeType.LOGICAL_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.EQUALITY_EXPRESSION)); } } return lhs; }*/ case NodeType.BITWISE_AND_EXPRESSION: return parseSimpleBinop(walker, recursion, NodeType.BITWISE_AND_EXPRESSION, NodeType.BITWISE_AND_OPERATOR, NodeType.EQUALITY_EXPRESSION); case NodeType.BITWISE_XOR_EXPRESSION: return parseSimpleBinop(walker, recursion, NodeType.BITWISE_XOR_EXPRESSION, NodeType.BITWISE_XOR_OPERATOR, NodeType.BITWISE_AND_EXPRESSION); case NodeType.BITWISE_OR_EXPRESSION: return parseSimpleBinop(walker, recursion, NodeType.BITWISE_OR_EXPRESSION, NodeType.BITWISE_OR_OPERATOR, NodeType.BITWISE_XOR_EXPRESSION); case NodeType.LOGICAL_AND_EXPRESSION: return parseSimpleBinop(walker, recursion, NodeType.LOGICAL_AND_EXPRESSION, NodeType.LOGICAL_AND_OPERATOR, NodeType.BITWISE_OR_EXPRESSION); case NodeType.LOGICAL_OR_EXPRESSION: return parseSimpleBinop(walker, recursion, NodeType.LOGICAL_OR_EXPRESSION, NodeType.LOGICAL_OR_OPERATOR, NodeType.LOGICAL_AND_EXPRESSION); case NodeType.CONDITIONAL_EXPRESSION: { Node cond = parseAny(walker, recursion + 1, NodeType.LOGICAL_OR_EXPRESSION /*NodeType.LOGICAL_EXPRESSION*/); // TODO: Change to only bracketed expression if (cond == null) { return null; } Node q = parseToken(walker, recursion + 1, TokenType.OPERATOR, "?"); if (q == null) { return cond; } Node opt1 = parseAny(walker, recursion + 1, NodeType.LAMBDA_EXPRESSION, NodeType.CONDITIONAL_EXPRESSION, NodeType.LOGICAL_OR_EXPRESSION); Node c = parseToken(walker, recursion + 1, TokenType.OPERATOR, ":"); // TODO: Expect Node opt2 = parseAny(walker, recursion + 1, NodeType.LAMBDA_EXPRESSION, NodeType.CONDITIONAL_EXPRESSION, NodeType.LOGICAL_OR_EXPRESSION); return new Branch(NodeType.CONDITIONAL_EXPRESSION, cond, q, opt1, c, opt2); } case NodeType.ASSIGNMENT_EXPRESSION: { Node lhs = parseInner(walker, recursion + 1, NodeType.SIMPLE_EXPRESSION); if (lhs != null && !walker.isAtEnd() && (lhs.getNodeType() == NodeType.REFERENCE_EXPRESSION || lhs.getNodeType() == NodeType.SUBREFERENCE_EXPRESSION || lhs.getNodeType() == NodeType.ARRAY_INDEX_EXPRESSION)) { Node op = parseInner(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR); if (op == null) { //op = parseInner(walker, recursion + 1, NodeType.COUNT_OPERATOR); //if (op == null) { return null; //} else { //return new Branch(NodeType.COUNT_EXPRESSION, lhs, op); //} } else { return new Branch(NodeType.ASSIGNMENT_EXPRESSION, lhs, op, expectAny(walker, recursion + 1, NodeType.EXPRESSION)); } } else { return null; } } case NodeType.COUNT_EXPRESSION: { Node lhs = parseInner(walker, recursion + 1, NodeType.SIMPLE_EXPRESSION); if (lhs != null && !walker.isAtEnd()/* && (lhs.getNodeType() == NodeType.REFERENCE_EXPRESSION || lhs.getNodeType() == NodeType.SUBREFERENCE_EXPRESSION || lhs.getNodeType() == NodeType.ARRAY_INDEX_EXPRESSION)*/) { Node op = parseInner(walker, recursion + 1, NodeType.COUNT_OPERATOR); if (op == null) { return lhs; } else { return new Branch(NodeType.COUNT_EXPRESSION, lhs, op); } } else { return lhs; } } case NodeType.ASSIGNMENT_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "+="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "-="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "*="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "/="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "%="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "&="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "|="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "^="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, "<<="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, ">>>="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ASSIGNMENT_OPERATOR, TokenType.OPERATOR, ">>="); return result; } case NodeType.COUNT_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COUNT_OPERATOR, TokenType.OPERATOR, "--"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COUNT_OPERATOR, TokenType.OPERATOR, "++"); return result; } case NodeType.UNARY_OPERATOR: { Node result = parseInner(walker, recursion + 1, NodeType.COUNT_OPERATOR); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.UNARY_OPERATOR, TokenType.OPERATOR, "-"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.UNARY_OPERATOR, TokenType.OPERATOR, "+"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.UNARY_OPERATOR, TokenType.OPERATOR, "!"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.UNARY_OPERATOR, TokenType.OPERATOR, "~"); return result; } case NodeType.MULTIPLICATIVE_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.MULTIPLICATIVE_OPERATOR, TokenType.OPERATOR, "*"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.MULTIPLICATIVE_OPERATOR, TokenType.OPERATOR, "/"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.MULTIPLICATIVE_OPERATOR, TokenType.OPERATOR, "%"); //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.MULTIPLICATIVE_OPERATOR, TokenType.OPERATOR, "&"); //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.MULTIPLICATIVE_OPERATOR, TokenType.OPERATOR, "|"); //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.MULTIPLICATIVE_OPERATOR, TokenType.OPERATOR, "^"); return result; } case NodeType.ADDITIVE_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ADDITIVE_OPERATOR, TokenType.OPERATOR, "+"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ADDITIVE_OPERATOR, TokenType.OPERATOR, "-"); //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ADDITIVE_OPERATOR, TokenType.OPERATOR, "&"); //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.ADDITIVE_OPERATOR, TokenType.OPERATOR, "|"); return result; } case NodeType.SHIFT_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.SHIFT_OPERATOR, TokenType.OPERATOR, "<<"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.SHIFT_OPERATOR, TokenType.OPERATOR, ">>"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.SHIFT_OPERATOR, TokenType.OPERATOR, ">>>"); // Special handling of combined ">" characters is required for generics result = result != null ? result : parseSpecialTokenBranch(walker, recursion + 1, NodeType.SHIFT_OPERATOR, TokenType.OPERATOR, ">", 3); result = result != null ? result : parseSpecialTokenBranch(walker, recursion + 1, NodeType.SHIFT_OPERATOR, TokenType.OPERATOR, ">", 2); return result; } case NodeType.COMPARISON_OPERATOR: { Node result = null; // Specifically fail if we can parse (especially muliple ">" characters) as a shift operator instead Node shiftop = parseAny(walker, recursion + 1, NodeType.SHIFT_OPERATOR); if (shiftop != null) { return null; } //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COMPARISON_OPERATOR, TokenType.OPERATOR, "=="); //result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COMPARISON_OPERATOR, TokenType.OPERATOR, "!="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COMPARISON_OPERATOR, TokenType.OPERATOR, "<"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COMPARISON_OPERATOR, TokenType.OPERATOR, "<="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COMPARISON_OPERATOR, TokenType.OPERATOR, ">"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.COMPARISON_OPERATOR, TokenType.OPERATOR, ">="); return result; } case NodeType.EQUALITY_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.EQUALITY_OPERATOR, TokenType.OPERATOR, "=="); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.EQUALITY_OPERATOR, TokenType.OPERATOR, "!="); return result; } case NodeType.BITWISE_AND_OPERATOR: return parseTokenBranch(walker, recursion + 1, NodeType.BITWISE_AND_OPERATOR, "&"); case NodeType.BITWISE_XOR_OPERATOR: return parseTokenBranch(walker, recursion + 1, NodeType.BITWISE_XOR_OPERATOR, "^"); case NodeType.BITWISE_OR_OPERATOR: return parseTokenBranch(walker, recursion + 1, NodeType.BITWISE_AND_OPERATOR, "|"); case NodeType.LOGICAL_AND_OPERATOR: return parseTokenBranch(walker, recursion + 1, NodeType.LOGICAL_AND_OPERATOR, "&&"); case NodeType.LOGICAL_OR_OPERATOR: return parseTokenBranch(walker, recursion + 1, NodeType.LOGICAL_OR_OPERATOR, "||"); case NodeType.LOGICAL_OPERATOR: { Node result = null; result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.LOGICAL_OPERATOR, TokenType.OPERATOR, "&&"); result = result != null ? result : parseTokenBranch(walker, recursion + 1, NodeType.LOGICAL_OPERATOR, TokenType.OPERATOR, "||"); return result; } case NodeType.EXPRESSION: return parseAny(walker, recursion + 1, NodeType.LAMBDA_EXPRESSION, NodeType.ASSIGNMENT_EXPRESSION, NodeType.CONDITIONAL_EXPRESSION, NodeType.LOGICAL_OR_EXPRESSION); case NodeType.EXPRESSIONS: return parseList(walker, recursion + 1, NodeType.EXPRESSIONS, NodeType.COMMA, false, NodeType.EXPRESSION); case NodeType.ARRAY_EXPRESSIONS: return parseList(walker, recursion + 1, NodeType.ARRAY_EXPRESSIONS, NodeType.COMMA, true, NodeType.ARRAY_INITIALISER, NodeType.EXPRESSION); case NodeType.MODIFIER_EXPRESSIONS: return parseList(walker, recursion + 1, NodeType.MODIFIER_EXPRESSIONS, NodeType.COMMA, true, NodeType.ARRAY_INITIALISER, NodeType.SIMPLE_ASSIGN, NodeType.EXPRESSION); case NodeType.SIMPLE_ASSIGN: { Node nam = parseAny(walker, recursion + 1, NodeType.NAME); if (nam == null) { return null; } Node eq = parseToken(walker, recursion + 1, TokenType.OPERATOR, "="); if (eq == null) { return null; } return new Branch(NodeType.SIMPLE_ASSIGN, nam, eq, expectAny(walker, recursion + 1, NodeType.ARRAY_INITIALISER, NodeType.EXPRESSION)); } case NodeType.SIMPLE_GENERIC_WILDCARD: return parseTokenBranch(walker, recursion + 1, NodeType.SIMPLE_GENERIC_WILDCARD, TokenType.OPERATOR, "?"); case NodeType.EXTENDED_GENERIC_WILDCARD: { Node start = parseTokenBranch(walker, recursion + 1, NodeType.QUESTIONMARK, TokenType.OPERATOR, "?"); if (start == null) { return null; } Node ext = parseToken(walker, recursion + 1, Language.Key.EXTENDS); //TokenType.KEYWORD, "extends"); if (ext == null) { return null; } Node typ = expectAny(walker, recursion + 1, NodeType.ANDABLE_TYPE); return new Branch(NodeType.EXTENDED_GENERIC_WILDCARD, start, ext, typ); } case NodeType.ANDABLE_TYPE: { ScanWalker pos = walker.clone(); Node firstType = parseAny(walker, recursion + 1, NodeType.TYPE); if (firstType == null) { return null; } walker.reset(pos); ScanWalker.recycle(pos); return parseList(walker, recursion + 1, NodeType.ANDABLE_TYPE, NodeType.SINGLE_AND, false, NodeType.TYPE); } case NodeType.SINGLE_AND: { return parseTokenBranch(walker, recursion + 1, NodeType.SINGLE_AND, TokenType.OPERATOR, "&"); } case NodeType.SUPER_GENERIC_WILDCARD: { Node start = parseTokenBranch(walker, recursion + 1, NodeType.QUESTIONMARK, TokenType.OPERATOR, "?"); if (start == null) { return null; } Node sup = parseToken(walker, recursion + 1, Language.Key.SUPER); //TokenType.KEYWORD, "super"); if (sup == null) { return null; } Node typ = expectAny(walker, recursion + 1, NodeType.TYPE); return new Branch(NodeType.SUPER_GENERIC_WILDCARD, start, sup, typ); } case NodeType.GENERIC_VALUE: //return new Branch(NodeType.GENERIC_VALUE, return parseAny(walker, recursion + 1, NodeType.TYPE, NodeType.EXTENDED_GENERIC_WILDCARD, NodeType.SUPER_GENERIC_WILDCARD, NodeType.SIMPLE_GENERIC_WILDCARD);//); case NodeType.GENERIC_EXPRESSIONS: return parseList(walker, recursion + 1, NodeType.GENERIC_EXPRESSIONS, NodeType.COMMA, false, NodeType.GENERIC_VALUE); case NodeType.BRACED_EXPRESSION: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); if (start == null) { return null; } else { return new Branch(NodeType.BRACED_EXPRESSION, start, expectAny(walker, recursion + 1, NodeType.EXPRESSION), expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE)); } } case NodeType.ARGUMENTS: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_ROUND_BRACE); if (start == null) { return null; } else { return new Branch(NodeType.ARGUMENTS, start, parseInner(walker, recursion + 1, NodeType.EXPRESSIONS), expectAny(walker, recursion + 1, NodeType.CLOSE_ROUND_BRACE)); } } case NodeType.ARRAY_INITIALISER: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_CURLY_BRACE); if (start == null) { return null; } else { return new Branch(NodeType.ARRAY_INITIALISER, start, parseInner(walker, recursion + 1, NodeType.ARRAY_EXPRESSIONS), expectAny(walker, recursion + 1, NodeType.CLOSE_CURLY_BRACE)); } } case NodeType.GENERIC_ARGUMENTS: { Node start = parseInner(walker, recursion + 1, NodeType.OPEN_ANGLE_BRACE); if (start == null) { return null; } else { Node middle = parseAny(walker, recursion + 1, NodeType.GENERIC_EXPRESSIONS); if (middle == null) { return null; } Node end = parseAny(walker, recursion + 1, NodeType.CLOSE_ANGLE_BRACE); if (end == null) { return null; } return new Branch(NodeType.GENERIC_ARGUMENTS, start, middle, end); } } case NodeType.SLOTS: return parseList(walker, recursion + 1, NodeType.SLOTS, NodeType.COMMA, false, NodeType.INITIALISED_SLOT); case NodeType.INITIALISED_SLOT: { Node n = parseInner(walker, recursion + 1, NodeType.INDEXED_NAME); if (n == null) { return null; } else { Token eq = parseToken(walker, recursion + 1, TokenType.OPERATOR, "="); if (eq == null) { return new Branch(NodeType.UNINITIALISED_SLOT, n); } else { return new Branch(NodeType.INITIALISED_SLOT, n, eq, expectAny(walker, recursion + 1, NodeType.EXPRESSION, NodeType.ARRAY_INITIALISER)); } } } case NodeType.SIMPLE_ARGUMENT_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.INDEXED_NAME); if (n == null) { return null; } else { return new Branch(NodeType.SIMPLE_ARGUMENT_DECLARATION, mods, t, n); } } } case NodeType.LAZY_ARGUMENT_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.LAZY_TYPE); if (t == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.INDEXED_NAME); if (n == null) { return null; } else { return new Branch(NodeType.SIMPLE_ARGUMENT_DECLARATION, mods, t, n); } } } case NodeType.LAZY_TYPE: { Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } Node bar = null; Branch result = null; while ((bar = parseToken(walker, recursion + 1, TokenType.OPERATOR, "|")) != null) { Node nextt = parseInner(walker, recursion + 1, NodeType.TYPE); if (nextt == null) { return null; } if (result == null) { result = new Branch(NodeType.LAZY_TYPE); result.append(t); } result.append(bar); result.append(nextt); } return result; // Will be null unless one or more "|" followed by another type was found } case NodeType.VARIABLE_ARGUMENT_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } else { Node dots = parseToken(walker, recursion + 1, TokenType.OPERATOR, "..."); if (dots == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.INDEXED_NAME); if (n == null) { return null; } else { return new Branch(NodeType.VARIABLE_ARGUMENT_DECLARATION, mods, t, dots, n); } } } } case NodeType.SIMPLE_GENERIC_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { return new Branch(NodeType.SIMPLE_GENERIC_DECLARATION, mods, n); } } case NodeType.SIMPLE_EXTENDED_GENERIC_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } Node ext = parseToken(walker, recursion + 1, Language.Key.EXTENDS); //TokenType.KEYWORD, "extends"); if (ext == null) { return null; } Node typ = expectAny(walker, recursion + 1, NodeType.ANDABLE_TYPE); return new Branch(NodeType.SIMPLE_EXTENDED_GENERIC_DECLARATION, mods, n, ext, typ); } case NodeType.SIMPLE_TYPED_GENERIC_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { return new Branch(NodeType.SIMPLE_TYPED_GENERIC_DECLARATION, mods, t, n); } } } case NodeType.VARIABLE_GENERIC_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node dots = parseToken(walker, recursion + 1, TokenType.OPERATOR, "..."); if (dots == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { return new Branch(NodeType.VARIABLE_GENERIC_DECLARATION, mods, dots, n); } } } case NodeType.VARIABLE_TYPED_GENERIC_DECLARATION: { Node mods = parseInner(walker, recursion + 1, NodeType.MODIFIER_LIST); Node t = parseInner(walker, recursion + 1, NodeType.TYPE); if (t == null) { return null; } else { Node dots = parseToken(walker, recursion + 1, TokenType.OPERATOR, "..."); if (dots == null) { return null; } else { Node n = parseInner(walker, recursion + 1, NodeType.NAME); if (n == null) { return null; } else { return new Branch(NodeType.VARIABLE_TYPED_GENERIC_DECLARATION, mods, t, dots, n); } } } } case NodeType.UNIT: return new Branch(NodeType.UNIT, parseInner(walker, recursion + 1, NodeType.PACKAGE_DECLARATION), parseList(walker, recursion + 1, NodeType.IMPORT_DECLARATIONS, null, false, NodeType.IMPORT_DECLARATION), parseInner(walker, recursion + 1, NodeType.TYPE_DECLARATIONS), expectAny(walker, recursion + 1, NodeType.EOF)); default: //System.out.println("TODO: Parsing of " + type); //return new Branch(NodeType.ERROR_ONLY).annotate(ErrorType.INTERNAL_ERROR, "TODO: Parsing of " + type); return null; } } public Node parseSafely(ScanWalker walker, int recursion, NodeType type) { checkRecursion(walker, recursion); ScanWalker w = walker.clone(); Node r = parseInner(walker, recursion + 1, type); if (r != null) { walker.reset(w); } ScanWalker.recycle(w); return r; } public Node parseUnit(Scan scan) { ScanWalker w = new ScanWalker(scan); return parseSafely(w, 0, NodeType.UNIT); } public void checkRecursion(ScanWalker walker, int recursion) { if (recursion >= maxRecursion) { throw new Error("Recursion got too deep around " + walker.peek()); } } }