java-parser
Version:
Java Parser in JavaScript
565 lines (511 loc) • 16.6 kB
JavaScript
;
const { tokenMatcher } = require("chevrotain");
// Spec Deviation: The "*NoShortIf" variations were removed as the ambiguity of
// the dangling else is resolved by attaching an "else" block
// to the nearest "if"
function defineRules($, t) {
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-Block
$.RULE("block", () => {
$.CONSUME(t.LCurly);
$.OPTION(() => {
$.SUBRULE($.blockStatements);
});
$.CONSUME(t.RCurly);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-BlockStatements
$.RULE("blockStatements", () => {
$.SUBRULE($.blockStatement);
$.MANY(() => {
$.SUBRULE2($.blockStatement);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-BlockStatement
$.RULE("blockStatement", () => {
const isLocalVariableDeclaration = this.BACKTRACK_LOOKAHEAD(
$.isLocalVariableDeclaration
);
const isClassDeclaration = this.BACKTRACK_LOOKAHEAD($.isClassDeclaration);
$.OR([
{
GATE: () => isLocalVariableDeclaration,
ALT: () => $.SUBRULE($.localVariableDeclarationStatement)
},
{
GATE: () => isClassDeclaration,
ALT: () => $.SUBRULE($.classDeclaration)
},
{ ALT: () => $.SUBRULE($.statement) }
]);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-LocalVariableDeclaration
$.RULE("localVariableDeclarationStatement", () => {
$.SUBRULE($.localVariableDeclaration);
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-LocalVariableDeclaration
$.RULE("localVariableDeclaration", () => {
$.MANY(() => {
$.SUBRULE($.variableModifier);
});
$.SUBRULE($.localVariableType);
$.SUBRULE($.variableDeclaratorList);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-LocalVariableType
$.RULE("localVariableType", () => {
$.OR({
DEF: [
{ ALT: () => $.SUBRULE($.unannType) },
{ ALT: () => $.CONSUME(t.Var) }
],
IGNORE_AMBIGUITIES: true
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-Statement
$.RULE("statement", () => {
$.OR({
DEF: [
{
ALT: () => $.SUBRULE($.statementWithoutTrailingSubstatement)
},
{ ALT: () => $.SUBRULE($.labeledStatement) },
// Spec deviation: combined "IfThenStatement" and "IfThenElseStatement"
{ ALT: () => $.SUBRULE($.ifStatement) },
{ ALT: () => $.SUBRULE($.whileStatement) },
{ ALT: () => $.SUBRULE($.forStatement) }
],
MAX_LOOKAHEAD: 2
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-StatementWithoutTrailingSubstatement
$.RULE("statementWithoutTrailingSubstatement", () => {
$.OR({
DEF: [
{ ALT: () => $.SUBRULE($.block) },
{ ALT: () => $.SUBRULE($.yieldStatement) },
{ ALT: () => $.SUBRULE($.emptyStatement) },
{
GATE: () => !tokenMatcher(this.LA(1).tokenType, t.Switch),
ALT: () => $.SUBRULE($.expressionStatement)
},
{ ALT: () => $.SUBRULE($.assertStatement) },
{ ALT: () => $.SUBRULE($.switchStatement) },
{ ALT: () => $.SUBRULE($.doStatement) },
{ ALT: () => $.SUBRULE($.breakStatement) },
{ ALT: () => $.SUBRULE($.continueStatement) },
{ ALT: () => $.SUBRULE($.returnStatement) },
{ ALT: () => $.SUBRULE($.synchronizedStatement) },
{ ALT: () => $.SUBRULE($.throwStatement) },
{ ALT: () => $.SUBRULE($.tryStatement) }
],
IGNORE_AMBIGUITIES: true
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-EmptyStatement
$.RULE("emptyStatement", () => {
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-LabeledStatement
$.RULE("labeledStatement", () => {
$.CONSUME(t.Identifier);
$.CONSUME(t.Colon);
$.SUBRULE($.statement);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ExpressionStatement
$.RULE("expressionStatement", () => {
$.SUBRULE($.statementExpression);
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-StatementExpression
$.RULE("statementExpression", () => {
// Spec deviation: The many alternatives here were replaced with
// the "expression" rule as it contains them all,
// and distinguishing between the alternatives cannot be done
// using a fixed lookahead.
// TODO: verify the resulting expression is one of the valid alternatives?
$.SUBRULE($.expression);
});
// Spec deviation: combined "IfThenStatement" and "IfThenElseStatement"
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-IfThenStatement
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-IfThenElseStatement
$.RULE("ifStatement", () => {
$.CONSUME(t.If);
$.CONSUME(t.LBrace);
$.SUBRULE($.expression);
$.CONSUME(t.RBrace);
$.SUBRULE($.statement);
$.OPTION(() => {
$.CONSUME(t.Else);
$.SUBRULE2($.statement);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-AssertStatement
$.RULE("assertStatement", () => {
$.CONSUME(t.Assert);
$.SUBRULE($.expression);
$.OPTION(() => {
$.CONSUME(t.Colon);
$.SUBRULE2($.expression);
});
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-SwitchStatement
$.RULE("switchStatement", () => {
$.CONSUME(t.Switch);
$.CONSUME(t.LBrace);
$.SUBRULE($.expression);
$.CONSUME(t.RBrace);
$.SUBRULE($.switchBlock);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-SwitchBlock
$.RULE("switchBlock", () => {
$.CONSUME(t.LCurly);
$.OR([
{
GATE: () => this.BACKTRACK_LOOKAHEAD($.isClassicSwitchLabel),
ALT: () => $.MANY(() => $.SUBRULE($.switchBlockStatementGroup))
},
{
ALT: () => $.MANY2(() => $.SUBRULE($.switchRule))
}
]);
$.CONSUME(t.RCurly);
});
$.RULE("switchBlockStatementGroup", () => {
$.AT_LEAST_ONE(() => {
$.SUBRULE($.switchLabel);
$.CONSUME(t.Colon);
});
$.OPTION(() => {
$.SUBRULE($.blockStatements);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-SwitchLabel
$.RULE("switchLabel", () => {
$.OR([
{
ALT: () => {
$.CONSUME(t.Case);
$.SUBRULE($.caseConstant);
$.MANY(() => {
$.CONSUME(t.Comma);
$.SUBRULE2($.caseConstant);
});
}
},
// SPEC Deviation: the variant with "enumConstantName" was removed
// as it can be matched by the "constantExpression" variant
// the distinction is semantic not syntactic.
{
ALT: () => $.CONSUME(t.Default)
}
]);
});
// https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-SwitchRule
$.RULE("switchRule", () => {
$.SUBRULE($.switchLabel);
$.CONSUME(t.Arrow);
$.OR([
{ ALT: () => $.SUBRULE($.throwStatement) },
{ ALT: () => $.SUBRULE($.block) },
{
ALT: () => {
$.SUBRULE($.expression);
$.CONSUME(t.Semicolon);
}
}
]);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-EnumConstantName
$.RULE("caseConstant", () => {
$.SUBRULE($.ternaryExpression);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-WhileStatement
$.RULE("whileStatement", () => {
$.CONSUME(t.While);
$.CONSUME(t.LBrace);
$.SUBRULE($.expression);
$.CONSUME(t.RBrace);
$.SUBRULE($.statement);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-DoStatement
$.RULE("doStatement", () => {
$.CONSUME(t.Do);
$.SUBRULE($.statement);
$.CONSUME(t.While);
$.CONSUME(t.LBrace);
$.SUBRULE($.expression);
$.CONSUME(t.RBrace);
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ForStatement
$.RULE("forStatement", () => {
$.OR([
{
GATE: () => this.BACKTRACK_LOOKAHEAD($.isBasicForStatement),
ALT: () => $.SUBRULE($.basicForStatement)
},
{ ALT: () => $.SUBRULE($.enhancedForStatement) }
]);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-BasicForStatement
$.RULE("basicForStatement", () => {
$.CONSUME(t.For);
$.CONSUME(t.LBrace);
$.OPTION(() => {
$.SUBRULE($.forInit);
});
$.CONSUME(t.Semicolon);
$.OPTION2(() => {
$.SUBRULE($.expression);
});
$.CONSUME2(t.Semicolon);
$.OPTION3(() => {
$.SUBRULE($.forUpdate);
});
$.CONSUME(t.RBrace);
$.SUBRULE($.statement);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ForInit
$.RULE("forInit", () => {
$.OR([
{
GATE: () => $.BACKTRACK_LOOKAHEAD($.isLocalVariableDeclaration),
ALT: () => $.SUBRULE($.localVariableDeclaration)
},
{ ALT: () => $.SUBRULE($.statementExpressionList) }
]);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ForUpdate
$.RULE("forUpdate", () => {
$.SUBRULE($.statementExpressionList);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-StatementExpressionList
$.RULE("statementExpressionList", () => {
$.SUBRULE($.statementExpression);
$.MANY(() => {
$.CONSUME(t.Comma);
$.SUBRULE2($.statementExpression);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-EnhancedForStatement
$.RULE("enhancedForStatement", () => {
$.CONSUME(t.For);
$.CONSUME(t.LBrace);
$.MANY(() => {
$.SUBRULE($.variableModifier);
});
$.SUBRULE($.localVariableType);
$.SUBRULE($.variableDeclaratorId);
$.CONSUME(t.Colon);
$.SUBRULE($.expression);
$.CONSUME(t.RBrace);
$.SUBRULE($.statement);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-BreakStatement
$.RULE("breakStatement", () => {
$.CONSUME(t.Break);
$.OPTION(() => {
$.CONSUME(t.Identifier);
});
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ContinueStatement
$.RULE("continueStatement", () => {
$.CONSUME(t.Continue);
$.OPTION(() => {
$.CONSUME(t.Identifier);
});
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ReturnStatement
$.RULE("returnStatement", () => {
$.CONSUME(t.Return);
$.OPTION(() => {
$.SUBRULE($.expression);
});
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ThrowStatement
$.RULE("throwStatement", () => {
$.CONSUME(t.Throw);
$.SUBRULE($.expression);
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-SynchronizedStatement
$.RULE("synchronizedStatement", () => {
$.CONSUME(t.Synchronized);
$.CONSUME(t.LBrace);
$.SUBRULE($.expression);
$.CONSUME(t.RBrace);
$.SUBRULE($.block);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-TryStatement
$.RULE("tryStatement", () => {
$.OR({
DEF: [
{
ALT: () => {
$.CONSUME(t.Try);
$.SUBRULE($.block);
$.OR2([
{
ALT: () => {
$.SUBRULE($.catches);
$.OPTION(() => {
$.SUBRULE($.finally);
});
}
},
{ ALT: () => $.SUBRULE2($.finally) }
]);
}
},
{ ALT: () => $.SUBRULE($.tryWithResourcesStatement) }
],
MAX_LOOKAHEAD: 2
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-Catches
$.RULE("catches", () => {
$.SUBRULE($.catchClause);
$.MANY(() => {
$.SUBRULE2($.catchClause);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-CatchClause
$.RULE("catchClause", () => {
$.CONSUME(t.Catch);
$.CONSUME(t.LBrace);
$.SUBRULE($.catchFormalParameter);
$.CONSUME(t.RBrace);
$.SUBRULE($.block);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-CatchFormalParameter
$.RULE("catchFormalParameter", () => {
$.MANY(() => {
$.SUBRULE($.variableModifier);
});
$.SUBRULE($.catchType);
$.SUBRULE($.variableDeclaratorId);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-CatchType
$.RULE("catchType", () => {
$.SUBRULE($.unannClassType);
$.MANY(() => {
$.CONSUME(t.Or);
$.SUBRULE2($.classType);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-Finally
$.RULE("finally", () => {
$.CONSUME(t.Finally);
$.SUBRULE($.block);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-TryWithResourcesStatement
$.RULE("tryWithResourcesStatement", () => {
$.CONSUME(t.Try);
$.SUBRULE($.resourceSpecification);
$.SUBRULE($.block);
$.OPTION(() => {
$.SUBRULE($.catches);
});
$.OPTION2(() => {
$.SUBRULE($.finally);
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ResourceSpecification
$.RULE("resourceSpecification", () => {
$.CONSUME(t.LBrace);
$.SUBRULE($.resourceList);
$.OPTION(() => {
$.CONSUME(t.Semicolon);
});
$.CONSUME(t.RBrace);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-ResourceList
$.RULE("resourceList", () => {
$.SUBRULE($.resource);
$.MANY({
GATE: () => tokenMatcher($.LA(2).tokenType, t.RBrace) === false,
DEF: () => {
$.CONSUME(t.Semicolon);
$.SUBRULE2($.resource);
}
});
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-Resource
$.RULE("resource", () => {
$.OR([
{
GATE: $.BACKTRACK($.resourceInit),
// Spec Deviation: extracted this alternative to "resourceInit"
// to enable backtracking.
ALT: () => $.SUBRULE($.resourceInit)
},
{ ALT: () => $.SUBRULE($.variableAccess) }
]);
});
// Spec Deviation: extracted from "resource"
$.RULE("resourceInit", () => {
$.MANY(() => {
$.SUBRULE($.variableModifier);
});
$.SUBRULE($.localVariableType);
$.CONSUME(t.Identifier);
$.CONSUME(t.Equals);
$.SUBRULE($.expression);
});
// https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-YieldStatement
$.RULE("yieldStatement", () => {
$.CONSUME(t.Yield);
$.SUBRULE($.expression);
$.CONSUME(t.Semicolon);
});
// https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-VariableAccess
$.RULE("variableAccess", () => {
// Spec Deviation: both "expressionName" and "fieldAccess" can be parsed
// by the "primary" rule
// TODO: verify that the primary is a fieldAccess or an expressionName.
$.SUBRULE($.primary);
});
// ------------------------------------
// Special optimized backtracking rules.
// ------------------------------------
$.RULE("isBasicForStatement", () => {
$.CONSUME(t.For);
$.CONSUME(t.LBrace);
$.OPTION(() => {
$.SUBRULE($.forInit);
});
$.CONSUME(t.Semicolon);
// consuming the first semiColon distinguishes between
// "basic" and "enhanced" for statements
return true;
});
$.RULE("isLocalVariableDeclaration", () => {
$.MANY(() => {
$.SUBRULE($.variableModifier);
});
$.SUBRULE($.localVariableType);
$.SUBRULE($.variableDeclaratorId);
const nextTokenType = this.LA(1).tokenType;
switch (nextTokenType) {
// Int x;
case t.Semicolon:
// Int x, y, z;
case t.Comma:
// Int x = 5;
case t.Equals:
return true;
default:
return false;
}
});
$.RULE("isClassicSwitchLabel", () => {
$.SUBRULE($.switchLabel);
$.CONSUME(t.Colon);
});
}
module.exports = {
defineRules
};