// Code generated by yy. DO NOT EDIT. %{ // Copyright 2016 The CC Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Based on [0], 6.10. Substantial portions of expression AST size // optimizations are from [2], license of which follows. // ---------------------------------------------------------------------------- // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This grammar is derived from the C grammar in the 'ansitize' // program, which carried this notice: // // Copyright (c) 2006 Russ Cox, // Massachusetts Institute of Technology // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated // documentation files (the "Software"), to deal in the // Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall // be included in all copies or substantial portions of the // Software. // // The software is provided "as is", without warranty of any // kind, express or implied, including but not limited to the // warranties of merchantability, fitness for a particular // purpose and noninfringement. In no event shall the authors // or copyright holders be liable for any claim, damages or // other liability, whether in an action of contract, tort or // otherwise, arising from, out of or in connection with the // software or the use or other dealings in the software. package cc import ( "fmt" "modernc.org/xc" "modernc.org/golex/lex" ) %} %union { Token xc.Token groupPart Node node Node toks PPTokenList } %token '!' '%' '&' '(' ')' '*' '+' ',' '-' '.' '/' ':' ';' '<' '=' '>' '?' '[' '\n' ']' '^' '{' '|' '}' '~' ADDASSIGN "+=" ALIGNOF "_Alignof" ANDAND "&&" ANDASSIGN "&=" ARROW "->" ASM "asm" AUTO "auto" BOOL "_Bool" BREAK "break" CASE "case" CAST CHAR "char" CHARCONST "character constant" COMPLEX "_Complex" CONST "const" CONSTANT_EXPRESSION 1048577 "constant expression prefix" CONTINUE "continue" DDD "..." DEC "--" DEFAULT "default" DIVASSIGN "/=" DO "do" DOUBLE "double" ELSE "else" ENUM "enum" EQ "==" EXTERN "extern" FLOAT "float" FLOATCONST "floating-point constant" FOR "for" GEQ ">=" GOTO "goto" IDENTIFIER "identifier" IDENTIFIER_LPAREN "identifier immediatelly followed by '('" IDENTIFIER_NONREPL "non replaceable identifier" IF "if" INC "++" INLINE "inline" INT "int" INTCONST "integer constant" LEQ "<=" LONG "long" LONGCHARCONST "long character constant" LONGSTRINGLITERAL "long string constant" LSH "<<" LSHASSIGN "<<=" MODASSIGN "%=" MULASSIGN "*=" NEQ "!=" NOELSE NORETURN "_Noreturn" NOSEMI ORASSIGN "|=" OROR "||" PPDEFINE "#define" PPELIF "#elif" PPELSE "#else" PPENDIF "#endif" PPERROR "#error" PPHASH_NL "#" PPHEADER_NAME "header name" PPIF "#if" PPIFDEF "#ifdef" PPIFNDEF "#ifndef" PPINCLUDE "#include" PPINCLUDE_NEXT "#include_next" PPLINE "#line" PPNONDIRECTIVE "#foo" PPNUMBER "preprocessing number" PPOTHER "ppother" PPPASTE "##" PPPRAGMA "#pragma" PPUNDEF "#undef" PREPROCESSING_FILE 1048576 "preprocessing file prefix" REGISTER "register" RESTRICT "restrict" RETURN "return" RSH ">>" RSHASSIGN ">>=" SHORT "short" SIGNED "signed" SIZEOF "sizeof" STATIC "static" STATIC_ASSERT "_Static_assert" STRINGLITERAL "string literal" STRUCT "struct" SUBASSIGN "-=" SWITCH "switch" TRANSLATION_UNIT 1048578 "translation unit prefix" TYPEDEF "typedef" TYPEDEFNAME "typedefname" TYPEOF "typeof" UNARY UNION "union" UNSIGNED "unsigned" VOID "void" VOLATILE "volatile" WHILE "while" XORASSIGN "^=" %type GroupPart "group part" %type AbstractDeclarator "abstract declarator" AbstractDeclaratorOpt "optional abstract declarator" ArgumentExpressionList "argument expression list" ArgumentExpressionListOpt "optional argument expression list" AssemblerInstructions "assembler instructions" AssemblerOperand "assembler operand" AssemblerOperands "assembler operands" AssemblerStatement "assembler statement" AssemblerSymbolicNameOpt "optional assembler symbolic name" BasicAssemblerStatement "basic assembler statement" BlockItem "block item" BlockItemList "block item list" BlockItemListOpt "optional block item list" Clobbers "clobbers" CommaOpt "optional comma" CompoundStatement "compound statement" ConstantExpression "constant expression" ControlLine "control line" Declaration "declaration" DeclarationList "declaration list" DeclarationListOpt "optional declaration list" DeclarationSpecifiers "declaration specifiers" DeclarationSpecifiersOpt "optional declaration specifiers" Declarator "declarator" DeclaratorOpt "optional declarator" Designation "designation" DesignationOpt "optional designation" Designator "designator" DesignatorList "designator list" DirectAbstractDeclarator "direct abstract declarator" DirectAbstractDeclaratorOpt "optional direct abstract declarator" DirectDeclarator "direct declarator" ElifGroup "elif group" ElifGroupList "elif group list" ElifGroupListOpt "optional elif group list" ElseGroup "else group" ElseGroupOpt "optional else group" EndifLine "endif line" EnumSpecifier "enum specifier" EnumerationConstant "enumearation constant" Enumerator "enumerator" EnumeratorList "enumerator list" Expression "expression" ExpressionList "expression list" ExpressionListOpt "optional expression list" ExpressionOpt "optional expression" ExpressionStatement "expression statement" ExternalDeclaration "external declaration" FunctionBody "function body" FunctionDefinition "function definition" FunctionSpecifier "function specifier" GroupList "group list" GroupListOpt "optional group list" IdentifierList "identifier list" IdentifierListOpt "optional identifier list" IdentifierOpt "optional identifier" IfGroup "if group" IfSection "if section" InitDeclarator "init declarator" InitDeclaratorList "init declarator list" InitDeclaratorListOpt "optional init declarator list" Initializer "initializer" InitializerList "initializer list" IterationStatement "iteration statement" JumpStatement "jump statement" LabeledStatement "labeled statement" PPTokens ParameterDeclaration "parameter declaration" ParameterList "parameter list" ParameterTypeList "parameter type list" ParameterTypeListOpt "optional parameter type list" Pointer "pointer" PointerOpt "optional pointer" PreprocessingFile "preprocessing file" SelectionStatement "selection statement" SpecifierQualifierList "specifier qualifier list" SpecifierQualifierListOpt "optional specifier qualifier list" Start Statement "statement" StaticAssertDeclaration "static assert declaration" StorageClassSpecifier "storage class specifier" StructDeclaration "struct declaration" StructDeclarationList "struct declaration list" StructDeclarator "struct declarator" StructDeclaratorList "struct declarator list" StructOrUnion "struct-or-union" StructOrUnionSpecifier "struct-or-union specifier" TranslationUnit "translation unit" TypeName "type name" TypeQualifier "type qualifier" TypeQualifierList "type qualifier list" TypeQualifierListOpt "optional type qualifier list" TypeSpecifier "type specifier" VolatileOpt "optional volatile" %type PPTokenList "token list" PPTokenListOpt "optional token list" ReplacementList "replacement list" TextLine "text line" %precedence NOSEMI %precedence ';' %precedence NOELSE %precedence ELSE %right '=' ADDASSIGN ANDASSIGN DIVASSIGN LSHASSIGN MODASSIGN MULASSIGN ORASSIGN RSHASSIGN SUBASSIGN XORASSIGN %right ':' '?' %left OROR %left ANDAND %left '|' %left '^' %left '&' %left EQ NEQ %left '<' '>' GEQ LEQ %left LSH RSH %left '+' '-' %left '%' '*' '/' %precedence CAST %left '!' '~' SIZEOF UNARY %right '(' '.' '[' ARROW DEC INC %start Start %% Start: PREPROCESSING_FILE { lx := yylex.(*lexer) lx.preprocessingFile = nil } PreprocessingFile { lx := yylex.(*lexer) lx.preprocessingFile = $3.(*PreprocessingFile) } | CONSTANT_EXPRESSION { lx := yylex.(*lexer) lx.constantExpression = nil } ConstantExpression { lx := yylex.(*lexer) lx.constantExpression = $3.(*ConstantExpression) } | TRANSLATION_UNIT { lx := yylex.(*lexer) lx.translationUnit = nil } TranslationUnit { lx := yylex.(*lexer) if lx.report.Errors(false) == nil && lx.scope.kind != ScopeFile { panic("internal error") } lx.translationUnit = $3.(*TranslationUnit).reverse() lx.translationUnit.Declarations = lx.scope } EnumerationConstant: IDENTIFIER { $$ = &EnumerationConstant{ Token: $1, } } ArgumentExpressionList: Expression { $$ = &ArgumentExpressionList{ Expression: $1.(*Expression), } } | ArgumentExpressionList ',' Expression { $$ = &ArgumentExpressionList{ Case: 1, ArgumentExpressionList: $1.(*ArgumentExpressionList), Token: $2, Expression: $3.(*Expression), } } ArgumentExpressionListOpt: /* empty */ { $$ = (*ArgumentExpressionListOpt)(nil) } | ArgumentExpressionList { $$ = &ArgumentExpressionListOpt{ ArgumentExpressionList: $1.(*ArgumentExpressionList).reverse(), } } Expression: IDENTIFIER %prec NOSEMI { lx := yylex.(*lexer) lhs := &Expression{ Token: $1, } $$ = lhs lhs.scope = lx.scope } | CHARCONST { $$ = &Expression{ Case: 1, Token: $1, } } | FLOATCONST { $$ = &Expression{ Case: 2, Token: $1, } } | INTCONST { $$ = &Expression{ Case: 3, Token: $1, } } | LONGCHARCONST { $$ = &Expression{ Case: 4, Token: $1, } } | LONGSTRINGLITERAL { $$ = &Expression{ Case: 5, Token: $1, } } | STRINGLITERAL { $$ = &Expression{ Case: 6, Token: $1, } } | '(' ExpressionList ')' { $$ = &Expression{ Case: 7, Token: $1, ExpressionList: $2.(*ExpressionList).reverse(), Token2: $3, } } | Expression '[' ExpressionList ']' { $$ = &Expression{ Case: 8, Expression: $1.(*Expression), Token: $2, ExpressionList: $3.(*ExpressionList).reverse(), Token2: $4, } } | Expression '(' ArgumentExpressionListOpt ')' { lx := yylex.(*lexer) lhs := &Expression{ Case: 9, Expression: $1.(*Expression), Token: $2, ArgumentExpressionListOpt: $3.(*ArgumentExpressionListOpt), Token2: $4, } $$ = lhs o := lhs.ArgumentExpressionListOpt if o == nil { break } if lhs.Expression.Case == 0 { // IDENTIFIER if lx.tweaks.enableBuiltinConstantP &&lhs.Expression.Token.Val == idBuiltinConstantP { break } b := lhs.Expression.scope.Lookup(NSIdentifiers, lhs.Expression.Token.Val) if b.Node == nil && lx.tweaks.enableImplicitFuncDef { for l := o.ArgumentExpressionList; l != nil; l = l.ArgumentExpressionList { l.Expression.eval(lx) } break } } lhs.Expression.eval(lx) for l := o.ArgumentExpressionList; l != nil; l = l.ArgumentExpressionList { l.Expression.eval(lx) } } | Expression '.' IDENTIFIER { $$ = &Expression{ Case: 10, Expression: $1.(*Expression), Token: $2, Token2: $3, } } | Expression "->" IDENTIFIER { $$ = &Expression{ Case: 11, Expression: $1.(*Expression), Token: $2, Token2: $3, } } | Expression "++" { $$ = &Expression{ Case: 12, Expression: $1.(*Expression), Token: $2, } } | Expression "--" { $$ = &Expression{ Case: 13, Expression: $1.(*Expression), Token: $2, } } | '(' TypeName ')' '{' InitializerList CommaOpt '}' { $$ = &Expression{ Case: 14, Token: $1, TypeName: $2.(*TypeName), Token2: $3, Token3: $4, InitializerList: $5.(*InitializerList).reverse(), CommaOpt: $6.(*CommaOpt), Token4: $7, } } | "++" Expression { $$ = &Expression{ Case: 15, Token: $1, Expression: $2.(*Expression), } } | "--" Expression { $$ = &Expression{ Case: 16, Token: $1, Expression: $2.(*Expression), } } | '&' Expression %prec UNARY { $$ = &Expression{ Case: 17, Token: $1, Expression: $2.(*Expression), } } | '*' Expression %prec UNARY { $$ = &Expression{ Case: 18, Token: $1, Expression: $2.(*Expression), } } | '+' Expression %prec UNARY { $$ = &Expression{ Case: 19, Token: $1, Expression: $2.(*Expression), } } | '-' Expression %prec UNARY { $$ = &Expression{ Case: 20, Token: $1, Expression: $2.(*Expression), } } | '~' Expression { $$ = &Expression{ Case: 21, Token: $1, Expression: $2.(*Expression), } } | '!' Expression { $$ = &Expression{ Case: 22, Token: $1, Expression: $2.(*Expression), } } | "sizeof" Expression { $$ = &Expression{ Case: 23, Token: $1, Expression: $2.(*Expression), } } | "sizeof" '(' TypeName ')' %prec SIZEOF { $$ = &Expression{ Case: 24, Token: $1, Token2: $2, TypeName: $3.(*TypeName), Token3: $4, } } | '(' TypeName ')' Expression %prec CAST { $$ = &Expression{ Case: 25, Token: $1, TypeName: $2.(*TypeName), Token2: $3, Expression: $4.(*Expression), } } | Expression '*' Expression { $$ = &Expression{ Case: 26, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '/' Expression { $$ = &Expression{ Case: 27, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '%' Expression { $$ = &Expression{ Case: 28, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '+' Expression { $$ = &Expression{ Case: 29, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '-' Expression { $$ = &Expression{ Case: 30, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "<<" Expression { $$ = &Expression{ Case: 31, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression ">>" Expression { $$ = &Expression{ Case: 32, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '<' Expression { $$ = &Expression{ Case: 33, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '>' Expression { $$ = &Expression{ Case: 34, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "<=" Expression { $$ = &Expression{ Case: 35, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression ">=" Expression { $$ = &Expression{ Case: 36, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "==" Expression { $$ = &Expression{ Case: 37, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "!=" Expression { $$ = &Expression{ Case: 38, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '&' Expression { $$ = &Expression{ Case: 39, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '^' Expression { $$ = &Expression{ Case: 40, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '|' Expression { $$ = &Expression{ Case: 41, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "&&" Expression { $$ = &Expression{ Case: 42, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "||" Expression { $$ = &Expression{ Case: 43, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression '?' ExpressionList ':' Expression { $$ = &Expression{ Case: 44, Expression: $1.(*Expression), Token: $2, ExpressionList: $3.(*ExpressionList).reverse(), Token2: $4, Expression2: $5.(*Expression), } } | Expression '=' Expression { $$ = &Expression{ Case: 45, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "*=" Expression { $$ = &Expression{ Case: 46, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "/=" Expression { $$ = &Expression{ Case: 47, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "%=" Expression { $$ = &Expression{ Case: 48, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "+=" Expression { $$ = &Expression{ Case: 49, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "-=" Expression { $$ = &Expression{ Case: 50, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "<<=" Expression { $$ = &Expression{ Case: 51, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression ">>=" Expression { $$ = &Expression{ Case: 52, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "&=" Expression { $$ = &Expression{ Case: 53, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "^=" Expression { $$ = &Expression{ Case: 54, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | Expression "|=" Expression { $$ = &Expression{ Case: 55, Expression: $1.(*Expression), Token: $2, Expression2: $3.(*Expression), } } | "_Alignof" '(' TypeName ')' { $$ = &Expression{ Case: 56, Token: $1, Token2: $2, TypeName: $3.(*TypeName), Token3: $4, } } | '(' CompoundStatement ')' { $$ = &Expression{ Case: 57, Token: $1, CompoundStatement: $2.(*CompoundStatement), Token2: $3, } } | "&&" IDENTIFIER { lx := yylex.(*lexer) lhs := &Expression{ Case: 58, Token: $1, Token2: $2, } $$ = lhs if !lx.tweaks.enableComputedGotos { lx.report.Err(lhs.Pos(), "computed gotos not enabled") } } | Expression '?' ':' Expression { lx := yylex.(*lexer) lhs := &Expression{ Case: 59, Expression: $1.(*Expression), Token: $2, Token2: $3, Expression2: $4.(*Expression), } $$ = lhs if !lx.tweaks.enableOmitConditionalOperand { lx.report.Err(lhs.Pos(), "omitting conditional operand not enabled") } } ExpressionOpt: /* empty */ { $$ = (*ExpressionOpt)(nil) } | Expression { lx := yylex.(*lexer) lhs := &ExpressionOpt{ Expression: $1.(*Expression), } $$ = lhs lhs.Expression.eval(lx) } ExpressionList: Expression { $$ = &ExpressionList{ Expression: $1.(*Expression), } } | ExpressionList ',' Expression { $$ = &ExpressionList{ Case: 1, ExpressionList: $1.(*ExpressionList), Token: $2, Expression: $3.(*Expression), } } ExpressionListOpt: /* empty */ { $$ = (*ExpressionListOpt)(nil) } | ExpressionList { lx := yylex.(*lexer) lhs := &ExpressionListOpt{ ExpressionList: $1.(*ExpressionList).reverse(), } $$ = lhs lhs.ExpressionList.eval(lx) } ConstantExpression: { lx := yylex.(*lexer) lx.constExprToks = []xc.Token{lx.last} } Expression { lx := yylex.(*lexer) lhs := &ConstantExpression{ Expression: $2.(*Expression), } $$ = lhs lhs.Value, lhs.Type = lhs.Expression.eval(lx) if lhs.Value == nil { lx.report.Err(lhs.Pos(), "not a constant expression") } l := lx.constExprToks lhs.toks = l[:len(l)-1] lx.constExprToks = nil } Declaration: DeclarationSpecifiers InitDeclaratorListOpt ';' { lx := yylex.(*lexer) lhs := &Declaration{ DeclarationSpecifiers: $1.(*DeclarationSpecifiers), InitDeclaratorListOpt: $2.(*InitDeclaratorListOpt), Token: $3, } $$ = lhs ts0 := lhs.DeclarationSpecifiers.typeSpecifiers() if ts0 == 0 && lx.tweaks.enableImplicitIntType { lhs.DeclarationSpecifiers.typeSpecifier = tsEncode(tsInt) } ts := tsDecode(lhs.DeclarationSpecifiers.typeSpecifiers()) ok := false for _, v := range ts { if v == tsStructSpecifier || v == tsUnionSpecifier { ok = true break } } if ok { s := lhs.DeclarationSpecifiers d := &Declarator{specifier: s} dd := &DirectDeclarator{ Token: xc.Token{Char: lex.NewChar(lhs.Pos(), 0)}, declarator: d, idScope: lx.scope, specifier: s, } d.DirectDeclarator = dd d.setFull(lx) for l := lhs.DeclarationSpecifiers; l != nil; { ts := l.TypeSpecifier if ts != nil && ts.Case == 11 && ts.StructOrUnionSpecifier.Case == 0 { // StructOrUnion IdentifierOpt '{' StructDeclarationList '}' ts.StructOrUnionSpecifier.declarator = d break } if o := l.DeclarationSpecifiersOpt; o != nil { l = o.DeclarationSpecifiers continue } break } } o := lhs.InitDeclaratorListOpt if o != nil { break } s := lhs.DeclarationSpecifiers d := &Declarator{specifier: s} dd := &DirectDeclarator{ Token: xc.Token{Char: lex.NewChar(lhs.Pos(), 0)}, declarator: d, idScope: lx.scope, specifier: s, } d.DirectDeclarator = dd d.setFull(lx) lhs.declarator = d } | StaticAssertDeclaration { $$ = &Declaration{ Case: 1, StaticAssertDeclaration: $1.(*StaticAssertDeclaration), } } DeclarationSpecifiers: StorageClassSpecifier DeclarationSpecifiersOpt { lx := yylex.(*lexer) lhs := &DeclarationSpecifiers{ StorageClassSpecifier: $1.(*StorageClassSpecifier), DeclarationSpecifiersOpt: $2.(*DeclarationSpecifiersOpt), } $$ = lhs lx.scope.specifier = lhs a := lhs.StorageClassSpecifier b := lhs.DeclarationSpecifiersOpt if b == nil { lhs.attr = a.attr break } if a.attr&b.attr != 0 { lx.report.Err(a.Pos(), "invalid storage class specifier") break } lhs.attr = a.attr|b.attr lhs.typeSpecifier = b.typeSpecifier if lhs.StorageClassSpecifier.Case != 0 /* "typedef" */ && lhs.IsTypedef() { lx.report.Err(a.Pos(), "invalid storage class specifier") } } | TypeSpecifier DeclarationSpecifiersOpt { lx := yylex.(*lexer) lhs := &DeclarationSpecifiers{ Case: 1, TypeSpecifier: $1.(*TypeSpecifier), DeclarationSpecifiersOpt: $2.(*DeclarationSpecifiersOpt), } $$ = lhs lx.scope.specifier = lhs a := lhs.TypeSpecifier b := lhs.DeclarationSpecifiersOpt if b == nil { lhs.typeSpecifier = a.typeSpecifier break } lhs.attr = b.attr tsb := tsDecode(b.typeSpecifier) if len(tsb) == 1 && tsb[0] == tsTypedefName && lx.tweaks.allowCompatibleTypedefRedefinitions { tsb[0] = 0 } ts := tsEncode(append(tsDecode(a.typeSpecifier), tsb...)...) if _, ok := tsValid[ts]; !ok { ts = tsEncode(tsInt) lx.report.Err(a.Pos(), "invalid type specifier") } lhs.typeSpecifier = ts } | TypeQualifier DeclarationSpecifiersOpt { lx := yylex.(*lexer) lhs := &DeclarationSpecifiers{ Case: 2, TypeQualifier: $1.(*TypeQualifier), DeclarationSpecifiersOpt: $2.(*DeclarationSpecifiersOpt), } $$ = lhs lx.scope.specifier = lhs a := lhs.TypeQualifier b := lhs.DeclarationSpecifiersOpt if b == nil { lhs.attr = a.attr break } if a.attr&b.attr != 0 { lx.report.Err(a.Pos(), "invalid type qualifier") break } lhs.attr = a.attr|b.attr lhs.typeSpecifier = b.typeSpecifier if lhs.IsTypedef() { lx.report.Err(a.Pos(), "invalid type qualifier") } } | FunctionSpecifier DeclarationSpecifiersOpt { lx := yylex.(*lexer) lhs := &DeclarationSpecifiers{ Case: 3, FunctionSpecifier: $1.(*FunctionSpecifier), DeclarationSpecifiersOpt: $2.(*DeclarationSpecifiersOpt), } $$ = lhs lx.scope.specifier = lhs a := lhs.FunctionSpecifier b := lhs.DeclarationSpecifiersOpt if b == nil { lhs.attr = a.attr break } if a.attr&b.attr != 0 { lx.report.Err(a.Pos(), "invalid function specifier") break } lhs.attr = a.attr|b.attr lhs.typeSpecifier = b.typeSpecifier if lhs.IsTypedef() { lx.report.Err(a.Pos(), "invalid function specifier") } } DeclarationSpecifiersOpt: /* empty */ { $$ = (*DeclarationSpecifiersOpt)(nil) } | DeclarationSpecifiers { lhs := &DeclarationSpecifiersOpt{ DeclarationSpecifiers: $1.(*DeclarationSpecifiers), } $$ = lhs lhs.attr = lhs.DeclarationSpecifiers.attr lhs.typeSpecifier = lhs.DeclarationSpecifiers.typeSpecifier } InitDeclaratorList: InitDeclarator { $$ = &InitDeclaratorList{ InitDeclarator: $1.(*InitDeclarator), } } | InitDeclaratorList ',' InitDeclarator { $$ = &InitDeclaratorList{ Case: 1, InitDeclaratorList: $1.(*InitDeclaratorList), Token: $2, InitDeclarator: $3.(*InitDeclarator), } } InitDeclaratorListOpt: /* empty */ { $$ = (*InitDeclaratorListOpt)(nil) } | InitDeclaratorList { $$ = &InitDeclaratorListOpt{ InitDeclaratorList: $1.(*InitDeclaratorList).reverse(), } } InitDeclarator: Declarator { lx := yylex.(*lexer) lhs := &InitDeclarator{ Declarator: $1.(*Declarator), } $$ = lhs lhs.Declarator.setFull(lx) } | Declarator { lx := yylex.(*lexer) d := $1.(*Declarator) d.setFull(lx) } '=' Initializer { lx := yylex.(*lexer) lhs := &InitDeclarator{ Case: 1, Declarator: $1.(*Declarator), Token: $3, Initializer: $4.(*Initializer), } $$ = lhs d := lhs.Declarator lhs.Initializer.typeCheck(&d.Type, d.Type, lhs.Declarator.specifier.IsStatic(), lx) if d.Type.Specifier().IsExtern() { id, _ := d.Identifier() lx.report.Err(d.Pos(), "'%s' initialized and declared 'extern'", dict.S(id)) } } StorageClassSpecifier: "typedef" { lhs := &StorageClassSpecifier{ Token: $1, } $$ = lhs lhs.attr = saTypedef } | "extern" { lhs := &StorageClassSpecifier{ Case: 1, Token: $1, } $$ = lhs lhs.attr = saExtern } | "static" { lhs := &StorageClassSpecifier{ Case: 2, Token: $1, } $$ = lhs lhs.attr = saStatic } | "auto" { lhs := &StorageClassSpecifier{ Case: 3, Token: $1, } $$ = lhs lhs.attr = saAuto } | "register" { lhs := &StorageClassSpecifier{ Case: 4, Token: $1, } $$ = lhs lhs.attr = saRegister } TypeSpecifier: "void" { lhs := &TypeSpecifier{ Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsVoid) } | "char" { lhs := &TypeSpecifier{ Case: 1, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsChar) } | "short" { lhs := &TypeSpecifier{ Case: 2, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsShort) } | "int" { lhs := &TypeSpecifier{ Case: 3, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsInt) } | "long" { lhs := &TypeSpecifier{ Case: 4, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsLong) } | "float" { lhs := &TypeSpecifier{ Case: 5, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsFloat) } | "double" { lhs := &TypeSpecifier{ Case: 6, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsDouble) } | "signed" { lhs := &TypeSpecifier{ Case: 7, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsSigned) } | "unsigned" { lhs := &TypeSpecifier{ Case: 8, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsUnsigned) } | "_Bool" { lhs := &TypeSpecifier{ Case: 9, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsBool) } | "_Complex" { lhs := &TypeSpecifier{ Case: 10, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsComplex) } | StructOrUnionSpecifier { lhs := &TypeSpecifier{ Case: 11, StructOrUnionSpecifier: $1.(*StructOrUnionSpecifier), } $$ = lhs lhs.typeSpecifier = tsEncode(lhs.StructOrUnionSpecifier.typeSpecifiers()) } | EnumSpecifier { lhs := &TypeSpecifier{ Case: 12, EnumSpecifier: $1.(*EnumSpecifier), } $$ = lhs lhs.typeSpecifier = tsEncode(tsEnumSpecifier) } | TYPEDEFNAME { lx := yylex.(*lexer) lhs := &TypeSpecifier{ Case: 13, Token: $1, } $$ = lhs lhs.typeSpecifier = tsEncode(tsTypedefName) _, lhs.scope = lx.scope.Lookup2(NSIdentifiers, lhs.Token.Val) } | "typeof" '(' Expression ')' { lx := yylex.(*lexer) lhs := &TypeSpecifier{ Case: 14, Token: $1, Token2: $2, Expression: $3.(*Expression), Token3: $4, } $$ = lhs lhs.typeSpecifier = tsEncode(tsTypeof) _, lhs.Type = lhs.Expression.eval(lx) } | "typeof" '(' TypeName ')' { lhs := &TypeSpecifier{ Case: 15, Token: $1, Token2: $2, TypeName: $3.(*TypeName), Token3: $4, } $$ = lhs lhs.typeSpecifier = tsEncode(tsTypeof) lhs.Type = undefined if t := lhs.TypeName.Type; t != nil { lhs.Type = t } } StructOrUnionSpecifier: StructOrUnion IdentifierOpt '{' { lx := yylex.(*lexer) if o := $2.(*IdentifierOpt); o != nil { lx.scope.declareStructTag(o.Token, lx.report) } lx.pushScope(ScopeMembers) lx.scope.isUnion = $1.(*StructOrUnion).Case == 1 // "union" lx.scope.prevStructDeclarator = nil } StructDeclarationList '}' { lx := yylex.(*lexer) lhs := &StructOrUnionSpecifier{ StructOrUnion: $1.(*StructOrUnion), IdentifierOpt: $2.(*IdentifierOpt), Token: $3, StructDeclarationList: $5.(*StructDeclarationList).reverse(), Token2: $6, } $$ = lhs sc := lx.scope lhs.scope = sc if sc.bitOffset != 0 { finishBitField(lhs, lx) } i := 0 var bt Type var d *Declarator for l := lhs.StructDeclarationList; l != nil; l = l.StructDeclarationList { for l := l.StructDeclaration.StructDeclaratorList; l != nil; l = l.StructDeclaratorList { switch sd := l.StructDeclarator; sd.Case { case 0: // Declarator d = sd.Declarator case 1: // DeclaratorOpt ':' ConstantExpression if o := sd.DeclaratorOpt; o != nil { x := o.Declarator if x.bitOffset == 0 { d = x bt = lx.scope.bitFieldTypes[i] i++ } x.bitFieldType = bt } } } } lx.scope.bitFieldTypes = nil lhs.alignOf = sc.maxAlign switch { case sc.isUnion: lhs.sizeOf = align(sc.maxSize, sc.maxAlign) default: off := sc.offset lhs.sizeOf = align(sc.offset, sc.maxAlign) if d != nil { d.padding = lhs.sizeOf-off } } lx.popScope(lhs.Token2) if o := lhs.IdentifierOpt; o != nil { lx.scope.defineStructTag(o.Token, lhs, lx.report) } } | StructOrUnion IDENTIFIER { lx := yylex.(*lexer) lhs := &StructOrUnionSpecifier{ Case: 1, StructOrUnion: $1.(*StructOrUnion), Token: $2, } $$ = lhs lx.scope.declareStructTag(lhs.Token, lx.report) lhs.scope = lx.scope } | StructOrUnion IdentifierOpt '{' '}' { lx := yylex.(*lexer) lhs := &StructOrUnionSpecifier{ Case: 2, StructOrUnion: $1.(*StructOrUnion), IdentifierOpt: $2.(*IdentifierOpt), Token: $3, Token2: $4, } $$ = lhs if !lx.tweaks.enableEmptyStructs { lx.report.Err(lhs.Token.Pos(), "empty structs/unions not allowed") } if o := $2.(*IdentifierOpt); o != nil { lx.scope.declareStructTag(o.Token, lx.report) } lx.scope.isUnion = $1.(*StructOrUnion).Case == 1 // "union" lx.scope.prevStructDeclarator = nil lhs.alignOf = 1 lhs.sizeOf = 0 if o := lhs.IdentifierOpt; o != nil { lx.scope.defineStructTag(o.Token, lhs, lx.report) } } StructOrUnion: "struct" { $$ = &StructOrUnion{ Token: $1, } } | "union" { $$ = &StructOrUnion{ Case: 1, Token: $1, } } StructDeclarationList: StructDeclaration { $$ = &StructDeclarationList{ StructDeclaration: $1.(*StructDeclaration), } } | StructDeclarationList StructDeclaration { $$ = &StructDeclarationList{ Case: 1, StructDeclarationList: $1.(*StructDeclarationList), StructDeclaration: $2.(*StructDeclaration), } } StructDeclaration: SpecifierQualifierList StructDeclaratorList ';' { lx := yylex.(*lexer) lhs := &StructDeclaration{ SpecifierQualifierList: $1.(*SpecifierQualifierList), StructDeclaratorList: $2.(*StructDeclaratorList).reverse(), Token: $3, } $$ = lhs s := lhs.SpecifierQualifierList if k := s.kind(); k != Struct && k != Union { break } d := &Declarator{specifier: s} dd := &DirectDeclarator{ Token: xc.Token{Char: lex.NewChar(lhs.Pos(), 0)}, declarator: d, idScope: lx.scope, specifier: s, } d.DirectDeclarator = dd d.setFull(lx) for l := lhs.SpecifierQualifierList; l != nil; { ts := l.TypeSpecifier if ts != nil && ts.Case == 11 && ts.StructOrUnionSpecifier.Case == 0 { // StructOrUnion IdentifierOpt '{' StructDeclarationList '}' ts.StructOrUnionSpecifier.declarator = d break } if o := l.SpecifierQualifierListOpt; o != nil { l = o.SpecifierQualifierList continue } break } } | SpecifierQualifierList ';' { lx := yylex.(*lexer) lhs := &StructDeclaration{ Case: 1, SpecifierQualifierList: $1.(*SpecifierQualifierList), Token: $2, } $$ = lhs s := lhs.SpecifierQualifierList if !lx.tweaks.enableAnonymousStructFields { lx.report.Err(lhs.Token.Pos(), "unnamed fields not allowed") } else if k := s.kind(); k != Struct && k != Union { lx.report.Err(lhs.Token.Pos(), "only unnamed structs and unions are allowed") break } d := &Declarator{specifier: s} dd := &DirectDeclarator{ Token: xc.Token{Char: lex.NewChar(lhs.Pos(), 0)}, declarator: d, idScope: lx.scope, specifier: s, } d.DirectDeclarator = dd d.setFull(lx) // we have no struct declarators to parse, so we have to create the case of one implicit declarator // because else the size of anonymous members is not included in the struct size! dummy := &StructDeclarator{Declarator: d} dummy.post(lx) for l := lhs.SpecifierQualifierList; l != nil; { ts := l.TypeSpecifier if ts != nil && ts.Case == 11 && ts.StructOrUnionSpecifier.Case == 0 { // StructOrUnion IdentifierOpt '{' StructDeclarationList '}' ts.StructOrUnionSpecifier.declarator = d break } if o := l.SpecifierQualifierListOpt; o != nil { l = o.SpecifierQualifierList continue } break } } | StaticAssertDeclaration { $$ = &StructDeclaration{ Case: 2, StaticAssertDeclaration: $1.(*StaticAssertDeclaration), } } SpecifierQualifierList: TypeSpecifier SpecifierQualifierListOpt { lx := yylex.(*lexer) lhs := &SpecifierQualifierList{ TypeSpecifier: $1.(*TypeSpecifier), SpecifierQualifierListOpt: $2.(*SpecifierQualifierListOpt), } $$ = lhs lx.scope.specifier = lhs a := lhs.TypeSpecifier b := lhs.SpecifierQualifierListOpt if b == nil { lhs.typeSpecifier = a.typeSpecifier break } lhs.attr = b.attr ts := tsEncode(append(tsDecode(a.typeSpecifier), tsDecode(b.typeSpecifier)...)...) if _, ok := tsValid[ts]; !ok { lx.report.Err(a.Pos(), "invalid type specifier") break } lhs.typeSpecifier = ts } | TypeQualifier SpecifierQualifierListOpt { lx := yylex.(*lexer) lhs := &SpecifierQualifierList{ Case: 1, TypeQualifier: $1.(*TypeQualifier), SpecifierQualifierListOpt: $2.(*SpecifierQualifierListOpt), } $$ = lhs lx.scope.specifier = lhs a := lhs.TypeQualifier b := lhs.SpecifierQualifierListOpt if b == nil { lhs.attr = a.attr break } if a.attr&b.attr != 0 { lx.report.Err(a.Pos(), "invalid type qualifier") break } lhs.attr = a.attr|b.attr lhs.typeSpecifier = b.typeSpecifier } SpecifierQualifierListOpt: /* empty */ { $$ = (*SpecifierQualifierListOpt)(nil) } | SpecifierQualifierList { lhs := &SpecifierQualifierListOpt{ SpecifierQualifierList: $1.(*SpecifierQualifierList), } $$ = lhs lhs.attr = lhs.SpecifierQualifierList.attr lhs.typeSpecifier = lhs.SpecifierQualifierList.typeSpecifier } StructDeclaratorList: StructDeclarator { $$ = &StructDeclaratorList{ StructDeclarator: $1.(*StructDeclarator), } } | StructDeclaratorList ',' StructDeclarator { $$ = &StructDeclaratorList{ Case: 1, StructDeclaratorList: $1.(*StructDeclaratorList), Token: $2, StructDeclarator: $3.(*StructDeclarator), } } StructDeclarator: Declarator { lx := yylex.(*lexer) lhs := &StructDeclarator{ Declarator: $1.(*Declarator), } $$ = lhs lhs.Declarator.setFull(lx) lhs.post(lx) } | DeclaratorOpt ':' ConstantExpression { lx := yylex.(*lexer) lhs := &StructDeclarator{ Case: 1, DeclaratorOpt: $1.(*DeclaratorOpt), Token: $2, ConstantExpression: $3.(*ConstantExpression), } $$ = lhs m := lx.model e := lhs.ConstantExpression if e.Value == nil { e.Value, e.Type = m.value2(1, m.IntType) } if !IsIntType(e.Type) { lx.report.Err(e.Pos(), "bit field width not an integer (have '%s')", e.Type) e.Value, e.Type = m.value2(1, m.IntType) } if o := lhs.DeclaratorOpt; o != nil { o.Declarator.setFull(lx) } lhs.post(lx) } CommaOpt: /* empty */ { $$ = (*CommaOpt)(nil) } | ',' { $$ = &CommaOpt{ Token: $1, } } EnumSpecifier: "enum" IdentifierOpt { lx := yylex.(*lexer) if o := $2.(*IdentifierOpt); o != nil { lx.scope.declareEnumTag(o.Token, lx.report) } lx.iota = 0 } '{' EnumeratorList CommaOpt '}' { lx := yylex.(*lexer) lhs := &EnumSpecifier{ Token: $1, IdentifierOpt: $2.(*IdentifierOpt), Token2: $4, EnumeratorList: $5.(*EnumeratorList).reverse(), CommaOpt: $6.(*CommaOpt), Token3: $7, } $$ = lhs if o := lhs.IdentifierOpt; o != nil { lx.scope.defineEnumTag(o.Token, lhs, lx.report) } if !lx.tweaks.enableUnsignedEnums { break } lhs.unsigned = true loop: for l := lhs.EnumeratorList; l != nil; l = l.EnumeratorList { switch e := l.Enumerator; x := e.Value.(type) { case int32: if x < 0 { lhs.unsigned = false break loop } case int64: if x < 0 { lhs.unsigned = false break loop } default: panic(fmt.Errorf("%s: TODO Enumerator.Value type %T", position(e.Pos()), x)) } } } | "enum" IDENTIFIER { lx := yylex.(*lexer) lhs := &EnumSpecifier{ Case: 1, Token: $1, Token2: $2, } $$ = lhs lx.scope.declareEnumTag(lhs.Token2, lx.report) } EnumeratorList: Enumerator { $$ = &EnumeratorList{ Enumerator: $1.(*Enumerator), } } | EnumeratorList ',' Enumerator { $$ = &EnumeratorList{ Case: 1, EnumeratorList: $1.(*EnumeratorList), Token: $2, Enumerator: $3.(*Enumerator), } } Enumerator: EnumerationConstant { lx := yylex.(*lexer) lhs := &Enumerator{ EnumerationConstant: $1.(*EnumerationConstant), } $$ = lhs m := lx.model v := m.MustConvert(lx.iota, m.IntType) lhs.Value = v lx.scope.defineEnumConst(lx, lhs.EnumerationConstant.Token, v) } | EnumerationConstant '=' ConstantExpression { lx := yylex.(*lexer) lhs := &Enumerator{ Case: 1, EnumerationConstant: $1.(*EnumerationConstant), Token: $2, ConstantExpression: $3.(*ConstantExpression), } $$ = lhs m := lx.model e := lhs.ConstantExpression var v interface{} // [0], 6.7.2.2 // The expression that defines the value of an enumeration // constant shall be an integer constant expression that has a // value representable as an int. switch { case !IsIntType(e.Type): lx.report.Err(e.Pos(), "not an integer constant expression (have '%s')", e.Type) v = m.MustConvert(int32(0), m.IntType) default: var ok bool if v, ok = m.enumValueToInt(e.Value); !ok { lx.report.Err(e.Pos(), "overflow in enumeration value: %v", e.Value) } } lhs.Value = v lx.scope.defineEnumConst(lx, lhs.EnumerationConstant.Token, v) } TypeQualifier: "const" { lhs := &TypeQualifier{ Token: $1, } $$ = lhs lhs.attr = saConst } | "restrict" { lhs := &TypeQualifier{ Case: 1, Token: $1, } $$ = lhs lhs.attr = saRestrict } | "volatile" { lhs := &TypeQualifier{ Case: 2, Token: $1, } $$ = lhs lhs.attr = saVolatile } FunctionSpecifier: "inline" { lhs := &FunctionSpecifier{ Token: $1, } $$ = lhs lhs.attr = saInline } | "_Noreturn" { lhs := &FunctionSpecifier{ Case: 1, Token: $1, } $$ = lhs lhs.attr = saNoreturn } Declarator: PointerOpt DirectDeclarator { lx := yylex.(*lexer) lhs := &Declarator{ PointerOpt: $1.(*PointerOpt), DirectDeclarator: $2.(*DirectDeclarator), } $$ = lhs lhs.specifier = lx.scope.specifier lhs.DirectDeclarator.declarator = lhs } DeclaratorOpt: /* empty */ { $$ = (*DeclaratorOpt)(nil) } | Declarator { $$ = &DeclaratorOpt{ Declarator: $1.(*Declarator), } } DirectDeclarator: IDENTIFIER { lx := yylex.(*lexer) lhs := &DirectDeclarator{ Token: $1, } $$ = lhs lhs.specifier = lx.scope.specifier lx.scope.declareIdentifier(lhs.Token, lhs, lx.report) lhs.idScope = lx.scope } | '(' Declarator ')' { lhs := &DirectDeclarator{ Case: 1, Token: $1, Declarator: $2.(*Declarator), Token2: $3, } $$ = lhs lhs.Declarator.specifier = nil lhs.Declarator.DirectDeclarator.parent = lhs } | DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']' { lx := yylex.(*lexer) lhs := &DirectDeclarator{ Case: 2, DirectDeclarator: $1.(*DirectDeclarator), Token: $2, TypeQualifierListOpt: $3.(*TypeQualifierListOpt), ExpressionOpt: $4.(*ExpressionOpt), Token2: $5, } $$ = lhs lhs.elements = -1 if o := lhs.ExpressionOpt; o != nil { var err error if lhs.elements, err = elements(o.Expression.eval(lx)); err != nil { lx.report.Err(o.Expression.Pos(), "%s", err) } } lhs.DirectDeclarator.parent = lhs } | DirectDeclarator '[' "static" TypeQualifierListOpt Expression ']' { lx := yylex.(*lexer) lhs := &DirectDeclarator{ Case: 3, DirectDeclarator: $1.(*DirectDeclarator), Token: $2, Token2: $3, TypeQualifierListOpt: $4.(*TypeQualifierListOpt), Expression: $5.(*Expression), Token3: $6, } $$ = lhs var err error if lhs.elements, err = elements(lhs.Expression.eval(lx)); err != nil { lx.report.Err(lhs.Expression.Pos(), "%s", err) } lhs.DirectDeclarator.parent = lhs } | DirectDeclarator '[' TypeQualifierList "static" Expression ']' { lx := yylex.(*lexer) lhs := &DirectDeclarator{ Case: 4, DirectDeclarator: $1.(*DirectDeclarator), Token: $2, TypeQualifierList: $3.(*TypeQualifierList).reverse(), Token2: $4, Expression: $5.(*Expression), Token3: $6, } $$ = lhs var err error if lhs.elements, err = elements(lhs.Expression.eval(lx)); err != nil { lx.report.Err(lhs.Expression.Pos(), "%s", err) } lhs.DirectDeclarator.parent = lhs } | DirectDeclarator '[' TypeQualifierListOpt '*' ']' { lhs := &DirectDeclarator{ Case: 5, DirectDeclarator: $1.(*DirectDeclarator), Token: $2, TypeQualifierListOpt: $3.(*TypeQualifierListOpt), Token2: $4, Token3: $5, } $$ = lhs lhs.DirectDeclarator.parent = lhs lhs.elements = -1 } | DirectDeclarator '(' { lx := yylex.(*lexer) lx.pushScope(ScopeParams) } ParameterTypeList ')' { lx := yylex.(*lexer) lhs := &DirectDeclarator{ Case: 6, DirectDeclarator: $1.(*DirectDeclarator), Token: $2, ParameterTypeList: $4.(*ParameterTypeList), Token2: $5, } $$ = lhs lhs.paramsScope, _ = lx.popScope(lhs.Token2) lhs.DirectDeclarator.parent = lhs } | DirectDeclarator '(' IdentifierListOpt ')' { lhs := &DirectDeclarator{ Case: 7, DirectDeclarator: $1.(*DirectDeclarator), Token: $2, IdentifierListOpt: $3.(*IdentifierListOpt), Token2: $4, } $$ = lhs lhs.DirectDeclarator.parent = lhs } Pointer: '*' TypeQualifierListOpt { $$ = &Pointer{ Token: $1, TypeQualifierListOpt: $2.(*TypeQualifierListOpt), } } | '*' TypeQualifierListOpt Pointer { $$ = &Pointer{ Case: 1, Token: $1, TypeQualifierListOpt: $2.(*TypeQualifierListOpt), Pointer: $3.(*Pointer), } } PointerOpt: /* empty */ { $$ = (*PointerOpt)(nil) } | Pointer { $$ = &PointerOpt{ Pointer: $1.(*Pointer), } } TypeQualifierList: TypeQualifier { lhs := &TypeQualifierList{ TypeQualifier: $1.(*TypeQualifier), } $$ = lhs lhs.attr = lhs.TypeQualifier.attr } | TypeQualifierList TypeQualifier { lx := yylex.(*lexer) lhs := &TypeQualifierList{ Case: 1, TypeQualifierList: $1.(*TypeQualifierList), TypeQualifier: $2.(*TypeQualifier), } $$ = lhs a := lhs.TypeQualifierList b := lhs.TypeQualifier if a.attr&b.attr != 0 { lx.report.Err(b.Pos(), "invalid type qualifier") break } lhs.attr = a.attr|b.attr } TypeQualifierListOpt: /* empty */ { $$ = (*TypeQualifierListOpt)(nil) } | TypeQualifierList { $$ = &TypeQualifierListOpt{ TypeQualifierList: $1.(*TypeQualifierList).reverse(), } } ParameterTypeList: ParameterList { lhs := &ParameterTypeList{ ParameterList: $1.(*ParameterList).reverse(), } $$ = lhs lhs.post() } | ParameterList ',' "..." { lhs := &ParameterTypeList{ Case: 1, ParameterList: $1.(*ParameterList).reverse(), Token: $2, Token2: $3, } $$ = lhs lhs.post() } ParameterTypeListOpt: /* empty */ { $$ = (*ParameterTypeListOpt)(nil) } | ParameterTypeList { $$ = &ParameterTypeListOpt{ ParameterTypeList: $1.(*ParameterTypeList), } } ParameterList: ParameterDeclaration { $$ = &ParameterList{ ParameterDeclaration: $1.(*ParameterDeclaration), } } | ParameterList ',' ParameterDeclaration { $$ = &ParameterList{ Case: 1, ParameterList: $1.(*ParameterList), Token: $2, ParameterDeclaration: $3.(*ParameterDeclaration), } } ParameterDeclaration: DeclarationSpecifiers Declarator { lx := yylex.(*lexer) lhs := &ParameterDeclaration{ DeclarationSpecifiers: $1.(*DeclarationSpecifiers), Declarator: $2.(*Declarator), } $$ = lhs lhs.Declarator.setFull(lx) lhs.declarator = lhs.Declarator } | DeclarationSpecifiers AbstractDeclaratorOpt { lx := yylex.(*lexer) lhs := &ParameterDeclaration{ Case: 1, DeclarationSpecifiers: $1.(*DeclarationSpecifiers), AbstractDeclaratorOpt: $2.(*AbstractDeclaratorOpt), } $$ = lhs if o := lhs.AbstractDeclaratorOpt; o != nil { lhs.declarator = o.AbstractDeclarator.declarator lhs.declarator.setFull(lx) break } d := &Declarator{ specifier: lx.scope.specifier, DirectDeclarator: &DirectDeclarator{ Case: 0, // IDENTIFIER }, } d.DirectDeclarator.declarator = d lhs.declarator = d d.setFull(lx) } IdentifierList: IDENTIFIER { $$ = &IdentifierList{ Token: $1, } } | IdentifierList ',' IDENTIFIER { $$ = &IdentifierList{ Case: 1, IdentifierList: $1.(*IdentifierList), Token: $2, Token2: $3, } } IdentifierListOpt: /* empty */ { $$ = (*IdentifierListOpt)(nil) } | IdentifierList { $$ = &IdentifierListOpt{ IdentifierList: $1.(*IdentifierList).reverse(), } } IdentifierOpt: /* empty */ { $$ = (*IdentifierOpt)(nil) } | IDENTIFIER { $$ = &IdentifierOpt{ Token: $1, } } TypeName: { lx := yylex.(*lexer) lx.pushScope(ScopeBlock) } SpecifierQualifierList AbstractDeclaratorOpt { lx := yylex.(*lexer) lhs := &TypeName{ SpecifierQualifierList: $2.(*SpecifierQualifierList), AbstractDeclaratorOpt: $3.(*AbstractDeclaratorOpt), } $$ = lhs if o := lhs.AbstractDeclaratorOpt; o != nil { lhs.declarator = o.AbstractDeclarator.declarator } else { d := &Declarator{ specifier: lhs.SpecifierQualifierList, DirectDeclarator: &DirectDeclarator{ Case: 0, // IDENTIFIER idScope: lx.scope, }, } d.DirectDeclarator.declarator = d lhs.declarator = d } lhs.Type = lhs.declarator.setFull(lx) lhs.scope = lx.scope lx.popScope(xc.Token{}) } AbstractDeclarator: Pointer { lx := yylex.(*lexer) lhs := &AbstractDeclarator{ Pointer: $1.(*Pointer), } $$ = lhs d := &Declarator{ specifier: lx.scope.specifier, PointerOpt: &PointerOpt { Pointer: lhs.Pointer, }, DirectDeclarator: &DirectDeclarator{ Case: 0, // IDENTIFIER idScope: lx.scope, }, } d.DirectDeclarator.declarator = d lhs.declarator = d } | PointerOpt DirectAbstractDeclarator { lx := yylex.(*lexer) lhs := &AbstractDeclarator{ Case: 1, PointerOpt: $1.(*PointerOpt), DirectAbstractDeclarator: $2.(*DirectAbstractDeclarator), } $$ = lhs d := &Declarator{ specifier: lx.scope.specifier, PointerOpt: lhs.PointerOpt, DirectDeclarator: lhs.DirectAbstractDeclarator.directDeclarator, } d.DirectDeclarator.declarator = d lhs.declarator = d } AbstractDeclaratorOpt: /* empty */ { $$ = (*AbstractDeclaratorOpt)(nil) } | AbstractDeclarator { $$ = &AbstractDeclaratorOpt{ AbstractDeclarator: $1.(*AbstractDeclarator), } } DirectAbstractDeclarator: '(' AbstractDeclarator ')' { lhs := &DirectAbstractDeclarator{ Token: $1, AbstractDeclarator: $2.(*AbstractDeclarator), Token2: $3, } $$ = lhs lhs.AbstractDeclarator.declarator.specifier = nil lhs.directDeclarator = &DirectDeclarator{ Case: 1, // '(' Declarator ')' Declarator: lhs.AbstractDeclarator.declarator, } lhs.AbstractDeclarator.declarator.DirectDeclarator.parent = lhs.directDeclarator } | DirectAbstractDeclaratorOpt '[' ExpressionOpt ']' { lx := yylex.(*lexer) lhs := &DirectAbstractDeclarator{ Case: 1, DirectAbstractDeclaratorOpt: $1.(*DirectAbstractDeclaratorOpt), Token: $2, ExpressionOpt: $3.(*ExpressionOpt), Token2: $4, } $$ = lhs nElements := -1 if o := lhs.ExpressionOpt; o != nil { var err error if nElements, err = elements(o.Expression.eval(lx)); err != nil { lx.report.Err(o.Expression.Pos(), "%s", err) } } var dd *DirectDeclarator switch o := lhs.DirectAbstractDeclaratorOpt; { case o == nil: dd = &DirectDeclarator{ Case: 0, // IDENTIFIER } default: dd = o.DirectAbstractDeclarator.directDeclarator } lhs.directDeclarator = &DirectDeclarator{ Case: 2, // DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']' DirectDeclarator: dd, ExpressionOpt: lhs.ExpressionOpt, elements: nElements, } dd.parent = lhs.directDeclarator } | DirectAbstractDeclaratorOpt '[' TypeQualifierList ExpressionOpt ']' { lx := yylex.(*lexer) lhs := &DirectAbstractDeclarator{ Case: 2, DirectAbstractDeclaratorOpt: $1.(*DirectAbstractDeclaratorOpt), Token: $2, TypeQualifierList: $3.(*TypeQualifierList).reverse(), ExpressionOpt: $4.(*ExpressionOpt), Token2: $5, } $$ = lhs if o := lhs.ExpressionOpt; o != nil { o.Expression.eval(lx) } var dd *DirectDeclarator switch o := lhs.DirectAbstractDeclaratorOpt; { case o == nil: dd = &DirectDeclarator{ Case: 0, // IDENTIFIER } default: dd = o.DirectAbstractDeclarator.directDeclarator } lhs.directDeclarator = &DirectDeclarator{ Case: 2, // DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']' DirectDeclarator: dd, TypeQualifierListOpt: &TypeQualifierListOpt{ lhs.TypeQualifierList }, ExpressionOpt: lhs.ExpressionOpt, } dd.parent = lhs.directDeclarator } | DirectAbstractDeclaratorOpt '[' "static" TypeQualifierListOpt Expression ']' { lx := yylex.(*lexer) lhs := &DirectAbstractDeclarator{ Case: 3, DirectAbstractDeclaratorOpt: $1.(*DirectAbstractDeclaratorOpt), Token: $2, Token2: $3, TypeQualifierListOpt: $4.(*TypeQualifierListOpt), Expression: $5.(*Expression), Token3: $6, } $$ = lhs lhs.Expression.eval(lx) var dd *DirectDeclarator switch o := lhs.DirectAbstractDeclaratorOpt; { case o == nil: dd = &DirectDeclarator{ Case: 0, // IDENTIFIER } default: dd = o.DirectAbstractDeclarator.directDeclarator } lhs.directDeclarator = &DirectDeclarator{ Case: 2, // DirectDeclarator '[' "static" TypeQualifierListOpt Expression ']' DirectDeclarator: dd, TypeQualifierListOpt: lhs.TypeQualifierListOpt, Expression: lhs.Expression, } dd.parent = lhs.directDeclarator } | DirectAbstractDeclaratorOpt '[' TypeQualifierList "static" Expression ']' { lx := yylex.(*lexer) lhs := &DirectAbstractDeclarator{ Case: 4, DirectAbstractDeclaratorOpt: $1.(*DirectAbstractDeclaratorOpt), Token: $2, TypeQualifierList: $3.(*TypeQualifierList).reverse(), Token2: $4, Expression: $5.(*Expression), Token3: $6, } $$ = lhs lhs.Expression.eval(lx) var dd *DirectDeclarator switch o := lhs.DirectAbstractDeclaratorOpt; { case o == nil: dd = &DirectDeclarator{ Case: 0, // IDENTIFIER } default: dd = o.DirectAbstractDeclarator.directDeclarator } lhs.directDeclarator = &DirectDeclarator{ Case: 4, // DirectDeclarator '[' TypeQualifierList "static" Expression ']' DirectDeclarator: dd, TypeQualifierList: lhs.TypeQualifierList, Expression: lhs.Expression, } dd.parent = lhs.directDeclarator } | DirectAbstractDeclaratorOpt '[' '*' ']' { lhs := &DirectAbstractDeclarator{ Case: 5, DirectAbstractDeclaratorOpt: $1.(*DirectAbstractDeclaratorOpt), Token: $2, Token2: $3, Token3: $4, } $$ = lhs var dd *DirectDeclarator switch o := lhs.DirectAbstractDeclaratorOpt; { case o == nil: dd = &DirectDeclarator{ Case: 0, // IDENTIFIER } default: dd = o.DirectAbstractDeclarator.directDeclarator } lhs.directDeclarator = &DirectDeclarator{ Case: 5, // DirectDeclarator '[' TypeQualifierListOpt '*' ']' DirectDeclarator: dd, } dd.parent = lhs.directDeclarator } | '(' { lx := yylex.(*lexer) lx.pushScope(ScopeParams) } ParameterTypeListOpt ')' { lx := yylex.(*lexer) lhs := &DirectAbstractDeclarator{ Case: 6, Token: $1, ParameterTypeListOpt: $3.(*ParameterTypeListOpt), Token2: $4, } $$ = lhs lhs.paramsScope, _ = lx.popScope(lhs.Token2) switch o := lhs.ParameterTypeListOpt; { case o != nil: lhs.directDeclarator = &DirectDeclarator{ Case: 6, // DirectDeclarator '(' ParameterTypeList ')' DirectDeclarator: &DirectDeclarator{ Case: 0, // IDENTIFIER }, ParameterTypeList: o.ParameterTypeList, } default: lhs.directDeclarator = &DirectDeclarator{ Case: 7, // DirectDeclarator '(' IdentifierListOpt ')' DirectDeclarator: &DirectDeclarator{ Case: 0, // IDENTIFIER }, } } lhs.directDeclarator.DirectDeclarator.parent = lhs.directDeclarator } | DirectAbstractDeclarator '(' { lx := yylex.(*lexer) lx.pushScope(ScopeParams) } ParameterTypeListOpt ')' { lx := yylex.(*lexer) lhs := &DirectAbstractDeclarator{ Case: 7, DirectAbstractDeclarator: $1.(*DirectAbstractDeclarator), Token: $2, ParameterTypeListOpt: $4.(*ParameterTypeListOpt), Token2: $5, } $$ = lhs lhs.paramsScope, _ = lx.popScope(lhs.Token2) switch o := lhs.ParameterTypeListOpt; { case o != nil: lhs.directDeclarator = &DirectDeclarator{ Case: 6, // DirectDeclarator '(' ParameterTypeList ')' DirectDeclarator: lhs.DirectAbstractDeclarator.directDeclarator, ParameterTypeList: o.ParameterTypeList, } default: lhs.directDeclarator = &DirectDeclarator{ Case: 7, // DirectDeclarator '(' IdentifierListOpt ')' DirectDeclarator: lhs.DirectAbstractDeclarator.directDeclarator, } } lhs.directDeclarator.DirectDeclarator.parent = lhs.directDeclarator } DirectAbstractDeclaratorOpt: /* empty */ { $$ = (*DirectAbstractDeclaratorOpt)(nil) } | DirectAbstractDeclarator { $$ = &DirectAbstractDeclaratorOpt{ DirectAbstractDeclarator: $1.(*DirectAbstractDeclarator), } } Initializer: Expression { lx := yylex.(*lexer) lhs := &Initializer{ Expression: $1.(*Expression), } $$ = lhs lhs.Expression.eval(lx) } | '{' InitializerList CommaOpt '}' { $$ = &Initializer{ Case: 1, Token: $1, InitializerList: $2.(*InitializerList).reverse(), CommaOpt: $3.(*CommaOpt), Token2: $4, } } | IDENTIFIER ':' Initializer { lx := yylex.(*lexer) lhs := &Initializer{ Case: 2, Token: $1, Token2: $2, Initializer: $3.(*Initializer), } $$ = lhs if !lx.tweaks.enableLegacyDesignators { lx.report.Err(lhs.Pos(), "legacy designators not enabled") } } InitializerList: DesignationOpt Initializer { $$ = &InitializerList{ DesignationOpt: $1.(*DesignationOpt), Initializer: $2.(*Initializer), } } | InitializerList ',' DesignationOpt Initializer { $$ = &InitializerList{ Case: 1, InitializerList: $1.(*InitializerList), Token: $2, DesignationOpt: $3.(*DesignationOpt), Initializer: $4.(*Initializer), } } | /* empty */ { $$ = (*InitializerList)(nil) } Designation: DesignatorList '=' { $$ = &Designation{ DesignatorList: $1.(*DesignatorList).reverse(), Token: $2, } } DesignationOpt: /* empty */ { $$ = (*DesignationOpt)(nil) } | Designation { $$ = &DesignationOpt{ Designation: $1.(*Designation), } } DesignatorList: Designator { $$ = &DesignatorList{ Designator: $1.(*Designator), } } | DesignatorList Designator { $$ = &DesignatorList{ Case: 1, DesignatorList: $1.(*DesignatorList), Designator: $2.(*Designator), } } Designator: '[' ConstantExpression ']' { $$ = &Designator{ Token: $1, ConstantExpression: $2.(*ConstantExpression), Token2: $3, } } | '.' IDENTIFIER { $$ = &Designator{ Case: 1, Token: $1, Token2: $2, } } Statement: LabeledStatement { $$ = &Statement{ LabeledStatement: $1.(*LabeledStatement), } } | CompoundStatement { $$ = &Statement{ Case: 1, CompoundStatement: $1.(*CompoundStatement), } } | ExpressionStatement { $$ = &Statement{ Case: 2, ExpressionStatement: $1.(*ExpressionStatement), } } | SelectionStatement { $$ = &Statement{ Case: 3, SelectionStatement: $1.(*SelectionStatement), } } | IterationStatement { $$ = &Statement{ Case: 4, IterationStatement: $1.(*IterationStatement), } } | JumpStatement { $$ = &Statement{ Case: 5, JumpStatement: $1.(*JumpStatement), } } | AssemblerStatement { $$ = &Statement{ Case: 6, AssemblerStatement: $1.(*AssemblerStatement), } } LabeledStatement: IDENTIFIER ':' Statement { $$ = &LabeledStatement{ Token: $1, Token2: $2, Statement: $3.(*Statement), } } | "case" ConstantExpression ':' Statement { $$ = &LabeledStatement{ Case: 1, Token: $1, ConstantExpression: $2.(*ConstantExpression), Token2: $3, Statement: $4.(*Statement), } } | "default" ':' Statement { $$ = &LabeledStatement{ Case: 2, Token: $1, Token2: $2, Statement: $3.(*Statement), } } CompoundStatement: '{' { lx := yylex.(*lexer) m := lx.scope.mergeScope lx.pushScope(ScopeBlock) if m != nil { lx.scope.merge(m) } lx.scope.mergeScope = nil } BlockItemListOpt '}' { lx := yylex.(*lexer) lhs := &CompoundStatement{ Token: $1, BlockItemListOpt: $3.(*BlockItemListOpt), Token2: $4, } $$ = lhs lhs.scope = lx.scope lx.popScope(lhs.Token2) } BlockItemList: BlockItem { $$ = &BlockItemList{ BlockItem: $1.(*BlockItem), } } | BlockItemList BlockItem { $$ = &BlockItemList{ Case: 1, BlockItemList: $1.(*BlockItemList), BlockItem: $2.(*BlockItem), } } BlockItemListOpt: /* empty */ { $$ = (*BlockItemListOpt)(nil) } | BlockItemList { $$ = &BlockItemListOpt{ BlockItemList: $1.(*BlockItemList).reverse(), } } BlockItem: Declaration { $$ = &BlockItem{ Declaration: $1.(*Declaration), } } | Statement { $$ = &BlockItem{ Case: 1, Statement: $1.(*Statement), } } ExpressionStatement: ExpressionListOpt ';' { $$ = &ExpressionStatement{ ExpressionListOpt: $1.(*ExpressionListOpt), Token: $2, } } SelectionStatement: "if" '(' ExpressionList ')' Statement %prec NOELSE { lx := yylex.(*lexer) lhs := &SelectionStatement{ Token: $1, Token2: $2, ExpressionList: $3.(*ExpressionList).reverse(), Token3: $4, Statement: $5.(*Statement), } $$ = lhs lhs.ExpressionList.eval(lx) } | "if" '(' ExpressionList ')' Statement "else" Statement { lx := yylex.(*lexer) lhs := &SelectionStatement{ Case: 1, Token: $1, Token2: $2, ExpressionList: $3.(*ExpressionList).reverse(), Token3: $4, Statement: $5.(*Statement), Token4: $6, Statement2: $7.(*Statement), } $$ = lhs lhs.ExpressionList.eval(lx) } | "switch" '(' ExpressionList ')' Statement { lx := yylex.(*lexer) lhs := &SelectionStatement{ Case: 2, Token: $1, Token2: $2, ExpressionList: $3.(*ExpressionList).reverse(), Token3: $4, Statement: $5.(*Statement), } $$ = lhs lhs.ExpressionList.eval(lx) } IterationStatement: "while" '(' ExpressionList ')' Statement { lx := yylex.(*lexer) lhs := &IterationStatement{ Token: $1, Token2: $2, ExpressionList: $3.(*ExpressionList).reverse(), Token3: $4, Statement: $5.(*Statement), } $$ = lhs lhs.ExpressionList.eval(lx) } | "do" Statement "while" '(' ExpressionList ')' ';' { lx := yylex.(*lexer) lhs := &IterationStatement{ Case: 1, Token: $1, Statement: $2.(*Statement), Token2: $3, Token3: $4, ExpressionList: $5.(*ExpressionList).reverse(), Token4: $6, Token5: $7, } $$ = lhs lhs.ExpressionList.eval(lx) } | "for" '(' ExpressionListOpt ';' ExpressionListOpt ';' ExpressionListOpt ')' Statement { $$ = &IterationStatement{ Case: 2, Token: $1, Token2: $2, ExpressionListOpt: $3.(*ExpressionListOpt), Token3: $4, ExpressionListOpt2: $5.(*ExpressionListOpt), Token4: $6, ExpressionListOpt3: $7.(*ExpressionListOpt), Token5: $8, Statement: $9.(*Statement), } } | "for" '(' Declaration ExpressionListOpt ';' ExpressionListOpt ')' Statement { $$ = &IterationStatement{ Case: 3, Token: $1, Token2: $2, Declaration: $3.(*Declaration), ExpressionListOpt: $4.(*ExpressionListOpt), Token3: $5, ExpressionListOpt2: $6.(*ExpressionListOpt), Token4: $7, Statement: $8.(*Statement), } } JumpStatement: "goto" IDENTIFIER ';' { $$ = &JumpStatement{ Token: $1, Token2: $2, Token3: $3, } } | "continue" ';' { $$ = &JumpStatement{ Case: 1, Token: $1, Token2: $2, } } | "break" ';' { $$ = &JumpStatement{ Case: 2, Token: $1, Token2: $2, } } | "return" ExpressionListOpt ';' { $$ = &JumpStatement{ Case: 3, Token: $1, ExpressionListOpt: $2.(*ExpressionListOpt), Token2: $3, } } | "goto" Expression ';' { lx := yylex.(*lexer) lhs := &JumpStatement{ Case: 4, Token: $1, Expression: $2.(*Expression), Token2: $3, } $$ = lhs _, t := lhs.Expression.eval(lx) if t == nil { break } for t != nil && t.Kind() == Ptr { t = t.Element() } if t == nil || t.Kind() != Void { lx.report.Err(lhs.Pos(), "invalid computed goto argument type, have '%s'", t) } if !lx.tweaks.enableComputedGotos { lx.report.Err(lhs.Pos(), "computed gotos not enabled") } } TranslationUnit: ExternalDeclaration { $$ = &TranslationUnit{ ExternalDeclaration: $1.(*ExternalDeclaration), } } | TranslationUnit ExternalDeclaration { $$ = &TranslationUnit{ Case: 1, TranslationUnit: $1.(*TranslationUnit), ExternalDeclaration: $2.(*ExternalDeclaration), } } ExternalDeclaration: FunctionDefinition { $$ = &ExternalDeclaration{ FunctionDefinition: $1.(*FunctionDefinition), } } | Declaration { $$ = &ExternalDeclaration{ Case: 1, Declaration: $1.(*Declaration), } } | BasicAssemblerStatement ';' { $$ = &ExternalDeclaration{ Case: 2, BasicAssemblerStatement: $1.(*BasicAssemblerStatement), Token: $2, } } | ';' { lx := yylex.(*lexer) lhs := &ExternalDeclaration{ Case: 3, Token: $1, } $$ = lhs if !lx.tweaks.enableEmptyDeclarations { lx.report.Err(lhs.Pos(), "C++11 empty declarations are illegal in C99.") } } FunctionDefinition: DeclarationSpecifiers Declarator DeclarationListOpt { lx := yylex.(*lexer) if ds := $1.(*DeclarationSpecifiers); ds.typeSpecifier == 0 { ds.typeSpecifier = tsEncode(tsInt) $2.(*Declarator).Type = lx.model.IntType if !lx.tweaks.enableOmitFuncRetType { lx.report.Err($2.Pos(), "missing function return type") } } var fd *FunctionDefinition fd.post(lx, $2.(*Declarator), $3.(*DeclarationListOpt)) } FunctionBody { $$ = &FunctionDefinition{ DeclarationSpecifiers: $1.(*DeclarationSpecifiers), Declarator: $2.(*Declarator), DeclarationListOpt: $3.(*DeclarationListOpt), FunctionBody: $5.(*FunctionBody), } } | { lx := yylex.(*lexer) lx.scope.specifier = &DeclarationSpecifiers{typeSpecifier: tsEncode(tsInt)} } Declarator DeclarationListOpt { lx := yylex.(*lexer) if !lx.tweaks.enableOmitFuncRetType { lx.report.Err($2.Pos(), "missing function return type") } var fd *FunctionDefinition fd.post(lx, $2.(*Declarator), $3.(*DeclarationListOpt)) } FunctionBody { $$ = &FunctionDefinition{ Case: 1, Declarator: $2.(*Declarator), DeclarationListOpt: $3.(*DeclarationListOpt), FunctionBody: $5.(*FunctionBody), } } FunctionBody: { lx := yylex.(*lexer) // Handle __func__, [0], 6.4.2.2. id, _ := lx.fnDeclarator.Identifier() lx.injectFunc = []xc.Token{ {lex.Char{Rune: STATIC}, idStatic}, {lex.Char{Rune: CONST}, idConst}, {lex.Char{Rune: CHAR}, idChar}, {lex.Char{Rune: IDENTIFIER}, idMagicFunc}, {lex.Char{Rune: '['}, 0}, {lex.Char{Rune: ']'}, 0}, {lex.Char{Rune: '='}, 0}, {lex.Char{Rune: STRINGLITERAL}, xc.Dict.SID(fmt.Sprintf("%q", xc.Dict.S(id)))}, {lex.Char{Rune: ';'}, 0}, } } CompoundStatement { lhs := &FunctionBody{ CompoundStatement: $2.(*CompoundStatement), } $$ = lhs lhs.scope = lhs.CompoundStatement.scope } | { lx := yylex.(*lexer) m := lx.scope.mergeScope lx.pushScope(ScopeBlock) if m != nil { lx.scope.merge(m) } lx.scope.mergeScope = nil } AssemblerStatement ';' { lx := yylex.(*lexer) lhs := &FunctionBody{ Case: 1, AssemblerStatement: $2.(*AssemblerStatement), Token: $3, } $$ = lhs lhs.scope = lx.scope lx.popScope(lx.tokPrev) } DeclarationList: Declaration { $$ = &DeclarationList{ Declaration: $1.(*Declaration), } } | DeclarationList Declaration { $$ = &DeclarationList{ Case: 1, DeclarationList: $1.(*DeclarationList), Declaration: $2.(*Declaration), } } DeclarationListOpt: /* empty */ { $$ = (*DeclarationListOpt)(nil) } | { lx := yylex.(*lexer) lx.pushScope(ScopeParams) } DeclarationList { lx := yylex.(*lexer) lhs := &DeclarationListOpt{ DeclarationList: $2.(*DeclarationList).reverse(), } $$ = lhs lhs.paramsScope, _ = lx.popScopePos(lhs.Pos()) } AssemblerInstructions: STRINGLITERAL { $$ = &AssemblerInstructions{ Token: $1, } } | AssemblerInstructions STRINGLITERAL { $$ = &AssemblerInstructions{ Case: 1, AssemblerInstructions: $1.(*AssemblerInstructions), Token: $2, } } BasicAssemblerStatement: "asm" VolatileOpt '(' AssemblerInstructions ')' { $$ = &BasicAssemblerStatement{ Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, AssemblerInstructions: $4.(*AssemblerInstructions).reverse(), Token3: $5, } } VolatileOpt: /* empty */ { $$ = (*VolatileOpt)(nil) } | "volatile" { $$ = &VolatileOpt{ Token: $1, } } AssemblerOperand: AssemblerSymbolicNameOpt STRINGLITERAL '(' Expression ')' { $$ = &AssemblerOperand{ AssemblerSymbolicNameOpt: $1.(*AssemblerSymbolicNameOpt), Token: $2, Token2: $3, Expression: $4.(*Expression), Token3: $5, } } AssemblerOperands: AssemblerOperand { $$ = &AssemblerOperands{ AssemblerOperand: $1.(*AssemblerOperand), } } | AssemblerOperands ',' AssemblerOperand { $$ = &AssemblerOperands{ Case: 1, AssemblerOperands: $1.(*AssemblerOperands), Token: $2, AssemblerOperand: $3.(*AssemblerOperand), } } AssemblerSymbolicNameOpt: /* empty */ { $$ = (*AssemblerSymbolicNameOpt)(nil) } | '[' IDENTIFIER ']' { $$ = &AssemblerSymbolicNameOpt{ Token: $1, Token2: $2, Token3: $3, } } Clobbers: STRINGLITERAL { $$ = &Clobbers{ Token: $1, } } | Clobbers ',' STRINGLITERAL { $$ = &Clobbers{ Case: 1, Clobbers: $1.(*Clobbers), Token: $2, Token2: $3, } } AssemblerStatement: BasicAssemblerStatement { $$ = &AssemblerStatement{ BasicAssemblerStatement: $1.(*BasicAssemblerStatement), } } | "asm" VolatileOpt '(' AssemblerInstructions ':' AssemblerOperands ')' { $$ = &AssemblerStatement{ Case: 1, Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, AssemblerInstructions: $4.(*AssemblerInstructions).reverse(), Token3: $5, AssemblerOperands: $6.(*AssemblerOperands).reverse(), Token4: $7, } } | "asm" VolatileOpt '(' AssemblerInstructions ':' AssemblerOperands ':' AssemblerOperands ')' { $$ = &AssemblerStatement{ Case: 2, Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, AssemblerInstructions: $4.(*AssemblerInstructions).reverse(), Token3: $5, AssemblerOperands: $6.(*AssemblerOperands).reverse(), Token4: $7, AssemblerOperands2: $8.(*AssemblerOperands).reverse(), Token5: $9, } } | "asm" VolatileOpt '(' AssemblerInstructions ':' AssemblerOperands ':' AssemblerOperands ':' Clobbers ')' { $$ = &AssemblerStatement{ Case: 3, Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, AssemblerInstructions: $4.(*AssemblerInstructions).reverse(), Token3: $5, AssemblerOperands: $6.(*AssemblerOperands).reverse(), Token4: $7, AssemblerOperands2: $8.(*AssemblerOperands).reverse(), Token5: $9, Clobbers: $10.(*Clobbers).reverse(), Token6: $11, } } | "asm" VolatileOpt "goto" '(' AssemblerInstructions ':' ':' AssemblerOperands ':' Clobbers ':' IdentifierList ')' { $$ = &AssemblerStatement{ Case: 4, Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, Token3: $4, AssemblerInstructions: $5.(*AssemblerInstructions).reverse(), Token4: $6, Token5: $7, AssemblerOperands: $8.(*AssemblerOperands).reverse(), Token6: $9, Clobbers: $10.(*Clobbers).reverse(), Token7: $11, IdentifierList: $12.(*IdentifierList).reverse(), Token8: $13, } } | "asm" VolatileOpt '(' AssemblerInstructions ':' ')' { $$ = &AssemblerStatement{ Case: 5, Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, AssemblerInstructions: $4.(*AssemblerInstructions).reverse(), Token3: $5, Token4: $6, } } | "asm" VolatileOpt '(' AssemblerInstructions ':' ':' AssemblerOperands ')' { $$ = &AssemblerStatement{ Case: 6, Token: $1, VolatileOpt: $2.(*VolatileOpt), Token2: $3, AssemblerInstructions: $4.(*AssemblerInstructions).reverse(), Token3: $5, Token4: $6, AssemblerOperands: $7.(*AssemblerOperands).reverse(), Token5: $8, } } StaticAssertDeclaration: "_Static_assert" '(' ConstantExpression ',' STRINGLITERAL ')' ';' { lx := yylex.(*lexer) lhs := &StaticAssertDeclaration{ Token: $1, Token2: $2, ConstantExpression: $3.(*ConstantExpression), Token3: $4, Token4: $5, Token5: $6, Token6: $7, } $$ = lhs ce := lhs.ConstantExpression if ce.Type == nil || ce.Type.Kind() == Undefined || ce.Value == nil || !IsIntType(ce.Type) { lx.report.Err(ce.Pos(), "invalid static assert expression (have '%v')", ce.Type) break } if !isNonZero(ce.Value) { lx.report.ErrTok(lhs.Token, "%s", lhs.Token4.S()) } } PreprocessingFile: GroupList { lx := yylex.(*lexer) lhs := &PreprocessingFile{ GroupList: $1.(*GroupList).reverse(), } $$ = lhs lhs.path = lx.file.Name() } GroupList: GroupPart { $$ = &GroupList{ GroupPart: $1, } } | GroupList GroupPart { $$ = &GroupList{ Case: 1, GroupList: $1.(*GroupList), GroupPart: $2, } } GroupListOpt: /* empty */ { $$ = (*GroupListOpt)(nil) } | GroupList { $$ = &GroupListOpt{ GroupList: $1.(*GroupList).reverse(), } } GroupPart: ControlLine { $$ = $1.(Node) } | IfSection { $$ = $1.(Node) } | PPNONDIRECTIVE PPTokenList '\n' { $$ = $1 } | TextLine { $$ = $1 } IfSection: IfGroup ElifGroupListOpt ElseGroupOpt EndifLine { $$ = &IfSection{ IfGroup: $1.(*IfGroup), ElifGroupListOpt: $2.(*ElifGroupListOpt), ElseGroupOpt: $3.(*ElseGroupOpt), EndifLine: $4.(*EndifLine), } } IfGroup: PPIF PPTokenList '\n' GroupListOpt { $$ = &IfGroup{ Token: $1, PPTokenList: $2, Token2: $3, GroupListOpt: $4.(*GroupListOpt), } } | PPIFDEF IDENTIFIER '\n' GroupListOpt { $$ = &IfGroup{ Case: 1, Token: $1, Token2: $2, Token3: $3, GroupListOpt: $4.(*GroupListOpt), } } | PPIFNDEF IDENTIFIER '\n' GroupListOpt { $$ = &IfGroup{ Case: 2, Token: $1, Token2: $2, Token3: $3, GroupListOpt: $4.(*GroupListOpt), } } ElifGroupList: ElifGroup { $$ = &ElifGroupList{ ElifGroup: $1.(*ElifGroup), } } | ElifGroupList ElifGroup { $$ = &ElifGroupList{ Case: 1, ElifGroupList: $1.(*ElifGroupList), ElifGroup: $2.(*ElifGroup), } } ElifGroupListOpt: /* empty */ { $$ = (*ElifGroupListOpt)(nil) } | ElifGroupList { $$ = &ElifGroupListOpt{ ElifGroupList: $1.(*ElifGroupList).reverse(), } } ElifGroup: PPELIF PPTokenList '\n' GroupListOpt { $$ = &ElifGroup{ Token: $1, PPTokenList: $2, Token2: $3, GroupListOpt: $4.(*GroupListOpt), } } ElseGroup: PPELSE '\n' GroupListOpt { $$ = &ElseGroup{ Token: $1, Token2: $2, GroupListOpt: $3.(*GroupListOpt), } } ElseGroupOpt: /* empty */ { $$ = (*ElseGroupOpt)(nil) } | ElseGroup { $$ = &ElseGroupOpt{ ElseGroup: $1.(*ElseGroup), } } EndifLine: PPENDIF { $$ = &EndifLine{ Token: $1, } } ControlLine: PPDEFINE IDENTIFIER ReplacementList { $$ = &ControlLine{ Token: $1, Token2: $2, ReplacementList: $3, } } | PPDEFINE IDENTIFIER_LPAREN "..." ')' ReplacementList { $$ = &ControlLine{ Case: 1, Token: $1, Token2: $2, Token3: $3, Token4: $4, ReplacementList: $5, } } | PPDEFINE IDENTIFIER_LPAREN IdentifierList ',' "..." ')' ReplacementList { $$ = &ControlLine{ Case: 2, Token: $1, Token2: $2, IdentifierList: $3.(*IdentifierList).reverse(), Token3: $4, Token4: $5, Token5: $6, ReplacementList: $7, } } | PPDEFINE IDENTIFIER_LPAREN IdentifierListOpt ')' ReplacementList { $$ = &ControlLine{ Case: 3, Token: $1, Token2: $2, IdentifierListOpt: $3.(*IdentifierListOpt), Token3: $4, ReplacementList: $5, } } | PPERROR PPTokenListOpt { $$ = &ControlLine{ Case: 4, Token: $1, PPTokenListOpt: $2, } } | PPHASH_NL { $$ = &ControlLine{ Case: 5, Token: $1, } } | PPINCLUDE PPTokenList '\n' { $$ = &ControlLine{ Case: 6, Token: $1, PPTokenList: $2, Token2: $3, } } | PPLINE PPTokenList '\n' { $$ = &ControlLine{ Case: 7, Token: $1, PPTokenList: $2, Token2: $3, } } | PPPRAGMA PPTokenListOpt { $$ = &ControlLine{ Case: 8, Token: $1, PPTokenListOpt: $2, } } | PPUNDEF IDENTIFIER '\n' { $$ = &ControlLine{ Case: 9, Token: $1, Token2: $2, Token3: $3, } } | PPDEFINE IDENTIFIER_LPAREN IdentifierList "..." ')' ReplacementList { lx := yylex.(*lexer) lhs := &ControlLine{ Case: 10, Token: $1, Token2: $2, IdentifierList: $3.(*IdentifierList).reverse(), Token3: $4, Token4: $5, ReplacementList: $6, } $$ = lhs if !lx.tweaks.enableDefineOmitCommaBeforeDDD { lx.report.ErrTok(lhs.Token4, "missing comma before \"...\"") } } | PPDEFINE '\n' { lx := yylex.(*lexer) lhs := &ControlLine{ Case: 11, Token: $1, Token2: $2, } $$ = lhs if !lx.tweaks.enableEmptyDefine { lx.report.ErrTok(lhs.Token2, "expected identifier") } } | PPUNDEF IDENTIFIER PPTokenList '\n' { lx := yylex.(*lexer) lhs := &ControlLine{ Case: 12, Token: $1, Token2: $2, PPTokenList: $3, Token3: $4, } $$ = lhs toks := decodeTokens(lhs.PPTokenList, nil, false) if len(toks) == 0 { lhs.Case = 9 // PPUNDEF IDENTIFIER '\n' break } lx.report.ErrTok(toks[0], "extra tokens after #undef argument") } | PPINCLUDE_NEXT PPTokenList '\n' { $$ = &ControlLine{ Case: 13, Token: $1, PPTokenList: $2, Token2: $3, } } TextLine: PPTokenListOpt { } ReplacementList: PPTokenListOpt { } PPTokenList: PPTokens { lx := yylex.(*lexer) $$ = PPTokenList(dict.ID(lx.encBuf)) lx.encBuf = lx.encBuf[:0] lx.encPos = 0 } PPTokenListOpt: '\n' { $$ = 0 } | PPTokenList '\n' { } PPTokens: PPOTHER { } | PPTokens PPOTHER { }