Chromium Code Reviews| Index: docs/language/Dart.g |
| diff --git a/docs/language/Dart.g b/docs/language/Dart.g |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fa6d6d235998fcbffab0ddf7b533371b642cff88 |
| --- /dev/null |
| +++ b/docs/language/Dart.g |
| @@ -0,0 +1,1722 @@ |
| +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +// CHANGES: |
| +// |
| +// v1.0 First version available in the SDK github repository. Covers the |
| +// Dart language as specified in the language specification based on the |
| +// many grammar rule snippets. That grammar was then adjusted to remove |
| +// known issues (e.g., misplaced metadata) and to resolve ambiguities. |
| +// HERE! |
| + |
| +grammar Dart; |
| + |
| +/* |
| +options { |
| + backtrack=true; |
| + memoize=true; |
| +} |
| +*/ |
| + |
| +@parser::header{ |
| +import java.util.Stack; |
| +} |
| + |
| +@lexer::header{ |
| +import java.util.Stack; |
| +} |
| + |
| +@parser::members { |
| + // Grammar debugging friendly output, 'The Definitive ANTLR Reference', p247. |
| + public String getErrorMessage(RecognitionException e, String[] tokenNames) { |
| + List stack = getRuleInvocationStack(e, this.getClass().getName()); |
| + String msg = null; |
| + if ( e instanceof NoViableAltException ) { |
| + NoViableAltException nvae = (NoViableAltException)e; |
| + msg = "no viable alt; token=" + e.token + |
| + " (decision=" + nvae.decisionNumber + |
| + " state " + nvae.stateNumber + ")" + |
| + " decision=<<" + nvae.grammarDecisionDescription + ">>"; |
| + } |
| + else { |
| + msg = super.getErrorMessage(e, tokenNames); |
| + } |
| + return stack + " " + msg; |
| + } |
| + |
| + public String getTokenErrorDisplay(Token t) { |
| + return t.toString(); |
| + } |
| + |
| + // Enable the parser to treat ASYNC/AWAIT/YIELD as keywords in the body of an |
| + // `async`, `async*`, or `sync*` function. Access via methods below. |
| + private Stack<Boolean> asyncEtcAreKeywords = new Stack<Boolean>(); |
| + { asyncEtcAreKeywords.push(false); } |
| + |
| + // Use this to indicate that we are now entering an `async`, `async*`, |
| + // or `sync*` function. |
| + void startAsyncFunction() { asyncEtcAreKeywords.push(true); } |
| + |
| + // Use this to indicate that we are now entering a function which is |
| + // neither `async`, `async*`, nor `sync*`. |
| + void startNonAsyncFunction() { asyncEtcAreKeywords.push(false); } |
| + |
| + // Use this to indicate that we are now leaving any funciton. |
| + void endFunction() { asyncEtcAreKeywords.pop(); } |
| + |
| + // Whether we can recognize ASYNC/AWAIT/YIELD as an identifier/typeIdentifier. |
| + boolean asyncEtcPredicate(int tokenId) { |
| + if (tokenId == ASYNC || tokenId == AWAIT || tokenId == YIELD) { |
| + return !asyncEtcAreKeywords.peek(); |
| + } |
| + return false; |
| + } |
| + |
| + // Debugging support methods. |
| + void dp(int indent, String method, String sep) { |
| + for (int i = 0; i < indent; i++) { |
| + System.out.print(" "); |
| + } |
| + System.out.println(method + sep + " " + input.LT(1) + " " + state.failed); |
| + } |
| + |
| + void dpBegin(int indent, String method) { dp(indent, method, ":"); } |
| + void dpEnd(int indent, String method) { dp(indent, method, " END:"); } |
| + void dpCall(int indent, String method) { dp(indent, method, "?"); } |
| + void dpCalled(int indent, String method) { dp(indent, method, ".."); } |
| + void dpResult(int indent, String method) { dp(indent, method, "!"); } |
| +} |
| + |
| +@lexer::members{ |
| + public static final int BRACE_NORMAL = 1; |
| + public static final int BRACE_SINGLE = 2; |
| + public static final int BRACE_DOUBLE = 3; |
| + public static final int BRACE_THREE_SINGLE = 4; |
| + public static final int BRACE_THREE_DOUBLE = 5; |
| + |
| + // Enable the parser to handle string interpolations via brace matching. |
| + // The top of the `braceLevels` stack describes the most recent unmatched |
| + // '{'. This is needed in order to enable/disable certain lexer rules. |
| + // |
| + // NORMAL: Most recent unmatched '{' was not string literal related. |
| + // SINGLE: Most recent unmatched '{' was `'...${`. |
| + // DOUBLE: Most recent unmatched '{' was `"...${`. |
| + // THREE_SINGLE: Most recent unmatched '{' was `'''...${`. |
| + // THREE_DOUBLE: Most recent unmatched '{' was `"""...${`. |
| + // |
| + // Access via functions below. |
| + private Stack<Integer> braceLevels = new Stack<Integer>(); |
| + |
| + // Whether we are currently in a string literal context, and which one. |
| + boolean currentBraceLevel(int braceLevel) { |
| + if (braceLevels.empty()) return false; |
| + return braceLevels.peek() == braceLevel; |
| + } |
| + |
| + // Use this to indicate that we are now entering a specific '{...}'. |
| + // Call it after accepting the '{'. |
| + void enterBrace() { |
| + braceLevels.push(BRACE_NORMAL); |
| + } |
| + void enterBraceSingleQuote() { |
| + braceLevels.push(BRACE_SINGLE); |
| + } |
| + void enterBraceDoubleQuote() { |
| + braceLevels.push(BRACE_DOUBLE); |
| + } |
| + void enterBraceThreeSingleQuotes() { |
| + braceLevels.push(BRACE_THREE_SINGLE); |
| + } |
| + void enterBraceThreeDoubleQuotes() { |
| + braceLevels.push(BRACE_THREE_DOUBLE); |
| + } |
| + |
| + // Use this to indicate that we are now exiting a specific '{...}', |
| + // no matter which kind. Call it before accepting the '}'. |
| + void exitBrace() { |
| + // We might raise a parse error here if the stack is empty, but the |
| + // parsing rules should ensure that we get a parse error anyway, and |
| + // it is not a big problem for the spec parser even if it misinterprets |
| + // the brace structure of some programs with syntax errors. |
| + if (!braceLevels.empty()) braceLevels.pop(); |
| + } |
| +} |
| + |
| +// ---------------------------------------- Grammar rules. |
| + |
| +libraryDefinition |
| + : FEFF? SCRIPT_TAG? |
| + ((metadata LIBRARY) => libraryName)? |
| + ((metadata (IMPORT | EXPORT)) => importOrExport)* |
| + ((metadata PART) => partDirective)* |
| + (metadata topLevelDefinition)* |
| + EOF |
| + ; |
| + |
| +// `functionSignature functionBody` is split into two alternatives because |
| +// this eliminates an ambiguity. |
| + |
| +topLevelDefinition |
| + : classDefinition |
| + | enumType |
| + | (TYPEDEF typeIdentifier typeParameters? '=') => typeAlias |
| + | (TYPEDEF functionPrefix ('<' | '(')) => typeAlias |
| + | (EXTERNAL functionSignature ';') => EXTERNAL functionSignature ';' |
| + | (EXTERNAL getterSignature) => EXTERNAL getterSignature ';' |
| + | (EXTERNAL type? SET identifier '(') => |
| + EXTERNAL setterSignature ';' |
| + | (getterSignature functionBodyPrefix) => getterSignature functionBody |
| + | (type? SET identifier '(') => setterSignature functionBody |
| + | (identifier typeParameters? '(') => functionSignature functionBody |
| + | (type identifier typeParameters? '(') => |
| + functionSignature functionBody |
| + | ((FINAL | CONST) type? identifier '=') => |
| + (FINAL | CONST) type? staticFinalDeclarationList ';' |
| + | initializedVariableDeclaration ';' |
| + ; |
| + |
| +declaredIdentifier |
| + : COVARIANT? finalConstVarOrType identifier |
|
floitsch
2017/08/28 09:18:48
Why is Covariant allowed at the top-level (through
Lasse Reichstein Nielsen
2017/08/28 10:51:32
I believe we handle that in prose: It's an error i
eernst
2017/08/28 11:35:16
Right, it's quite "imprecise" to allow COVARIANT o
|
| + ; |
| + |
| +finalConstVarOrType |
| + : FINAL type? |
| + | CONST type? |
| + | varOrType |
| + ; |
| + |
| +varOrType |
| + : VAR |
| + | type |
| + ; |
| + |
| +initializedVariableDeclaration |
| + : declaredIdentifier ('=' expression)? (',' initializedIdentifier)* |
| + ; |
| + |
| +initializedIdentifier |
| + : identifier ('=' expression)? |
| + ; |
| + |
| +initializedIdentifierList |
| + : initializedIdentifier (',' initializedIdentifier)* |
| + ; |
| + |
| +functionSignature |
| + : (type identifier typeParameters? '(') => |
| + type identifier formalParameterPart |
| + | identifier formalParameterPart |
| + ; |
| + |
| +functionBodyPrefix |
| + : ASYNC? '=>' |
| + | (ASYNC | ASYNC '*' | SYNC '*')? LBRACE |
| + ; |
| + |
| +functionBody |
| + : '=>' { startNonAsyncFunction(); } expression { endFunction(); } ';' |
| + | { startNonAsyncFunction(); } block { endFunction(); } |
| + | ASYNC '=>' |
| + { startAsyncFunction(); } expression { endFunction(); } ';' |
| + | (ASYNC | ASYNC '*' | SYNC '*') |
| + { startAsyncFunction(); } block { endFunction(); } |
| + ; |
| + |
| +block |
| + : LBRACE statements RBRACE |
| + ; |
| + |
| +formalParameterPart |
| + : typeParameters? formalParameterList |
| + ; |
| + |
| +formalParameterList |
| + : '(' ')' |
| + | '(' normalFormalParameters (','? | ',' optionalFormalParameters) ')' |
| + | '(' optionalFormalParameters ')' |
| + ; |
| + |
| +normalFormalParameters |
| + : normalFormalParameter (',' normalFormalParameter)* |
| + ; |
| + |
| +optionalFormalParameters |
| + : optionalPositionalFormalParameters |
| + | namedFormalParameters |
| + ; |
| + |
| +optionalPositionalFormalParameters |
| + : '[' defaultFormalParameter (',' defaultFormalParameter)* ','? ']' |
| + ; |
| + |
| +namedFormalParameters |
| + : LBRACE defaultNamedParameter (',' defaultNamedParameter)* ','? RBRACE |
| + ; |
| + |
| +normalFormalParameter |
| + : metadata normalFormalParameterNoMetadata |
| + ; |
| + |
| +// `functionFormalParameter` is split into two alternatives because |
| +// this eliminates an ambiguity. |
| + |
| +normalFormalParameterNoMetadata |
| + : (COVARIANT? identifier typeParameters? '(') => functionFormalParameter |
| + | (COVARIANT? type identifier typeParameters? '(') => |
| + functionFormalParameter |
| + | (finalConstVarOrType? THIS) => fieldFormalParameter |
| + | simpleFormalParameter |
| + ; |
| + |
| +functionFormalParameter |
| + : (COVARIANT? type identifier typeParameters? '(') => |
| + COVARIANT? type identifier formalParameterPart |
| + | COVARIANT? identifier formalParameterPart |
| + ; |
| + |
| +simpleFormalParameter |
| + : declaredIdentifier |
| + | COVARIANT? identifier |
| + ; |
| + |
| +fieldFormalParameter |
| + : finalConstVarOrType? THIS '.' identifier formalParameterPart? |
| + ; |
| + |
| +defaultFormalParameter |
| + : normalFormalParameter ('=' expression)? |
| + ; |
| + |
| +defaultNamedParameter |
| + : normalFormalParameter ((':' | '=') expression)? |
| + ; |
| + |
| +typeApplication |
| + : typeIdentifier typeParameters? |
| + ; |
| + |
| +classDefinition |
| + : (ABSTRACT? CLASS typeApplication (EXTENDS|IMPLEMENTS|LBRACE)) => |
| + ABSTRACT? CLASS typeApplication (superclass mixins?)? interfaces? |
| + LBRACE (metadata classMemberDefinition)* RBRACE |
| + | (ABSTRACT? CLASS typeApplication '=') => |
| + ABSTRACT? CLASS mixinApplicationClass |
| + ; |
| + |
| +mixins |
| + : WITH typeNotVoidNotFunctionList |
| + ; |
| + |
| +classMemberDefinition |
| + : (methodSignature functionBodyPrefix) => methodSignature functionBody |
| + | declaration ';' |
| + ; |
| + |
| +// `STATIC? functionSignature` is split into two alternatives because this |
| +// eliminates an ambiguity. |
| + |
| +methodSignature |
| + : (constructorName '(') => constructorSignature initializers? |
| + | (FACTORY constructorName '(') => factoryConstructorSignature |
| + | (STATIC? identifier typeParameters? '(') => STATIC? functionSignature |
| + | (STATIC? type identifier typeParameters? '(') => |
| + STATIC? functionSignature |
| + | (STATIC? type? GET) => STATIC? getterSignature |
| + | (STATIC? type? SET) => STATIC? setterSignature |
| + | operatorSignature |
| + ; |
| + |
| +// https://github.com/dart-lang/sdk/issues/29501 reports on the problem which |
| +// was solved by adding a case for redirectingFactoryConstructorSignature. |
| +// TODO(eernst): Close that issue when this is integrated into the spec. |
| + |
| +// https://github.com/dart-lang/sdk/issues/29502 reports on the problem that |
| +// than external const factory constructor declaration cannot be derived by |
| +// the spec grammar (and also not by this grammar). The following fixes were |
| +// introduced for that: Added the 'factoryConstructorSignature' case below in |
| +// 'declaration'; also added 'CONST?' in the 'factoryConstructorSignature' |
| +// rule, such that const factories in general are allowed. |
| +// TODO(eernst): Close that issue when this is integrated into the spec. |
| + |
| +declaration |
| + : (EXTERNAL CONST? FACTORY constructorName '(') => |
| + EXTERNAL factoryConstructorSignature |
| + | EXTERNAL constantConstructorSignature |
| + | (EXTERNAL constructorName '(') => EXTERNAL constructorSignature |
| + | ((EXTERNAL STATIC?)? type? GET) => (EXTERNAL STATIC?)? getterSignature |
| + | ((EXTERNAL STATIC?)? type? SET) => (EXTERNAL STATIC?)? setterSignature |
| + | (EXTERNAL? type? OPERATOR) => EXTERNAL? operatorSignature |
| + | (STATIC (FINAL | CONST)) => |
| + STATIC (FINAL | CONST) type? staticFinalDeclarationList |
| + | FINAL type? initializedIdentifierList |
| + | ((STATIC | COVARIANT)? (VAR | type) identifier ('=' | ',' | ';')) => |
| + (STATIC | COVARIANT)? (VAR | type) initializedIdentifierList |
| + | (EXTERNAL? STATIC? functionSignature ';') => |
| + EXTERNAL? STATIC? functionSignature |
| + | (CONST? FACTORY constructorName formalParameterList '=') => |
| + redirectingFactoryConstructorSignature |
| + | constantConstructorSignature (redirection | initializers)? |
| + | constructorSignature (redirection | initializers)? |
| + ; |
| + |
| +staticFinalDeclarationList |
| + : staticFinalDeclaration (',' staticFinalDeclaration)* |
| + ; |
| + |
| +staticFinalDeclaration |
| + : identifier '=' expression |
| + ; |
| + |
| +operatorSignature |
| + : type? OPERATOR operator formalParameterList |
| + ; |
| + |
| +operator |
| + : '~' |
| + | binaryOperator |
| + | '[' ']' |
| + | '[' ']' '=' |
| + ; |
| + |
| +binaryOperator |
| + : multiplicativeOperator |
| + | additiveOperator |
| + | (shiftOperator) => shiftOperator |
| + | relationalOperator |
| + | '==' |
| + | bitwiseOperator |
| + ; |
| + |
| +getterSignature |
| + : type? GET identifier |
| + ; |
| + |
| +setterSignature |
| + : type? SET identifier formalParameterList |
| + ; |
| + |
| +constructorSignature |
| + : constructorName formalParameterList |
| + ; |
| + |
| +constructorName |
| + : typeIdentifier ('.' identifier)? |
| + ; |
| + |
| +redirection |
| + : ':' THIS ('.' identifier)? arguments |
| + ; |
| + |
| +initializers |
| + : ':' superCallOrFieldInitializer (',' superCallOrFieldInitializer)* |
| + ; |
| + |
| +superCallOrFieldInitializer |
| + : SUPER arguments |
| + | SUPER '.' identifier arguments |
| + | fieldInitializer |
| + | assertClause |
| + ; |
| + |
| +fieldInitializer |
| + : (THIS '.')? identifier '=' conditionalExpression cascadeSection* |
| + ; |
| + |
| +factoryConstructorSignature |
| + : CONST? FACTORY constructorName formalParameterList |
| + ; |
| + |
| +redirectingFactoryConstructorSignature |
| + : CONST? FACTORY constructorName formalParameterList '=' |
| + constructorDesignation |
| + ; |
| + |
| +constantConstructorSignature |
| + : CONST constructorName formalParameterList |
| + ; |
| + |
| +superclass |
| + : EXTENDS typeNotVoidNotFunction |
| + ; |
| + |
| +interfaces |
| + : IMPLEMENTS typeNotVoidNotFunctionList |
| + ; |
| + |
| +mixinApplicationClass |
| + : typeApplication '=' mixinApplication ';' |
| + ; |
| + |
| +mixinApplication |
| + : typeNotVoidNotFunction mixins interfaces? |
| + ; |
| + |
| +enumType |
| + : ENUM typeIdentifier LBRACE identifier (',' identifier)* (',')? RBRACE |
| + ; |
| + |
| +typeParameter |
| + : metadata typeIdentifier (EXTENDS typeNotVoid)? |
| + ; |
| + |
| +typeParameters |
| + : '<' typeParameter (',' typeParameter)* '>' |
| + ; |
| + |
| +metadata |
| + : ('@' metadatum)* |
| + ; |
| + |
| +metadatum |
| + : constructorDesignation arguments |
| + | qualified |
| + ; |
| + |
| +expression |
| + : (formalParameterPart functionExpressionBodyPrefix) => |
| + functionExpression |
| + | throwExpression |
| + | (assignableExpression assignmentOperator) => |
| + assignableExpression assignmentOperator expression |
| + | conditionalExpression cascadeSection* |
| + ; |
| + |
| +expressionWithoutCascade |
| + : (formalParameterPart functionExpressionBodyPrefix) => |
| + functionExpressionWithoutCascade |
| + | throwExpressionWithoutCascade |
| + | (assignableExpression assignmentOperator) => |
| + assignableExpression assignmentOperator expressionWithoutCascade |
| + | conditionalExpression |
| + ; |
| + |
| +expressionList |
| + : expression (',' expression)* |
| + ; |
| + |
| +primary |
| + : thisExpression |
| + | SUPER unconditionalAssignableSelector |
| + | (CONST constructorDesignation) => constObjectExpression |
| + | newExpression |
| + | (formalParameterPart functionPrimaryBodyPrefix) => functionPrimary |
| + | '(' expression ')' |
| + | literal |
| + | identifier |
| + ; |
| + |
| +literal |
| + : nullLiteral |
| + | booleanLiteral |
| + | numericLiteral |
| + | stringLiteral |
| + | symbolLiteral |
| + | (CONST? typeArguments? LBRACE) => mapLiteral |
| + | listLiteral |
| + ; |
| + |
| +nullLiteral |
| + : NULL |
| + ; |
| + |
| +numericLiteral |
| + : NUMBER |
| + | HEX_NUMBER |
| + ; |
| + |
| +booleanLiteral |
| + : TRUE |
| + | FALSE |
| + ; |
| + |
| +stringLiteral |
| + : (multiLineString | singleLineString)+ |
| + ; |
| + |
| +stringLiteralWithoutInterpolation |
| + : singleLineStringWithoutInterpolation+ |
| + ; |
| + |
| +listLiteral |
| + : CONST? typeArguments? '[' (expressionList ','?)? ']' |
| + ; |
| + |
| +mapLiteral |
| + : CONST? typeArguments? |
| + LBRACE (mapLiteralEntry (',' mapLiteralEntry)* ','?)? RBRACE |
| + ; |
| + |
| +mapLiteralEntry |
| + : expression ':' expression |
| + ; |
| + |
| +throwExpression |
| + : THROW expression |
| + ; |
| + |
| +throwExpressionWithoutCascade |
| + : THROW expressionWithoutCascade |
| + ; |
| + |
| +functionExpression |
| + : formalParameterPart functionExpressionBody |
| + ; |
| + |
| +functionExpressionBody |
| + : '=>' { startNonAsyncFunction(); } expression { endFunction(); } |
| + | ASYNC '=>' { startAsyncFunction(); } expression { endFunction(); } |
| + ; |
| + |
| +functionExpressionBodyPrefix |
| + : ASYNC? '=>' |
| + ; |
| + |
| +functionExpressionWithoutCascade |
| + : formalParameterPart functionExpressionWithoutCascadeBody |
| + ; |
| + |
| +functionExpressionWithoutCascadeBody |
| + : '=>' { startNonAsyncFunction(); } |
| + expressionWithoutCascade { endFunction(); } |
| + | ASYNC '=>' { startAsyncFunction(); } |
| + expressionWithoutCascade { endFunction(); } |
| + ; |
| + |
| +functionPrimary |
| + : formalParameterPart functionPrimaryBody |
| + ; |
| + |
| +functionPrimaryBody |
| + : { startNonAsyncFunction(); } block { endFunction(); } |
| + | (ASYNC | ASYNC '*' | SYNC '*') |
| + { startAsyncFunction(); } block { endFunction(); } |
| + ; |
| + |
| +functionPrimaryBodyPrefix |
| + : (ASYNC | ASYNC '*' | SYNC '*')? LBRACE |
| + ; |
| + |
| +thisExpression |
| + : THIS |
| + ; |
| + |
| +newExpression |
| + : NEW constructorDesignation arguments |
| + ; |
| + |
| +constObjectExpression |
| + : CONST constructorDesignation arguments |
| + ; |
| + |
| +arguments |
| + : '(' (argumentList ','?)? ')' |
| + ; |
| + |
| +argumentList |
| + : namedArgument (',' namedArgument)* |
| + | expressionList (',' namedArgument)* |
| + ; |
| + |
| +namedArgument |
| + : label expression |
| + ; |
| + |
| +cascadeSection |
| + : '..' |
| + (cascadeSelector argumentPart*) |
| + (assignableSelector argumentPart*)* |
| + (assignmentOperator expressionWithoutCascade)? |
| + ; |
| + |
| +cascadeSelector |
| + : '[' expression ']' |
| + | identifier |
| + ; |
| + |
| +assignmentOperator |
| + : '=' |
| + | compoundAssignmentOperator |
| + ; |
| + |
| +compoundAssignmentOperator |
| + : '*=' |
| + | '/=' |
| + | '~/=' |
| + | '%=' |
| + | '+=' |
| + | '-=' |
| + | '<<=' |
| + | '>' '>' '=' |
| + | '&=' |
| + | '^=' |
| + | '|=' |
| + | '??=' |
| + ; |
| + |
| +conditionalExpression |
| + : ifNullExpression |
| + ('?' expressionWithoutCascade ':' expressionWithoutCascade)? |
| + ; |
| + |
| +ifNullExpression |
| + : logicalOrExpression ('??' logicalOrExpression)* |
| + ; |
| + |
| +logicalOrExpression |
| + : logicalAndExpression ('||' logicalAndExpression)* |
| + ; |
| + |
| +logicalAndExpression |
| + : equalityExpression ('&&' equalityExpression)* |
| + ; |
| + |
| +equalityExpression |
| + : relationalExpression (equalityOperator relationalExpression)? |
| + | SUPER equalityOperator relationalExpression |
| + ; |
| + |
| +equalityOperator |
| + : '==' |
| + | '!=' |
| + ; |
| + |
| +relationalExpression |
| + : bitwiseOrExpression |
| + (typeTest | typeCast | relationalOperator bitwiseOrExpression)? |
| + | SUPER relationalOperator bitwiseOrExpression |
| + ; |
| + |
| +relationalOperator |
| + : '>' '=' |
| + | '>' |
| + | '<=' |
| + | '<' |
| + ; |
| + |
| +bitwiseOrExpression |
| + : bitwiseXorExpression ('|' bitwiseXorExpression)* |
| + | SUPER ('|' bitwiseXorExpression)+ |
| + ; |
| + |
| +bitwiseXorExpression |
| + : bitwiseAndExpression ('^' bitwiseAndExpression)* |
| + | SUPER ('^' bitwiseAndExpression)+ |
| + ; |
| + |
| +bitwiseAndExpression |
| + : shiftExpression ('&' shiftExpression)* |
| + | SUPER ('&' shiftExpression)+ |
| + ; |
| + |
| +bitwiseOperator |
| + : '&' |
| + | '^' |
| + | '|' |
| + ; |
| + |
| +shiftExpression |
| + : additiveExpression (shiftOperator additiveExpression)* |
| + | SUPER (shiftOperator additiveExpression)+ |
| + ; |
| + |
| +shiftOperator |
| + : '<<' |
| + | '>' '>' |
| + ; |
| + |
| +additiveExpression |
| + : multiplicativeExpression (additiveOperator multiplicativeExpression)* |
| + | SUPER (additiveOperator multiplicativeExpression)+ |
| + ; |
| + |
| +additiveOperator |
| + : '+' |
| + | '-' |
| + ; |
| + |
| +multiplicativeExpression |
| + : unaryExpression (multiplicativeOperator unaryExpression)* |
| + | SUPER (multiplicativeOperator unaryExpression)+ |
| + ; |
| + |
| +multiplicativeOperator |
| + : '*' |
| + | '/' |
| + | '%' |
| + | '~/' |
| + ; |
| + |
| +unaryExpression |
| + : (prefixOperator ~SUPER) => prefixOperator unaryExpression |
| + | (awaitExpression) => awaitExpression |
| + | postfixExpression |
| + | (minusOperator | tildeOperator) SUPER |
| + | incrementOperator assignableExpression |
| + ; |
| + |
| +prefixOperator |
| + : minusOperator |
| + | negationOperator |
| + | tildeOperator |
| + ; |
| + |
| +minusOperator |
| + : '-' |
| + ; |
| + |
| +negationOperator |
| + : '!' |
| + ; |
| + |
| +tildeOperator |
| + : '~' |
| + ; |
| + |
| +awaitExpression |
| + : AWAIT unaryExpression |
| + ; |
| + |
| +// The `(selector)` predicate ensures that the parser commits to the longest |
| +// possible chain of selectors, e.g., `a<b,c>(d)` as a call rather than as a |
| +// sequence of two relational expressions. |
| + |
| +postfixExpression |
| + : (assignableExpression postfixOperator) => |
| + assignableExpression postfixOperator |
| + | primary ((selector) => selector)* |
| + ; |
| + |
| +postfixOperator |
| + : incrementOperator |
| + ; |
| + |
| +selector |
| + : assignableSelector |
| + | argumentPart |
| + ; |
| + |
| +argumentPart |
| + : typeArguments? arguments |
| + ; |
| + |
| +incrementOperator |
| + : '++' |
| + | '--' |
| + ; |
| + |
| +// The `(assignableSelectorPart)` predicate ensures that the parser |
| +// commits to the longest possible chain, e.g., `a<b,c>(d).e` as one rather |
| +// than two expressions. The first `identifier` alternative handles all |
| +// the simple cases; the final `identifier` alternative at the end catches |
| +// the case where we have `identifier '<'` and the '<' is used as a |
| +// relationalOperator, not the beginning of typeArguments. |
| + |
| +assignableExpression |
| + : (SUPER unconditionalAssignableSelector |
| + ~('<' | '(' | '[' | '.' | '?.')) => |
| + SUPER unconditionalAssignableSelector |
| + | (identifier ~('<' | '(' | '[' | '.' | '?.')) => identifier |
| + | (primary argumentPart* assignableSelector) => |
| + primary ((assignableSelectorPart) => assignableSelectorPart)+ |
| + | identifier |
| + ; |
| + |
| +assignableSelectorPart |
| + : argumentPart* assignableSelector |
| + ; |
| + |
| +unconditionalAssignableSelector |
| + : '[' expression ']' |
| + | '.' identifier |
| + ; |
| + |
| +assignableSelector |
| + : unconditionalAssignableSelector |
| + | '?.' identifier |
| + ; |
| + |
| +identifier |
| + : IDENTIFIER |
| + | ABSTRACT |
| + | AS |
| + | COVARIANT |
| + | DEFERRED |
| + | DYNAMIC |
| + | EXPORT |
| + | EXTERNAL |
| + | FACTORY |
| + | GET |
| + | IMPLEMENTS |
| + | IMPORT |
| + | LIBRARY |
| + | OPERATOR |
| + | PART |
| + | SET |
| + | STATIC |
| + | TYPEDEF |
| + | HIDE // Not a built-in identifier. |
| + | OF // Not a built-in identifier. |
| + | ON // Not a built-in identifier. |
| + | SHOW // Not a built-in identifier. |
| + | SYNC // Not a built-in identifier. |
| + | FUNCTION // Not a built-in identifier. |
| + | { asyncEtcPredicate(input.LA(1)) }? (ASYNC|AWAIT|YIELD) |
| + ; |
| + |
| +qualified |
| + : identifier ('.' identifier)? |
| + ; |
| + |
| +typeIdentifier |
| + : IDENTIFIER |
| + | DYNAMIC // The only built-in identifier that can be used as a type. |
| + | HIDE // Not a built-in identifier. |
| + | OF // Not a built-in identifier. |
| + | ON // Not a built-in identifier. |
| + | SHOW // Not a built-in identifier. |
| + | SYNC // Not a built-in identifier. |
| + | FUNCTION // Not a built-in identifier. |
| + | { asyncEtcPredicate(input.LA(1)) }? (ASYNC|AWAIT|YIELD) |
| + ; |
| + |
| +typeTest |
| + : isOperator typeNotVoid |
| + ; |
| + |
| +isOperator |
| + : IS '!'? |
| + ; |
| + |
| +typeCast |
| + : asOperator typeNotVoid |
| + ; |
| + |
| +asOperator |
| + : AS |
| + ; |
| + |
| +statements |
| + : statement* |
| + ; |
| + |
| +statement |
| + : label* nonLabelledStatement |
| + ; |
| + |
| +// Exception in the language specification: An expressionStatement cannot |
| +// start with LBRACE. We force anything that starts with LBRACE to be a block, |
| +// which will prevent an expressionStatement from starting with LBRACE, and |
| +// which will not interfere with the recognition of any other case. If we |
| +// add another statement which can start with LBRACE we must adjust this |
| +// check. |
| +nonLabelledStatement |
| + : (LBRACE) => block |
| + | (declaredIdentifier ('='|','|';')) => localVariableDeclaration |
| + | (AWAIT? FOR) => forStatement |
| + | whileStatement |
| + | doStatement |
| + | switchStatement |
| + | ifStatement |
| + | rethrowStatement |
| + | tryStatement |
| + | breakStatement |
| + | continueStatement |
| + | returnStatement |
| + | (functionSignature functionBodyPrefix) => localFunctionDeclaration |
| + | assertStatement |
| + | (YIELD ~'*') => yieldStatement |
| + | yieldEachStatement |
| + | expressionStatement |
| + ; |
| + |
| +expressionStatement |
| + : expression? ';' |
| + ; |
| + |
| +localVariableDeclaration |
| + : initializedVariableDeclaration ';' |
| + ; |
| + |
| +localFunctionDeclaration |
| + : functionSignature functionBody |
| + ; |
| + |
| +ifStatement |
| + : IF '(' expression ')' statement ((ELSE) => ELSE statement | ()) |
| + ; |
| + |
| +forStatement |
| + : AWAIT? FOR '(' forLoopParts ')' statement |
| + ; |
| + |
| +forLoopParts |
| + : (declaredIdentifier IN) => declaredIdentifier IN expression |
| + | (identifier IN) => identifier IN expression |
| + | forInitializerStatement expression? ';' expressionList? |
| + ; |
| + |
| +// The localVariableDeclaration cannot be CONST, but that can |
| +// be enforced in a later phase, and the grammar allows it. |
| +forInitializerStatement |
| + : (localVariableDeclaration) => localVariableDeclaration |
| + | expression? ';' |
| + ; |
| + |
| +whileStatement |
| + : WHILE '(' expression ')' statement |
| + ; |
| + |
| +doStatement |
| + : DO statement WHILE '(' expression ')' ';' |
| + ; |
| + |
| +switchStatement |
| + : SWITCH '(' expression ')' LBRACE switchCase* defaultCase? RBRACE |
| + ; |
| + |
| +switchCase |
| + : label* CASE expression ':' statements |
| + ; |
| + |
| +defaultCase |
| + : label* DEFAULT ':' statements |
| + ; |
| + |
| +rethrowStatement |
| + : RETHROW ';' |
| + ; |
| + |
| +tryStatement |
| + : TRY block (onParts finallyPart? | finallyPart) |
| + ; |
| + |
| +onPart |
| + : catchPart block |
| + | ON typeNotVoid catchPart? block |
| + ; |
| + |
| +onParts |
| + : (onPart (ON|CATCH)) => onPart onParts |
| + | onPart |
| + ; |
| + |
| +catchPart |
| + : CATCH '(' identifier (',' identifier)? ')' |
| + ; |
| + |
| +finallyPart |
| + : FINALLY block |
| + ; |
| + |
| +returnStatement |
| + : RETURN expression? ';' |
| + ; |
| + |
| +label |
| + : identifier ':' |
| + ; |
| + |
| +breakStatement |
| + : BREAK identifier? ';' |
| + ; |
| + |
| +continueStatement |
| + : CONTINUE identifier? ';' |
| + ; |
| + |
| +yieldStatement |
| + : YIELD expression ';' |
| + ; |
| + |
| +yieldEachStatement |
| + : YIELD '*' expression ';' |
| + ; |
| + |
| +assertStatement |
| + : assertClause ';' |
| + ; |
| + |
| +assertClause |
| + : ASSERT '(' expression (',' expression)? ')' |
| + ; |
| + |
| +libraryName |
| + : metadata LIBRARY identifier ('.' identifier)* ';' |
| + ; |
| + |
| +importOrExport |
| + : (metadata IMPORT) => libraryImport |
| + | (metadata EXPORT) => libraryExport |
| + ; |
| + |
| +libraryImport |
| + : metadata importSpecification |
| + ; |
| + |
| +importSpecification |
| + : IMPORT uri (AS identifier)? combinator* ';' |
| + | IMPORT uri DEFERRED AS identifier combinator* ';' |
| + ; |
| + |
| +combinator |
| + : SHOW identifierList |
| + | HIDE identifierList |
| + ; |
| + |
| +identifierList |
| + : identifier (',' identifier)* |
| + ; |
| + |
| +libraryExport |
| + : metadata EXPORT uri combinator* ';' |
| + ; |
| + |
| +partDirective |
| + : metadata PART uri ';' |
| + ; |
| + |
| +partHeader |
| + : metadata PART OF identifier ('.' identifier)* ';' |
| + ; |
| + |
| +partDeclaration |
| + : partHeader topLevelDefinition* EOF |
| + ; |
| + |
| +uri |
| + : stringLiteralWithoutInterpolation |
| + ; |
| + |
| +type |
| + : (FUNCTION ('('|'<')) => functionTypeTails |
| + | (typeNotFunction FUNCTION ('('|'<')) => |
| + typeNotFunction functionTypeTails |
| + | typeNotFunction |
| + ; |
| + |
| +typeNotFunction |
| + : typeNotVoidNotFunction |
| + | VOID |
| + ; |
| + |
| +typeNotVoid |
| + : (typeNotFunction? FUNCTION ('('|'<')) => functionType |
| + | typeNotVoidNotFunction |
| + ; |
| + |
| +typeNotVoidNotFunction |
| + : typeName typeArguments? |
| + ; |
| + |
| +typeName |
| + : typeIdentifier ('.' typeIdentifier)? |
| + ; |
| + |
| +typeArguments |
| + : '<' typeList '>' |
| + ; |
| + |
| +typeList |
| + : type (',' type)* |
| + ; |
| + |
| +typeNotVoidNotFunctionList |
| + : typeNotVoidNotFunction (',' typeNotVoidNotFunction)* |
| + ; |
| + |
| +typeAlias |
| + : (TYPEDEF typeIdentifier typeParameters? '=') => |
| + TYPEDEF typeIdentifier typeParameters? '=' functionType ';' |
| + | TYPEDEF functionTypeAlias |
| + ; |
| + |
| +functionTypeAlias |
| + : functionPrefix formalParameterPart ';' |
| + ; |
| + |
| +functionPrefix |
| + : (type identifier) => type identifier |
| + | identifier |
| + ; |
| + |
| +functionTypeTail |
| + : FUNCTION typeParameters? parameterTypeList |
| + ; |
| + |
| +functionTypeTails |
| + : (functionTypeTail FUNCTION ('<'|'(')) => |
| + functionTypeTail functionTypeTails |
| + | functionTypeTail |
| + ; |
| + |
| +functionType |
| + : (FUNCTION ('<'|'(')) => functionTypeTails |
| + | typeNotFunction functionTypeTails |
| + ; |
| + |
| +parameterTypeList |
| + : ('(' ')') => '(' ')' |
| + | ('(' normalParameterTypes ',' ('['|'{')) => |
| + '(' normalParameterTypes ',' optionalParameterTypes ')' |
| + | ('(' normalParameterTypes ','? ')') => |
| + '(' normalParameterTypes ','? ')' |
| + | '(' optionalParameterTypes ')' |
| + ; |
| + |
| +normalParameterTypes |
| + : normalParameterType (',' normalParameterType)* |
| + ; |
| + |
| +normalParameterType |
| + : (typedIdentifier) => typedIdentifier |
| + | type |
| + ; |
| + |
| +optionalParameterTypes |
| + : optionalPositionalParameterTypes |
| + | namedParameterTypes |
| + ; |
| + |
| +optionalPositionalParameterTypes |
| + : '[' normalParameterTypes ','? ']' |
| + ; |
| + |
| +namedParameterTypes |
| + : '{' typedIdentifier (',' typedIdentifier)* ','? '}' |
| + ; |
| + |
| +typedIdentifier |
| + : type identifier |
| + ; |
| + |
| +constructorDesignation |
| + : typeIdentifier |
| + | identifier '.' identifier |
| + | identifier '.' typeIdentifier '.' identifier |
| + | typeName typeArguments ('.' identifier)? |
| + ; |
| + |
| +// Predicate: Force resolution as composite symbolLiteral as far as possible. |
| +symbolLiteral |
| + : '#' (operator | (identifier (('.' identifier) => '.' identifier)*)) |
| + ; |
| + |
| +singleLineStringWithoutInterpolation |
| + : RAW_SINGLE_LINE_STRING |
| + | SINGLE_LINE_STRING_DQ_BEGIN_END |
| + | SINGLE_LINE_STRING_SQ_BEGIN_END |
| + ; |
| + |
| +singleLineString |
| + : RAW_SINGLE_LINE_STRING |
| + | SINGLE_LINE_STRING_SQ_BEGIN_END |
| + | SINGLE_LINE_STRING_SQ_BEGIN_MID expression |
| + (SINGLE_LINE_STRING_SQ_MID_MID expression)* |
| + SINGLE_LINE_STRING_SQ_MID_END |
| + | SINGLE_LINE_STRING_DQ_BEGIN_END |
| + | SINGLE_LINE_STRING_DQ_BEGIN_MID expression |
| + (SINGLE_LINE_STRING_DQ_MID_MID expression)* |
| + SINGLE_LINE_STRING_DQ_MID_END |
| + ; |
| + |
| +multiLineString |
| + : RAW_MULTI_LINE_STRING |
| + | MULTI_LINE_STRING_SQ_BEGIN_END |
| + | MULTI_LINE_STRING_SQ_BEGIN_MID expression |
| + (MULTI_LINE_STRING_SQ_MID_MID expression)* |
| + MULTI_LINE_STRING_SQ_MID_END |
| + | MULTI_LINE_STRING_DQ_BEGIN_END |
| + | MULTI_LINE_STRING_DQ_BEGIN_MID expression |
| + (MULTI_LINE_STRING_DQ_MID_MID expression)* |
| + MULTI_LINE_STRING_DQ_MID_END |
| + ; |
| + |
| +// ---------------------------------------- Lexer rules. |
| + |
| +fragment |
| +LETTER |
| + : 'a' .. 'z' |
| + | 'A' .. 'Z' |
| + ; |
| + |
| +fragment |
| +DIGIT |
| + : '0' .. '9' |
| + ; |
| + |
| +fragment |
| +EXPONENT |
| + : ('e' | 'E') ('+' | '-')? DIGIT+ |
| + ; |
| + |
| +fragment |
| +HEX_DIGIT |
| + : ('a' | 'b' | 'c' | 'd' | 'e' | 'f') |
| + | ('A' | 'B' | 'C' | 'D' | 'E' | 'F') |
| + | DIGIT |
| + ; |
| + |
| +FINAL |
| + : 'final' |
| + ; |
| + |
| +CONST |
| + : 'const' |
| + ; |
| + |
| +VAR |
| + : 'var' |
| + ; |
| + |
| +VOID |
| + : 'void' |
| + ; |
| + |
| +ASYNC |
| + : 'async' |
| + ; |
| + |
| +THIS |
| + : 'this' |
| + ; |
| + |
| +ABSTRACT |
| + : 'abstract' |
| + ; |
| + |
| +AS |
| + : 'as' |
| + ; |
| + |
| +SYNC |
| + : 'sync' |
| + ; |
| + |
| +CLASS |
| + : 'class' |
| + ; |
| + |
| +WITH |
| + : 'with' |
| + ; |
| + |
| +STATIC |
| + : 'static' |
| + ; |
| + |
| +DYNAMIC |
| + : 'dynamic' |
| + ; |
| + |
| +EXTERNAL |
| + : 'external' |
| + ; |
| + |
| +GET |
| + : 'get' |
| + ; |
| + |
| +SET |
| + : 'set' |
| + ; |
| + |
| +OPERATOR |
| + : 'operator' |
| + ; |
| + |
| +SUPER |
| + : 'super' |
| + ; |
| + |
| +FACTORY |
| + : 'factory' |
| + ; |
| + |
| +EXTENDS |
| + : 'extends' |
| + ; |
| + |
| +IMPLEMENTS |
| + : 'implements' |
| + ; |
| + |
| +ENUM |
| + : 'enum' |
| + ; |
| + |
| +NULL |
| + : 'null' |
| + ; |
| + |
| +TRUE |
| + : 'true' |
| + ; |
| + |
| +FALSE |
| + : 'false' |
| + ; |
| + |
| +THROW |
| + : 'throw' |
| + ; |
| + |
| +NEW |
| + : 'new' |
| + ; |
| + |
| +AWAIT |
| + : 'await' |
| + ; |
| + |
| +DEFERRED |
| + : 'deferred' |
| + ; |
| + |
| +EXPORT |
| + : 'export' |
| + ; |
| + |
| +IMPORT |
| + : 'import' |
| + ; |
| + |
| +LIBRARY |
| + : 'library' |
| + ; |
| + |
| +PART |
| + : 'part' |
| + ; |
| + |
| +TYPEDEF |
| + : 'typedef' |
| + ; |
| + |
| +IS |
| + : 'is' |
| + ; |
| + |
| +IF |
| + : 'if' |
| + ; |
| + |
| +ELSE |
| + : 'else' |
| + ; |
| + |
| +WHILE |
| + : 'while' |
| + ; |
| + |
| +FOR |
| + : 'for' |
| + ; |
| + |
| +IN |
| + : 'in' |
| + ; |
| + |
| +DO |
| + : 'do' |
| + ; |
| + |
| +SWITCH |
| + : 'switch' |
| + ; |
| + |
| +CASE |
| + : 'case' |
| + ; |
| + |
| +DEFAULT |
| + : 'default' |
| + ; |
| + |
| +RETHROW |
| + : 'rethrow' |
| + ; |
| + |
| +TRY |
| + : 'try' |
| + ; |
| + |
| +ON |
| + : 'on' |
| + ; |
| + |
| +CATCH |
| + : 'catch' |
| + ; |
| + |
| +FINALLY |
| + : 'finally' |
| + ; |
| + |
| +RETURN |
| + : 'return' |
| + ; |
| + |
| +BREAK |
| + : 'break' |
| + ; |
| + |
| +CONTINUE |
| + : 'continue' |
| + ; |
| + |
| +YIELD |
| + : 'yield' |
| + ; |
| + |
| +SHOW |
| + : 'show' |
| + ; |
| + |
| +HIDE |
| + : 'hide' |
| + ; |
| + |
| +OF |
| + : 'of' |
| + ; |
| + |
| +ASSERT |
| + : 'assert' |
| + ; |
| + |
| +COVARIANT |
| + : 'covariant' |
| + ; |
| + |
| +FUNCTION |
| + : 'Function' |
| + ; |
| + |
| +NUMBER |
| + : (DIGIT+ '.' DIGIT) => DIGIT+ '.' DIGIT+ EXPONENT? |
| + | DIGIT+ EXPONENT? |
| + | '.' DIGIT+ EXPONENT? |
| + ; |
| + |
| +HEX_NUMBER |
| + : '0x' HEX_DIGIT+ |
| + | '0X' HEX_DIGIT+ |
| + ; |
| + |
| +RAW_SINGLE_LINE_STRING |
| + : 'r' '\'' (~('\'' | '\r' | '\n'))* '\'' |
| + | 'r' '"' (~('"' | '\r' | '\n'))* '"' |
| + ; |
| + |
| +RAW_MULTI_LINE_STRING |
| + : 'r' '"""' (options {greedy=false;} : .)* '"""' |
| + | 'r' '\'\'\'' (options {greedy=false;} : .)* '\'\'\'' |
| + ; |
| + |
| +fragment |
| +SIMPLE_STRING_INTERPOLATION |
| + : '$' IDENTIFIER_NO_DOLLAR |
| + ; |
| + |
| +fragment |
| +STRING_CONTENT_SQ |
| + : ~('\\' | '\'' | '$' | '\r' | '\n') |
| + | '\\' ~( '\r' | '\n') |
| + | SIMPLE_STRING_INTERPOLATION |
| + ; |
| + |
| +SINGLE_LINE_STRING_SQ_BEGIN_END |
| + : '\'' STRING_CONTENT_SQ* '\'' |
| + ; |
| + |
| +SINGLE_LINE_STRING_SQ_BEGIN_MID |
| + : '\'' STRING_CONTENT_SQ* '${' { enterBraceSingleQuote(); } |
| + ; |
| + |
| +SINGLE_LINE_STRING_SQ_MID_MID |
| + : { currentBraceLevel(BRACE_SINGLE) }? => |
| + ('}' STRING_CONTENT_SQ* '${') => |
| + { exitBrace(); } '}' STRING_CONTENT_SQ* '${' |
| + { enterBraceSingleQuote(); } |
| + ; |
| + |
| +SINGLE_LINE_STRING_SQ_MID_END |
| + : { currentBraceLevel(BRACE_SINGLE) }? => |
| + ('}' STRING_CONTENT_SQ* '\'') => |
| + { exitBrace(); } '}' STRING_CONTENT_SQ* '\'' |
| + ; |
| + |
| +fragment |
| +STRING_CONTENT_DQ |
| + : ~('\\' | '"' | '$' | '\r' | '\n') |
| + | '\\' ~('\r' | '\n') |
| + | SIMPLE_STRING_INTERPOLATION |
| + ; |
| + |
| +SINGLE_LINE_STRING_DQ_BEGIN_END |
| + : '"' STRING_CONTENT_DQ* '"' |
| + ; |
| + |
| +SINGLE_LINE_STRING_DQ_BEGIN_MID |
| + : '"' STRING_CONTENT_DQ* '${' { enterBraceDoubleQuote(); } |
| + ; |
| + |
| +SINGLE_LINE_STRING_DQ_MID_MID |
| + : { currentBraceLevel(BRACE_DOUBLE) }? => |
| + ('}' STRING_CONTENT_DQ* '${') => |
| + { exitBrace(); } '}' STRING_CONTENT_DQ* '${' |
| + { enterBraceDoubleQuote(); } |
| + ; |
| + |
| +SINGLE_LINE_STRING_DQ_MID_END |
| + : { currentBraceLevel(BRACE_DOUBLE) }? => |
| + ('}' STRING_CONTENT_DQ* '"') => |
| + { exitBrace(); } '}' STRING_CONTENT_DQ* '"' |
| + ; |
| + |
| +fragment |
| +QUOTES_SQ |
| + : |
| + | '\'' |
| + | '\'\'' |
| + ; |
| + |
| +// Read string contents, which may be almost anything, but stop when seeing |
| +// '\'\'\'' and when seeing '${'. We do this by allowing all other |
| +// possibilities including escapes, simple interpolation, and fewer than |
| +// three '\''. |
| +fragment |
| +STRING_CONTENT_TSQ |
| + : QUOTES_SQ |
| + (~('\\' | '$' | '\'') | '\\' . | SIMPLE_STRING_INTERPOLATION) |
| + ; |
| + |
| +MULTI_LINE_STRING_SQ_BEGIN_END |
| + : '\'\'\'' STRING_CONTENT_TSQ* '\'\'\'' |
| + ; |
| + |
| +MULTI_LINE_STRING_SQ_BEGIN_MID |
| + : '\'\'\'' STRING_CONTENT_TSQ* QUOTES_SQ '${' |
| + { enterBraceThreeSingleQuotes(); } |
| + ; |
| + |
| +MULTI_LINE_STRING_SQ_MID_MID |
| + : { currentBraceLevel(BRACE_THREE_SINGLE) }? => |
| + ('}' STRING_CONTENT_TSQ* QUOTES_SQ '${') => |
| + { exitBrace(); } '}' STRING_CONTENT_TSQ* QUOTES_SQ '${' |
| + { enterBraceThreeSingleQuotes(); } |
| + ; |
| + |
| +MULTI_LINE_STRING_SQ_MID_END |
| + : { currentBraceLevel(BRACE_THREE_SINGLE) }? => |
| + ('}' STRING_CONTENT_TSQ* '\'\'\'') => |
| + { exitBrace(); } '}' STRING_CONTENT_TSQ* '\'\'\'' |
| + ; |
| + |
| +fragment |
| +QUOTES_DQ |
| + : |
| + | '"' |
| + | '""' |
| + ; |
| + |
| +// Read string contents, which may be almost anything, but stop when seeing |
| +// '"""' and when seeing '${'. We do this by allowing all other possibilities |
| +// including escapes, simple interpolation, and fewer-than-three '"'. |
| +fragment |
| +STRING_CONTENT_TDQ |
| + : QUOTES_DQ |
| + (~('\\' | '$' | '"') | '\\' . | SIMPLE_STRING_INTERPOLATION) |
| + ; |
| + |
| +MULTI_LINE_STRING_DQ_BEGIN_END |
| + : '"""' STRING_CONTENT_TDQ* '"""' |
| + ; |
| + |
| +MULTI_LINE_STRING_DQ_BEGIN_MID |
| + : '"""' STRING_CONTENT_TDQ* QUOTES_DQ '${' |
| + { enterBraceThreeDoubleQuotes(); } |
| + ; |
| + |
| +MULTI_LINE_STRING_DQ_MID_MID |
| + : { currentBraceLevel(BRACE_THREE_DOUBLE) }? => |
| + ('}' STRING_CONTENT_TDQ* QUOTES_DQ '${') => |
| + { exitBrace(); } '}' STRING_CONTENT_TDQ* QUOTES_DQ '${' |
| + { enterBraceThreeDoubleQuotes(); } |
| + ; |
| + |
| +MULTI_LINE_STRING_DQ_MID_END |
| + : { currentBraceLevel(BRACE_THREE_DOUBLE) }? => |
| + ('}' STRING_CONTENT_TDQ* '"""') => |
| + { exitBrace(); } '}' STRING_CONTENT_TDQ* '"""' |
| + ; |
| + |
| +LBRACE |
| + : '{' { enterBrace(); } |
| + ; |
| + |
| +RBRACE |
| + : { currentBraceLevel(BRACE_NORMAL) }? => ('}') => { exitBrace(); } '}' |
| + ; |
| + |
| +fragment |
| +IDENTIFIER_START_NO_DOLLAR |
| + : LETTER |
| + | '_' |
| + ; |
| + |
| +fragment |
| +IDENTIFIER_PART_NO_DOLLAR |
| + : IDENTIFIER_START_NO_DOLLAR |
| + | DIGIT |
| + ; |
| + |
| +fragment |
| +IDENTIFIER_NO_DOLLAR |
| + : IDENTIFIER_START_NO_DOLLAR IDENTIFIER_PART_NO_DOLLAR* |
| + ; |
| + |
| +fragment |
| +IDENTIFIER_START |
| + : IDENTIFIER_START_NO_DOLLAR |
| + | '$' |
| + ; |
| + |
| +fragment |
| +IDENTIFIER_PART |
| + : IDENTIFIER_START |
| + | DIGIT |
| + ; |
| + |
| +SCRIPT_TAG |
| + : '#!' (~('\r' | '\n'))* NEWLINE |
| + ; |
| + |
| +IDENTIFIER |
| + : IDENTIFIER_START IDENTIFIER_PART* |
| + ; |
| + |
| +SINGLE_LINE_COMMENT |
| + : '//' (~('\r' | '\n'))* NEWLINE? |
| + { skip(); } |
| + ; |
| + |
| +MULTI_LINE_COMMENT |
| + : '/*' (options {greedy=false;} : (MULTI_LINE_COMMENT | .))* '*/' |
| + { skip(); } |
| + ; |
| + |
| +fragment |
| +NEWLINE |
| + : ('\r' | '\n' | '\r\n') |
| + ; |
| + |
| +FEFF |
| + : '\uFEFF' |
| + ; |
| + |
| +WS |
| + : (' ' | '\t' | '\r' | '\n')+ |
| + { skip(); } |
| + ; |