This a grammar for plain C reformatted from
this
Yacc file. Tokens are in
bold.
TranslationUnit | → | ExternalDecl |
| | | TranslationUnitExternalDecl |
ExternalDecl | → | FunctionDefinition |
| | | Decl |
FunctionDefinition | → | DeclSpecsDeclaratorDeclListCompoundStat |
| | | DeclaratorDeclListCompoundStat |
| | | DeclSpecsDeclaratorCompoundStat |
| | | DeclaratorCompoundStat |
Decl | → | DeclSpecsInitDeclaratorList; |
| | | DeclSpecs; |
DeclList | → | Decl |
| | | DeclListDecl |
DeclSpecs | → | StorageClassSpecDeclSpecs |
| | | StorageClassSpec |
| | | TypeSpecDeclSpecs |
| | | TypeSpec |
| | | TypeQualifierDeclSpecs |
| | | TypeQualifier |
StorageClassSpec | → | auto|register|static|extern|typedef |
TypeSpec | → | void|char|short|int|long|float
|double|signed|unsigned |
| | | StructOrUnionSpec|EnumSpec|TypedefName |
TypeQualifier | → | const|volatile |
StructOrUnionSpec | → | StructOrUnionId{StructDeclList} |
| | | StructOrUnion{StructDeclList} |
| | | StructOrUnionId |
StructOrUnion | → | struct|union |
StructDeclList | → | StructDecl |
| | | StructDeclListStructDecl |
InitDeclaratorList | → | InitDeclarator |
| | | InitDeclaratorList,InitDeclarator |
InitDeclarator | → | Declarator |
| | | Declarator=Initializer |
StructDecl | → | SpecQualifierListStructDeclaratorList; |
SpecQualifierList | → | TypeSpecSpecQualifierList |
| | | TypeSpec |
| | | TypeQualifierSpecQualifierList |
| | | TypeQualifier |
StructDeclaratorList | → | StructDeclarator |
| | | StructDeclaratorList,StructDeclarator |
StructDeclarator | → | Declarator |
| | | Declarator:ConstExp |
| | | :ConstExp |
EnumSpec | → | enumId{EnumeratorList} |
| | | enum{EnumeratorList} |
| | | enumId |
EnumeratorList | → | Enumerator |
| | | EnumeratorList,Enumerator |
Enumerator | → | Id |
| | | Id=ConstExp |
Declarator | → | PointerDirectDeclarator |
| | | DirectDeclarator |
DirectDeclarator | → | Id |
| | | (Declarator) |
| | | DirectDeclarator[ConstExp] |
| | | DirectDeclarator[] |
| | | DirectDeclarator(ParamTypeList |
| | | DirectDeclarator(IdList) |
| | | DirectDeclarator() |
Pointer | → | *TypeQualifierList |
| | | * |
| | | *TypeQualifierListPointer |
| | | *Pointer |
TypeQualifierList | → | TypeQualifier |
| | | TypeQualifierListTypeQualifier |
ParamTypeList | → | ParamList |
| | | ParamList,... |
ParamList | → | ParamDecl |
| | | ParamList,ParamDecl |
ParamDecl | → | DeclSpecsDeclarator |
| | | DeclSpecsAbstractDeclarator |
| | | DeclSpecs |
IdList | → | Id |
| | | IdList,Id |
Initializer | → | AssignmentExp |
| | | {InitializerList} |
| | | {InitializerList,} |
InitializerList | → | Initializer |
| | | InitializerList,Initializer |
TypeName | → | SpecQualifierListAbstractDeclarator |
| | | SpecQualifierList |
AbstractDeclarator | → | Pointer |
| | | PointerDirectAbstractDeclarator |
| | | DirectAbstractDeclarator |
DirectAbstractDeclarator | → | (AbstractDeclarator) |
| | | DirectAbstractDeclarator[ConstExp] |
| | | [ConstExp] |
| | | DirectAbstractDeclarator[] |
| | | [] |
| | | DirectAbstractDeclarator(ParamTypeList) |
| | | (ParamTypeList) |
| | | DirectAbstractDeclarator() |
| | | () |
TypedefName | → | Id |
Stat | → | LabeledStat|ExpStat|CompoundStat|SelectionStat|
IterationStat|JumpStat |
LabeledStat | → | Id:Stat |
| | | caseConstExp:Stat |
| | | default:Stat |
ExpStat | → | Exp; |
| | | ; |
CompoundStat | → | {DeclListStatList} |
| | | {StatList} |
| | | {DeclList} |
| | | {} |
StatList | → | Stat |
| | | StatListStat |
SelectionStat | → | if(Exp)Stat |
| | | if(Exp)StatelseStat |
| | | switch(Exp)Stat |
IterationStat | → | while(Exp)Stat |
| | | doStatwhile(Exp); |
| | | for(Exp;Exp;Exp)Stat |
| | | for(Exp;Exp;)Stat |
| | | for(Exp;;Exp)Stat |
| | | for(Exp;;)Stat |
| | | for(;Exp;Exp)Stat |
| | | for(;Exp;)Stat |
| | | for(;;Exp)Stat |
| | | for(;;)Stat |
JumpStat | → | JumpSpec; |
JumpSpec | → | gotoId|continue|break|returnExp|return |
Exp | → | AssignmentExp |
| | | Exp,AssignmentExp |
AssignmentExp | → | ConditionalExp |
| | | UnaryExpAssignmentOperatorAssignmentExp |
AssignmentOperator | → | =|*=|/=|%=|+=|-=|<<=|
>>=|&=|^=||= |
ConditionalExp | → | LogicalOrExp |
| | | LogicalOrExp?Exp:ConditionalExp |
ConstExp | → | ConditionalExp |
LogicalOrExp | → | LogicalAndExp |
| | | LogicalOrExp||LogicalAndExp |
LogicalAndExp | → | InclusiveOrExp |
| | | LogicalAndExp&&InclusiveOrExp |
InclusiveOrExp | → | ExclusiveOrExp |
| | | InclusiveOrExp|ExclusiveOrExp |
ExclusiveOrExp | → | AndExp |
| | | ExclusiveOrExp^AndExp |
AndExp | → | EqualityExp |
| | | AndExp&EqualityExp |
EqualityExp | → | RelationalExp |
| | | EqualityExp==RelationalExp |
| | | EqualityExp!=RelationalExp |
RelationalExp | → | ShiftExpression |
| | | RelationalExp<ShiftExpression |
| | | RelationalExp>ShiftExpression |
| | | RelationalExp<=ShiftExpression |
| | | RelationalExp>=ShiftExpression |
ShiftExpression | → | AdditiveExp |
| | | ShiftExpression<<AdditiveExp |
| | | ShiftExpression>>AdditiveExp |
AdditiveExp | → | MultExp |
| | | AdditiveExp+MultExp |
| | | AdditiveExp-MultExp |
MultExp | → | CastExp |
| | | MultExp*CastExp |
| | | MultExp/CastExp |
| | | MultExp%CastExp |
CastExp | → | UnaryExp |
| | | (TypeName)CastExp |
UnaryExp | → | PostfixExp |
| | | ++UnaryExp |
| | | --UnaryExp |
| | | UnaryOperatorCastExp |
| | | sizeofUnaryExp |
| | | sizeof(TypeName) |
UnaryOperator | → | &|*|+|-|~|! |
PostfixExp | → | PrimaryExp |
| | | PostfixExp[Exp] |
| | | PostfixExp(ArgumentExpList) |
| | | PostfixExp() |
| | | PostfixExp.Id |
| | | PostfixExp->Id |
| | | PostfixExp++ |
| | | PostfixExp-- |
PrimaryExp | → | Id|IntConst|FloatConst|
EnumerationConst|StringConst|
(Exp) |
ArgumentExpList | → | AssignmentExp |
| | | ArgumentExpList,AssignmentExp |
Nothing Helps
In the above grammar, the replacement is always a non-empty string.
Right sides may be empty, usually written as ε. A rule can
then take the form
Whatever→ε, meaning that
the non-terminal
Whatever is allowed to just disappear during a
derivation. This can simplify certain things. For instance,
the C
for statement may omit any of the initialization,
test, or increment parts of the header. In the above, this is
represented by giving eight versions of the
for header, with each
combination of presence or omission. But using an epsilon rule, we
can write this more concisely.
IterationStat | → | while(Exp)Stat |
| | | doStatwhile(Exp); |
| | | for(OptExp;OptExp;OptExp)Stat |
OptExp | → | Exp|ε |
Epsilon may help in other places as well, but this seems the most
dramatic.