2400 lines
89 KiB
Plaintext
2400 lines
89 KiB
Plaintext
|
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<String,List<String>>). */
|
||
|
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());
|
||
|
}
|
||
|
}
|
||
|
}
|