/** * This Objective-C grammar was copied and adapted from the Objective-C-CPD-Language Github project. (https://github.com/jkennedy1980/Objective-C-CPD-Language) * * Original author: * @author Michael Hall - Based on Parnel SableCC ObjectiveC grammar and javacc C grammar * * Original source file: * https://github.com/jkennedy1980/Objective-C-CPD-Language/blob/master/src/main/javacc/ObjC2.0.jj (commit 5b07b5cc424522e435929bbff7589c690100edf6) */ options { JAVA_UNICODE_ESCAPE = true; BUILD_PARSER=false; CACHE_TOKENS=true; STATIC=false; } PARSER_BEGIN(ObjectiveCParserImpl) package net.sourceforge.pmd.lang.objectivec.ast; /** * Grammar to parse ObjectiveC 2.0 * @author Michael Hall - Based on Parnel SableCC ObjectiveC grammar and javacc C grammar * * Josh Kennedy - added CSTRING_LITERAL so parser doesn't die on CStrings. * Paul Taykalo - added support for 0x literals, @compatibility_alias, and the $ character identifier * Paul Taykalo - vertical tab (\v) and alert (\a) characters are added */ public class ObjectiveCParserImpl {} PARSER_END(ObjectiveCParserImpl) SKIP : { " " | "\t" | "\n" | "\r" | "\f" | "\\\n" /* Special issue for long strings concatenation */ | "\\\r\n" /* Special issue for long strings concatenation */ | "__weak" | "__strong" | "__attribute__" | "__objc_exception__" | "#" : PREPROCESSOR_OUTPUT | "extern \"C\" {" | "CF_EXPORT" | "CF_INLINE" | "CF_EXTERN_C_BEGIN" | "CF_EXTERN_C_END" | "CA_EXTERN_C_BEGIN" | "CA_EXTERN_C_END" | "CA_EXTERN" | "CA_DEPRECATED" | "COREDATA_EXTERN" | "NS_INLINE" | "APPKIT_EXTERN" | "FOUNDATION_EXPORT" : PREPROCESSOR_OUTPUT /* mjh - Cocoa specific not currently of interest, ignore like preprocessor stuff */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER" /* mjh - not currently of interest */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_1_AND_LATER" /* mjh - not currently of interest */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_2_AND_LATER" /* mjh - not currently of interest */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_3_AND_LATER" /* mjh - not currently of interest */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_4_AND_LATER" /* mjh - not currently of interest */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER" /* mjh - not currently of interest */ | "DEPRECATED_IN_MAC_OS_X_VERSION_10_6_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER_BUT_DEPRECATED" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6" | "AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4" | "AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4" | "AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5" | "AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5" | "AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4" | "AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5" | "AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5" | "AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6" | "AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0" | "AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0" | "AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER" /* mjh - not currently of interest */ | "AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED" /* mjh - not currently of interest */ | "AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED" /* mjh - not currently of interest */ | "AVAILABLE_IN_WEBKIT_VERSION_4_0" /* mjh - not currently of interest */ | "NP_LOADDS" /* mjh - not currently of interest */ | "NS_REQUIRES_NIL_TERMINATION" | "UNAVAILABLE_ATTRIBUTE" | <"," "NS_NONATOMIC_IPHONEONLY"> /* mjh - not currently of interest */ | "NS_FORMAT_FUNCTION" : FORMAT_FUNC | "CF_FORMAT_ARGUMENT" : FORMAT_FUNC | "__OSX_AVAILABLE_STARTING" : FORMAT_FUNC /* mjh - same sort of thing */ | "WEBKIT_OBJC_METHOD_ANNOTATION" : FORMAT_FUNC /* mjh - same sort of thing */ | "(void (^)" : VOID_BLOCK } /* mjh - we try to just ignore the parameter list */ SKIP : { "))" : DEFAULT } MORE: { < ~[")"] > } SKIP: { "\n" : DEFAULT } MORE: { "\\\n" | "\\\r\n" | < ~[] > } /* mjh - we try to just ignore the "(" whatever ")" */ SKIP : { ")" : DEFAULT } SPECIAL_TOKEN : { } MORE : { "\\\n" | "\\\r\n" | < ~[")"] > } /* COMMENTS */ MORE : { "/*" : IN_MULTI_LINE_COMMENT } SPECIAL_TOKEN : { } SPECIAL_TOKEN : { : DEFAULT } MORE : { < ~[] > } /* OPERATORS */ TOKEN : { < ASSIGN: "=" > | < LT: "<" > | < GT: ">" > | < BANG: "!" > | < TILDE: "~" > | < HOOK: "?" > | < COLON: ":" > | < EQ: "==" > | < LE: "<=" > | < GE: ">=" > | < NE: "!=" > | < SC_OR: "||" > | < SC_AND: "&&" > | < INCR: "++" > | < DECR: "--" > | < PLUS: "+" > | < MINUS: "-" > | < STAR: "*" > | < SLASH: "/" > | < BIT_AND: "&" > | < BIT_OR: "|" > | < XOR: "^" > | < REM: "%" > | < LSHIFT: "<<" > | < PLUSASSIGN: "+=" > | < MINUSASSIGN: "-=" > | < STARASSIGN: "*=" > | < SLASHASSIGN: "/=" > | < ANDASSIGN: "&=" > | < ORASSIGN: "|=" > | < XORASSIGN: "^=" > | < REMASSIGN: "%=" > | < LSHIFTASSIGN: "<<=" > | < RSIGNEDSHIFTASSIGN: ">>=" > | < RUNSIGNEDSHIFTASSIGN: ">>>=" > | < ELLIPSIS: "..." > } TOKEN : { < ESCAPE_SEQUENCE : "\\" ["'","\"","?","\\","a","b","f","n","r","t","v"] /* SIMPLE_ESCAPE_SEQUENCE */ | "\\" ( ()?)? /* OCTAL_ESCAPE_SEQUENCE */ | "\\" "x" ()+ /* HEX_ESCAPE_SEQUENCE */ > } TOKEN : { (["l","L"] | ("ul" | "UL") )? | (["l","L","U"])? | (["l","L"])?> | <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* | (["0"])+> | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> | <#OCTAL_LITERAL: "0" (["0"-"7"])*> | )? (["f","F","d","D"])? | "." (["0"-"9"])+ ()? (["f","F","d","D"])? | (["0"-"9"])+ (["f","F","d","D"])? | (["0"-"9"])+ ()? ["f","F","d","D"]> | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> | | | } TOKEN : { < DIGIT: ["0"-"9"] > | < NONZERO_DIGIT : ["1"-"9"] > | < OCTAL_DIGIT : ["1"-"7"] > | < #HEX_DIGIT : | ["a"-"f"] | ["A"-"F"] > | < #HEX_QUAD : > | < #UNSIGNED_SUFFIX : ["u","U"] | ("UL" | "ul") > | < #LONG_SUFFIX : ["l","L"] | ("LL" | "ll") > | < #INTEGER_SUFFIX : ()? | ()? > | < DECIMAL_CONSTANT : ()* > | < OCTAL_CONSTANT : "0" | > | < HEX_PREFIX : "0" ["x","X"] > | < HEX_CONSTANT : ()+ > } TOKEN : { < INTEGER_CONSTANT : ()? | ()? | ()? > } TOKEN : { } TOKEN : { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | } TOKEN : { | | | | | | } /* mjh - see ProtocolQualifier TOKEN : { } */ TOKEN : { } TOKEN : { | | | | | | } TOKEN : { | | | | | | | | | | | | | | | | | | | | | | | | } TOKEN : { | | | | } TOKEN : { | "_")*> | | "_")*> } TOKEN : { } TOKEN : { < IDENT : ( | )* > | <#IDENT_NONDIGIT : | > // "may include other implementation-defined characters" | <#NONDIGIT : ["a"-"z"] | ["A"-"Z"] | "_" | "$" | > | <#NONDIGIT_UNICODE : [ /* source: http://stackoverflow.com/questions/30933785 */ "\u0024", "\u0041"-"\u005a", "\u005f", "\u0061"-"\u007a", "\u00c0"-"\u00d6", "\u00d8"-"\u00f6", "\u00f8"-"\u00ff", "\u0100"-"\u1fff" ] > | <#UNIVERSAL_CHARACTER_NAME : ("\\u" ) | ("\\U" ) > } TOKEN : { } /*********************************************** * THE OBJECTIVEC LANGUAGE GRAMMAR STARTS HERE * ***********************************************/ void TranslationUnit() : {} { (ExternalDeclaration())+ } void ExternalDeclaration() : {} { ( LOOKAHEAD( FunctionDefinition() ) FunctionDefinition() | LOOKAHEAD(3) StrippedParens() /* mjh if we skip all but parens for something like __attribute__((__objc_exception__)) */ | Declaration() | LOOKAHEAD(3) ClassInterface() | LOOKAHEAD(3) ClassImplementation() | CategoryInterface() | CategoryImplementation() | ProtocolDeclaration() | ClassDeclarationList() ) } void StrippedParens() : {} /* See ExternalDeclaration above */ { [ StrippedParens() ] } void FunctionDefinition() : {} { [LOOKAHEAD(DeclarationSpecifiers()) DeclarationSpecifiers()] Declarator() [ DeclarationList() ] CompoundStatement() } void Declaration() : {} { DeclarationSpecifiers() [ InitDeclaratorList() ] [ "(" ParameterTypeList() ")" "(" ParameterTypeList() ")" ] /* ugly hack for single header typedef */ ";" } void ClassInterface() : {} { ClassName() (ColonSuperClassName())? (ProtocolReferenceList())? [ LOOKAHEAD(2) ["{"] ClassName() (ColonSuperClassName())? (ProtocolReferenceList())? ] /* dup for preprocessor #else */ (InstanceVariables())? (InterfaceDeclaration())* } void ClassImplementation() : {} { ClassName() (LOOKAHEAD(2) ColonSuperClassName())? (InstanceVariables())? (ImplementationDefinition())* } void CategoryInterface() : {} { ClassName() (CategoryName())? (ProtocolReferenceList())? (InterfaceDeclaration())* } void CategoryImplementation() : {} { ClassName() CategoryName() (ImplementationDefinition())* } void ProtocolDeclaration() : {} { ProtocolList() (ProtocolReferenceList())? ProtocolInterfaceDeclaration() ( | ";" ) } void ClassDeclarationList() : {} { ClassList() ";" } void ClassList() : {} { ClassName() ["," ClassList()] } void ProtocolReferenceList() : {} { ProtocolList() [ ProtocolList() /* if preproc #else, see AppKit NSWindow */ ] } void ProtocolList() : {} { ProtocolName() ["," ProtocolList()] } Token ObjCIDENT() : { Token t; } { t = { return t; } | t = { return t; } | t = { return t; } } void ClassName() : {} { ObjCIDENT() } void SuperClassName() : {} { ObjCIDENT() } void ColonSuperClassName() : {} { SuperClassName() } void CategoryName() : {} { | | } void ProtocolName() : {} { | | } void InstanceVariables() : {} { (InstanceVariableDeclaration())* [ ";" ] } void InstanceVariableDeclaration() : {} { VisibilitySpecification() | LOOKAHEAD(3) InstanceVariableDeclarator() | StructDeclaration() } void InstanceVariableDeclarator() : {} { ( LOOKAHEAD(3) [ IBOutlet() ] (LOOKAHEAD(2) ClassName() "*" | [ ProtocolReferenceList() ]) ";" | Declaration() ) } void VisibilitySpecification() : {} { [ ";" ] | | | } void IBOutlet() : {} /* mjh */ { } void ProtocolInterfaceDeclaration() : {} { (InterfaceDeclaration())* (QualifiedProtocolInterfaceDeclaration())* } void QualifiedProtocolInterfaceDeclaration() : {} { (InterfaceDeclaration())* | (InterfaceDeclaration())* } void InterfaceDeclaration() : {} { Declaration() | PropertyDeclaration() | MethodDeclaration() } void PropertyDeclaration() : {} { (PropertyAttributesDeclaration())? ( LOOKAHEAD(3) StructDeclaration() | (ProtocolReferenceList())? ";" ) } void PropertyAttributesDeclaration() : {} { PropertyAttributesList() } void PropertyAttributesList() : {} { PropertyAttribute() ["," PropertyAttributesList()] } void PropertyAttribute() : {} { LOOKAHEAD(3) /* prop */ [ ] // setter // | LOOKAHEAD(2) /* getter or ivar */ // getter ivar | // nonatomic, readwrite, readonly, retain, assign, copy | /* NS_NONATOMIC_IPHONEONLY */ } void MethodDeclaration() : {} { ClassMethodDeclaration() | InstanceMethodDeclaration() } void ClassMethodDeclaration() : {} { (MethodType())? MethodSelector() } void InstanceMethodDeclaration() : {} { (MethodType())? MethodSelector() } void ImplementationDefinition() : {} { ( LOOKAHEAD( FunctionDefinition() ) FunctionDefinition() | Declaration() | PropertyImplementation() | MethodDefinition() ) } void PropertyImplementation() : {} { PropertySynthesizeList() | PropertySynthesizeList() } void PropertySynthesizeList() : {} { PropertySynthesizeItem() ["," PropertySynthesizeList()] /* PropertySynthesizeList() "," PropertySynthesizeItem() | PropertySynthesizeItem() */ } void PropertySynthesizeItem() : {} { LOOKAHEAD(2) | } void MethodDefinition() : {} { ClassMethodDefinition() | InstanceMethodDefinition() } void ClassMethodDefinition() : {} { (MethodType())? MethodSelectorNoList() (Declaration())* ()? CompoundStatement() } void InstanceMethodDefinition() : {} { (MethodType())? MethodSelectorNoList() (Declaration())* ()? CompoundStatement() } void MethodSelectorNoList() : {} { LOOKAHEAD(3) KeywordSelector() [LOOKAHEAD(2) (",..." | "," "...")] | UnarySelector() } void MethodSelector() : {} { LOOKAHEAD(3) MethodSelectorNoList() | KeywordSelector() "," ParameterTypeList() // this is correct according to objcbook, but causes conflict if followed by declaration* } void UnarySelector() : {} { Selector() } void KeywordSelector() : {} { (LOOKAHEAD(2) KeywordDeclarator())+ } void KeywordDeclarator() : {} { (Selector())? (MethodType())? } void Selector() : {} { } void MethodType() : {} { (LOOKAHEAD(3) Block() | TypeNameWithUnknownType()) } void SelectorExpression() : {} { SelectorName() } void SelectorName() : {} { LOOKAHEAD(2) Selector() | (KeywordName())+ } void KeywordName() : {} { (Selector())? } void ProtocolExpression() : {} { ProtocolName() } void EncodeExpression() : {} { TypeNameWithUnknownType() } void DeclarationList() : {} { ( LOOKAHEAD(Declaration()) Declaration() )+ } void DeclarationSpecifiers() : {} { /** * We enumerate the possibilities (closure?) like SpecifierQualifierList * instead of the standard C grammar recursive definition * Although more complex it might actually end up cleaner? * (For one thing you don't keep recursively matching types * in TypeSpecifier(), this can muddle things or require semantic lookahead * workarounds, see the sample javacc C implementation of this nonterminal) * * Assumes none actually should be duplicated */ LOOKAHEAD(3) TypeSpecifier() [ StorageClassSpecifier() ] [ TypeQualifier() ] | TypeSpecifier() [ TypeQualifier() ] [ StorageClassSpecifier() ] | LOOKAHEAD(3) StorageClassSpecifier() [ TypeQualifier() ] [ LOOKAHEAD(2) TypeSpecifier() ] | LOOKAHEAD(3) StorageClassSpecifier() [ LOOKAHEAD(2) TypeSpecifier() ] [ TypeQualifier() ] | LOOKAHEAD(3) TypeQualifier() [ StorageClassSpecifier() ] [ LOOKAHEAD(2) TypeSpecifier() ] | LOOKAHEAD(2) TypeQualifier() [ LOOKAHEAD(2) TypeSpecifier() ] [ StorageClassSpecifier() ] } void StorageClassSpecifier() : {} { ( | | | | { typedefParsingStack.push(Boolean.TRUE); } ) } void TypeSpecifier() : {} { ( GreedyFixedNumType() | | | | | | /* mjh - same as void */ | | /* Cocoa additions */ | | | | | | | | | /* mjh - more cocoa additions */ | | /* CoreFoundation additions */ | | StructOrUnionSpecifier() | EnumSpecifier() | LOOKAHEAD( { isType(getToken(1).image) } )TypedefName() | PossibleCocoaType() | PossibleCoreType() | PossibleUnknownType() ) } void GreedyFixedNumType() : {} { LOOKAHEAD(2) [ | ] [ LOOKAHEAD(2) ] /* long long */ | | } void PossibleCocoaType() : { Token t; } { t = { if (verbose) System.out.println("WARNING: Adding typedef on possible Cocoa type " + t.getImage() + " at " + t.getReportLocation().startPosToString()); addType(t.getImage()); } } void PossibleCoreType() : { Token t; } { t = { if (verbose) System.out.println("WARNING: Adding typedef on possible CoreFoundation type " + t.getImage() + " at " + t.getReportLocation().startPosToString()); addType(t.getImage()); } } void PossibleUnknownType() : { Token t; } { t = { if (verbose) System.out.println("WARNING: Adding typedef on unknown identifier " + t.getImage() + " at " + t.getReportLocation().startPosToString()); addType(t.getImage()); } } void TypeSpecifierWithUnknownType() : {} { LOOKAHEAD(2) (ObjCIDENT() | ) (ProtocolReferenceList())? | TypeSpecifier() } void TypeQualifier() : {} { ( | ) } void StructOrUnionSpecifier() : {} { { typedefParsingStack.push(Boolean.FALSE); } StructOrUnion() ( LOOKAHEAD(3) [ LOOKAHEAD(2) ObjCIDENT() ] ( "{" StructDeclarationList() "}" | ObjCIDENT() ) | ) { typedefParsingStack.pop(); } } void StructOrUnion() : {} { ( | ) } void StructDeclarationList() : {} { (StructDeclaration())+ } void InitDeclaratorList() : {} { InitDeclarator() ("," InitDeclarator())* { // Finished with a typedefDeclaration?? if(!(typedefParsingStack.empty()) && ((Boolean)typedefParsingStack.peek()).booleanValue()){ typedefParsingStack.pop(); } } } void InitDeclarator() : {} { Declarator() [ "=" Initializer() ] } void ProtocolQualifier() : {} { | /* */ In() /* Making it a IN_KEYWORD token disallows other uses */ } void In() : {} { LOOKAHEAD( { getToken(0).image.equals("in") } ) } void StructDeclaration() : {} { SpecifierQualifierList() ( StructDeclaratorList() | "[" ConstantExpression() "]" ) ";" } void SpecifierQualifierWithUnknownType() : {} { LOOKAHEAD(2) TypeSpecifierWithUnknownType() | TypeQualifier() | ProtocolQualifier() } void SpecifierQualifierList() : {} { /** * Since we don't know what all possible typedef's might be and end up matching any as a possible type * we could recursively match both tokens in something like... * CFIndex version; * to PossibleUnknownType() in TypeSpecifier(). * So we don't follow the elegant C recursive definition but enumeratte the two possible combinations */ TypeSpecifier() [ TypeQualifier() ] | TypeQualifier() TypeSpecifier() } void StructDeclaratorList() : {} { StructDeclarator() ( "," StructDeclarator() )* } void StructDeclarator() : {} { Declarator() } void EnumSpecifier() : {} { ( LOOKAHEAD(3) [ ObjCIDENT() ] "{" EnumeratorList() "}" | ) } void EnumeratorList() : {} { Enumerator() ("," [ Enumerator() ])* } void Enumerator() : {} { ObjCIDENT() [ "=" ConstantExpression() ] } void Declarator() : {} { LOOKAHEAD(3) Block() | LOOKAHEAD(3) [ Pointer() ] DirectDeclarator() [ ":" ConstantExpression() ] | ":" ConstantExpression() | LOOKAHEAD(2) TypeSpecifier() // trying to handle 'typedef type-spec type-spec' special case, a little ugly } void Block() : {} { ( LOOKAHEAD(3) | | | ObjCIDENT() [ "*" ])? [ ObjCIDENT() ] ParameterList() } void DirectDeclarator() : { Token t;} { ( t = ObjCIDENT() { if(!(typedefParsingStack.empty()) && ((Boolean)typedefParsingStack.peek()).booleanValue()){ addType(t.getImage()); } } | LOOKAHEAD(3) "(" Declarator() ")" ) { typedefParsingStack.push( Boolean.FALSE ); } ( "[" [ ConstantExpression() ] "]" | LOOKAHEAD(3) "(" ParameterTypeList() ")" | "(" [ IdentifierList() ] ")" )* { typedefParsingStack.pop(); } } void Pointer() : {} { "*" [ TypeQualifierList() ] [ Pointer() ] } void TypeQualifierList() : {} { (TypeQualifier())+ } void ParameterTypeList() : {} { ParameterList() ["," "..." ] } void ParameterList() : {} { ParameterDeclaration() (LOOKAHEAD(2) "," ParameterDeclaration())* } void ParameterDeclaration() : {} { DeclarationSpecifiers() ( LOOKAHEAD(Declarator()) Declarator() | [ AbstractDeclarator() ] ) } void IdentifierList() : {} { ("," )* } void Initializer() : {} { ( AssignmentExpression() | "{" InitializerList() [","] "}" ) } void InitializerList() : {} { Initializer() (LOOKAHEAD(2) "," Initializer())* } void TypeName() : {} { SpecifierQualifierList() [ AbstractDeclarator() ] } void TypeNameWithUnknownType() : {} { (SpecifierQualifierWithUnknownType())+ (AbstractDeclarator())? } void AbstractDeclarator() : {} { ( LOOKAHEAD(3) Pointer() | [Pointer()] DirectAbstractDeclarator() ) } void DirectAbstractDeclarator() : {} { ( LOOKAHEAD(2) "(" AbstractDeclarator() ")" | "[" [ConstantExpression()] "]" | "(" [ParameterTypeList()] ")" ) ( "[" [ ConstantExpression() ] "]" | "(" [ ParameterTypeList() ] ")" )* } void TypedefName() : {} { ObjCIDENT() } void Statement() : {} { ( LOOKAHEAD(2) LabeledStatement() | LOOKAHEAD(3) InitStatement() | ExpressionStatement() | CompoundStatement() | SelectionStatement() | IterationStatement() | JumpStatement() ) } void LabeledStatement() : {} { ( ":" Statement() | ConstantExpression() ":" Statement() | ":" Statement() ) } void InitStatement() : {} /* mjh not part of normal C grammar but works */ { [ LOOKAHEAD(2) TypeSpecifier() ] ["*"] ("," )* ("=" ( LOOKAHEAD(3) MessageExpression() | PostfixExpression() ) ( ";" | "," InitStatement() ) | ";") /* catch embedded variable declarations */ } void ExpressionStatement() : {} { [ Expression() ] ";" } void CompoundStatement() : {} { "{" ( LOOKAHEAD(DeclarationList()) DeclarationList() | StatementList() )* "}" } void StatementList() : {} { (LOOKAHEAD(2) Statement())+ } void SelectionStatement() : {} { ( "(" [ LOOKAHEAD(2) NestedLogicalExpression() ] Expression() ")" Statement() [ LOOKAHEAD(2) Statement() ] | "(" Expression() ")" Statement() ) } void NestedLogicalExpression() : {} /* mjh - introduced as part of nesting handling */ { "(" [ LOOKAHEAD(2) NestedLogicalExpression() ] Expression() ")" LogicalOperator() } void LogicalOperator() : {} /* mjh - introduced as part of nesting handling */ { | | | } void IterationStatement() : {} { ( "(" Expression() ")" Statement() | Statement() "(" Expression() ")" ";" | "(" ( LOOKAHEAD(3) TypeSpecifier() In() PrimaryExpression() | [ LOOKAHEAD(NumberTypeInit()) NumberTypeInit() ] [ Expression() ] ";" [ Expression() ] ";" [ Expression() ] ) ")" Statement() ) } void NumberTypeInit() : {} /* mjh - allow number type initializers, e.g. on 'for' statement inits */ { ( | | ) } void JumpStatement() : {} { ( ";" | ";" | ";" | [ Expression() ] ";" ) } void Expression() : {} { AssignmentExpression() ( "," AssignmentExpression() )* } void AssignmentExpression() : {} { LOOKAHEAD(UnaryExpression() AssignmentOperator()) UnaryExpression() AssignmentOperator() AssignmentExpression() | LOOKAHEAD(3) ConditionalExpression() } void AssignmentOperator() : {} { ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" ) } void ConditionalExpression() : {} { LogicalORExpression() [ "?" Expression() ":" ConditionalExpression() ] } void ConstantExpression() : {} { ConditionalExpression() } void LogicalORExpression() : {} { LogicalANDExpression() [ "||" (LOOKAHEAD(3) LogicalORExpression() | NestedLogicalExpression()) ] } void LogicalANDExpression() : {} { InclusiveORExpression() [ "&&" (LOOKAHEAD(3) LogicalANDExpression() | NestedLogicalExpression()) ] } void InclusiveORExpression() : {} { ExclusiveORExpression() [ "|" InclusiveORExpression() ] } void ExclusiveORExpression() : {} { ANDExpression() [ "^" ExclusiveORExpression() ] } void ANDExpression() : {} { EqualityExpression() [ "&" ANDExpression() ] } void EqualityExpression() : {} { RelationalExpression() [ ( "==" | "!=" ) EqualityExpression() ] } void RelationalExpression() : {} { ShiftExpression() [ ( "<" | ">" | "<=" | ">=" ) RelationalExpression() ] } void ShiftExpression() : {} { AdditiveExpression() [ ( "<<" | ">>" ) ShiftExpression() ] } void AdditiveExpression() : {} { MultiplicativeExpression() [ ( "+" | "-" ) AdditiveExpression() ] } void MultiplicativeExpression() : {} { CastExpression() [ ( "*" | "/" | "%" ) MultiplicativeExpression() ] } void CastExpression() : {} { LOOKAHEAD("(" TypeName() ")" CastExpression() ) "(" TypeName() ")" CastExpression() | // LOOKAHEAD(3) "(" TypeSpecifier() ")" CastExpression() | UnaryExpression() } void UnaryExpression() : {} { ( LOOKAHEAD(3) PostfixExpression() | "++" UnaryExpression() | "--" UnaryExpression() | UnaryOperator() CastExpression() | ( LOOKAHEAD(UnaryExpression() ) UnaryExpression() | "(" TypeName() ")" ) ) } void UnaryOperator() : {} { ( "&" | "*" | "+" | "-" | "~" | "!" ) } void PostfixExpression() : {} { | /* mjh */ PrimaryExpression() ( "[" Expression() "]" | "(" [ LOOKAHEAD(ArgumentExpressionList() ) ArgumentExpressionList() ] ")" | "." | "->" | "++" | "--" )* } void PrimaryExpression() : {} { ( ObjCIDENT() | Constant() | "(" Expression() ")" | MessageExpression() | SelectorExpression() | ProtocolExpression() | EncodeExpression() ) } void MessageExpression() : {} { Receiver() MessageSelector() } void Receiver() : {} { LOOKAHEAD(2) Expression() // catches 'self' and 'super' as ident | TypeDefedIDENT() } void TypeDefedIDENT() : {} { | | | | } void MessageSelector() : {} { LOOKAHEAD(2) (KeywordArgument())+ | } void KeywordArgument() : {} { LOOKAHEAD(3) Expression() | | LOOKAHEAD(2) | Expression() } void ArgumentExpressionList() : {} { AssignmentExpression() ( "," AssignmentExpression() )* } void Constant() : {} { | | | | | }