mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-12 23:08:52 +01:00
1113 lines
27 KiB
Plaintext
1113 lines
27 KiB
Plaintext
|
header {
|
||
|
package processing.app.preproc;
|
||
|
|
||
|
import processing.app.*;
|
||
|
}
|
||
|
class PdeRecognizer extends Parser;
|
||
|
|
||
|
options {
|
||
|
importVocab= Java;
|
||
|
exportVocab= PdePartial;
|
||
|
codeGenMakeSwitchThreshold=10;
|
||
|
codeGenBitsetTestThreshold=10;
|
||
|
defaultErrorHandler= false;
|
||
|
k= 2;
|
||
|
buildAST= true;
|
||
|
}
|
||
|
|
||
|
tokens {
|
||
|
CONSTRUCTOR_CAST; EMPTY_FIELD;
|
||
|
}
|
||
|
pdeProgram :( "public" "class" | "import" ) => javaProgram
|
||
|
{ PdePreprocessor.programType = PdePreprocessor.JAVA; }
|
||
|
|
||
|
// the syntactic predicate here looks for any minimal (thus
|
||
|
// the non-greedy qualifier) number of fields, followed by
|
||
|
// the tokens that represent the definition of loop() or
|
||
|
// some other member function. java mode programs may have such
|
||
|
// definitions, but they won't reach this point, having already been
|
||
|
// selected in the previous alternative. static mode programs
|
||
|
// don't have member functions.
|
||
|
//
|
||
|
| ( ( options {greedy=false;}: possiblyEmptyField)* "void" IDENT LPAREN )
|
||
|
=> activeProgram
|
||
|
{ PdePreprocessor.programType = PdePreprocessor.ACTIVE; }
|
||
|
|
||
|
| staticProgram
|
||
|
{ PdePreprocessor.programType = PdePreprocessor.STATIC; }
|
||
|
;
|
||
|
|
||
|
javaProgram :compilationUnit
|
||
|
;
|
||
|
|
||
|
activeProgram :(possiblyEmptyField)+
|
||
|
;
|
||
|
|
||
|
staticProgram :(statement)*
|
||
|
;
|
||
|
|
||
|
constant :NUM_INT
|
||
|
| CHAR_LITERAL
|
||
|
| STRING_LITERAL
|
||
|
| NUM_FLOAT
|
||
|
| NUM_LONG
|
||
|
| NUM_DOUBLE
|
||
|
| webcolor_literal
|
||
|
;
|
||
|
|
||
|
webcolor_literal :w:WEBCOLOR_LITERAL
|
||
|
{ Preferences.getBoolean("preproc.web_colors") &&
|
||
|
w.getText().length() == 6 }? // must be exactly 6 hex digits
|
||
|
;
|
||
|
|
||
|
builtInConsCastType :"void"
|
||
|
| "boolean"
|
||
|
| "byte"
|
||
|
| "char"
|
||
|
| "short"
|
||
|
| "int"
|
||
|
| "float"
|
||
|
| "long"
|
||
|
| "double"
|
||
|
;
|
||
|
|
||
|
builtInType :builtInConsCastType
|
||
|
| "color" // aliased to an int in PDE
|
||
|
{ Preferences.getBoolean("preproc.color_datatype") }?
|
||
|
;
|
||
|
|
||
|
constructorCast! :t:consCastTypeSpec[true]
|
||
|
LPAREN!
|
||
|
e:expression
|
||
|
RPAREN!
|
||
|
// if this is a string literal, make sure the type we're trying to cast
|
||
|
// to is one of the supported ones
|
||
|
//
|
||
|
{ #e.getType() != STRING_LITERAL ||
|
||
|
( #t.getType() == LITERAL_byte ||
|
||
|
#t.getType() == LITERAL_double ||
|
||
|
#t.getType() == LITERAL_float ||
|
||
|
#t.getType() == LITERAL_int ||
|
||
|
#t.getType() == LITERAL_long ||
|
||
|
#t.getType() == LITERAL_short ) }?
|
||
|
// create the node
|
||
|
//
|
||
|
{#constructorCast = #(#[CONSTRUCTOR_CAST,"CONSTRUCTOR_CAST"], t, e);}
|
||
|
;
|
||
|
|
||
|
consCastTypeSpec[boolean addImagNode] :builtInConsCastTypeSpec[addImagNode]
|
||
|
// trying to remove String() cast [fry]
|
||
|
;
|
||
|
|
||
|
builtInConsCastTypeSpec[boolean addImagNode] :builtInConsCastType
|
||
|
{
|
||
|
if ( addImagNode ) {
|
||
|
#builtInConsCastTypeSpec = #(#[TYPE,"TYPE"],
|
||
|
#builtInConsCastTypeSpec);
|
||
|
}
|
||
|
}
|
||
|
;
|
||
|
|
||
|
colorMethodCall :c:"color" {#c.setType(IDENT);} // this would default to LITERAL_color
|
||
|
lp:LPAREN^ {#lp.setType(METHOD_CALL);}
|
||
|
argList
|
||
|
RPAREN!
|
||
|
;
|
||
|
|
||
|
primaryExpression :(consCastTypeSpec[false] LPAREN) => constructorCast
|
||
|
{ Preferences.getBoolean("preproc.enhanced_casting") }?
|
||
|
| identPrimary ( options {greedy=true;} : DOT^ "class" )?
|
||
|
| constant
|
||
|
| "true"
|
||
|
| "false"
|
||
|
| "null"
|
||
|
| newExpression
|
||
|
| "this"
|
||
|
| "super"
|
||
|
| LPAREN! assignmentExpression RPAREN!
|
||
|
| colorMethodCall
|
||
|
// look for int.class and int[].class
|
||
|
| builtInType
|
||
|
( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
|
||
|
DOT^ "class"
|
||
|
;
|
||
|
|
||
|
variableDefinitions![AST mods, AST t] :vd:variableDeclarator[getASTFactory().dupTree(mods),
|
||
|
getASTFactory().dupTree(t)]
|
||
|
{#variableDefinitions = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods,
|
||
|
t, vd);}
|
||
|
;
|
||
|
|
||
|
variableDeclarator[AST mods, AST t] :( id:IDENT (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
|
||
|
v:varInitializer (COMMA!)? )+
|
||
|
;
|
||
|
|
||
|
explicitConstructorInvocation! :t:"this" LPAREN a1:argList RPAREN SEMI
|
||
|
{#explicitConstructorInvocation = #(#[CTOR_CALL, "CTOR_CALL"],
|
||
|
#t, #a1);}
|
||
|
| s:"super" LPAREN a2:argList RPAREN SEMI
|
||
|
{#explicitConstructorInvocation = #(#[SUPER_CTOR_CALL,
|
||
|
"SUPER_CTOR_CALL"],
|
||
|
#s, #a2);}
|
||
|
;
|
||
|
|
||
|
classDefinition![AST modifiers] :"class" i:IDENT
|
||
|
// it _might_ have a superclass...
|
||
|
sc:superClassClause
|
||
|
// it might implement some interfaces...
|
||
|
ic:implementsClause
|
||
|
// now parse the body of the class
|
||
|
cb:classBlock
|
||
|
{#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
|
||
|
modifiers,i,sc,ic,cb);
|
||
|
PdePreprocessor.advClassName = i.getText();}
|
||
|
;
|
||
|
|
||
|
possiblyEmptyField :field
|
||
|
| s:SEMI {#s.setType(EMPTY_FIELD);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
compilationUnit :// A compilation unit starts with an optional package definition
|
||
|
( packageDefinition
|
||
|
| /* nothing */
|
||
|
)
|
||
|
|
||
|
// Next we have a series of zero or more import statements
|
||
|
( importDefinition )*
|
||
|
|
||
|
// Wrapping things up with any number of class or interface
|
||
|
// definitions
|
||
|
( typeDefinition )*
|
||
|
|
||
|
EOF!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
packageDefinition
|
||
|
options {
|
||
|
defaultErrorHandler= true;
|
||
|
}
|
||
|
:p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
importDefinition
|
||
|
options {
|
||
|
defaultErrorHandler= true;
|
||
|
}
|
||
|
:i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
typeDefinition
|
||
|
options {
|
||
|
defaultErrorHandler= true;
|
||
|
}
|
||
|
:m:modifiers!
|
||
|
( classDefinition[#m]
|
||
|
| interfaceDefinition[#m]
|
||
|
)
|
||
|
| SEMI!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
declaration! :m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
|
||
|
{#declaration = #v;}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
typeSpec[boolean addImagNode] :classTypeSpec[addImagNode]
|
||
|
| builtInTypeSpec[addImagNode]
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
classTypeSpec[boolean addImagNode] :identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
|
||
|
{
|
||
|
if ( addImagNode ) {
|
||
|
#classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
|
||
|
}
|
||
|
}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
builtInTypeSpec[boolean addImagNode] :builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
|
||
|
{
|
||
|
if ( addImagNode ) {
|
||
|
#builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
|
||
|
}
|
||
|
}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
type :identifier
|
||
|
| builtInType
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
identifier :IDENT ( DOT^ IDENT )*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
identifierStar :IDENT
|
||
|
( DOT^ IDENT )*
|
||
|
( DOT^ STAR )?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
modifiers :( modifier )*
|
||
|
{#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
modifier :"private"
|
||
|
| "public"
|
||
|
| "protected"
|
||
|
| "static"
|
||
|
| "transient"
|
||
|
| "final"
|
||
|
| "abstract"
|
||
|
| "native"
|
||
|
| "threadsafe"
|
||
|
| "synchronized"
|
||
|
// | "const" // reserved word, but not valid
|
||
|
| "volatile"
|
||
|
| "strictfp"
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
superClassClause! :( "extends" id:identifier )?
|
||
|
{#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
interfaceDefinition![AST modifiers] :"interface" IDENT
|
||
|
// it might extend some other interfaces
|
||
|
ie:interfaceExtends
|
||
|
// now parse the body of the interface (looks like a class...)
|
||
|
cb:classBlock
|
||
|
{#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
|
||
|
modifiers,IDENT,ie,cb);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
classBlock :LCURLY!
|
||
|
( field | SEMI! )*
|
||
|
RCURLY!
|
||
|
{#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
interfaceExtends :(
|
||
|
e:"extends"!
|
||
|
identifier ( COMMA! identifier )*
|
||
|
)?
|
||
|
{#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
|
||
|
#interfaceExtends);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
implementsClause :(
|
||
|
i:"implements"! identifier ( COMMA! identifier )*
|
||
|
)?
|
||
|
{#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
|
||
|
#implementsClause);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
field! :// method, constructor, or variable declaration
|
||
|
mods:modifiers
|
||
|
( h:ctorHead s:constructorBody // constructor
|
||
|
{#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);}
|
||
|
|
||
|
| cd:classDefinition[#mods] // inner class
|
||
|
{#field = #cd;}
|
||
|
|
||
|
| id:interfaceDefinition[#mods] // inner interface
|
||
|
{#field = #id;}
|
||
|
|
||
|
| t:typeSpec[false] // method or variable declaration(s)
|
||
|
( IDENT // the name of the method
|
||
|
|
||
|
// parse the formal parameter declarations.
|
||
|
LPAREN! param:parameterDeclarationList RPAREN!
|
||
|
|
||
|
rt:declaratorBrackets[#t]
|
||
|
|
||
|
// get the list of exceptions that this method is
|
||
|
// declared to throw
|
||
|
(tc:throwsClause)?
|
||
|
|
||
|
( s2:compoundStatement | SEMI )
|
||
|
{#field = #(#[METHOD_DEF,"METHOD_DEF"],
|
||
|
mods,
|
||
|
#(#[TYPE,"TYPE"],rt),
|
||
|
IDENT,
|
||
|
param,
|
||
|
tc,
|
||
|
s2);}
|
||
|
| v:variableDefinitions[#mods,#t] SEMI
|
||
|
// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);}
|
||
|
{#field = #v;}
|
||
|
)
|
||
|
)
|
||
|
|
||
|
// "static { ... }" class initializer
|
||
|
| "static" s3:compoundStatement
|
||
|
{#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);}
|
||
|
|
||
|
// "{ ... }" instance initializer
|
||
|
| s4:compoundStatement
|
||
|
{#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
constructorBody :lc:LCURLY^ {#lc.setType(SLIST);}
|
||
|
( options { greedy=true; } : explicitConstructorInvocation)?
|
||
|
(statement)*
|
||
|
RCURLY!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
declaratorBrackets[AST typ] :{#declaratorBrackets=typ;}
|
||
|
(lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
varInitializer :( ASSIGN^ initializer )?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
arrayInitializer :lc:LCURLY^ {#lc.setType(ARRAY_INIT);}
|
||
|
( initializer
|
||
|
(
|
||
|
// CONFLICT: does a COMMA after an initializer start a new
|
||
|
// initializer or start the option ',' at end?
|
||
|
// ANTLR generates proper code by matching
|
||
|
// the comma as soon as possible.
|
||
|
options {
|
||
|
warnWhenFollowAmbig = false;
|
||
|
}
|
||
|
:
|
||
|
COMMA! initializer
|
||
|
)*
|
||
|
(COMMA!)?
|
||
|
)?
|
||
|
RCURLY!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
initializer :expression
|
||
|
| arrayInitializer
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
ctorHead :IDENT // the name of the method
|
||
|
|
||
|
// parse the formal parameter declarations.
|
||
|
LPAREN! parameterDeclarationList RPAREN!
|
||
|
|
||
|
// get the list of exceptions that this method is declared to throw
|
||
|
(throwsClause)?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
throwsClause :"throws"^ identifier ( COMMA! identifier )*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
parameterDeclarationList :( parameterDeclaration ( COMMA! parameterDeclaration )* )?
|
||
|
{#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
|
||
|
#parameterDeclarationList);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
parameterDeclaration! :pm:parameterModifier t:typeSpec[false] id:IDENT
|
||
|
pd:declaratorBrackets[#t]
|
||
|
{#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
|
||
|
pm, #([TYPE,"TYPE"],pd), id);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
parameterModifier :(f:"final")?
|
||
|
{#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
compoundStatement :lc:LCURLY^ {#lc.setType(SLIST);}
|
||
|
// include the (possibly-empty) list of statements
|
||
|
(statement)*
|
||
|
RCURLY!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
statement :compoundStatement
|
||
|
|
||
|
// declarations are ambiguous with "ID DOT" relative to expression
|
||
|
// statements. Must backtrack to be sure. Could use a semantic
|
||
|
// predicate to test symbol table to see what the type was coming
|
||
|
// up, but that's pretty hard without a symbol table ;)
|
||
|
| (declaration)=> declaration SEMI!
|
||
|
|
||
|
// An expression statement. This could be a method call,
|
||
|
// assignment statement, or any other expression evaluated for
|
||
|
// side-effects.
|
||
|
| expression SEMI!
|
||
|
|
||
|
// class definition
|
||
|
| m:modifiers! classDefinition[#m]
|
||
|
|
||
|
// Attach a label to the front of a statement
|
||
|
| IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
|
||
|
|
||
|
// If-else statement
|
||
|
| "if"^ LPAREN! expression RPAREN! statement
|
||
|
(
|
||
|
// CONFLICT: the old "dangling-else" problem...
|
||
|
// ANTLR generates proper code matching
|
||
|
// as soon as possible. Hush warning.
|
||
|
options {
|
||
|
warnWhenFollowAmbig = false;
|
||
|
}
|
||
|
:
|
||
|
"else"! statement
|
||
|
)?
|
||
|
|
||
|
// For statement
|
||
|
| "for"^
|
||
|
LPAREN!
|
||
|
forInit SEMI! // initializer
|
||
|
forCond SEMI! // condition test
|
||
|
forIter // updater
|
||
|
RPAREN!
|
||
|
statement // statement to loop over
|
||
|
|
||
|
// While statement
|
||
|
| "while"^ LPAREN! expression RPAREN! statement
|
||
|
|
||
|
// do-while statement
|
||
|
| "do"^ statement "while"! LPAREN! expression RPAREN! SEMI!
|
||
|
|
||
|
// get out of a loop (or switch)
|
||
|
| "break"^ (IDENT)? SEMI!
|
||
|
|
||
|
// do next iteration of a loop
|
||
|
| "continue"^ (IDENT)? SEMI!
|
||
|
|
||
|
// Return an expression
|
||
|
| "return"^ (expression)? SEMI!
|
||
|
|
||
|
// switch/case statement
|
||
|
| "switch"^ LPAREN! expression RPAREN! LCURLY!
|
||
|
( casesGroup )*
|
||
|
RCURLY!
|
||
|
|
||
|
// exception try-catch block
|
||
|
| tryBlock
|
||
|
|
||
|
// throw an exception
|
||
|
| "throw"^ expression SEMI!
|
||
|
|
||
|
// synchronize a statement
|
||
|
| "synchronized"^ LPAREN! expression RPAREN! compoundStatement
|
||
|
|
||
|
// asserts (uncomment if you want 1.4 compatibility)
|
||
|
| "assert"^ expression ( COLON! expression )? SEMI!
|
||
|
|
||
|
// empty statement
|
||
|
| s:SEMI {#s.setType(EMPTY_STAT);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
casesGroup :( // CONFLICT: to which case group do the statements bind?
|
||
|
// ANTLR generates proper code: it groups the
|
||
|
// many "case"/"default" labels together then
|
||
|
// follows them with the statements
|
||
|
options {
|
||
|
greedy = true;
|
||
|
}
|
||
|
:
|
||
|
aCase
|
||
|
)+
|
||
|
caseSList
|
||
|
{#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
aCase :("case"^ expression | "default") COLON!
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
caseSList :(statement)*
|
||
|
{#caseSList = #(#[SLIST,"SLIST"],#caseSList);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
forInit :( (declaration)=> declaration
|
||
|
// otherwise it could be an expression list...
|
||
|
| expressionList
|
||
|
)?
|
||
|
{#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
forCond :(expression)?
|
||
|
{#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
forIter :(expressionList)?
|
||
|
{#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
tryBlock :"try"^ compoundStatement
|
||
|
(handler)*
|
||
|
( finallyClause )?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
finallyClause :"finally"^ compoundStatement
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
handler :"catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
expression :assignmentExpression
|
||
|
{#expression = #(#[EXPR,"EXPR"],#expression);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
expressionList :expression (COMMA! expression)*
|
||
|
{#expressionList = #(#[ELIST,"ELIST"], expressionList);}
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
assignmentExpression :conditionalExpression
|
||
|
( ( ASSIGN^
|
||
|
| PLUS_ASSIGN^
|
||
|
| MINUS_ASSIGN^
|
||
|
| STAR_ASSIGN^
|
||
|
| DIV_ASSIGN^
|
||
|
| MOD_ASSIGN^
|
||
|
| SR_ASSIGN^
|
||
|
| BSR_ASSIGN^
|
||
|
| SL_ASSIGN^
|
||
|
| BAND_ASSIGN^
|
||
|
| BXOR_ASSIGN^
|
||
|
| BOR_ASSIGN^
|
||
|
)
|
||
|
assignmentExpression
|
||
|
)?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
conditionalExpression :logicalOrExpression
|
||
|
( QUESTION^ assignmentExpression COLON! conditionalExpression )?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
logicalOrExpression :logicalAndExpression (LOR^ logicalAndExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
logicalAndExpression :inclusiveOrExpression (LAND^ inclusiveOrExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
inclusiveOrExpression :exclusiveOrExpression (BOR^ exclusiveOrExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
exclusiveOrExpression :andExpression (BXOR^ andExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
andExpression :equalityExpression (BAND^ equalityExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
equalityExpression :relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
relationalExpression :shiftExpression
|
||
|
( ( ( LT^
|
||
|
| GT^
|
||
|
| LE^
|
||
|
| GE^
|
||
|
)
|
||
|
shiftExpression
|
||
|
)*
|
||
|
| "instanceof"^ typeSpec[true]
|
||
|
)
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
shiftExpression :additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
additiveExpression :multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
multiplicativeExpression :unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
unaryExpression :INC^ unaryExpression
|
||
|
| DEC^ unaryExpression
|
||
|
| MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
|
||
|
| PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
|
||
|
| unaryExpressionNotPlusMinus
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
unaryExpressionNotPlusMinus :BNOT^ unaryExpression
|
||
|
| LNOT^ unaryExpression
|
||
|
|
||
|
| ( // subrule allows option to shut off warnings
|
||
|
options {
|
||
|
// "(int" ambig with postfixExpr due to lack of sequence
|
||
|
// info in linear approximate LL(k). It's ok. Shut up.
|
||
|
generateAmbigWarnings=false;
|
||
|
}
|
||
|
: // If typecast is built in type, must be numeric operand
|
||
|
// Also, no reason to backtrack if type keyword like int, float...
|
||
|
lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN!
|
||
|
unaryExpression
|
||
|
|
||
|
// Have to backtrack to see if operator follows. If no operator
|
||
|
// follows, it's a typecast. No semantic checking needed to parse.
|
||
|
// if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)"
|
||
|
| (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
|
||
|
lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN!
|
||
|
unaryExpressionNotPlusMinus
|
||
|
|
||
|
| postfixExpression
|
||
|
)
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
postfixExpression :/*
|
||
|
"this"! lp1:LPAREN^ argList RPAREN!
|
||
|
{#lp1.setType(CTOR_CALL);}
|
||
|
|
||
|
| "super"! lp2:LPAREN^ argList RPAREN!
|
||
|
{#lp2.setType(SUPER_CTOR_CALL);}
|
||
|
|
|
||
|
*/
|
||
|
primaryExpression
|
||
|
|
||
|
(
|
||
|
/*
|
||
|
options {
|
||
|
// the use of postfixExpression in SUPER_CTOR_CALL adds DOT
|
||
|
// to the lookahead set, and gives loads of false non-det
|
||
|
// warnings.
|
||
|
// shut them off.
|
||
|
generateAmbigWarnings=false;
|
||
|
}
|
||
|
: */
|
||
|
DOT^ IDENT
|
||
|
( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
|
||
|
argList
|
||
|
RPAREN!
|
||
|
)?
|
||
|
| DOT^ "this"
|
||
|
|
||
|
| DOT^ "super"
|
||
|
( // (new Outer()).super() (create enclosing instance)
|
||
|
lp3:LPAREN^ argList RPAREN!
|
||
|
{#lp3.setType(SUPER_CTOR_CALL);}
|
||
|
| DOT^ IDENT
|
||
|
( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
|
||
|
argList
|
||
|
RPAREN!
|
||
|
)?
|
||
|
)
|
||
|
| DOT^ newExpression
|
||
|
| lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK!
|
||
|
)*
|
||
|
|
||
|
( // possibly add on a post-increment or post-decrement.
|
||
|
// allows INC/DEC on too much, but semantics can check
|
||
|
in:INC^ {#in.setType(POST_INC);}
|
||
|
| de:DEC^ {#de.setType(POST_DEC);}
|
||
|
)?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
identPrimary :IDENT
|
||
|
(
|
||
|
options {
|
||
|
// .ident could match here or in postfixExpression.
|
||
|
// We do want to match here. Turn off warning.
|
||
|
greedy=true;
|
||
|
}
|
||
|
: DOT^ IDENT
|
||
|
)*
|
||
|
(
|
||
|
options {
|
||
|
// ARRAY_DECLARATOR here conflicts with INDEX_OP in
|
||
|
// postfixExpression on LBRACK RBRACK.
|
||
|
// We want to match [] here, so greedy. This overcomes
|
||
|
// limitation of linear approximate lookahead.
|
||
|
greedy=true;
|
||
|
}
|
||
|
: ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! )
|
||
|
| ( options {greedy=true;} :
|
||
|
lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK!
|
||
|
)+
|
||
|
)?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
newExpression :"new"^ type
|
||
|
( LPAREN! argList RPAREN! (classBlock)?
|
||
|
|
||
|
//java 1.1
|
||
|
// Note: This will allow bad constructs like
|
||
|
// new int[4][][3] {exp,exp}.
|
||
|
// There needs to be a semantic check here...
|
||
|
// to make sure:
|
||
|
// a) [ expr ] and [ ] are not mixed
|
||
|
// b) [ expr ] and an init are not used together
|
||
|
|
||
|
| newArrayDeclarator (arrayInitializer)?
|
||
|
)
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
argList :( expressionList
|
||
|
| /*nothing*/
|
||
|
{#argList = #[ELIST,"ELIST"];}
|
||
|
)
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaRecognizer
|
||
|
newArrayDeclarator :(
|
||
|
// CONFLICT:
|
||
|
// newExpression is a primaryExpression which can be
|
||
|
// followed by an array index reference. This is ok,
|
||
|
// as the generated code will stay in this loop as
|
||
|
// long as it sees an LBRACK (proper behavior)
|
||
|
options {
|
||
|
warnWhenFollowAmbig = false;
|
||
|
}
|
||
|
:
|
||
|
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
|
||
|
(expression)?
|
||
|
RBRACK!
|
||
|
)+
|
||
|
;
|
||
|
|
||
|
class PdeLexer extends Lexer;
|
||
|
|
||
|
options {
|
||
|
importVocab=PdePartial;
|
||
|
exportVocab=Pde;
|
||
|
testLiterals=false;
|
||
|
k=4;
|
||
|
charVocabulary='\u0003'..'\uFFFF';
|
||
|
codeGenBitsetTestThreshold=20;
|
||
|
}
|
||
|
|
||
|
WS :( ' '
|
||
|
| '\t'
|
||
|
| '\f'
|
||
|
// handle newlines
|
||
|
| ( options {generateAmbigWarnings=false;}
|
||
|
: "\r\n" // Evil DOS
|
||
|
| '\r' // Macintosh
|
||
|
| '\n' // Unix (the right way)
|
||
|
)
|
||
|
{ newline(); }
|
||
|
)+
|
||
|
;
|
||
|
|
||
|
SL_COMMENT :"//"
|
||
|
(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
|
||
|
{newline();}
|
||
|
;
|
||
|
|
||
|
ML_COMMENT :"/*"
|
||
|
( /* '\r' '\n' can be matched in one alternative or by matching
|
||
|
'\r' in one iteration and '\n' in another. I am trying to
|
||
|
handle any flavor of newline that comes in, but the language
|
||
|
that allows both "\r\n" and "\r" and "\n" to all be valid
|
||
|
newline is ambiguous. Consequently, the resulting grammar
|
||
|
must be ambiguous. I'm shutting this warning off.
|
||
|
*/
|
||
|
options {
|
||
|
generateAmbigWarnings=false;
|
||
|
}
|
||
|
:
|
||
|
{ LA(2)!='/' }? '*'
|
||
|
| '\r' '\n' {newline();}
|
||
|
| '\r' {newline();}
|
||
|
| '\n' {newline();}
|
||
|
| ~('*'|'\n'|'\r')
|
||
|
)*
|
||
|
"*/"
|
||
|
;
|
||
|
|
||
|
WEBCOLOR_LITERAL :'#'! (HEX_DIGIT)+
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
QUESTION :'?' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LPAREN :'(' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
RPAREN :')' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LBRACK :'[' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
RBRACK :']' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LCURLY :'{' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
RCURLY :'}' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
COLON :':' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
COMMA :',' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
ASSIGN :'=' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
EQUAL :"==" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LNOT :'!' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BNOT :'~' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
NOT_EQUAL :"!=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
DIV :'/' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
DIV_ASSIGN :"/=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
PLUS :'+' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
PLUS_ASSIGN :"+=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
INC :"++" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
MINUS :'-' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
MINUS_ASSIGN :"-=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
DEC :"--" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
STAR :'*' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
STAR_ASSIGN :"*=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
MOD :'%' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
MOD_ASSIGN :"%=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
SR :">>" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
SR_ASSIGN :">>=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BSR :">>>" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BSR_ASSIGN :">>>=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
GE :">=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
GT :">" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
SL :"<<" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
SL_ASSIGN :"<<=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LE :"<=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LT :'<' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BXOR :'^' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BXOR_ASSIGN :"^=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BOR :'|' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BOR_ASSIGN :"|=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LOR :"||" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BAND :'&' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
BAND_ASSIGN :"&=" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
LAND :"&&" ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
SEMI :';' ;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
CHAR_LITERAL :'\'' ( ESC | ~'\'' ) '\''
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
STRING_LITERAL :'"' (ESC|~('"'|'\\'))* '"'
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
protected ESC :'\\'
|
||
|
( 'n'
|
||
|
| 'r'
|
||
|
| 't'
|
||
|
| 'b'
|
||
|
| 'f'
|
||
|
| '"'
|
||
|
| '\''
|
||
|
| '\\'
|
||
|
| ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
||
|
| '0'..'3'
|
||
|
(
|
||
|
options {
|
||
|
warnWhenFollowAmbig = false;
|
||
|
}
|
||
|
: '0'..'7'
|
||
|
(
|
||
|
options {
|
||
|
warnWhenFollowAmbig = false;
|
||
|
}
|
||
|
: '0'..'7'
|
||
|
)?
|
||
|
)?
|
||
|
| '4'..'7'
|
||
|
(
|
||
|
options {
|
||
|
warnWhenFollowAmbig = false;
|
||
|
}
|
||
|
: '0'..'7'
|
||
|
)?
|
||
|
)
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
protected HEX_DIGIT :('0'..'9'|'A'..'F'|'a'..'f')
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
protected VOCAB :'\3'..'\377'
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
IDENT
|
||
|
options {
|
||
|
testLiterals=true;
|
||
|
}
|
||
|
:('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
NUM_INT {boolean isDecimal=false; Token t=null;}
|
||
|
:'.' {_ttype = DOT;}
|
||
|
( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
|
||
|
{
|
||
|
if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
|
||
|
_ttype = NUM_FLOAT;
|
||
|
}
|
||
|
else {
|
||
|
_ttype = NUM_DOUBLE; // assume double
|
||
|
}
|
||
|
}
|
||
|
)?
|
||
|
|
||
|
| ( '0' {isDecimal = true;} // special case for just '0'
|
||
|
( ('x'|'X')
|
||
|
( // hex
|
||
|
// the 'e'|'E' and float suffix stuff look
|
||
|
// like hex digits, hence the (...)+ doesn't
|
||
|
// know when to stop: ambig. ANTLR resolves
|
||
|
// it correctly by matching immediately. It
|
||
|
// is therefor ok to hush warning.
|
||
|
options {
|
||
|
warnWhenFollowAmbig=false;
|
||
|
}
|
||
|
: HEX_DIGIT
|
||
|
)+
|
||
|
| ('0'..'7')+ // octal
|
||
|
)?
|
||
|
| ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
|
||
|
)
|
||
|
( ('l'|'L') { _ttype = NUM_LONG; }
|
||
|
|
||
|
// only check to see if it's a float if looks like decimal so far
|
||
|
| {isDecimal}?
|
||
|
( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
|
||
|
| EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
|
||
|
| f4:FLOAT_SUFFIX {t=f4;}
|
||
|
)
|
||
|
{
|
||
|
if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
|
||
|
_ttype = NUM_FLOAT;
|
||
|
}
|
||
|
else {
|
||
|
_ttype = NUM_DOUBLE; // assume double
|
||
|
}
|
||
|
}
|
||
|
)?
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
protected EXPONENT :('e'|'E') ('+'|'-')? ('0'..'9')+
|
||
|
;
|
||
|
|
||
|
// inherited from grammar JavaLexer
|
||
|
protected FLOAT_SUFFIX :'f'|'F'|'d'|'D'
|
||
|
;
|
||
|
|
||
|
|