Plain C CFG
This a grammar for plain C reformatted from this Yacc file. Tokens are in bold.
TranslationUnitExternalDecl
|TranslationUnitExternalDecl
ExternalDeclFunctionDefinition
|Decl
FunctionDefinitionDeclSpecsDeclaratorDeclListCompoundStat
|DeclaratorDeclListCompoundStat
|DeclSpecsDeclaratorCompoundStat
|DeclaratorCompoundStat
DeclDeclSpecsInitDeclaratorList;
|DeclSpecs;
DeclListDecl
|DeclListDecl
DeclSpecsStorageClassSpecDeclSpecs
|StorageClassSpec
|TypeSpecDeclSpecs
|TypeSpec
|TypeQualifierDeclSpecs
|TypeQualifier
StorageClassSpecauto|register|static|extern|typedef
TypeSpecvoid|char|short|int|long|float |double|signed|unsigned
|StructOrUnionSpec|EnumSpec|TypedefName
TypeQualifierconst|volatile
StructOrUnionSpecStructOrUnionId{StructDeclList}
|StructOrUnion{StructDeclList}
|StructOrUnionId
StructOrUnionstruct|union
StructDeclListStructDecl
|StructDeclListStructDecl
InitDeclaratorListInitDeclarator
|InitDeclaratorList,InitDeclarator
InitDeclaratorDeclarator
|Declarator=Initializer
StructDeclSpecQualifierListStructDeclaratorList;
SpecQualifierListTypeSpecSpecQualifierList
|TypeSpec
|TypeQualifierSpecQualifierList
|TypeQualifier
StructDeclaratorListStructDeclarator
|StructDeclaratorList,StructDeclarator
StructDeclaratorDeclarator
|Declarator:ConstExp
|:ConstExp
EnumSpecenumId{EnumeratorList}
|enum{EnumeratorList}
|enumId
EnumeratorListEnumerator
|EnumeratorList,Enumerator
EnumeratorId
|Id=ConstExp
DeclaratorPointerDirectDeclarator
|DirectDeclarator
DirectDeclaratorId
|(Declarator)
|DirectDeclarator[ConstExp]
|DirectDeclarator[]
|DirectDeclarator(ParamTypeList
|DirectDeclarator(IdList)
|DirectDeclarator()
Pointer*TypeQualifierList
|*
|*TypeQualifierListPointer
|*Pointer
TypeQualifierListTypeQualifier
|TypeQualifierListTypeQualifier
ParamTypeListParamList
|ParamList,...
ParamListParamDecl
|ParamList,ParamDecl
ParamDeclDeclSpecsDeclarator
|DeclSpecsAbstractDeclarator
|DeclSpecs
IdListId
|IdList,Id
InitializerAssignmentExp
|{InitializerList}
|{InitializerList,}
InitializerListInitializer
|InitializerList,Initializer
TypeNameSpecQualifierListAbstractDeclarator
|SpecQualifierList
AbstractDeclaratorPointer
|PointerDirectAbstractDeclarator
|DirectAbstractDeclarator
DirectAbstractDeclarator(AbstractDeclarator)
|DirectAbstractDeclarator[ConstExp]
|[ConstExp]
|DirectAbstractDeclarator[]
|[]
|DirectAbstractDeclarator(ParamTypeList)
|(ParamTypeList)
|DirectAbstractDeclarator()
|()
TypedefNameId
StatLabeledStat|ExpStat|CompoundStat|SelectionStat| IterationStat|JumpStat
LabeledStatId:Stat
|caseConstExp:Stat
|default:Stat
ExpStatExp;
|;
CompoundStat{DeclListStatList}
|{StatList}
|{DeclList}
|{}
StatListStat
|StatListStat
SelectionStatif(Exp)Stat
|if(Exp)StatelseStat
|switch(Exp)Stat
IterationStatwhile(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
JumpStatJumpSpec;
JumpSpecgotoId|continue|break|returnExp|return
ExpAssignmentExp
|Exp,AssignmentExp
AssignmentExpConditionalExp
|UnaryExpAssignmentOperatorAssignmentExp
AssignmentOperator=|*=|/=|%=|+=|-=|<<=| >>=|&=|^=||=
ConditionalExpLogicalOrExp
|LogicalOrExp?Exp:ConditionalExp
ConstExpConditionalExp
LogicalOrExpLogicalAndExp
|LogicalOrExp||LogicalAndExp
LogicalAndExpInclusiveOrExp
|LogicalAndExp&&InclusiveOrExp
InclusiveOrExpExclusiveOrExp
|InclusiveOrExp|ExclusiveOrExp
ExclusiveOrExpAndExp
|ExclusiveOrExp^AndExp
AndExpEqualityExp
|AndExp&EqualityExp
EqualityExpRelationalExp
|EqualityExp==RelationalExp
|EqualityExp!=RelationalExp
RelationalExpShiftExpression
|RelationalExp<ShiftExpression
|RelationalExp>ShiftExpression
|RelationalExp<=ShiftExpression
|RelationalExp>=ShiftExpression
ShiftExpressionAdditiveExp
|ShiftExpression<<AdditiveExp
|ShiftExpression>>AdditiveExp
AdditiveExpMultExp
|AdditiveExp+MultExp
|AdditiveExp-MultExp
MultExpCastExp
|MultExp*CastExp
|MultExp/CastExp
|MultExp%CastExp
CastExpUnaryExp
|(TypeName)CastExp
UnaryExpPostfixExp
|++UnaryExp
|--UnaryExp
|UnaryOperatorCastExp
|sizeofUnaryExp
|sizeof(TypeName)
UnaryOperator&|*|+|-|~|!
PostfixExpPrimaryExp
|PostfixExp[Exp]
|PostfixExp(ArgumentExpList)
|PostfixExp()
|PostfixExp.Id
|PostfixExp->Id
|PostfixExp++
|PostfixExp--
PrimaryExpId|IntConst|FloatConst| EnumerationConst|StringConst| (Exp)
ArgumentExpListAssignmentExp
|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.
IterationStatwhile(Exp)Stat
|doStatwhile(Exp);
|for(OptExp;OptExp;OptExp)Stat
OptExpExp|ε
Epsilon may help in other places as well, but this seems the most dramatic.