📄 gnucparser.g
字号:
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Copyright (c) Non, Inc. 1998 -- All Rights Reserved
PROJECT: C Compiler
MODULE: GnuCParser
FILE: GnuCParser.g
AUTHOR: Monty Zukowski (jamz@cdsnet.net) April 28, 1998
DESCRIPTION:
This is a grammar for the GNU C compiler. It is a
grammar subclass of StdCParser, overriding only those
rules which are different from Standard C.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
header {
package isis.anp.gnuc;
}
{
import isis.anp.common.CSymbolTable;
import isis.anp.common.TNode;
import antlr.ASTFactory;
import antlr.ASTPair;
import antlr.MismatchedTokenException;
import antlr.NoViableAltException;
import antlr.ParserSharedInputState;
import antlr.RecognitionException;
import antlr.SemanticException;
import antlr.Token;
import antlr.TokenBuffer;
import antlr.TokenStream;
import antlr.TokenStreamException;
import antlr.collections.AST;
import antlr.collections.impl.ASTArray;
import antlr.collections.impl.BitSet;
}
class GnuCParser extends StdCParser;
options
{
k = 2;
exportVocab = GnuC;
buildAST = true;
ASTLabelType = "TNode";
// Copied following options from java grammar.
codeGenMakeSwitchThreshold = 2;
codeGenBitsetTestThreshold = 3;
}
{
// 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
;
/* these two are here because GCC allows "cat = 13;" as a valid program! */
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
)
;
// GCC allows more specific initializers
initializerElementLabel
: ( ( LBRACKET ((constExpr VARARGS)=> rangeExpr | constExpr) RBRACKET (ASSIGN)? )
| ID COLON
| DOT ID ASSIGN
)
{ ## = #( #[NInitializerElementLabel], ##) ; }
;
// GCC allows empty initializer lists
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"
| 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -