Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.sonar.javascript.parser.EcmaScriptGrammarImpl Maven / Gradle / Ivy
/*
* Sonar JavaScript Plugin
* Copyright (C) 2011 Eriks Nukis and SonarSource
* [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.javascript.parser;
import com.sonar.sslr.impl.matcher.GrammarFunctions;
import org.sonar.javascript.api.EcmaScriptGrammar;
import static com.sonar.sslr.api.GenericTokenType.EOF;
import static com.sonar.sslr.api.GenericTokenType.IDENTIFIER;
import static com.sonar.sslr.api.GenericTokenType.LITERAL;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Predicate.next;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Predicate.not;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.and;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.o2n;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.one2n;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.opt;
import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.or;
import static org.sonar.javascript.api.EcmaScriptKeyword.BREAK;
import static org.sonar.javascript.api.EcmaScriptKeyword.CASE;
import static org.sonar.javascript.api.EcmaScriptKeyword.CATCH;
import static org.sonar.javascript.api.EcmaScriptKeyword.CONTINUE;
import static org.sonar.javascript.api.EcmaScriptKeyword.DEBUGGER;
import static org.sonar.javascript.api.EcmaScriptKeyword.DEFAULT;
import static org.sonar.javascript.api.EcmaScriptKeyword.DELETE;
import static org.sonar.javascript.api.EcmaScriptKeyword.DO;
import static org.sonar.javascript.api.EcmaScriptKeyword.ELSE;
import static org.sonar.javascript.api.EcmaScriptKeyword.FALSE;
import static org.sonar.javascript.api.EcmaScriptKeyword.FINALLY;
import static org.sonar.javascript.api.EcmaScriptKeyword.FOR;
import static org.sonar.javascript.api.EcmaScriptKeyword.FUNCTION;
import static org.sonar.javascript.api.EcmaScriptKeyword.IF;
import static org.sonar.javascript.api.EcmaScriptKeyword.IN;
import static org.sonar.javascript.api.EcmaScriptKeyword.INSTANCEOF;
import static org.sonar.javascript.api.EcmaScriptKeyword.NEW;
import static org.sonar.javascript.api.EcmaScriptKeyword.NULL;
import static org.sonar.javascript.api.EcmaScriptKeyword.RETURN;
import static org.sonar.javascript.api.EcmaScriptKeyword.SWITCH;
import static org.sonar.javascript.api.EcmaScriptKeyword.THIS;
import static org.sonar.javascript.api.EcmaScriptKeyword.THROW;
import static org.sonar.javascript.api.EcmaScriptKeyword.TRUE;
import static org.sonar.javascript.api.EcmaScriptKeyword.TRY;
import static org.sonar.javascript.api.EcmaScriptKeyword.TYPEOF;
import static org.sonar.javascript.api.EcmaScriptKeyword.VAR;
import static org.sonar.javascript.api.EcmaScriptKeyword.VOID;
import static org.sonar.javascript.api.EcmaScriptKeyword.WHILE;
import static org.sonar.javascript.api.EcmaScriptKeyword.WITH;
import static org.sonar.javascript.api.EcmaScriptPunctuator.AND;
import static org.sonar.javascript.api.EcmaScriptPunctuator.ANDAND;
import static org.sonar.javascript.api.EcmaScriptPunctuator.AND_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.BANG;
import static org.sonar.javascript.api.EcmaScriptPunctuator.COLON;
import static org.sonar.javascript.api.EcmaScriptPunctuator.COMMA;
import static org.sonar.javascript.api.EcmaScriptPunctuator.DEC;
import static org.sonar.javascript.api.EcmaScriptPunctuator.DIV;
import static org.sonar.javascript.api.EcmaScriptPunctuator.DIV_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.DOT;
import static org.sonar.javascript.api.EcmaScriptPunctuator.EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.EQUAL;
import static org.sonar.javascript.api.EcmaScriptPunctuator.EQUAL2;
import static org.sonar.javascript.api.EcmaScriptPunctuator.GE;
import static org.sonar.javascript.api.EcmaScriptPunctuator.GT;
import static org.sonar.javascript.api.EcmaScriptPunctuator.INC;
import static org.sonar.javascript.api.EcmaScriptPunctuator.LBRACKET;
import static org.sonar.javascript.api.EcmaScriptPunctuator.LCURLYBRACE;
import static org.sonar.javascript.api.EcmaScriptPunctuator.LE;
import static org.sonar.javascript.api.EcmaScriptPunctuator.LPARENTHESIS;
import static org.sonar.javascript.api.EcmaScriptPunctuator.LT;
import static org.sonar.javascript.api.EcmaScriptPunctuator.MINUS;
import static org.sonar.javascript.api.EcmaScriptPunctuator.MINUS_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.MOD;
import static org.sonar.javascript.api.EcmaScriptPunctuator.MOD_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.NOTEQUAL;
import static org.sonar.javascript.api.EcmaScriptPunctuator.NOTEQUAL2;
import static org.sonar.javascript.api.EcmaScriptPunctuator.OR;
import static org.sonar.javascript.api.EcmaScriptPunctuator.OROR;
import static org.sonar.javascript.api.EcmaScriptPunctuator.OR_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.PLUS;
import static org.sonar.javascript.api.EcmaScriptPunctuator.PLUS_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.QUERY;
import static org.sonar.javascript.api.EcmaScriptPunctuator.RBRACKET;
import static org.sonar.javascript.api.EcmaScriptPunctuator.RCURLYBRACE;
import static org.sonar.javascript.api.EcmaScriptPunctuator.RPARENTHESIS;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SEMI;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SL;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SL_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SR;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SR2;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SR_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.SR_EQU2;
import static org.sonar.javascript.api.EcmaScriptPunctuator.STAR;
import static org.sonar.javascript.api.EcmaScriptPunctuator.STAR_EQU;
import static org.sonar.javascript.api.EcmaScriptPunctuator.TILDA;
import static org.sonar.javascript.api.EcmaScriptPunctuator.XOR;
import static org.sonar.javascript.api.EcmaScriptPunctuator.XOR_EQU;
import static org.sonar.javascript.api.EcmaScriptTokenType.NUMERIC_LITERAL;
import static org.sonar.javascript.api.EcmaScriptTokenType.REGULAR_EXPRESSION_LITERAL;
/**
* Grammar for ECMAScript.
* Based on ECMA-262
* edition 5.1 (June 2011).
*/
public class EcmaScriptGrammarImpl extends EcmaScriptGrammar {
public EcmaScriptGrammarImpl() {
eos.is(or(
opt(SEMI),
next(RCURLYBRACE),
next(EOF)));
eosNoLb.is(or(
opt(SEMI),
next(RCURLYBRACE),
next(EOF)));
identifierName.is(IDENTIFIER);
literal.is(or(
nullLiteral,
booleanLiteral,
NUMERIC_LITERAL,
stringLiteral,
regularExpressionLiteral));
nullLiteral.is(NULL);
booleanLiteral.is(or(
TRUE,
FALSE));
stringLiteral.is(LITERAL);
regularExpressionLiteral.is(REGULAR_EXPRESSION_LITERAL);
expressions();
statements();
functionsAndPrograms();
GrammarFunctions.enableMemoizationOfMatchesForAllRules(this);
}
/**
* A.3 Expressions
*/
private void expressions() {
primaryExpression.is(or(
THIS,
IDENTIFIER,
literal,
arrayLiteral,
objectLiteral,
and(LPARENTHESIS, expression, RPARENTHESIS)));
arrayLiteral.is(LBRACKET, o2n(or(COMMA, assignmentExpression)), RBRACKET);
objectLiteral.is(LCURLYBRACE, opt(propertyAssignment, o2n(COMMA, propertyAssignment), opt(COMMA)), RCURLYBRACE);
propertyAssignment.is(or(
and(propertyName, COLON, assignmentExpression),
and("get", propertyName, LPARENTHESIS, RPARENTHESIS, LCURLYBRACE, functionBody, RCURLYBRACE),
and("set", propertyName, LPARENTHESIS, propertySetParameterList, RPARENTHESIS, LCURLYBRACE, functionBody, RCURLYBRACE)));
propertyName.is(or(
identifierName,
stringLiteral,
NUMERIC_LITERAL));
propertySetParameterList.is(IDENTIFIER);
memberExpression.is(
or(
primaryExpression,
functionExpression,
and(NEW, memberExpression, arguments)),
o2n(or(
and(LBRACKET, expression, RBRACKET),
and(DOT, identifierName))));
newExpression.is(or(
memberExpression,
and(NEW, newExpression)));
callExpression.is(
and(memberExpression, arguments),
o2n(or(
arguments,
and(LBRACKET, expression, RBRACKET),
and(DOT, identifierName))));
arguments.is(LPARENTHESIS, opt(assignmentExpression, o2n(COMMA, assignmentExpression)), RPARENTHESIS);
leftHandSideExpression.is(or(
callExpression,
newExpression));
postfixExpression.is(leftHandSideExpression, opt(/* no line terminator here */or(INC, DEC)));
unaryExpression.is(or(
postfixExpression,
and(DELETE, unaryExpression),
and(VOID, unaryExpression),
and(TYPEOF, unaryExpression),
and(INC, unaryExpression),
and(DEC, unaryExpression),
and(PLUS, unaryExpression),
and(MINUS, unaryExpression),
and(TILDA, unaryExpression),
and(BANG, unaryExpression)));
multiplicativeExpression.is(unaryExpression, o2n(or(STAR, DIV, MOD), unaryExpression)).skipIfOneChild();
additiveExpression.is(multiplicativeExpression, o2n(or(PLUS, MINUS), multiplicativeExpression)).skipIfOneChild();
shiftExpression.is(additiveExpression, o2n(or(SL, SR, SR2), additiveExpression)).skipIfOneChild();
relationalExpression.is(shiftExpression, o2n(or(LT, GT, LE, GE, INSTANCEOF, IN), shiftExpression)).skipIfOneChild();
relationalExpressionNoIn.is(shiftExpression, o2n(or(LT, GT, LE, GE, INSTANCEOF), shiftExpression)).skipIfOneChild();
equalityExpression.is(relationalExpression, o2n(or(EQUAL, NOTEQUAL, EQUAL2, NOTEQUAL2), relationalExpression)).skipIfOneChild();
equalityExpressionNoIn.is(relationalExpressionNoIn, o2n(or(EQUAL, NOTEQUAL, EQUAL2, NOTEQUAL2), relationalExpressionNoIn)).skipIfOneChild();
bitwiseAndExpression.is(equalityExpression, o2n(AND, equalityExpression)).skipIfOneChild();
bitwiseAndExpressionNoIn.is(equalityExpressionNoIn, o2n(AND, equalityExpressionNoIn)).skipIfOneChild();
bitwiseXorExpression.is(bitwiseAndExpression, o2n(XOR, bitwiseAndExpression)).skipIfOneChild();
bitwiseXorExpressionNoIn.is(bitwiseAndExpressionNoIn, o2n(XOR, bitwiseAndExpressionNoIn)).skipIfOneChild();
bitwiseOrExpression.is(bitwiseXorExpression, o2n(OR, bitwiseXorExpression)).skipIfOneChild();
bitwiseOrExpressionNoIn.is(bitwiseXorExpressionNoIn, o2n(OR, bitwiseXorExpressionNoIn)).skipIfOneChild();
logicalAndExpression.is(bitwiseOrExpression, o2n(ANDAND, bitwiseOrExpression)).skipIfOneChild();
logicalAndExpressionNoIn.is(bitwiseOrExpressionNoIn, o2n(ANDAND, bitwiseOrExpressionNoIn)).skipIfOneChild();
logicalOrExpression.is(logicalAndExpression, o2n(OROR, logicalAndExpression)).skipIfOneChild();
logicalOrExpressionNoIn.is(logicalAndExpressionNoIn, o2n(OROR, logicalAndExpressionNoIn)).skipIfOneChild();
conditionalExpression.is(logicalOrExpression, opt(QUERY, assignmentExpression, COLON, assignmentExpression)).skipIfOneChild();
conditionalExpressionNoIn.is(logicalOrExpressionNoIn, opt(QUERY, assignmentExpression, COLON, assignmentExpressionNoIn)).skipIfOneChild();
assignmentExpression.is(or(
and(leftHandSideExpression, assignmentOperator, assignmentExpression),
conditionalExpression)).skipIfOneChild();
assignmentExpressionNoIn.is(or(
and(leftHandSideExpression, assignmentOperator, assignmentExpressionNoIn),
conditionalExpressionNoIn)).skipIfOneChild();
assignmentOperator.is(or(
EQU,
STAR_EQU,
DIV_EQU,
MOD_EQU,
PLUS_EQU,
MINUS_EQU,
SL_EQU,
SR_EQU,
SR_EQU2,
AND_EQU,
XOR_EQU,
OR_EQU));
expression.is(assignmentExpression, o2n(COMMA, assignmentExpression));
expressionNoIn.is(assignmentExpressionNoIn, o2n(COMMA, assignmentExpressionNoIn));
}
/**
* A.4 Statement
*/
private void statements() {
statement.is(or(
block,
variableStatement,
emptyStatement,
labelledStatement,
expressionStatement,
ifStatement,
iterationStatement,
continueStatement,
breakStatement,
returnStatement,
withStatement,
switchStatement,
throwStatement,
tryStatement,
debuggerStatement));
block.is(LCURLYBRACE, opt(statementList), RCURLYBRACE);
statementList.is(one2n(or(statement, permissive(functionDeclaration))));
variableStatement.is(VAR, variableDeclarationList, eos);
variableDeclarationList.is(variableDeclaration, o2n(COMMA, variableDeclaration));
variableDeclarationListNoIn.is(variableDeclarationNoIn, o2n(COMMA, variableDeclarationNoIn));
variableDeclaration.is(IDENTIFIER, opt(initialiser));
variableDeclarationNoIn.is(IDENTIFIER, opt(initialiserNoIn));
initialiser.is(EQU, assignmentExpression);
initialiserNoIn.is(EQU, assignmentExpressionNoIn);
emptyStatement.is(SEMI);
expressionStatement.is(not(or(LCURLYBRACE, FUNCTION)), expression, eos);
condition.is(expression);
ifStatement.is(IF, LPARENTHESIS, condition, RPARENTHESIS, statement, opt(ELSE, statement));
iterationStatement.is(or(
doWhileStatement,
whileStatement,
forInStatement,
forStatement));
doWhileStatement.is(DO, statement, WHILE, LPARENTHESIS, condition, RPARENTHESIS, eos);
whileStatement.is(WHILE, LPARENTHESIS, condition, RPARENTHESIS, statement);
forInStatement.is(or(
and(FOR, LPARENTHESIS, leftHandSideExpression, IN, expression, RPARENTHESIS, statement),
and(FOR, LPARENTHESIS, VAR, variableDeclarationListNoIn, IN, expression, RPARENTHESIS, statement)));
forStatement.is(or(
and(FOR, LPARENTHESIS, opt(expressionNoIn), SEMI, opt(condition), SEMI, opt(expression), RPARENTHESIS, statement),
and(FOR, LPARENTHESIS, VAR, variableDeclarationListNoIn, SEMI, opt(condition), SEMI, opt(expression), RPARENTHESIS, statement)));
continueStatement.is(or(
and(CONTINUE, /* TODO no line terminator here */IDENTIFIER, eos),
and(CONTINUE, eosNoLb)));
breakStatement.is(or(
and(BREAK, /* TODO no line terminator here */IDENTIFIER, eos),
and(BREAK, eosNoLb)));
returnStatement.is(or(
and(RETURN, /* TODO no line terminator here */expression, eos),
and(RETURN, eosNoLb)));
withStatement.is(WITH, LPARENTHESIS, expression, RPARENTHESIS, statement);
switchStatement.is(SWITCH, LPARENTHESIS, expression, RPARENTHESIS, caseBlock);
caseBlock.is(LCURLYBRACE, opt(caseClauses), opt(defaultClause, opt(caseClauses)), RCURLYBRACE);
caseClauses.is(one2n(caseClause));
caseClause.is(CASE, expression, COLON, opt(statementList));
defaultClause.is(DEFAULT, COLON, opt(statementList));
labelledStatement.is(IDENTIFIER, COLON, statement);
throwStatement.is(THROW, /* TODO no line terminator here */expression, eos);
tryStatement.is(TRY, block, or(and(catch_, opt(finally_)), finally_));
catch_.is(CATCH, LPARENTHESIS, IDENTIFIER, RPARENTHESIS, block);
finally_.is(FINALLY, block);
debuggerStatement.is(DEBUGGER, eos);
}
/**
* A.5 Functions and Programs
*/
private void functionsAndPrograms() {
functionDeclaration.is(FUNCTION, IDENTIFIER, LPARENTHESIS, opt(formalParameterList), RPARENTHESIS, LCURLYBRACE, functionBody, RCURLYBRACE);
functionExpression.is(FUNCTION, opt(IDENTIFIER), LPARENTHESIS, opt(formalParameterList), RPARENTHESIS, LCURLYBRACE, functionBody, RCURLYBRACE);
formalParameterList.is(IDENTIFIER, o2n(COMMA, IDENTIFIER));
functionBody.is(opt(sourceElements));
program.is(opt(sourceElements), EOF);
sourceElements.is(one2n(sourceElement));
sourceElement.is(or(
statement,
functionDeclaration));
}
/**
* Declares some constructs, which ES5 grammar does not support, but script engines support.
* For example prototype.js version 1.7 has a function declaration in a block, which is invalid under both ES3 and ES5.
*/
private static Object permissive(Object object) {
return object;
}
}