📄 stdcparser.g
字号:
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Copyright (c) Non, Inc. 1997 -- All Rights Reserved
PROJECT: C Compiler
MODULE: Parser
FILE: stdc.g
AUTHOR: John D. Mitchell (john@non.net), Jul 12, 1997
REVISION HISTORY:
Name Date Description
---- ---- -----------
JDM 97.07.12 Initial version.
JTC 97.11.18 Declaration vs declarator & misc. hacking.
JDM 97.11.20 Fixed: declaration vs funcDef,
parenthesized expressions,
declarator iteration,
varargs recognition,
empty source file recognition,
and some typos.
DESCRIPTION:
This grammar supports the Standard C language.
Note clearly that this grammar does *NOT* deal with
preprocessor functionality (including things like trigraphs)
Nor does this grammar deal with multi-byte characters nor strings
containing multi-byte characters [these constructs are "exercises
for the reader" as it were :-)].
Please refer to the ISO/ANSI C Language Standard if you believe
this grammar to be in error. Please cite chapter and verse in any
correspondence to the author to back up your claim.
TODO:
- typedefName is commented out, needs a symbol table to resolve
ambiguity.
- trees
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
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 StdCParser extends Parser;
options
{
k = 2;
exportVocab = StdC;
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 *not* allowed. */
{
System.err.println ( "Empty source file!" );
}
;
externalList
: ( externalDef )+
;
externalDef
: ( "typedef" | declaration )=> declaration
| functionDef
| asm_expr
;
asm_expr
: "asm"^
("volatile")? LCURLY! expr RCURLY! SEMI!
;
declaration
{ AST ds1 = null; }
: ds:declSpecifiers { ds1 = astFactory.dupList(#ds); }
(
initDeclList[ds1]
)?
SEMI!
{ ## = #( #[NDeclaration], ##); }
;
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]
)+
;
storageClassSpecifier
: "auto"
| "register"
| "typedef"
| functionStorageClassSpecifier
;
functionStorageClassSpecifier
: "extern"
| "static"
;
typeQualifier
: "const"
| "volatile"
;
typeSpecifier [int specCount] returns [int retSpecCount]
{ retSpecCount = specCount + 1; }
:
( "void"
| "char"
| "short"
| "int"
| "long"
| "float"
| "double"
| "signed"
| "unsigned"
| structOrUnionSpecifier
| enumSpecifier
| { specCount == 0 }? typedefName
)
;
typedefName
: { isTypedefName ( LT(1).getText() ) }?
i:ID { ## = #(#[NTypedefName], #i); }
;
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, ## );
}
;
structOrUnion
: "struct"
| "union"
;
structDeclarationList
: ( structDeclaration )+
;
structDeclaration
: specifierQualifierList structDeclaratorList ( SEMI! )+
;
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
)+
;
structDeclaratorList
: structDeclarator ( COMMA! structDeclarator )*
;
structDeclarator
:
( COLON constExpr
| declarator[false] ( COLON constExpr )?
)
{ ## = #( #[NStructDeclarator], ##); }
;
enumSpecifier
: "enum"^
( ( ID LCURLY )=> i:ID LCURLY enumList[i.getText()] RCURLY!
| LCURLY enumList["anonymous"] RCURLY!
| ID
)
;
enumList[String enumName]
: enumerator[enumName] ( COMMA! enumerator[enumName] )*
;
enumerator[String enumName]
: i:ID { symbolTable.add( i.getText(),
#( null,
#[LITERAL_enum, "enum"],
#[ ID, enumName]
)
);
}
(ASSIGN constExpr)?
;
initDeclList[AST declarationSpecifiers]
: initDecl[declarationSpecifiers]
( COMMA! initDecl[declarationSpecifiers] )*
;
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) );
}
( ASSIGN initializer
| COLON expr
)?
{ ## = #( #[NInitDecl], ## ); }
;
pointerGroup
: ( STAR ( typeQualifier )* )+ { ## = #( #[NPointerGroup], ##); }
;
idList
: ID ( COMMA! ID )*
;
initializer
: ( assignExpr
| LCURLY initializerList ( COMMA! )? RCURLY!
)
{ ## = #( #[NInitializer], ## ); }
;
initializerList
: initializer ( COMMA! initializer )*
;
declarator[boolean isFunctionDefinition] returns [String declName]
{ declName = ""; }
:
( pointerGroup )?
( id:ID { declName = id.getText(); }
| LPAREN declName = declarator[false] RPAREN
)
( ! LPAREN
{
if (isFunctionDefinition) {
pushScope(declName);
}
else {
pushScope("!"+declName);
}
}
(
(declSpecifiers)=> p:parameterTypeList
{
## = #( null, ##, #( #[NParameterTypeList], #p ) );
}
| (i:idList)?
{
## = #( null, ##, #( #[NParameterTypeList], #i ) );
}
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -