mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-02 13:24:12 +01:00
1336 lines
42 KiB
Plaintext
1336 lines
42 KiB
Plaintext
header {
|
|
package processing.app.preproc;
|
|
|
|
import java.io.*;
|
|
|
|
import antlr.CommonAST;
|
|
import antlr.DumpASTVisitor;
|
|
}
|
|
class WParser extends Parser;
|
|
|
|
options {
|
|
k= 2;
|
|
exportVocab= W;
|
|
buildAST= true;
|
|
ASTLabelType= "TNode";
|
|
defaultErrorHandler= false;
|
|
codeGenMakeSwitchThreshold= 2;
|
|
codeGenBitsetTestThreshold= 3;
|
|
importVocab=STDC;
|
|
}
|
|
|
|
{
|
|
// Suppport C++-style single-line comments?
|
|
public static boolean CPPComments = true;
|
|
|
|
// access to symbol table
|
|
public CSymbolTable symbolTable = new CSymbolTable();
|
|
|
|
// source for names to unnamed scopes
|
|
protected int unnamedScopeCounter = 0;
|
|
|
|
public boolean isTypedefName(String name) {
|
|
boolean returnValue = false;
|
|
TNode node = symbolTable.lookupNameInCurrentScope(name);
|
|
for (; node != null; node = (TNode) node.getNextSibling() ) {
|
|
if(node.getType() == LITERAL_typedef) {
|
|
returnValue = true;
|
|
break;
|
|
}
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
public String getAScopeName() {
|
|
return "" + (unnamedScopeCounter++);
|
|
}
|
|
|
|
public void pushScope(String scopeName) {
|
|
symbolTable.pushScope(scopeName);
|
|
}
|
|
|
|
public void popScope() {
|
|
symbolTable.popScope();
|
|
}
|
|
|
|
int traceDepth = 0;
|
|
public void reportError(RecognitionException ex) {
|
|
try {
|
|
System.err.println("ANTLR Parsing Error: "+ex + " token name:" + tokenNames[LA(1)]);
|
|
ex.printStackTrace(System.err);
|
|
}
|
|
catch (TokenStreamException e) {
|
|
System.err.println("ANTLR Parsing Error: "+ex);
|
|
ex.printStackTrace(System.err);
|
|
}
|
|
}
|
|
public void reportError(String s) {
|
|
System.err.println("ANTLR Parsing Error from String: " + s);
|
|
}
|
|
public void reportWarning(String s) {
|
|
System.err.println("ANTLR Parsing Warning from String: " + s);
|
|
}
|
|
public void match(int t) throws MismatchedTokenException {
|
|
boolean debugging = false;
|
|
|
|
if ( debugging ) {
|
|
for (int x=0; x<traceDepth; x++) System.out.print(" ");
|
|
try {
|
|
System.out.println("Match("+tokenNames[t]+") with LA(1)="+
|
|
tokenNames[LA(1)] + ((inputState.guessing>0)?" [inputState.guessing "+ inputState.guessing + "]":""));
|
|
}
|
|
catch (TokenStreamException e) {
|
|
System.out.println("Match("+tokenNames[t]+") " + ((inputState.guessing>0)?" [inputState.guessing "+ inputState.guessing + "]":""));
|
|
|
|
}
|
|
|
|
}
|
|
try {
|
|
if ( LA(1)!=t ) {
|
|
if ( debugging ){
|
|
for (int x=0; x<traceDepth; x++) System.out.print(" ");
|
|
System.out.println("token mismatch: "+tokenNames[LA(1)]
|
|
+ "!="+tokenNames[t]);
|
|
}
|
|
throw new MismatchedTokenException(tokenNames, LT(1), t, false, getFilename());
|
|
|
|
} else {
|
|
// mark token as consumed -- fetch next token deferred until LA/LT
|
|
consume();
|
|
}
|
|
}
|
|
catch (TokenStreamException e) {
|
|
}
|
|
|
|
}
|
|
public void traceIn(String rname) {
|
|
traceDepth += 1;
|
|
for (int x=0; x<traceDepth; x++) System.out.print(" ");
|
|
try {
|
|
System.out.println("> "+rname+"; LA(1)==("+ tokenNames[LT(1).getType()]
|
|
+ ") " + LT(1).getText() + " [inputState.guessing "+ inputState.guessing + "]");
|
|
}
|
|
catch (TokenStreamException e) {
|
|
}
|
|
}
|
|
public void traceOut(String rname) {
|
|
for (int x=0; x<traceDepth; x++) System.out.print(" ");
|
|
try {
|
|
System.out.println("< "+rname+"; LA(1)==("+ tokenNames[LT(1).getType()]
|
|
+ ") "+LT(1).getText() + " [inputState.guessing "+ inputState.guessing + "]");
|
|
}
|
|
catch (TokenStreamException e) {
|
|
}
|
|
traceDepth -= 1;
|
|
}
|
|
|
|
}
|
|
translationUnit :( externalList )? /* Empty source files are allowed. */
|
|
;
|
|
|
|
asm_expr :"asm"^
|
|
("volatile")? LCURLY expr RCURLY ( SEMI )+
|
|
;
|
|
|
|
idList :ID ( options{warnWhenFollowAmbig=false;}: COMMA ID )*
|
|
;
|
|
|
|
externalDef :( "typedef" | declaration )=> declaration
|
|
| ( functionPrefix )=> functionDef
|
|
| typelessDeclaration
|
|
| asm_expr
|
|
| SEMI
|
|
;
|
|
|
|
functionPrefix { String declName; }
|
|
:( (functionDeclSpecifiers)=> ds:functionDeclSpecifiers
|
|
| //epsilon
|
|
)
|
|
declName = d:declarator[true]
|
|
( declaration )* (VARARGS)? ( SEMI )*
|
|
LCURLY
|
|
;
|
|
|
|
typelessDeclaration { AST typeMissing = #[NTypeMissing]; }
|
|
:initDeclList[typeMissing] SEMI { ## = #( #[NTypeMissing], ##); }
|
|
;
|
|
|
|
initializer :( ( ( (initializerElementLabel)=> initializerElementLabel )?
|
|
( assignExpr | lcurlyInitializer ) { ## = #( #[NInitializer], ## ); }
|
|
)
|
|
| lcurlyInitializer
|
|
)
|
|
;
|
|
|
|
initializerElementLabel :( ( LBRACKET ((constExpr VARARGS)=> rangeExpr | constExpr) RBRACKET (ASSIGN)? )
|
|
| ID COLON
|
|
| DOT ID ASSIGN
|
|
)
|
|
{ ## = #( #[NInitializerElementLabel], ##) ; }
|
|
;
|
|
|
|
lcurlyInitializer :LCURLY^ (initializerList ( COMMA! )? )? RCURLY
|
|
{ ##.setType( NLcurlyInitializer ); }
|
|
;
|
|
|
|
initializerList :initializer ( options{warnWhenFollowAmbig=false;}:COMMA! initializer )*
|
|
;
|
|
|
|
declarator[boolean isFunctionDefinition] returns [String declName]{ declName = ""; }
|
|
:( pointerGroup )?
|
|
|
|
( id:ID { declName = id.getText(); }
|
|
| LPAREN declName = declarator[false] RPAREN
|
|
)
|
|
|
|
( declaratorParamaterList[isFunctionDefinition, declName]
|
|
| LBRACKET ( expr )? RBRACKET
|
|
)*
|
|
{ ## = #( #[NDeclarator], ## ); }
|
|
;
|
|
|
|
declaratorParamaterList[boolean isFunctionDefinition, String declName] :LPAREN^
|
|
{
|
|
if (isFunctionDefinition) {
|
|
pushScope(declName);
|
|
}
|
|
else {
|
|
pushScope("!"+declName);
|
|
}
|
|
}
|
|
(
|
|
(declSpecifiers)=> parameterTypeList
|
|
| (idList)?
|
|
)
|
|
{
|
|
popScope();
|
|
}
|
|
( COMMA! )?
|
|
RPAREN
|
|
{ ##.setType(NParameterTypeList); }
|
|
;
|
|
|
|
parameterTypeList :parameterDeclaration
|
|
( options {
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
( COMMA | SEMI )
|
|
parameterDeclaration
|
|
)*
|
|
( ( COMMA | SEMI )
|
|
VARARGS
|
|
)?
|
|
;
|
|
|
|
declarationList :( options { // this loop properly aborts when
|
|
// it finds a non-typedefName ID MBZ
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
|
|
localLabelDeclaration
|
|
| ( declarationPredictor )=> declaration
|
|
)+
|
|
;
|
|
|
|
localLabelDeclaration :( //GNU note: any __label__ declarations must come before regular declarations.
|
|
"__label__"^ ID (options{warnWhenFollowAmbig=false;}: COMMA! ID)* ( COMMA! )? ( SEMI! )+
|
|
)
|
|
;
|
|
|
|
declaration { AST ds1 = null; }
|
|
:ds:declSpecifiers { ds1 = astFactory.dupList(#ds); }
|
|
(
|
|
initDeclList[ds1]
|
|
)?
|
|
( SEMI )+
|
|
{ ## = #( #[NDeclaration], ##); }
|
|
|
|
;
|
|
|
|
functionStorageClassSpecifier :"extern"
|
|
| "static"
|
|
| "inline"
|
|
;
|
|
|
|
typeSpecifier[int specCount] returns [int retSpecCount]{ retSpecCount = specCount + 1; }
|
|
:( "void"
|
|
| "char"
|
|
| "short"
|
|
| "int"
|
|
| "long"
|
|
| "float"
|
|
| "double"
|
|
| "signed"
|
|
| "unsigned"
|
|
| "byte"
|
|
| "boolean"
|
|
| "Servo"
|
|
| "Wire"
|
|
| structOrUnionSpecifier ( options{warnWhenFollowAmbig=false;}: attributeDecl )*
|
|
| enumSpecifier
|
|
| { specCount==0 }? typedefName
|
|
| "typeof"^ LPAREN
|
|
( ( typeName )=> typeName
|
|
| expr
|
|
)
|
|
RPAREN
|
|
| "__complex"
|
|
)
|
|
;
|
|
|
|
structOrUnionSpecifier { String scopeName; }
|
|
:sou:structOrUnion!
|
|
( ( ID LCURLY )=> i:ID l:LCURLY
|
|
{
|
|
scopeName = #sou.getText() + " " + #i.getText();
|
|
#l.setText(scopeName);
|
|
pushScope(scopeName);
|
|
}
|
|
( structDeclarationList )?
|
|
{ popScope();}
|
|
RCURLY
|
|
| l1:LCURLY
|
|
{
|
|
scopeName = getAScopeName();
|
|
#l1.setText(scopeName);
|
|
pushScope(scopeName);
|
|
}
|
|
( structDeclarationList )?
|
|
{ popScope(); }
|
|
RCURLY
|
|
| ID
|
|
)
|
|
{
|
|
## = #( #sou, ## );
|
|
}
|
|
;
|
|
|
|
structDeclaration :specifierQualifierList structDeclaratorList ( COMMA! )? ( SEMI! )+
|
|
;
|
|
|
|
structDeclaratorList :structDeclarator ( options{warnWhenFollowAmbig=false;}: COMMA! structDeclarator )*
|
|
;
|
|
|
|
structDeclarator :( declarator[false] )?
|
|
( COLON constExpr )?
|
|
( attributeDecl )*
|
|
{ ## = #( #[NStructDeclarator], ##); }
|
|
;
|
|
|
|
enumSpecifier :"enum"^
|
|
( ( ID LCURLY )=> i:ID LCURLY enumList[i.getText()] RCURLY
|
|
| LCURLY enumList["anonymous"] RCURLY
|
|
| ID
|
|
)
|
|
;
|
|
|
|
enumList[String enumName] :enumerator[enumName] ( options{warnWhenFollowAmbig=false;}: COMMA! enumerator[enumName] )* ( COMMA! )?
|
|
;
|
|
|
|
initDeclList[AST declarationSpecifiers] :initDecl[declarationSpecifiers]
|
|
( options{warnWhenFollowAmbig=false;}: COMMA! initDecl[declarationSpecifiers] )*
|
|
( COMMA! )?
|
|
;
|
|
|
|
initDecl[AST declarationSpecifiers] { String declName = ""; }
|
|
:declName = d:declarator[false]
|
|
{ AST ds1, d1;
|
|
ds1 = astFactory.dupList(declarationSpecifiers);
|
|
d1 = astFactory.dupList(#d);
|
|
symbolTable.add(declName, #(null, ds1, d1) );
|
|
}
|
|
( attributeDecl )*
|
|
( ASSIGN initializer
|
|
| COLON expr
|
|
)?
|
|
{ ## = #( #[NInitDecl], ## ); }
|
|
;
|
|
|
|
attributeDecl :"__attribute"^ LPAREN LPAREN attributeList RPAREN RPAREN
|
|
| "asm"^ LPAREN stringConst RPAREN { ##.setType( NAsmAttribute ); }
|
|
;
|
|
|
|
attributeList :attribute ( options{warnWhenFollowAmbig=false;}: COMMA attribute)* ( COMMA )?
|
|
;
|
|
|
|
attribute :( ~(LPAREN | RPAREN | COMMA)
|
|
| LPAREN attributeList RPAREN
|
|
)*
|
|
;
|
|
|
|
compoundStatement[String scopeName] :LCURLY^
|
|
|
|
{
|
|
pushScope(scopeName);
|
|
}
|
|
( //this ambiguity is ok, declarationList and nestedFunctionDef end properly
|
|
options {
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
( "typedef" | "__label__" | declaration )=> declarationList
|
|
| (nestedFunctionDef)=> nestedFunctionDef
|
|
)*
|
|
( statementList )?
|
|
{ popScope(); }
|
|
RCURLY
|
|
{ ##.setType( NCompoundStatement ); ##.setAttribute( "scopeName", scopeName ); }
|
|
;
|
|
|
|
nestedFunctionDef { String declName; }
|
|
:( "auto" )? //only for nested functions
|
|
( (functionDeclSpecifiers)=> ds:functionDeclSpecifiers
|
|
)?
|
|
declName = d:declarator[false]
|
|
{
|
|
AST d2, ds2;
|
|
d2 = astFactory.dupList(#d);
|
|
ds2 = astFactory.dupList(#ds);
|
|
symbolTable.add(declName, #(null, ds2, d2));
|
|
pushScope(declName);
|
|
}
|
|
( declaration )*
|
|
{ popScope(); }
|
|
compoundStatement[declName]
|
|
{ ## = #( #[NFunctionDef], ## );}
|
|
;
|
|
|
|
statement :SEMI // Empty statements
|
|
|
|
| compoundStatement[getAScopeName()] // Group of statements
|
|
|
|
| expr SEMI! { ## = #( #[NStatementExpr], ## );} // Expressions
|
|
|
|
// Iteration statements:
|
|
|
|
| "while"^ LPAREN! expr RPAREN! statement
|
|
| "do"^ statement "while"! LPAREN! expr RPAREN! SEMI!
|
|
|! "for"
|
|
LPAREN ( e1:expr )? SEMI ( e2:expr )? SEMI ( e3:expr )? RPAREN
|
|
s:statement
|
|
{
|
|
if ( #e1 == null) { #e1 = #[ NEmptyExpression ]; }
|
|
if ( #e2 == null) { #e2 = #[ NEmptyExpression ]; }
|
|
if ( #e3 == null) { #e3 = #[ NEmptyExpression ]; }
|
|
## = #( #[LITERAL_for, "for"], #e1, #e2, #e3, #s );
|
|
}
|
|
|
|
|
|
// Jump statements:
|
|
|
|
| "goto"^ expr SEMI!
|
|
| "continue" SEMI!
|
|
| "break" SEMI!
|
|
| "return"^ ( expr )? SEMI!
|
|
|
|
|
|
| ID COLON! (options {warnWhenFollowAmbig=false;}: statement)? { ## = #( #[NLabel], ## ); }
|
|
// GNU allows range expressions in case statements
|
|
| "case"^ ((constExpr VARARGS)=> rangeExpr | constExpr) COLON! ( options{warnWhenFollowAmbig=false;}:statement )?
|
|
| "default"^ COLON! ( options{warnWhenFollowAmbig=false;}: statement )?
|
|
|
|
// Selection statements:
|
|
|
|
| "if"^
|
|
LPAREN! expr RPAREN! statement
|
|
( //standard if-else ambiguity
|
|
options {
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
"else" statement )?
|
|
| "switch"^ LPAREN! expr RPAREN! statement
|
|
;
|
|
|
|
conditionalExpr :logicalOrExpr
|
|
( QUESTION^ (expr)? COLON conditionalExpr )?
|
|
;
|
|
|
|
rangeExpr :constExpr VARARGS constExpr
|
|
{ ## = #(#[NRangeExpr], ##); }
|
|
;
|
|
|
|
castExpr :( LPAREN typeName RPAREN )=>
|
|
LPAREN^ typeName RPAREN ( castExpr | lcurlyInitializer )
|
|
{ ##.setType(NCast); }
|
|
|
|
| unaryExpr
|
|
;
|
|
|
|
nonemptyAbstractDeclarator :(
|
|
pointerGroup
|
|
( (LPAREN
|
|
( nonemptyAbstractDeclarator
|
|
| parameterTypeList
|
|
)?
|
|
( COMMA! )?
|
|
RPAREN)
|
|
| (LBRACKET (expr)? RBRACKET)
|
|
)*
|
|
|
|
| ( (LPAREN
|
|
( nonemptyAbstractDeclarator
|
|
| parameterTypeList
|
|
)?
|
|
( COMMA! )?
|
|
RPAREN)
|
|
| (LBRACKET (expr)? RBRACKET)
|
|
)+
|
|
)
|
|
{ ## = #( #[NNonemptyAbstractDeclarator], ## ); }
|
|
|
|
;
|
|
|
|
unaryExpr :postfixExpr
|
|
| INC^ castExpr
|
|
| DEC^ castExpr
|
|
| u:unaryOperator castExpr { ## = #( #[NUnaryExpr], ## ); }
|
|
|
|
| "sizeof"^
|
|
( ( LPAREN typeName )=> LPAREN typeName RPAREN
|
|
| unaryExpr
|
|
)
|
|
| "__alignof"^
|
|
( ( LPAREN typeName )=> LPAREN typeName RPAREN
|
|
| unaryExpr
|
|
)
|
|
| gnuAsmExpr
|
|
;
|
|
|
|
unaryOperator :BAND
|
|
| STAR
|
|
| PLUS
|
|
| MINUS
|
|
| BNOT //also stands for complex conjugation
|
|
| LNOT
|
|
| LAND //for label dereference (&&label)
|
|
| "__real"
|
|
| "__imag"
|
|
;
|
|
|
|
gnuAsmExpr :"asm"^ ("volatile")?
|
|
LPAREN stringConst
|
|
( options { warnWhenFollowAmbig = false; }:
|
|
COLON (strOptExprPair ( COMMA strOptExprPair)* )?
|
|
( options { warnWhenFollowAmbig = false; }:
|
|
COLON (strOptExprPair ( COMMA strOptExprPair)* )?
|
|
)?
|
|
)?
|
|
( COLON stringConst ( COMMA stringConst)* )?
|
|
RPAREN
|
|
{ ##.setType(NGnuAsmExpr); }
|
|
;
|
|
|
|
strOptExprPair :stringConst ( LPAREN expr RPAREN )?
|
|
;
|
|
|
|
primaryExpr :ID
|
|
| Number
|
|
| charConst
|
|
| stringConst
|
|
// JTC:
|
|
// ID should catch the enumerator
|
|
// leaving it in gives ambiguous err
|
|
// | enumerator
|
|
| (LPAREN LCURLY) => LPAREN^ compoundStatement[getAScopeName()] RPAREN
|
|
| LPAREN^ expr RPAREN { ##.setType(NExpressionGroup); }
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
externalList :( externalDef )+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
declSpecifiers { int specCount=0; }
|
|
:( options { // this loop properly aborts when
|
|
// it finds a non-typedefName ID MBZ
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
s:storageClassSpecifier
|
|
| typeQualifier
|
|
| ( "struct" | "union" | "enum" | typeSpecifier[specCount] )=>
|
|
specCount = typeSpecifier[specCount]
|
|
)+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
storageClassSpecifier :"auto"
|
|
| "register"
|
|
| "typedef"
|
|
| functionStorageClassSpecifier
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
typeQualifier :"const"
|
|
| "volatile"
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
typedefName :{ isTypedefName ( LT(1).getText() ) }?
|
|
i:ID { ## = #(#[NTypedefName], #i); }
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
structOrUnion :"struct"
|
|
| "union"
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
structDeclarationList :( structDeclaration )+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
specifierQualifierList { int specCount = 0; }
|
|
:( options { // this loop properly aborts when
|
|
// it finds a non-typedefName ID MBZ
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
( "struct" | "union" | "enum" | typeSpecifier[specCount] )=>
|
|
specCount = typeSpecifier[specCount]
|
|
| typeQualifier
|
|
)+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
enumerator[String enumName] :i:ID { symbolTable.add( i.getText(),
|
|
#( null,
|
|
#[LITERAL_enum, "enum"],
|
|
#[ ID, enumName]
|
|
)
|
|
);
|
|
}
|
|
(ASSIGN constExpr)?
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
pointerGroup :( STAR ( typeQualifier )* )+ { ## = #( #[NPointerGroup], ##); }
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
parameterDeclaration { String declName; }
|
|
:ds:declSpecifiers
|
|
( ( declarator[false] )=> declName = d:declarator[false]
|
|
{
|
|
AST d2, ds2;
|
|
d2 = astFactory.dupList(#d);
|
|
ds2 = astFactory.dupList(#ds);
|
|
symbolTable.add(declName, #(null, ds2, d2));
|
|
}
|
|
| nonemptyAbstractDeclarator
|
|
)?
|
|
{
|
|
## = #( #[NParameterDeclaration], ## );
|
|
}
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
functionDef { String declName; }
|
|
:( (functionDeclSpecifiers)=> ds:functionDeclSpecifiers
|
|
| //epsilon
|
|
)
|
|
declName = d:declarator[true]
|
|
{
|
|
AST d2, ds2;
|
|
d2 = astFactory.dupList(#d);
|
|
ds2 = astFactory.dupList(#ds);
|
|
symbolTable.add(declName, #(null, ds2, d2));
|
|
pushScope(declName);
|
|
}
|
|
( declaration )* (VARARGS)? ( SEMI! )*
|
|
{ popScope(); }
|
|
compoundStatement[declName]
|
|
{ ## = #( #[NFunctionDef], ## );}
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
functionDeclSpecifiers { int specCount = 0; }
|
|
:( options { // this loop properly aborts when
|
|
// it finds a non-typedefName ID MBZ
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
functionStorageClassSpecifier
|
|
| typeQualifier
|
|
| ( "struct" | "union" | "enum" | typeSpecifier[specCount] )=>
|
|
specCount = typeSpecifier[specCount]
|
|
)+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
declarationPredictor :(options { //only want to look at declaration if I don't see typedef
|
|
warnWhenFollowAmbig = false;
|
|
}:
|
|
"typedef"
|
|
| declaration
|
|
)
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
statementList :( statement )+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
expr :assignExpr (options {
|
|
/* MBZ:
|
|
COMMA is ambiguous between comma expressions and
|
|
argument lists. argExprList should get priority,
|
|
and it does by being deeper in the expr rule tree
|
|
and using (COMMA assignExpr)*
|
|
*/
|
|
warnWhenFollowAmbig = false;
|
|
} :
|
|
c:COMMA^ { #c.setType(NCommaExpr); } assignExpr
|
|
)*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
assignExpr :conditionalExpr ( a:assignOperator! assignExpr { ## = #( #a, ## );} )?
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
assignOperator :ASSIGN
|
|
| DIV_ASSIGN
|
|
| PLUS_ASSIGN
|
|
| MINUS_ASSIGN
|
|
| STAR_ASSIGN
|
|
| MOD_ASSIGN
|
|
| RSHIFT_ASSIGN
|
|
| LSHIFT_ASSIGN
|
|
| BAND_ASSIGN
|
|
| BOR_ASSIGN
|
|
| BXOR_ASSIGN
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
constExpr :conditionalExpr
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
logicalOrExpr :logicalAndExpr ( LOR^ logicalAndExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
logicalAndExpr :inclusiveOrExpr ( LAND^ inclusiveOrExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
inclusiveOrExpr :exclusiveOrExpr ( BOR^ exclusiveOrExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
exclusiveOrExpr :bitAndExpr ( BXOR^ bitAndExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
bitAndExpr :equalityExpr ( BAND^ equalityExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
equalityExpr :relationalExpr
|
|
( ( EQUAL^ | NOT_EQUAL^ ) relationalExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
relationalExpr :shiftExpr
|
|
( ( LT^ | LTE^ | GT^ | GTE^ ) shiftExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
shiftExpr :additiveExpr
|
|
( ( LSHIFT^ | RSHIFT^ ) additiveExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
additiveExpr :multExpr
|
|
( ( PLUS^ | MINUS^ ) multExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
multExpr :castExpr
|
|
( ( STAR^ | DIV^ | MOD^ ) castExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
typeName :specifierQualifierList (nonemptyAbstractDeclarator)?
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
postfixExpr :primaryExpr
|
|
(
|
|
postfixSuffix {## = #( #[NPostfixExpr], ## );}
|
|
)?
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
postfixSuffix :( PTR ID
|
|
| DOT ID
|
|
| functionCall
|
|
| LBRACKET expr RBRACKET
|
|
| INC
|
|
| DEC
|
|
)+
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
functionCall :LPAREN^ (a:argExprList)? RPAREN
|
|
{
|
|
##.setType( NFunctionCallArgs );
|
|
}
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
argExprList :assignExpr ( COMMA! assignExpr )*
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
protected charConst :CharLiteral
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
protected stringConst :(StringLiteral)+ { ## = #(#[NStringSeq], ##); }
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
protected intConst :IntOctalConst
|
|
| LongOctalConst
|
|
| UnsignedOctalConst
|
|
| IntIntConst
|
|
| LongIntConst
|
|
| UnsignedIntConst
|
|
| IntHexConst
|
|
| LongHexConst
|
|
| UnsignedHexConst
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
protected floatConst :FloatDoubleConst
|
|
| DoubleDoubleConst
|
|
| LongDoubleConst
|
|
;
|
|
|
|
// inherited from grammar StdCParser
|
|
dummy :NTypedefName
|
|
| NInitDecl
|
|
| NDeclarator
|
|
| NStructDeclarator
|
|
| NDeclaration
|
|
| NCast
|
|
| NPointerGroup
|
|
| NExpressionGroup
|
|
| NFunctionCallArgs
|
|
| NNonemptyAbstractDeclarator
|
|
| NInitializer
|
|
| NStatementExpr
|
|
| NEmptyExpression
|
|
| NParameterTypeList
|
|
| NFunctionDef
|
|
| NCompoundStatement
|
|
| NParameterDeclaration
|
|
| NCommaExpr
|
|
| NUnaryExpr
|
|
| NLabel
|
|
| NPostfixExpr
|
|
| NRangeExpr
|
|
| NStringSeq
|
|
| NInitializerElementLabel
|
|
| NLcurlyInitializer
|
|
| NAsmAttribute
|
|
| NGnuAsmExpr
|
|
| NTypeMissing
|
|
;
|
|
|
|
{
|
|
// import CToken;
|
|
import java.io.*;
|
|
// import LineObject;
|
|
import antlr.*;
|
|
}class WLexer extends Lexer;
|
|
|
|
options {
|
|
k= 3;
|
|
importVocab= W;
|
|
testLiterals= false;
|
|
}
|
|
|
|
tokens {
|
|
LITERAL___extension__ = "__extension__";
|
|
}
|
|
{
|
|
public void initialize(String src)
|
|
{
|
|
setOriginalSource(src);
|
|
initialize();
|
|
}
|
|
|
|
public void initialize()
|
|
{
|
|
literals.put(new ANTLRHashString("__alignof__", this), new Integer(LITERAL___alignof));
|
|
literals.put(new ANTLRHashString("__asm", this), new Integer(LITERAL_asm));
|
|
literals.put(new ANTLRHashString("__asm__", this), new Integer(LITERAL_asm));
|
|
literals.put(new ANTLRHashString("__attribute__", this), new Integer(LITERAL___attribute));
|
|
literals.put(new ANTLRHashString("__complex__", this), new Integer(LITERAL___complex));
|
|
literals.put(new ANTLRHashString("__const", this), new Integer(LITERAL_const));
|
|
literals.put(new ANTLRHashString("__const__", this), new Integer(LITERAL_const));
|
|
literals.put(new ANTLRHashString("__imag__", this), new Integer(LITERAL___imag));
|
|
literals.put(new ANTLRHashString("__inline", this), new Integer(LITERAL_inline));
|
|
literals.put(new ANTLRHashString("__inline__", this), new Integer(LITERAL_inline));
|
|
literals.put(new ANTLRHashString("__real__", this), new Integer(LITERAL___real));
|
|
literals.put(new ANTLRHashString("__signed", this), new Integer(LITERAL_signed));
|
|
literals.put(new ANTLRHashString("__signed__", this), new Integer(LITERAL_signed));
|
|
literals.put(new ANTLRHashString("__typeof", this), new Integer(LITERAL_typeof));
|
|
literals.put(new ANTLRHashString("__typeof__", this), new Integer(LITERAL_typeof));
|
|
literals.put(new ANTLRHashString("__volatile", this), new Integer(LITERAL_volatile));
|
|
literals.put(new ANTLRHashString("__volatile__", this), new Integer(LITERAL_volatile));
|
|
}
|
|
|
|
|
|
LineObject lineObject = new LineObject();
|
|
String originalSource = "";
|
|
PreprocessorInfoChannel preprocessorInfoChannel = new PreprocessorInfoChannel();
|
|
int tokenNumber = 0;
|
|
boolean countingTokens = true;
|
|
int deferredLineCount = 0;
|
|
|
|
public void setCountingTokens(boolean ct)
|
|
{
|
|
countingTokens = ct;
|
|
if ( countingTokens ) {
|
|
tokenNumber = 0;
|
|
}
|
|
else {
|
|
tokenNumber = 1;
|
|
}
|
|
}
|
|
|
|
public void setOriginalSource(String src)
|
|
{
|
|
originalSource = src;
|
|
lineObject.setSource(src);
|
|
}
|
|
public void setSource(String src)
|
|
{
|
|
lineObject.setSource(src);
|
|
}
|
|
|
|
public PreprocessorInfoChannel getPreprocessorInfoChannel()
|
|
{
|
|
return preprocessorInfoChannel;
|
|
}
|
|
|
|
public void setPreprocessingDirective(String pre)
|
|
{
|
|
preprocessorInfoChannel.addLineForTokenNumber( pre, new Integer(tokenNumber) );
|
|
}
|
|
|
|
protected Token makeToken(int t)
|
|
{
|
|
if ( t != Token.SKIP && countingTokens) {
|
|
tokenNumber++;
|
|
}
|
|
CToken tok = (CToken) super.makeToken(t);
|
|
tok.setLine(lineObject.line);
|
|
tok.setSource(lineObject.source);
|
|
tok.setTokenNumber(tokenNumber);
|
|
|
|
lineObject.line += deferredLineCount;
|
|
deferredLineCount = 0;
|
|
return tok;
|
|
}
|
|
|
|
public void deferredNewline() {
|
|
deferredLineCount++;
|
|
}
|
|
|
|
public void newline() {
|
|
lineObject.newline();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
Whitespace :( ( ' ' | '\t' | '\014')
|
|
| "\r\n" { newline(); }
|
|
| ( '\n' | '\r' ) { newline(); }
|
|
) { _ttype = Token.SKIP; }
|
|
;
|
|
|
|
protected Escape :'\\'
|
|
( options{warnWhenFollowAmbig=false;}:
|
|
~('0'..'7' | 'x')
|
|
| ('0'..'3') ( options{warnWhenFollowAmbig=false;}: Digit )*
|
|
| ('4'..'7') ( options{warnWhenFollowAmbig=false;}: Digit )*
|
|
| 'x' ( options{warnWhenFollowAmbig=false;}: Digit | 'a'..'f' | 'A'..'F' )+
|
|
)
|
|
;
|
|
|
|
protected IntSuffix :'L'
|
|
| 'l'
|
|
| 'U'
|
|
| 'u'
|
|
| 'I'
|
|
| 'i'
|
|
| 'J'
|
|
| 'j'
|
|
;
|
|
|
|
protected NumberSuffix :IntSuffix
|
|
| 'F'
|
|
| 'f'
|
|
;
|
|
|
|
Number :( ( Digit )+ ( '.' | 'e' | 'E' ) )=> ( Digit )+
|
|
( '.' ( Digit )* ( Exponent )?
|
|
| Exponent
|
|
)
|
|
( NumberSuffix
|
|
)*
|
|
|
|
| ( "..." )=> "..." { _ttype = VARARGS; }
|
|
|
|
| '.' { _ttype = DOT; }
|
|
( ( Digit )+ ( Exponent )?
|
|
{ _ttype = Number; }
|
|
( NumberSuffix
|
|
)*
|
|
)?
|
|
|
|
| '0' ( '0'..'7' )*
|
|
( NumberSuffix
|
|
)*
|
|
|
|
| '1'..'9' ( Digit )*
|
|
( NumberSuffix
|
|
)*
|
|
|
|
| '0' ( 'x' | 'X' ) ( 'a'..'f' | 'A'..'F' | Digit )+
|
|
( IntSuffix
|
|
)*
|
|
;
|
|
|
|
IDMEAT :i:ID {
|
|
|
|
if ( i.getType() == LITERAL___extension__ ) {
|
|
$setType(Token.SKIP);
|
|
}
|
|
else {
|
|
$setType(i.getType());
|
|
}
|
|
|
|
}
|
|
;
|
|
|
|
protected ID
|
|
options {
|
|
testLiterals= true;
|
|
}
|
|
:( 'a'..'z' | 'A'..'Z' | '_' | '$')
|
|
( 'a'..'z' | 'A'..'Z' | '_' | '$' | '0'..'9' )*
|
|
;
|
|
|
|
WideCharLiteral :'L' CharLiteral
|
|
{ $setType(CharLiteral); }
|
|
;
|
|
|
|
WideStringLiteral :'L' StringLiteral
|
|
{ $setType(StringLiteral); }
|
|
;
|
|
|
|
StringLiteral :'"'
|
|
( ('\\' ~('\n'))=> Escape
|
|
| ( '\r' { newline(); }
|
|
| '\n' {
|
|
newline();
|
|
}
|
|
| '\\' '\n' {
|
|
newline();
|
|
}
|
|
)
|
|
| ~( '"' | '\r' | '\n' | '\\' )
|
|
)*
|
|
'"'
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected Vocabulary :'\3'..'\377'
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
ASSIGN :'=' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
COLON :':' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
COMMA :',' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
QUESTION :'?' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
SEMI :';' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
PTR :"->" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected DOT :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected VARARGS :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LPAREN :'(' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
RPAREN :')' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LBRACKET :'[' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
RBRACKET :']' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LCURLY :'{' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
RCURLY :'}' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
EQUAL :"==" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
NOT_EQUAL :"!=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LTE :"<=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LT :"<" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
GTE :">=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
GT :">" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
DIV :'/' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
DIV_ASSIGN :"/=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
PLUS :'+' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
PLUS_ASSIGN :"+=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
INC :"++" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
MINUS :'-' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
MINUS_ASSIGN :"-=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
DEC :"--" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
STAR :'*' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
STAR_ASSIGN :"*=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
MOD :'%' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
MOD_ASSIGN :"%=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
RSHIFT :">>" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
RSHIFT_ASSIGN :">>=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LSHIFT :"<<" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LSHIFT_ASSIGN :"<<=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LAND :"&&" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LNOT :'!' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
LOR :"||" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BAND :'&' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BAND_ASSIGN :"&=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BNOT :'~' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BOR :'|' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BOR_ASSIGN :"|=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BXOR :'^' ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
BXOR_ASSIGN :"^=" ;
|
|
|
|
// inherited from grammar StdCLexer
|
|
Comment :"/*"
|
|
( { LA(2) != '/' }? '*'
|
|
| "\r\n" { deferredNewline(); }
|
|
| ( '\r' | '\n' ) { deferredNewline(); }
|
|
| ~( '*'| '\r' | '\n' )
|
|
)*
|
|
"*/" { _ttype = Token.SKIP;
|
|
}
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
CPPComment :"//" ( ~('\n') )*
|
|
{
|
|
_ttype = Token.SKIP;
|
|
}
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
PREPROC_DIRECTIVE
|
|
options {
|
|
paraphrase= "a line directive";
|
|
}
|
|
:'#'
|
|
( ( "line" || (( ' ' | '\t' | '\014')+ '0'..'9')) => LineDirective
|
|
| (~'\n')* { setPreprocessingDirective(getText()); }
|
|
)
|
|
{
|
|
_ttype = Token.SKIP;
|
|
}
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected Space :( ' ' | '\t' | '\014')
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected LineDirective {
|
|
boolean oldCountingTokens = countingTokens;
|
|
countingTokens = false;
|
|
}
|
|
:{
|
|
lineObject = new LineObject();
|
|
deferredLineCount = 0;
|
|
}
|
|
("line")? //this would be for if the directive started "#line", but not there for GNU directives
|
|
(Space)+
|
|
n:Number { lineObject.setLine(Integer.parseInt(n.getText())); }
|
|
(Space)+
|
|
( fn:StringLiteral { try {
|
|
lineObject.setSource(fn.getText().substring(1,fn.getText().length()-1));
|
|
}
|
|
catch (StringIndexOutOfBoundsException e) { /*not possible*/ }
|
|
}
|
|
| fi:ID { lineObject.setSource(fi.getText()); }
|
|
)?
|
|
(Space)*
|
|
("1" { lineObject.setEnteringFile(true); } )?
|
|
(Space)*
|
|
("2" { lineObject.setReturningToFile(true); } )?
|
|
(Space)*
|
|
("3" { lineObject.setSystemHeader(true); } )?
|
|
(Space)*
|
|
("4" { lineObject.setTreatAsC(true); } )?
|
|
(~('\r' | '\n'))*
|
|
("\r\n" | "\r" | "\n")
|
|
{
|
|
preprocessorInfoChannel.addLineForTokenNumber(new LineObject(lineObject), new Integer(tokenNumber));
|
|
countingTokens = oldCountingTokens;
|
|
}
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
CharLiteral :'\'' ( Escape | ~( '\'' ) ) '\''
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected BadStringLiteral :// Imaginary token.
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected Digit :'0'..'9'
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected LongSuffix :'l'
|
|
| 'L'
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected UnsignedSuffix :'u'
|
|
| 'U'
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected FloatSuffix :'f'
|
|
| 'F'
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected Exponent :( 'e' | 'E' ) ( '+' | '-' )? ( Digit )+
|
|
;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected DoubleDoubleConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected FloatDoubleConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected LongDoubleConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected IntOctalConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected LongOctalConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected UnsignedOctalConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected IntIntConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected LongIntConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected UnsignedIntConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected IntHexConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected LongHexConst :;
|
|
|
|
// inherited from grammar StdCLexer
|
|
protected UnsignedHexConst :;
|
|
|
|
|