// Copyright 2021 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. package cc // import "modernc.org/cc/v4" import ( "bytes" "fmt" "strings" ) var defaultKeywords = map[string]rune{ // C99 "_Bool": rune(BOOL), "_Complex": rune(COMPLEX), "_Imaginary": rune(IMAGINARY), "auto": rune(AUTO), "break": rune(BREAK), "case": rune(CASE), "char": rune(CHAR), "const": rune(CONST), "continue": rune(CONTINUE), "default": rune(DEFAULT), "do": rune(DO), "double": rune(DOUBLE), "else": rune(ELSE), "enum": rune(ENUM), "extern": rune(EXTERN), "float": rune(FLOAT), "for": rune(FOR), "goto": rune(GOTO), "if": rune(IF), "inline": rune(INLINE), "int": rune(INT), "long": rune(LONG), "register": rune(REGISTER), "restrict": rune(RESTRICT), "return": rune(RETURN), "short": rune(SHORT), "signed": rune(SIGNED), "sizeof": rune(SIZEOF), "static": rune(STATIC), "struct": rune(STRUCT), "switch": rune(SWITCH), "typedef": rune(TYPEDEF), "union": rune(UNION), "unsigned": rune(UNSIGNED), "void": rune(VOID), "volatile": rune(VOLATILE), "while": rune(WHILE), // C11 "_Alignas": rune(ALIGNAS), "_Alignof": rune(ALIGNOF), "_Atomic": rune(ATOMIC), "_Generic": rune(GENERIC), "_Noreturn": rune(NORETURN), "_Static_assert": rune(STATICASSERT), "_Thread_local": rune(THREADLOCAL), // GCC/clang/other extensions. "_Decimal128": rune(DECIMAL128), "_Decimal32": rune(DECIMAL32), "_Decimal64": rune(DECIMAL64), "_Float128": rune(FLOAT128), "_Float128x": rune(FLOAT128X), "_Float16": rune(FLOAT16), "_Float32": rune(FLOAT32), "_Float32x": rune(FLOAT32X), "_Float64": rune(FLOAT64), "_Float64x": rune(FLOAT64X), "_Nonnull": rune(NONNULL), "__alignof": rune(ALIGNOF), "__alignof__": rune(ALIGNOF), "__asm": rune(ASM), "__asm__": rune(ASM), "__attribute": rune(ATTRIBUTE), "__attribute__": rune(ATTRIBUTE), "__auto_type": rune(AUTOTYPE), "__complex": rune(COMPLEX), "__complex__": rune(COMPLEX), "__const": rune(CONST), "__declspec": rune(DECLSPEC), "__float128": rune(FLOAT128), "__imag": rune(IMAG), "__imag__": rune(IMAG), "__inline": rune(INLINE), "__inline__": rune(INLINE), "__int128": rune(INT128), "__label__": rune(LABEL), "__real": rune(REAL), "__real__": rune(REAL), "__restrict": rune(RESTRICT), "__restrict__": rune(RESTRICT), "__signed": rune(SIGNED), "__signed__": rune(SIGNED), "__thread": rune(THREADLOCAL), "__typeof": rune(TYPEOF), "__typeof__": rune(TYPEOF), "__uint128_t": rune(UINT128), "__volatile": rune(VOLATILE), "__volatile__": rune(VOLATILE), "asm": rune(ASM), "typeof": rune(TYPEOF), } type parser struct { cpp *cpp fnScope *Scope funcTokens []Token gotos []*JumpStatement keywords map[string]rune prevNL Token scope *Scope switchCtx *SelectionStatement toks []Token seq int32 } func newParser(cfg *Config, fset *fset, sources []Source) (*parser, error) { cpp, err := newCPP(cfg, fset, sources, nil) if err != nil { return nil, err } funcTokens := []Token{ {Ch: rune(STATIC)}, {Ch: rune(CONST)}, {Ch: rune(CHAR)}, {Ch: rune(IDENTIFIER)}, {Ch: '['}, {Ch: ']'}, {Ch: '='}, {Ch: rune(STRINGLITERAL)}, {Ch: ';'}, } if cfg.keywords == nil { cfg.keywords = defaultKeywords } funcTokens = funcTokens[:len(funcTokens):len(funcTokens)] return &parser{ cpp: cpp, funcTokens: funcTokens, scope: &Scope{}, keywords: cfg.keywords, }, nil } func (p *parser) newScope() { p.scope = newScope(p.scope) } func (p *parser) closeScope() { if parent := p.scope.Parent; parent != nil { p.scope = parent return } p.rune(false) p.cpp.eh("%v: internal error (%v:)", p.toks[0].Position(), origin(1)) if isTesting { trc("%v: internal error (%v:)", p.toks[0].Position(), origin(1)) } } func (p *parser) isKeyword(s []byte) (r rune, ok bool) { r, ok = p.keywords[string(s)] return r, ok } func (p *parser) next() { var b []byte set := false if p.prevNL.Ch != 0 { b = p.prevNL.Sep() set = true } for { p.cpp.rune() t := p.cpp.shift() switch t.Ch { case ' ': // nop case '\n': if p.prevNL.Ch != 0 { b = append(b, p.prevNL.Src()...) set = true } p.prevNL = t b = append(b, t.Sep()...) default: if set && !bytes.Equal(b, p.prevNL.Sep()) { p.prevNL.Set(b, p.prevNL.Src()) } p.seq++ t.seq = p.seq p.toks = append(p.toks, p.tok(t)) return } } } func (p *parser) rune(checkTypeName bool) (r rune) { if len(p.toks) == 0 { p.next() } switch { case checkTypeName: t := p.toks[0] p.checkTypeName(&t) return t.Ch default: return p.toks[0].Ch } } func (p *parser) checkTypeName(t *Token) (r bool) { if t.Ch != rune(IDENTIFIER) { return false } if x, ok := p.scope.ident(*t).(*Declarator); ok { if x.isTypename { t.Ch = rune(TYPENAME) return true } } return false } func (p *parser) tok(t Token) (r Token) { r = t switch t.Ch { case rune(IDENTIFIER): if c, ok := p.isKeyword(r.Src()); ok { r.Ch = c break } case rune(PPNUMBER): switch s := r.SrcStr(); { case strings.ContainsAny(s, ".+-ijpIJP"): r.Ch = rune(FLOATCONST) case strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X"): r.Ch = rune(INTCONST) case strings.ContainsAny(s, "Ee"): r.Ch = rune(FLOATCONST) default: r.Ch = rune(INTCONST) } } return r } func (p *parser) shift0() (r Token) { r = p.toks[0] if r.Ch != '\n' && p.prevNL.Ch != 0 { sep := append(p.prevNL.Sep(), p.prevNL.Src()...) sep = append(sep, r.Sep()...) r.Set(sep, r.Src()) } if r.Ch != eof { switch { case len(p.toks) == 1: p.toks = p.toks[:0] default: p.toks = p.toks[1:] } p.prevNL.Ch = 0 p.rune(false) } return r } func (p *parser) shift(checkTypeName bool) (r Token) { r = p.shift0() // if r.Ch != ' ' && r.Ch != '\n' { // trc("%v: %v", pos(r), r) // } switch { case r.Ch == rune(STRINGLITERAL) && p.rune(false) == rune(STRINGLITERAL): sep := r.Sep() src := r.Src() for p.rune(false) == rune(STRINGLITERAL) { t := p.shift0() sep = append(sep, t.Sep()...) src = append(src[:len(src)-1], t.Src()[1:]...) } r.Set(sep, src) case r.Ch == rune(LONGSTRINGLITERAL) && (p.rune(false) == rune(LONGSTRINGLITERAL) || p.rune(false) == rune(STRINGLITERAL)): sep := r.Sep() src := r.Src() out: for { switch p.rune(false) { case rune(LONGSTRINGLITERAL): t := p.shift0() sep = append(sep, t.Sep()...) src = append(src[:len(src)-1], t.Src()[2:]...) case rune(STRINGLITERAL): t := p.shift0() sep = append(sep, t.Sep()...) src = append(src[:len(src)-1], t.Src()[1:]...) default: break out } } r.Set(sep, src) } if checkTypeName { p.checkTypeName(&r) } return r } func (p *parser) peek(i int, checkTypeName bool) (r Token) { for len(p.toks) <= i { p.next() } switch { case checkTypeName: r = p.toks[i] p.checkTypeName(&r) return r default: return p.toks[i] } } func (p *parser) must(r rune) Token { c := p.rune(false) t := p.shift(false) if c != r { p.cpp.eh("%v: unexpected %v, expected %v", t.Position(), runeName(c), runeName(r)) } return t } func (p *parser) parse() (ast *AST, err error) { var errors errors p.cpp.eh = func(msg string, args ...interface{}) { s := fmt.Sprintf(msg, args...) if isTesting { s += fmt.Sprintf(" (%v: %v)", origin(2), origin(3)) if traceFails { trc("%s FAIL (%v)", s, origin(1)) // trc("\n%s", debug.Stack()) } } errors = append(errors, s) } p.cpp.rune() tu := p.translationUnit() p.cpp.mmap = nil if p.scope == nil && p.scope.Parent != nil { p.cpp.eh("internal error (%v:)", origin(1)) } switch p.rune(false) { case eof: var pd *Declarator if a := p.scope.Nodes["__predefined_declarator"]; len(a) != 0 { pd, _ = a[0].(*Declarator) } if pd == nil && !p.cpp.cfg.noPredefinedDeclarator { errors.add(errorf(": missing definition of '__predefined_declarator'")) } t := p.shift(false) t.Set(append(p.prevNL.Sep(), p.prevNL.Src()...), nil) return &AST{ ABI: p.cpp.cfg.ABI, EOF: t, Macros: p.cpp.macros, Scope: p.scope, TranslationUnit: tu, predefinedDeclarator0: pd, }, errors.err() default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected EOF", t.Position(), runeName(t.Ch)) return nil, errors.err() } } // [0], 6.9 External definitions // // translation-unit: // external-declaration // translation-unit external-declaration func (p *parser) translationUnit() (r *TranslationUnit) { var prev *TranslationUnit for p.rune(false) != eof { tu := &TranslationUnit{ExternalDeclaration: p.externalDeclaration()} if tu.ExternalDeclaration == nil { return r } switch { case r == nil: r = tu default: prev.TranslationUnit = tu } prev = tu } return r } // external-declaration: // function-definition // declaration // asm-function-definition // asm-statement // ; func (p *parser) externalDeclaration() *ExternalDeclaration { again: switch p.rune(false) { case eof: return nil case rune(ASM): return &ExternalDeclaration{Case: ExternalDeclarationAsmStmt, AsmStatement: p.asmStatement()} case rune(STATICASSERT), rune(AUTOTYPE): return &ExternalDeclaration{Case: ExternalDeclarationDecl, Declaration: p.declaration(nil, nil, false)} } ds, ok := p.declarationSpecifiers() if !ok { goto again } var d *Declarator if p.rune(false) != ';' { d = p.declarator(nil, ds, true) } switch p.rune(false) { case ',', ';', '=', rune(ASM), rune(ATTRIBUTE): //TODO wrong parse of pr37573.c return &ExternalDeclaration{Case: ExternalDeclarationDecl, Declaration: p.declaration(ds, d, true)} case '{': return &ExternalDeclaration{Case: ExternalDeclarationFuncDef, FunctionDefinition: p.functionDefinition(ds, d)} default: if d.isFn() { return &ExternalDeclaration{Case: ExternalDeclarationFuncDef, FunctionDefinition: p.functionDefinition(ds, d)} } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected external declaration", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.9.1 Function definitions // // function-definition: // declaration-specifiers declarator declaration-list_opt compound-statement func (p *parser) functionDefinition(ds *DeclarationSpecifiers, d *Declarator) (r *FunctionDefinition) { defer func() { r.scope = p.fnScope p.fnScope = nil }() d.isFuncDef = true return &FunctionDefinition{DeclarationSpecifiers: ds, Declarator: d, DeclarationList: p.declarationListOpt(), CompoundStatement: p.compoundStatement(false, true, d)} } // declaration-list: // declaration // declaration-list declaration func (p *parser) declarationListOpt() (r *DeclarationList) { var prev *DeclarationList for { switch p.rune(false) { case '{', eof: return r } dl := &DeclarationList{Declaration: p.declaration(nil, nil, false)} switch { case r == nil: r = dl default: prev.DeclarationList = dl } prev = dl } return r } // [0], 6.8.2 Compound statement // // compound-statement: // { label-declaration_opt block-item-list_opt } func (p *parser) compoundStatement(inFreshNewScope, isFnScope bool, d *Declarator) (r *CompoundStatement) { if !inFreshNewScope { p.newScope() defer p.closeScope() } if isFnScope { p.fnScope = p.scope gotos := p.gotos p.gotos = nil if d != nil { for dd := d.DirectDeclarator; dd != nil; { if s := dd.params; s != nil { for nm, nodes := range s.Nodes { for _, node := range nodes { p.scope.declare(p.cpp.eh, nm, node) } } } switch dd.Case { case DirectDeclaratorIdent: dd = nil case DirectDeclaratorDecl: dd = dd.Declarator.DirectDeclarator default: dd = dd.DirectDeclarator } } } defer func() { r.gotos = p.gotos next: for _, s := range r.Gotos() { switch s.Case { case JumpStatementGoto: nm := s.Token2.SrcStr() for sc := s.LexicalScope(); sc != nil && sc.Parent != nil; sc = sc.Parent { for _, n := range sc.Nodes[nm] { switch x := n.(type) { case *LabeledStatement: if nm == x.Token.SrcStr() { s.label = x continue next } case *LabelDeclaration: s.label = x continue next } } } p.cpp.eh("%v: label undefined: %s", s.Token2.Position(), nm) } } p.gotos = gotos }() } lbrace := p.must('{') if isFnScope && d != nil && !p.cpp.cfg.doNotInjectFunc { p.injectFuncTokens(lbrace, d.Name()) } return &CompoundStatement{Token: lbrace, BlockItemList: p.blockItemListOpt(), Token2: p.must('}'), lexicalScope: (*lexicalScope)(p.scope)} } var funcTokensText = [][]byte{ []byte("static"), // 0 []byte("const"), // 1 []byte("char"), // 2 []byte("__func__"), // 3 []byte("["), // 4 []byte("]"), // 5 []byte("="), // 6 []byte("function-name"), // 7 []byte(";"), // 8 } func (p *parser) injectFuncTokens(lbrace Token, nm string) { seq := lbrace.seq for i := range p.funcTokens { pt := &p.funcTokens[i] pt.s = lbrace.s pt.off = lbrace.off seq++ pt.seq = seq if i != 7 { pt.Set(sp, funcTokensText[i]) } } p.funcTokens[7].Set(sp, []byte(`"`+nm+`"`)) p.rune(false) for i := range p.toks { seq++ p.toks[i].seq = seq } p.seq = seq + 1 p.toks = append(p.funcTokens, p.toks...) } // block-item-list: // block-item // block-item-list block-item func (p *parser) blockItemListOpt() (r *BlockItemList) { var prev *BlockItemList for { switch p.rune(false) { case '}', eof: return r default: bil := &BlockItemList{BlockItem: p.blockItem()} switch { case r == nil: r = bil default: prev.BlockItemList = bil } prev = bil } } } // block-item: // declaration // statement // label-declaration // declaration-specifiers declarator compound-statement func (p *parser) blockItem() *BlockItem { again: switch ch := p.rune(true); { case p.isStatement(ch) || p.isExpression(ch) || ch == rune(TYPENAME) && p.peek(1, false).Ch == ':': return &BlockItem{Case: BlockItemStmt, Statement: p.statement(false)} case p.isDeclarationSpecifier(ch, true): r0 := p.rune(false) ds, ok := p.declarationSpecifiers() if !ok { goto again } if r0 == rune(ATTRIBUTE) && p.rune(false) == ';' { return &BlockItem{ Case: BlockItemStmt, Statement: &Statement{ Case: StatementExpr, ExpressionStatement: &ExpressionStatement{declarationSpecifiers: ds, AttributeSpecifierList: p.attributeSpecifierListOpt(), Token: p.shift(false)}, }, } } var d *Declarator if p.rune(false) != ';' { d = p.declarator(nil, ds, true) } switch p.rune(false) { case '{': return &BlockItem{Case: BlockItemFuncDef, DeclarationSpecifiers: ds, Declarator: d, CompoundStatement: p.compoundStatement(false, true, d)} default: return &BlockItem{Case: BlockItemDecl, Declaration: p.declaration(ds, d, true)} } case ch == rune(LABEL): return &BlockItem{Case: BlockItemLabel, LabelDeclaration: p.labelDeclaration()} case ch == rune(STATICASSERT), ch == rune(AUTOTYPE): return &BlockItem{Case: BlockItemDecl, Declaration: p.declaration(nil, nil, false)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected block item", t.Position(), runeName(t.Ch)) return nil } } // label-declaration // __label__ identifier-list ; func (p *parser) labelDeclaration() (r *LabelDeclaration) { r = &LabelDeclaration{Token: p.shift(false), IdentifierList: p.identifierList(false), Token2: p.must(';')} for l := r.IdentifierList; l != nil; l = l.IdentifierList { p.scope.declare(p.cpp.eh, l.Token2.SrcStr(), r) } return r } // [0], 6.8 Statements and blocks // // statement: // labeled-statement // compound-statement // expression-statement // selection-statement // iteration-statement // jump-statement // asm-statement func (p *parser) statement(newBlock bool) *Statement { if newBlock { p.newScope() defer p.closeScope() } switch ch := p.rune(false); { case ch == rune(IDENTIFIER): switch p.peek(1, false).Ch { case ':': return &Statement{Case: StatementLabeled, LabeledStatement: p.labeledStatement()} default: return &Statement{Case: StatementExpr, ExpressionStatement: p.expressionStatement()} } case p.isExpression(ch) || ch == ';' || ch == rune(ATTRIBUTE): return &Statement{Case: StatementExpr, ExpressionStatement: p.expressionStatement()} } switch p.rune(true) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '{': return &Statement{Case: StatementCompound, CompoundStatement: p.compoundStatement(newBlock, false, nil)} case rune(ASM): return &Statement{Case: StatementAsm, AsmStatement: p.asmStatement()} case rune(DO), rune(FOR), rune(WHILE): return &Statement{Case: StatementIteration, IterationStatement: p.iterationStatement()} case rune(BREAK), rune(CONTINUE), rune(GOTO), rune(RETURN): return &Statement{Case: StatementJump, JumpStatement: p.jumpStatement()} case rune(IF), rune(SWITCH): return &Statement{Case: StatementSelection, SelectionStatement: p.selectionStatement()} case rune(CASE), rune(DEFAULT): return &Statement{Case: StatementLabeled, LabeledStatement: p.labeledStatement()} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected statement", t.Position(), runeName(t.Ch)) return nil } } func (p *parser) isStatement(ch rune) bool { switch ch { case '(', '*', ';', '{', rune(ASM), rune(BREAK), rune(CASE), rune(CONTINUE), rune(DEC), rune(DEFAULT), rune(DO), rune(FOR), rune(GOTO), rune(IDENTIFIER), rune(IF), rune(INC), rune(LONGSTRINGLITERAL), rune(RETURN), rune(STRINGLITERAL), rune(SWITCH), rune(WHILE): return true } return false } // [0], 6.8.4 Selection statements // // selection-statement: // if ( expression ) statement // if ( expression ) statement else statement // switch ( expression ) statement func (p *parser) selectionStatement() (r *SelectionStatement) { // [0]6.8.4/3 // // A selection statement is a block whose scope is a strict subset of the scope // of its enclosing block. Each associated substatement is also a block whose // scope is a strict subset of the scope of the selection statement. p.newScope() defer p.closeScope() switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(IF): r = &SelectionStatement{Case: SelectionStatementIf, Token: p.shift(false), Token2: p.must('('), ExpressionList: p.expression(false), Token3: p.must(')'), Statement: p.statement(true), lexicalScope: (*lexicalScope)(p.scope)} switch p.rune(false) { case rune(ELSE): r.Case = SelectionStatementIfElse r.Token4 = p.shift(false) r.Statement2 = p.statement(true) return r default: return r } case rune(SWITCH): r = &SelectionStatement{Case: SelectionStatementSwitch, Token: p.shift(false), Token2: p.must('('), ExpressionList: p.expression(false), Token3: p.must(')'), lexicalScope: (*lexicalScope)(p.scope)} ctx := p.switchCtx p.switchCtx = r defer func() { p.switchCtx = ctx }() r.Statement = p.statement(true) return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected selection statement", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.8.6 Jump statements // // jump-statement: // goto identifier ; // goto * expression ; // continue ; // break ; // return expression_opt ; func (p *parser) jumpStatement() (r *JumpStatement) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(BREAK): return &JumpStatement{Case: JumpStatementBreak, Token: p.shift(false), Token2: p.must(';'), lexicalScope: (*lexicalScope)(p.scope)} case rune(CONTINUE): return &JumpStatement{Case: JumpStatementContinue, Token: p.shift(false), Token2: p.must(';'), lexicalScope: (*lexicalScope)(p.scope)} case rune(GOTO): switch p.peek(1, false).Ch { case '*': r = &JumpStatement{Case: JumpStatementGotoExpr, Token: p.shift(false), Token2: p.shift(false), ExpressionList: p.expression(false), Token3: p.must(';'), lexicalScope: (*lexicalScope)(p.scope)} default: r = &JumpStatement{Case: JumpStatementGoto, Token: p.shift(false), Token2: p.must(rune(IDENTIFIER)), Token3: p.must(';'), lexicalScope: (*lexicalScope)(p.scope)} } p.gotos = append(p.gotos, r) return r case rune(RETURN): return &JumpStatement{Case: JumpStatementReturn, Token: p.shift(false), ExpressionList: p.expression(true), Token2: p.must(';'), lexicalScope: (*lexicalScope)(p.scope)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected jump statement", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.8.1 Labeled statements // // labeled-statement: // identifier : statement // case constant-expression : statement // case constant-expression ... constant-expression : statement // default : statement func (p *parser) labeledStatement() (r *LabeledStatement) { defer func() { if ctx := p.switchCtx; ctx != nil && r != nil { ctx.labeled = append(ctx.labeled, r) } }() switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(CASE): r = &LabeledStatement{Token: p.shift(false), ConstantExpression: p.constantExpression(), lexicalScope: (*lexicalScope)(p.scope), switchCtx: p.switchCtx} switch p.rune(false) { case rune(DDD): r.Case = LabeledStatementRange r.Token2 = p.shift(false) r.ConstantExpression2 = p.constantExpression() r.Token3 = p.must(':') r.Statement = p.statement(false) return r default: r.Case = LabeledStatementCaseLabel r.Token2 = p.must(':') r.Statement = p.statement(false) return r } case rune(DEFAULT): return &LabeledStatement{Case: LabeledStatementDefault, Token: p.shift(false), Token2: p.must(':'), Statement: p.statement(false), lexicalScope: (*lexicalScope)(p.scope), switchCtx: p.switchCtx} case rune(IDENTIFIER): r = &LabeledStatement{Case: LabeledStatementLabel, Token: p.shift(false), Token2: p.must(':'), Statement: p.statement(false), lexicalScope: (*lexicalScope)(p.scope), switchCtx: p.switchCtx} switch { case p.fnScope == nil: t := p.shift(false) p.cpp.eh("%v: unexpected label", t.Position()) default: p.fnScope.declare(p.cpp.eh, r.Token.SrcStr(), r) } return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected labeled statement", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.8.5 Iteration statements // // iteration-statement: // while ( expression ) statement // do statement while ( expression ) ; // for ( expression_opt ; expression_opt ; expression_opt ) statement // for ( declaration expression_opt ; expression_opt ) statement func (p *parser) iterationStatement() (r *IterationStatement) { // [0]6.8.5/5 // // An iteration statement is a block whose scope is a strict subset of the // scope of its enclosing block. The loop body is also a block whose scope is a // strict subset of the scope of the iteration statement. p.newScope() defer p.closeScope() switch p.rune(false) { case rune(WHILE): return &IterationStatement{Case: IterationStatementWhile, Token: p.shift(false), Token2: p.must('('), ExpressionList: p.expression(false), Token3: p.must(')'), Statement: p.statement(true), lexicalScope: (*lexicalScope)(p.scope)} case rune(DO): return &IterationStatement{Case: IterationStatementDo, Token: p.shift(false), Statement: p.statement(true), Token2: p.must(rune(WHILE)), Token3: p.must('('), ExpressionList: p.expression(false), Token4: p.must(')'), Token5: p.must(';'), lexicalScope: (*lexicalScope)(p.scope)} case rune(FOR): switch ch := p.peek(2, true).Ch; { case p.isDeclarationSpecifier(ch, true): return &IterationStatement{Case: IterationStatementForDecl, Token: p.shift(false), Token2: p.must('('), Declaration: p.declaration(nil, nil, true), ExpressionList: p.expression(true), Token3: p.must(';'), ExpressionList2: p.expression(true), Token4: p.must(')'), Statement: p.statement(true), lexicalScope: (*lexicalScope)(p.scope)} } return &IterationStatement{Case: IterationStatementFor, Token: p.shift(false), Token2: p.must('('), ExpressionList: p.expression(true), Token3: p.must(';'), ExpressionList2: p.expression(true), Token4: p.must(';'), ExpressionList3: p.expression(true), Token5: p.must(')'), Statement: p.statement(true), lexicalScope: (*lexicalScope)(p.scope)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected iteration statement", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.8.3 Expression and null statements // // expression-statement: // expression_opt; func (p *parser) expressionStatement() *ExpressionStatement { switch p.rune(false) { case rune(ATTRIBUTE): t := p.shift(false) p.cpp.eh("%v: internal error: TODO", t.Position(), runeName(t.Ch)) return nil default: return &ExpressionStatement{ExpressionList: p.expression(true), Token: p.must(';')} } } // asm-statement: // asm ; func (p *parser) asmStatement() *AsmStatement { return &AsmStatement{Asm: p.asm(), Token: p.must(';')} } // asm: // asm asm-qualifier-list_opt ( string-literal asm-arg-list_opt ) func (p *parser) asm() *Asm { return &Asm{Token: p.must(rune(ASM)), AsmQualifierList: p.asmQualifierListOpt(), Token2: p.must('('), Token3: p.must(rune(STRINGLITERAL)), AsmArgList: p.asmArgListOpt(), Token4: p.must(')')} } // asm-qualifier-list: // asm-qualifier // asm-qualifier-list asm-qualifier func (p *parser) asmQualifierListOpt() (r *AsmQualifierList) { var prev *AsmQualifierList for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return r case rune(GOTO), rune(INLINE), rune(VOLATILE): aql := &AsmQualifierList{AsmQualifier: p.asmQualifier()} switch { case r == nil: r = aql default: prev.AsmQualifierList = aql } prev = aql default: return r } } } // asm-qualifier: // volatile // inline // goto" func (p *parser) asmQualifier() *AsmQualifier { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(VOLATILE): return &AsmQualifier{Case: AsmQualifierVolatile, Token: p.shift(false)} case rune(INLINE): return &AsmQualifier{Case: AsmQualifierInline, Token: p.shift(false)} case rune(GOTO): return &AsmQualifier{Case: AsmQualifierGoto, Token: p.shift(false)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected asm qualifier", t.Position(), runeName(t.Ch)) return nil } } // asm-arg-list: // : asm-expression-list // asm-arg-list : asm-expression-list func (p *parser) asmArgListOpt() (r *AsmArgList) { var prev *AsmArgList for p.rune(false) == ':' { var aal *AsmArgList switch p.peek(1, false).Ch { case ')', ':': aal = &AsmArgList{Token: p.shift(false)} default: aal = &AsmArgList{Token: p.shift(false), AsmExpressionList: p.asmExpressionList()} } switch { case r == nil: r = aal default: prev.AsmArgList = aal } prev = aal } return r } // asm-expression-list: // asm-index_opt assignment-expression // asm-expression-list , asm-index_opt assignment-expression func (p *parser) asmExpressionList() (r *AsmExpressionList) { r = &AsmExpressionList{AsmIndex: p.asmIndexOpt(), AssignmentExpression: p.assignmentExpression(true)} prev := r for p.rune(false) == ',' { ael := &AsmExpressionList{Token: p.shift(false), AsmIndex: p.asmIndexOpt(), AssignmentExpression: p.assignmentExpression(true)} prev.AsmExpressionList = ael prev = ael } return r } // asm-index: // [ expression ] func (p *parser) asmIndexOpt() *AsmIndex { if p.rune(false) != '[' { return nil } return &AsmIndex{Token: p.shift(false), ExpressionList: p.expression(false), Token2: p.must(']')} } // [0], 6.5.17 Comma operator // // expression: // assignment-expression // expression , assignment-expression func (p *parser) expression(opt bool) ExpressionNode { var r, prev *ExpressionList if p.isExpression(p.rune(false)) { ae := p.assignmentExpression(true) if p.rune(false) != ',' { return ae } r = &ExpressionList{AssignmentExpression: ae} prev = r for p.rune(false) == ',' { el := &ExpressionList{Token: p.shift(false), AssignmentExpression: p.assignmentExpression(true)} prev.ExpressionList = el prev = el } return r } if opt { return nil } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected asm expression", t.Position(), runeName(t.Ch)) return nil } func (p *parser) isExpression(ch rune) bool { switch ch { case '!', '&', '(', '*', '+', '-', '~', rune(ALIGNOF), rune(ANDAND), rune(CHARCONST), rune(DEC), rune(FLOATCONST), rune(GENERIC), rune(IDENTIFIER), rune(IMAG), rune(INC), rune(INTCONST), rune(LONGCHARCONST), rune(LONGSTRINGLITERAL), rune(REAL), rune(SIZEOF), rune(STRINGLITERAL): return true } return false } // [0], 6.7 Declarations // // declaration: // declaration-specifiers init-declarator-list_opt attribute-specifier-list_opt; // static-assert-declaration // __auto_type ident = initializer ; func (p *parser) declaration(ds *DeclarationSpecifiers, d *Declarator, declare bool) (r *Declaration) { switch p.rune(false) { case rune(STATICASSERT): return &Declaration{Case: DeclarationAssert, StaticAssertDeclaration: p.staticAssertDeclaration()} case rune(AUTOTYPE): nm := p.peek(1, true) if nm.Ch != rune(IDENTIFIER) { p.cpp.eh("%v: unexpected %v, expected identifier", nm.Position(), runeName(nm.Ch)) p.shift(false) p.shift(false) return nil } r = &Declaration{Case: DeclarationAuto, Token: p.shift(false), Declarator: p.declarator(nil, nil, false)} r.Token2 = p.must('=') r.Initializer = p.initializer(nil) r.Token3 = p.must(';') r.Declarator.visible = visible(r.Token3.seq) p.scope.declare(p.cpp.eh, nm.SrcStr(), r.Declarator) return r } if ds == nil { var ok bool if ds, ok = p.declarationSpecifiers(); !ok { return nil } } return &Declaration{Case: DeclarationDecl, DeclarationSpecifiers: ds, InitDeclaratorList: p.initDeclaratorListOpt(ds, d, declare), AttributeSpecifierList: p.attributeSpecifierListOpt(), Token: p.must(';')} } // static-assert-declaration // _Static_assert ( constant-expression , string-literal ) func (p *parser) staticAssertDeclaration() *StaticAssertDeclaration { return &StaticAssertDeclaration{Token: p.must(rune(STATICASSERT)), Token2: p.must('('), ConstantExpression: p.constantExpression(), Token3: p.must(','), Token4: p.must(rune(STRINGLITERAL)), Token5: p.must(')')} } // attribute-specifier-list: // attribute-specifier // attribute-specifier-list attribute-specifier func (p *parser) attributeSpecifierListOpt() (r *AttributeSpecifierList) { if p.rune(false) != rune(ATTRIBUTE) { return nil } r = &AttributeSpecifierList{AttributeSpecifier: p.attributeSpecifier()} prev := r for p.rune(false) == rune(ATTRIBUTE) { asl := &AttributeSpecifierList{AttributeSpecifier: p.attributeSpecifier()} prev.AttributeSpecifierList = asl prev = asl } //trc("%v: %s (%v: %v: %v)", r.Position(), NodeSource(r), origin(4), origin(3), origin(2)) return r } // attribute-specifier: // __attribute__ (( attribute-value-list_opt )) func (p *parser) attributeSpecifier() (r *AttributeSpecifier) { return &AttributeSpecifier{Token: p.must(rune(ATTRIBUTE)), Token2: p.must('('), Token3: p.must('('), AttributeValueList: p.attributeValueListOpt(), Token4: p.must(')'), Token5: p.must(')')} } // attribute-value-list: // attribute-value // attribute-value-list , attribute-value func (p *parser) attributeValueListOpt() (r *AttributeValueList) { switch p.rune(false) { case eof: return r case rune(IDENTIFIER): r = &AttributeValueList{AttributeValue: p.attributeValue()} case ')': return nil default: if _, ok := p.isKeyword(p.toks[0].Src()); ok { r = &AttributeValueList{AttributeValue: p.attributeValue()} break } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected attribute value", t.Position(), runeName(t.Ch)) } prev := r for p.rune(false) == ',' { avl := &AttributeValueList{Token: p.shift(false), AttributeValue: p.attributeValue()} prev.AttributeValueList = avl } return r } // attribute-value: // identifier // identifier ( expression-list_opt ) func (p *parser) attributeValue() (r *AttributeValue) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(IDENTIFIER): switch p.peek(1, false).Ch { case '(': return &AttributeValue{Case: AttributeValueExpr, Token: p.shift(false), Token2: p.shift(false), ArgumentExpressionList: p.argumentExpressionListOpt(false), Token3: p.must(')')} default: return &AttributeValue{Case: AttributeValueIdent, Token: p.shift(false)} } default: if _, ok := p.isKeyword(p.toks[0].Src()); ok { r = &AttributeValue{Case: AttributeValueIdent, Token: p.shift(false)} r.Token.Ch = rune(IDENTIFIER) return r } p.cpp.eh("%v: unexpected %v, expected identifier", p.toks[0].Position(), runeName(p.rune(false))) p.shift(false) return nil } } // init-declarator-list: // init-declarator // init-declarator-list , init-declarator func (p *parser) initDeclaratorListOpt(ds *DeclarationSpecifiers, d *Declarator, declare bool) (r *InitDeclaratorList) { switch { case d == nil: switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ';': return nil case '(', '*', rune(IDENTIFIER): d = p.declarator(nil, ds, declare) default: p.cpp.eh("%v: unexpected %v, expected direct-declarator", p.toks[0].Position(), runeName(p.rune(false))) p.shift(false) return nil } } r = &InitDeclaratorList{InitDeclarator: p.initDeclarator(ds, d, declare)} prev := r for p.rune(false) == ',' { idl := &InitDeclaratorList{Token: p.shift(false), AttributeSpecifierList: p.attributeSpecifierListOpt(), InitDeclarator: p.initDeclarator(ds, nil, declare)} prev.InitDeclaratorList = idl prev = idl } return r } // init-declarator: // declarator asm-register-var_opt // declarator asm-register-var_opt = initializer func (p *parser) initDeclarator(ds *DeclarationSpecifiers, d *Declarator, declare bool) (r *InitDeclarator) { if d == nil { d = p.declarator(nil, ds, declare) } r = &InitDeclarator{Case: InitDeclaratorDecl, Declarator: d} if p.rune(false) == rune(ASM) { r.Asm = p.asm() } if p.rune(false) == rune(ATTRIBUTE) { r.AttributeSpecifierList = p.attributeSpecifierListOpt() } if p.rune(false) == '=' { d.hasInitializer = true if d.isTypename { p.cpp.eh("%v: typedef '%s' is initialized", p.toks[0].Position(), d.Name()) } r.Case = InitDeclaratorInit r.Token = p.shift(false) r.Initializer = p.initializer(nil) } return r } // [0], 6.7.8 Initialization // // initializer: // assignment-expression // { initializer-list } // { initializer-list , } func (p *parser) initializer(parent *Initializer) (r *Initializer) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '{': r = &Initializer{Case: InitializerInitList, Token: p.shift(false), parent: parent} r.InitializerList = p.initializerList(r) if p.rune(false) == ',' { r.Token2 = p.shift(false) } r.Token3 = p.must('}') return r default: return &Initializer{Case: InitializerExpr, AssignmentExpression: p.assignmentExpression(true), parent: parent} } } // initializer-list: // designation_opt initializer // initializer-list , designation_opt initializer func (p *parser) initializerList(parent *Initializer) (r *InitializerList) { switch p.rune(true) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '[', '.': r = &InitializerList{Designation: p.designation(), Initializer: p.initializer(parent)} case rune(IDENTIFIER): switch p.peek(1, false).Ch { case ':': r = &InitializerList{Designation: p.designation(), Initializer: p.initializer(parent)} default: r = &InitializerList{Initializer: p.initializer(parent)} } case '{': r = &InitializerList{Initializer: p.initializer(parent)} case '}': return nil default: if p.isExpression(p.rune(true)) { r = &InitializerList{Initializer: p.initializer(parent)} break } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected designation or initializer", t.Position(), runeName(t.Ch)) } prev := r for p.rune(false) == ',' { var il *InitializerList switch p.peek(1, true).Ch { case '.', '[': il = &InitializerList{Token: p.shift(false), Designation: p.designation(), Initializer: p.initializer(parent)} case rune(IDENTIFIER): switch p.peek(2, false).Ch { case ':': il = &InitializerList{Token: p.shift(false), Designation: p.designation(), Initializer: p.initializer(parent)} default: il = &InitializerList{Token: p.shift(false), Initializer: p.initializer(parent)} } case '}': return r default: il = &InitializerList{Token: p.shift(false), Initializer: p.initializer(parent)} } prev.InitializerList = il prev = il } return r } // designation: // designator-list = func (p *parser) designation() (r *Designation) { p.rune(false) dl, last := p.designatorList() r = &Designation{DesignatorList: dl} if last != DesignatorField2 { r.Token = p.must('=') } return r } // designator-list: // designator // designator-list designator func (p *parser) designatorList() (r *DesignatorList, last DesignatorCase) { var prev *DesignatorList for { var dl *DesignatorList switch p.rune(true) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, 0 case '[', '.': dl = &DesignatorList{Designator: p.designator()} case rune(IDENTIFIER): switch p.peek(1, false).Ch { case ':': dl = &DesignatorList{Designator: p.designator()} default: return r, last } default: return r, last } last = dl.Designator.Case switch { case r == nil: r = dl default: prev.DesignatorList = dl } prev = dl } } // designator: // [ constant-expression ] // [ constant-expression ... constant-expression] // . identifier // identifier : func (p *parser) designator() (r *Designator) { switch p.rune(true) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '[': r = &Designator{Case: DesignatorIndex, Token: p.shift(false), ConstantExpression: p.constantExpression()} switch p.rune(false) { case rune(DDD): r.Case = DesignatorIndex2 r.Token2 = p.shift(false) r.ConstantExpression2 = p.constantExpression() r.Token3 = p.must(']') return r default: r.Token2 = p.must(']') return r } case '.': return &Designator{Case: DesignatorField, Token: p.shift(false), Token2: p.must(rune(IDENTIFIER))} case rune(IDENTIFIER): switch p.peek(1, false).Ch { case ':': return &Designator{Case: DesignatorField2, Token: p.shift(false), Token2: p.shift(false)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected designator", t.Position(), runeName(t.Ch)) return nil } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected designator", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.5.16 Assignment operators // // assignment-expression: // conditional-expression // unary-expression assignment-operator assignment-expression // // assignment-operator: one of // = *= /= %= += -= <<= >>= &= ^= |= func (p *parser) assignmentExpression(checkTypeName bool) ExpressionNode { lhs, u := p.conditionalExpression(checkTypeName) var r *AssignmentExpression switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '=': r = &AssignmentExpression{Case: AssignmentExpressionAssign, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(MULASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionMul, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(DIVASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionDiv, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(MODASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionMod, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(ADDASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionAdd, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(SUBASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionSub, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(LSHASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionLsh, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(RSHASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionRsh, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(ANDASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionAnd, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(XORASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionXor, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} case rune(ORASSIGN): r = &AssignmentExpression{Case: AssignmentExpressionOr, UnaryExpression: u, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} default: return lhs } if u == nil { p.cpp.eh("%v: LHS must be unary-expression", r.Token.Position()) } return r } // [0], 6.5.15 Conditional operator // // conditional-expression: // logical-OR-expression // logical-OR-expression ? expression : conditional-expression func (p *parser) conditionalExpression(checkTypeName bool) (r, u ExpressionNode) { lhs, u := p.logicalOrExpression(checkTypeName) switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '?': r := &ConditionalExpression{Case: ConditionalExpressionCond, LogicalOrExpression: lhs, Token: p.shift(false), ExpressionList: p.expression(true), Token2: p.must(':')} r.ConditionalExpression, _ = p.conditionalExpression(checkTypeName) return r, nil default: return lhs, u } } // [0], 6.5.14 Logical OR operator // // logical-OR-expression: // logical-AND-expression // logical-OR-expression || logical-AND-expression func (p *parser) logicalOrExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.logicalAndExpression(checkTypeName) var s *LogicalOrExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case rune(OROR): s = &LogicalOrExpression{Case: LogicalOrExpressionLOr, LogicalOrExpression: r, Token: p.shift(false)} s.LogicalAndExpression, _ = p.logicalAndExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.13 Logical AND operator // // logical-AND-expression: // inclusive-OR-expression // logical-AND-expression && inclusive-OR-expression func (p *parser) logicalAndExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.inclusiveOrExpression(checkTypeName) var s *LogicalAndExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case rune(ANDAND): s = &LogicalAndExpression{Case: LogicalAndExpressionLAnd, LogicalAndExpression: r, Token: p.shift(false)} s.InclusiveOrExpression, _ = p.inclusiveOrExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.12 Bitwise inclusive OR operator // // inclusive-OR-expression: // exclusive-OR-expression // inclusive-OR-expression | exclusive-OR-expression func (p *parser) inclusiveOrExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.exclusiveOrExpression(checkTypeName) var s *InclusiveOrExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '|': s = &InclusiveOrExpression{Case: InclusiveOrExpressionOr, InclusiveOrExpression: r, Token: p.shift(false)} s.ExclusiveOrExpression, _ = p.exclusiveOrExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.11 Bitwise exclusive OR operator // // exclusive-OR-expression: // AND-expression // exclusive-OR-expression ^ AND-expression func (p *parser) exclusiveOrExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.andExpression(checkTypeName) var s *ExclusiveOrExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '^': s = &ExclusiveOrExpression{Case: ExclusiveOrExpressionXor, ExclusiveOrExpression: r, Token: p.shift(false)} s.AndExpression, _ = p.andExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.10 Bitwise AND operator // // AND-expression: // equality-expression // AND-expression & equality-expression func (p *parser) andExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.equalityExpression(checkTypeName) var s *AndExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '&': s = &AndExpression{Case: AndExpressionAnd, AndExpression: r, Token: p.shift(false)} s.EqualityExpression, _ = p.equalityExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.9 Equality operators // // equality-expression: // relational-expression // equality-expression == relational-expression // equality-expression != relational-expression func (p *parser) equalityExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.relationalExpression(checkTypeName) var s *EqualityExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case rune(EQ): s = &EqualityExpression{Case: EqualityExpressionEq, EqualityExpression: r, Token: p.shift(false)} s.RelationalExpression, _ = p.relationalExpression(checkTypeName) case rune(NEQ): s = &EqualityExpression{Case: EqualityExpressionNeq, EqualityExpression: r, Token: p.shift(false)} s.RelationalExpression, _ = p.relationalExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.8 Relational operators // // relational-expression: // shift-expression // relational-expression < shift-expression // relational-expression > shift-expression // relational-expression <= shift-expression // relational-expression >= shift-expression func (p *parser) relationalExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.shiftExpression(checkTypeName) var s *RelationalExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '<': s = &RelationalExpression{Case: RelationalExpressionLt, RelationalExpression: r, Token: p.shift(false)} s.ShiftExpression, _ = p.shiftExpression(checkTypeName) case '>': s = &RelationalExpression{Case: RelationalExpressionGt, RelationalExpression: r, Token: p.shift(false)} s.ShiftExpression, _ = p.shiftExpression(checkTypeName) case rune(LEQ): s = &RelationalExpression{Case: RelationalExpressionLeq, RelationalExpression: r, Token: p.shift(false)} s.ShiftExpression, _ = p.shiftExpression(checkTypeName) case rune(GEQ): s = &RelationalExpression{Case: RelationalExpressionGeq, RelationalExpression: r, Token: p.shift(false)} s.ShiftExpression, _ = p.shiftExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.7 Bitwise shift operators // // shift-expression: // additive-expression // shift-expression << additive-expression // shift-expression >> additive-expression func (p *parser) shiftExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.additiveExpression(checkTypeName) var s *ShiftExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case rune(LSH): s = &ShiftExpression{Case: ShiftExpressionLsh, ShiftExpression: r, Token: p.shift(false)} s.AdditiveExpression, _ = p.additiveExpression(checkTypeName) case rune(RSH): s = &ShiftExpression{Case: ShiftExpressionRsh, ShiftExpression: r, Token: p.shift(false)} s.AdditiveExpression, _ = p.additiveExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.6 Additive operators // // additive-expression: // multiplicative-expression // additive-expression + multiplicative-expression // additive-expression - multiplicative-expression func (p *parser) additiveExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.multiplicativeExpression(checkTypeName) var s *AdditiveExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '+': s = &AdditiveExpression{Case: AdditiveExpressionAdd, AdditiveExpression: r, Token: p.shift(false)} s.MultiplicativeExpression, _ = p.multiplicativeExpression(checkTypeName) case '-': s = &AdditiveExpression{Case: AdditiveExpressionSub, AdditiveExpression: r, Token: p.shift(false)} s.MultiplicativeExpression, _ = p.multiplicativeExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.5 Multiplicative operators // // multiplicative-expression: // cast-expression // multiplicative-expression * cast-expression // multiplicative-expression / cast-expression // multiplicative-expression % cast-expression func (p *parser) multiplicativeExpression(checkTypeName bool) (r, u ExpressionNode) { r, u = p.castExpression(checkTypeName) var s *MultiplicativeExpression for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '*': s = &MultiplicativeExpression{Case: MultiplicativeExpressionMul, MultiplicativeExpression: r, Token: p.shift(false)} s.CastExpression, _ = p.castExpression(checkTypeName) case '/': s = &MultiplicativeExpression{Case: MultiplicativeExpressionDiv, MultiplicativeExpression: r, Token: p.shift(false)} s.CastExpression, _ = p.castExpression(checkTypeName) case '%': s = &MultiplicativeExpression{Case: MultiplicativeExpressionMod, MultiplicativeExpression: r, Token: p.shift(false)} s.CastExpression, _ = p.castExpression(checkTypeName) default: return r, u } r = s u = nil } } // [0], 6.5.4 Cast operators // // cast-expression: // unary-expression // ( type-name ) cast-expression func (p *parser) castExpression(checkTypeName bool) (r, u ExpressionNode) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '(': switch ch := p.peek(1, true).Ch; { case p.isSpecifierQualifer(ch, true) || ch == rune(ATTRIBUTE): lparen := p.shift(false) tn := p.typeName() rparen := p.must(')') switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, nil case '{': u = p.unaryExpression(lparen, tn, rparen, checkTypeName) return &CastExpression{Case: CastExpressionUnary, UnaryExpression: u}, u default: r := &CastExpression{Case: CastExpressionCast, Token: lparen, TypeName: tn, Token2: rparen} r.CastExpression, _ = p.castExpression(checkTypeName) return r, nil } case p.isExpression(ch) || ch == '{': r = p.unaryExpression(Token{}, nil, Token{}, checkTypeName) return r, r } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected cast expression", t.Position(), runeName(t.Ch)) return nil, nil default: r := p.unaryExpression(Token{}, nil, Token{}, checkTypeName) return r, r } } // [0], 6.7.6 Type names // // type-name: // specifier-qualifier-list abstract-declarator_opt func (p *parser) typeName() *TypeName { return &TypeName{SpecifierQualifierList: p.specifierQualifierList(), AbstractDeclarator: p.abstractDeclarator(nil, true)} } // abstract-declarator: // pointer // pointer_opt direct-abstract-declarator func (p *parser) abstractDeclarator(ptr *Pointer, opt bool) *AbstractDeclarator { if ptr == nil { p.attributeSpecifierListOpt() //TODO not stored yet ptr = p.pointer(true) } switch { case ptr == nil: switch p.rune(false) { case ')', ':': if opt { return nil } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected abstract declarator", t.Position(), runeName(t.Ch)) return nil case '[': return &AbstractDeclarator{Case: AbstractDeclaratorDecl, DirectAbstractDeclarator: p.directAbstractDeclarator()} case '(': switch p.peek(1, true).Ch { case '*', rune(ATTRIBUTE): return &AbstractDeclarator{Case: AbstractDeclaratorPtr, DirectAbstractDeclarator: p.directAbstractDeclarator()} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected abstract declarator", t.Position(), runeName(t.Ch)) return nil } default: switch p.rune(true) { case rune(IDENTIFIER): t := p.shift(true) p.cpp.eh("%v: unexpected %v, expected ';'", t.Position(), runeName(t.Ch)) return nil default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected abstract declarator", t.Position(), runeName(t.Ch)) return nil } } default: switch p.rune(false) { case ')', ':': return &AbstractDeclarator{Case: AbstractDeclaratorPtr, Pointer: ptr} case '[': return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr, DirectAbstractDeclarator: p.directAbstractDeclarator()} case '(': switch ch := p.peek(1, true).Ch; { case ch == '*' || p.isDeclarationSpecifier(ch, true): return &AbstractDeclarator{Case: AbstractDeclaratorPtr, Pointer: ptr, DirectAbstractDeclarator: p.directAbstractDeclarator()} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected abstract declarator", t.Position(), runeName(t.Ch)) return nil } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected abstract declarator", t.Position(), runeName(t.Ch)) return nil } } } // direct-abstract-declarator: // ( abstract-declarator ) // direct-abstract-declarator_opt [ type-qualifier-list_opt assignment-expression_opt ] // direct-abstract-declarator_opt [ static type-qualifier-list_opt assignment-expression ] // direct-abstract-declarator_opt [ type-qualifier-list static assignment-expression ] // direct-abstract-declarator_opt [ * ] // direct-abstract-declarator_opt ( parameter-type-list_opt ) func (p *parser) directAbstractDeclarator() (r *DirectAbstractDeclarator) { out: switch p.rune(false) { case '[': switch ch := p.peek(1, false).Ch; { case p.isTypeQualifier(ch): lbracket := p.shift(false) tql := p.typeQualifierList(false, false) switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(INTCONST): r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: lbracket, TypeQualifiers: tql, AssignmentExpression: p.assignmentExpression(true), Token2: p.must(']')} break out case rune(STATIC): r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: lbracket, TypeQualifiers: tql, Token2: p.shift(false), AssignmentExpression: p.assignmentExpression(true), Token3: p.must(']')} break out default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } case ch != '*' && p.isExpression(ch): r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(true), Token2: p.must(']')} break out } switch p.peek(1, false).Ch { case ']': r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: p.shift(false), Token2: p.shift(false)} case rune(STATIC): lbracket := p.shift(false) switch { case p.isTypeQualifier(p.peek(1, false).Ch): r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorStaticArr, Token: lbracket, Token2: p.shift(false), TypeQualifiers: p.typeQualifierList(false, false), AssignmentExpression: p.assignmentExpression(true), Token3: p.must(']')} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } case '*': switch p.peek(2, false).Ch { case ']': r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArrStar, Token: p.shift(false), Token2: p.shift(false), Token3: p.shift(false)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } case '(': switch ch := p.peek(1, true).Ch; { case p.in(ch, '*', rune(ATTRIBUTE)): r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorDecl, Token: p.shift(false), AbstractDeclarator: p.abstractDeclarator(nil, false), Token2: p.must(')')} case p.isDeclarationSpecifier(ch, true): p.newScope() func() { defer p.closeScope() r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, Token: p.shift(false), ParameterTypeList: p.parameterTypeListOpt(), Token2: p.must(')'), params: p.scope} }() default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } return p.directAbstractDeclarator2(r) } func (p *parser) directAbstractDeclarator2(dad *DirectAbstractDeclarator) (r *DirectAbstractDeclarator) { r = dad for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ')', ',', ':': return r case '(': r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, DirectAbstractDeclarator: r, Token: p.shift(false), ParameterTypeList: p.parameterTypeListOpt(), Token2: p.must(')')} case '[': ch := p.peek(1, true).Ch switch { case ch == ']': r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, DirectAbstractDeclarator: r, Token: p.shift(false), Token2: p.must(']')} case p.isExpression(ch): r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, DirectAbstractDeclarator: r, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(true), Token2: p.must(']')} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct abstract declarator", t.Position(), runeName(t.Ch)) } } } // specifier-qualifier-list: // type-specifier specifier-qualifier-list_opt // type-qualifier specifier-qualifier-list_opt // alignment-specifier specifier-qualifier-list_opt func (p *parser) specifierQualifierList() (r *SpecifierQualifierList) { var prev *SpecifierQualifierList acceptTypeName := true for { var sql *SpecifierQualifierList switch ch := p.rune(false); { case ch == rune(IDENTIFIER): if !acceptTypeName || !p.checkTypeName(&p.toks[0]) { return r } sql = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()} acceptTypeName = false case ch == rune(ATOMIC) && p.peek(1, false).Ch == '(': sql = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()} acceptTypeName = false case p.isTypeSpecifier(ch, false): sql = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()} acceptTypeName = false case p.isTypeQualifier(ch) || ch == rune(ATTRIBUTE): sql = &SpecifierQualifierList{Case: SpecifierQualifierListTypeQual, TypeQualifier: p.typeQualifier(true)} case ch == rune(ALIGNAS): sql = &SpecifierQualifierList{Case: SpecifierQualifierListAlignSpec, AlignmentSpecifier: p.alignmentSpecifier()} default: return r } switch { case r == nil: r = sql default: prev.SpecifierQualifierList = sql } prev = sql } } func (p *parser) isSpecifierQualifer(ch rune, typenameOk bool) bool { return p.isTypeSpecifier(ch, typenameOk) || p.isTypeQualifier(ch) } // [0], 6.5.3 Unary operators // // unary-expression: // postfix-expression // ++ unary-expression // -- unary-expression // unary-operator cast-expression // sizeof unary-expression // sizeof ( type-name ) // && identifier // _Alignof unary-expression // _Alignof ( type-name ) // __imag__ unary-expression // __real__ unary-expression // // unary-operator: one of // & * + - ~ ! func (p *parser) unaryExpression(lp Token, tn *TypeName, rp Token, checkTypeName bool) ExpressionNode { if tn != nil { return p.postfixExpression(lp, tn, rp, checkTypeName) } var r *UnaryExpression switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '&': r = &UnaryExpression{Case: UnaryExpressionAddrof, Token: p.shift(false)} r.CastExpression, _ = p.castExpression(checkTypeName) return r case '*': r = &UnaryExpression{Case: UnaryExpressionDeref, Token: p.shift(false)} r.CastExpression, _ = p.castExpression(checkTypeName) return r case '+': r = &UnaryExpression{Case: UnaryExpressionPlus, Token: p.shift(false)} r.CastExpression, _ = p.castExpression(checkTypeName) return r case '-': r = &UnaryExpression{Case: UnaryExpressionMinus, Token: p.shift(false)} r.CastExpression, _ = p.castExpression(checkTypeName) return r case '~': r = &UnaryExpression{Case: UnaryExpressionCpl, Token: p.shift(false)} r.CastExpression, _ = p.castExpression(checkTypeName) return r case '!': r = &UnaryExpression{Case: UnaryExpressionNot, Token: p.shift(false)} r.CastExpression, _ = p.castExpression(checkTypeName) return r case rune(SIZEOF): switch p.peek(1, false).Ch { case '(': switch { case p.isSpecifierQualifer(p.peek(2, true).Ch, true): sz := p.shift(false) lp := p.shift(false) tn := p.typeName() rp := p.must(')') switch p.rune(false) { case '{': return &UnaryExpression{Case: UnaryExpressionSizeofExpr, Token: sz, UnaryExpression: p.unaryExpression(lp, tn, rp, checkTypeName)} default: return &UnaryExpression{Case: UnaryExpressionSizeofType, Token: sz, Token2: lp, TypeName: tn, Token3: rp} } default: return &UnaryExpression{Case: UnaryExpressionSizeofExpr, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} } default: return &UnaryExpression{Case: UnaryExpressionSizeofExpr, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} } case '(', rune(CHARCONST), rune(FLOATCONST), rune(GENERIC), rune(IDENTIFIER), rune(INTCONST), rune(LONGCHARCONST), rune(LONGSTRINGLITERAL), rune(STRINGLITERAL): return p.postfixExpression(Token{}, nil, Token{}, checkTypeName) case rune(INC): return &UnaryExpression{Case: UnaryExpressionInc, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} case rune(DEC): return &UnaryExpression{Case: UnaryExpressionDec, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} case rune(ALIGNOF): switch p.peek(1, false).Ch { case '(': switch { case p.isSpecifierQualifer(p.peek(2, true).Ch, true): return &UnaryExpression{Case: UnaryExpressionAlignofType, Token: p.shift(false), Token2: p.shift(false), TypeName: p.typeName(), Token3: p.must(')')} default: return &UnaryExpression{Case: UnaryExpressionAlignofExpr, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected unary expression or (type name)", t.Position(), runeName(t.Ch)) return nil } case rune(ANDAND): return &UnaryExpression{Case: UnaryExpressionLabelAddr, Token: p.shift(false), Token2: p.must(rune(IDENTIFIER))} case rune(REAL): return &UnaryExpression{Case: UnaryExpressionReal, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} case rune(IMAG): return &UnaryExpression{Case: UnaryExpressionImag, Token: p.shift(false), UnaryExpression: p.unaryExpression(Token{}, nil, Token{}, checkTypeName)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected unary expression", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.5.2 Postfix operators // // postfix-expression: // primary-expression // postfix-expression [ expression ] // postfix-expression ( argument-expression-list_opt ) // postfix-expression . identifier // postfix-expression -> identifier // postfix-expression ++ // postfix-expression -- // ( type-name ) { initializer-list } // ( type-name ) { initializer-list , } // __builtin_types_compatible_p ( type-name , type-name ) func (p *parser) postfixExpression(lp Token, tn *TypeName, rp Token, checkTypeName bool) (r ExpressionNode) { var r0 *PostfixExpression switch { case tn != nil: r0 = &PostfixExpression{Case: PostfixExpressionComplit, Token: lp, TypeName: tn, Token2: rp, Token3: p.must('{'), InitializerList: p.initializerList(nil)} switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ',': r0.Token4 = p.shift(false) fallthrough default: r0.Token5 = p.must('}') } default: switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '(': switch ch := p.peek(1, true).Ch; { case p.isExpression(ch) || ch == '{': r0 = &PostfixExpression{Case: PostfixExpressionPrimary, PrimaryExpression: p.primaryExpression(checkTypeName)} case p.isSpecifierQualifer(ch, true): r0 = &PostfixExpression{Case: PostfixExpressionComplit, Token: p.shift(false), TypeName: p.typeName(), Token2: p.must(')'), Token3: p.must('{'), InitializerList: p.initializerList(nil)} switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ',': r0.Token4 = p.shift(false) fallthrough default: r0.Token5 = p.must('}') return r0 } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected postfix expression", t.Position(), runeName(t.Ch)) return nil } default: r0 = &PostfixExpression{Case: PostfixExpressionPrimary, PrimaryExpression: p.primaryExpression(checkTypeName)} } } r = r0 if r0.Case == PostfixExpressionPrimary && r0.PrimaryExpression != nil { r = r0.PrimaryExpression } for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '[': r = &PostfixExpression{Case: PostfixExpressionIndex, PostfixExpression: r, Token: p.shift(false), ExpressionList: p.expression(false), Token2: p.must(']')} case '(': switch ch := p.peek(1, true).Ch; { case p.isExpression(ch) || ch == ')': r = &PostfixExpression{Case: PostfixExpressionCall, PostfixExpression: r, Token: p.shift(false), ArgumentExpressionList: p.argumentExpressionListOpt(true), Token2: p.must(')')} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected postfix expression", t.Position(), runeName(t.Ch)) } case '.': r = &PostfixExpression{Case: PostfixExpressionSelect, PostfixExpression: r, Token: p.shift(false), Token2: p.must(rune(IDENTIFIER))} case rune(ARROW): r = &PostfixExpression{Case: PostfixExpressionPSelect, PostfixExpression: r, Token: p.shift(false), Token2: p.must(rune(IDENTIFIER))} case rune(INC): r = &PostfixExpression{Case: PostfixExpressionInc, PostfixExpression: r, Token: p.shift(false)} case rune(DEC): r = &PostfixExpression{Case: PostfixExpressionDec, PostfixExpression: r, Token: p.shift(false)} default: return r } } } // argument-expression-list: // assignment-expression // argument-expression-list , assignment-expression func (p *parser) argumentExpressionListOpt(checkTypeName bool) (r *ArgumentExpressionList) { p.rune(false) switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ')': return nil } r = &ArgumentExpressionList{AssignmentExpression: p.assignmentExpression(checkTypeName)} prev := r for p.rune(false) == ',' { ael := &ArgumentExpressionList{Token: p.shift(false), AssignmentExpression: p.assignmentExpression(checkTypeName)} prev.ArgumentExpressionList = ael prev = ael p.rune(false) } p.rune(false) return r } // [0], 6.5.1 Primary expressions // // primary-expression: // identifier // constant // string-literal // ( expression ) // ( compound-statement ) // generic-selection func (p *parser) primaryExpression(checkTypeName bool) (r *PrimaryExpression) { switch p.rune(checkTypeName) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(CHARCONST): r = &PrimaryExpression{Case: PrimaryExpressionChar, Token: p.shift(false)} case rune(FLOATCONST): r = &PrimaryExpression{Case: PrimaryExpressionFloat, Token: p.shift(false)} case rune(IDENTIFIER): r = &PrimaryExpression{Case: PrimaryExpressionIdent, Token: p.shift(false), lexicalScope: (*lexicalScope)(p.scope)} case rune(INTCONST): r = &PrimaryExpression{Case: PrimaryExpressionInt, Token: p.shift(false)} case rune(LONGCHARCONST): r = &PrimaryExpression{Case: PrimaryExpressionLChar, Token: p.shift(false)} case rune(LONGSTRINGLITERAL): r = &PrimaryExpression{Case: PrimaryExpressionLString, Token: p.shift(false)} case rune(STRINGLITERAL): r = &PrimaryExpression{Case: PrimaryExpressionString, Token: p.shift(false)} case '(': switch p.peek(1, false).Ch { case '{': return &PrimaryExpression{Case: PrimaryExpressionStmt, Token: p.shift(false), CompoundStatement: p.compoundStatement(false, false, nil), Token2: p.must(')')} default: return &PrimaryExpression{Case: PrimaryExpressionExpr, Token: p.shift(false), ExpressionList: p.expression(false), Token2: p.must(')')} } case rune(GENERIC): return &PrimaryExpression{Case: PrimaryExpressionGeneric, GenericSelection: p.genericSelection()} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected primary expression", t.Position(), runeName(t.Ch)) return nil } r.m = p.cpp.mmap[mmapKey{r.Token.s, r.Token.off}] return r } // generic-selection: // _Generic ( assignment-expression , generic-assoc-list ) func (p *parser) genericSelection() (r *GenericSelection) { return &GenericSelection{Token: p.must(rune(GENERIC)), Token2: p.must('('), AssignmentExpression: p.assignmentExpression(true), Token3: p.must(','), GenericAssociationList: p.genericAssociationList(), Token4: p.must(')')} } // generic-assoc-list: // generic-association // generic-assoc-list , generic-association func (p *parser) genericAssociationList() (r *GenericAssociationList) { r = &GenericAssociationList{GenericAssociation: p.genericAssociation()} prev := r for p.rune(false) == ',' { gal := &GenericAssociationList{Token: p.shift(false), GenericAssociation: p.genericAssociation()} prev.GenericAssociationList = gal prev = gal } return r } // generic-association: // type-name : assignment-expression // default : assignment-expression func (p *parser) genericAssociation() (r *GenericAssociation) { switch { case p.rune(false) == rune(DEFAULT): return &GenericAssociation{Case: GenericAssociationDefault, Token: p.shift(false), Token2: p.must(':'), AssignmentExpression: p.assignmentExpression(true)} default: return &GenericAssociation{Case: GenericAssociationType, TypeName: p.typeName(), Token: p.must(':'), AssignmentExpression: p.assignmentExpression(true)} } } // [0], 6.7.5 Declarators // // declarator: // pointer_opt direct-declarator func (p *parser) declarator(ptr *Pointer, ds *DeclarationSpecifiers, declare bool) (r *Declarator) { if ptr == nil { ptr = p.pointer(true) } r = &Declarator{Pointer: ptr, DirectDeclarator: p.directDeclarator(declare), lexicalScope: (*lexicalScope)(p.scope)} if ds != nil { r.isTypename = ds.isTypedef } if declare { r.visible = visible(p.seq) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Name(), r) } return r } // direct-declarator: // identifier // ( declarator ) // direct-declarator [ type-qualifier-list_opt assignment-expression_opt ] // direct-declarator [ static type-qualifier-list_opt assignment-expression ] // direct-declarator [ type-qualifier-list static assignment-expression ] // direct-declarator [ type-qualifier-list_opt * ] // direct-declarator ( parameter-type-list_opt ) // direct-declarator ( identifier-list_opt ) func (p *parser) directDeclarator(declare bool) (r *DirectDeclarator) { switch p.rune(false) { case rune(IDENTIFIER): r = &DirectDeclarator{Case: DirectDeclaratorIdent, Token: p.shift(false)} case '(': r = &DirectDeclarator{Case: DirectDeclaratorDecl, Token: p.shift(false)} p.attributeSpecifierListOpt() //TODO not stored yet r.Declarator = p.declarator(nil, nil, false) r.Token2 = p.must(')') default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct declarator", t.Position(), runeName(t.Ch)) } return p.directDeclarator2(r, declare) } func (p *parser) directDeclarator2(dd *DirectDeclarator, declare bool) (r *DirectDeclarator) { r = dd for { switch p.rune(false) { case '(': p.newScope() func() { defer p.closeScope() switch p.peek(1, true).Ch { case rune(IDENTIFIER): r = &DirectDeclarator{Case: DirectDeclaratorFuncIdent, DirectDeclarator: r, Token: p.shift(false), IdentifierList: p.identifierList(true), Token2: p.must(')')} default: r = &DirectDeclarator{Case: DirectDeclaratorFuncParam, DirectDeclarator: r, Token: p.shift(false), ParameterTypeList: p.parameterTypeListOpt(), Token2: p.must(')')} } r.params = p.scope }() case '[': ch := p.peek(1, true).Ch switch { case p.isExpression(ch): r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: p.shift(false), AssignmentExpression: p.assignmentExpression(true), Token2: p.must(']')} continue case p.isTypeQualifier(ch): lbracket := p.shift(false) tql := p.typeQualifierList(false, false) switch p.rune(false) { case rune(STATIC): r = &DirectDeclarator{Case: DirectDeclaratorArrStatic, DirectDeclarator: r, Token: lbracket, TypeQualifiers: tql, Token2: p.shift(false), AssignmentExpression: p.assignmentExpression(true), Token3: p.must(']')} case '*': r = &DirectDeclarator{Case: DirectDeclaratorStar, DirectDeclarator: r, Token: lbracket, TypeQualifiers: tql, Token2: p.shift(false), Token3: p.must(']')} case ']': r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: lbracket, TypeQualifiers: tql, Token3: p.must(']')} default: r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: lbracket, TypeQualifiers: tql, AssignmentExpression: p.assignmentExpression(true), Token3: p.must(']')} } continue } switch ch { case ']': r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: p.shift(false), Token2: p.shift(false)} case rune(STATIC): r = &DirectDeclarator{Case: DirectDeclaratorStaticArr, DirectDeclarator: r, Token: p.shift(false), Token2: p.shift(false), TypeQualifiers: p.typeQualifierList(true, false), AssignmentExpression: p.assignmentExpression(true), Token3: p.must(']')} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected direct declarator", t.Position(), runeName(t.Ch)) } default: return r } } return r } // identifier-list: // identifier // identifier-list , identifier func (p *parser) identifierList(declare bool) (r *IdentifierList) { switch p.rune(true) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(IDENTIFIER): r = &IdentifierList{Token2: p.shift(false)} if declare { param := &Parameter{name: r.Token2, visible: visible(r.Token2.seq)} p.scope.declare(p.cpp.eh, r.Token2.SrcStr(), param) r.parameters = append(r.parameters, param) } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected identifier", t.Position(), runeName(t.Ch)) return nil } r0 := r prev := r for p.rune(false) == ',' { il := &IdentifierList{Token: p.shift(false), Token2: p.must(rune(IDENTIFIER))} if declare { param := &Parameter{name: il.Token2, visible: visible(il.Token2.seq)} p.scope.declare(p.cpp.eh, il.Token2.SrcStr(), param) r0.parameters = append(r0.parameters, param) } prev.IdentifierList = il prev = il } return r } // parameter-type-list: // parameter-list // parameter-list , ... func (p *parser) parameterTypeListOpt() (r *ParameterTypeList) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ')': return nil } pl := p.parameterList() switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ',': return &ParameterTypeList{Case: ParameterTypeListVar, ParameterList: pl, Token: p.shift(false), Token2: p.must(rune(DDD))} default: return &ParameterTypeList{Case: ParameterTypeListList, ParameterList: pl} } } // parameter-list: // parameter-declaration // parameter-list , parameter-declaration func (p *parser) parameterList() (r *ParameterList) { r = &ParameterList{ParameterDeclaration: p.parameterDeclaration()} prev := r for p.rune(false) == ',' { if p.peek(1, false).Ch == rune(DDD) { return r } pl := &ParameterList{Token: p.shift(false), ParameterDeclaration: p.parameterDeclaration()} prev.ParameterList = pl prev = pl } return r } // parameter-declaration: // declaration-specifiers declarator // declaration-specifiers abstract-declarator_opt func (p *parser) parameterDeclaration() (r *ParameterDeclaration) { ds, ok := p.declarationSpecifiers() if !ok { return nil } switch p.rune(false) { case ')', ',': return &ParameterDeclaration{Case: ParameterDeclarationAbstract, DeclarationSpecifiers: ds} default: switch x := p.declaratorOrAbstractDeclarator(true).(type) { case *AbstractDeclarator: return &ParameterDeclaration{Case: ParameterDeclarationAbstract, DeclarationSpecifiers: ds, AbstractDeclarator: x} case *Declarator: return &ParameterDeclaration{Case: ParameterDeclarationDecl, DeclarationSpecifiers: ds, Declarator: x, AttributeSpecifierList: p.attributeSpecifierListOpt()} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected parameter declaration", t.Position(), runeName(t.Ch)) return nil } } } func (p *parser) declaratorOrAbstractDeclarator(declare bool) (r Node) { // state 2 ptr0 := p.pointer(true) switch p.rune(false) { case ')', ',': if ptr0 != nil { return &AbstractDeclarator{Case: AbstractDeclaratorPtr, Pointer: ptr0} } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil case '(': lparen := p.shift(false) p.attributeSpecifierListOpt() //TODO not stored yet if p.isSpecifierQualifer(p.rune(true), true) { dad := &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, Token: lparen, ParameterTypeList: p.parameterTypeListOpt(), Token2: p.must(')')} switch { case p.in(p.rune(false), ',', ')'): return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr0, DirectAbstractDeclarator: dad} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } } switch p.rune(true) { case ')': dad := &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, Token: lparen, Token2: p.shift(false)} return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr0, DirectAbstractDeclarator: p.directAbstractDeclarator2(dad)} case '(': switch x := p.declaratorOrAbstractDeclarator(false).(type) { case *AbstractDeclarator: dad := &DirectAbstractDeclarator{ Case: DirectAbstractDeclaratorDecl, Token: lparen, AbstractDeclarator: x, Token2: p.must(')'), } return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr0, DirectAbstractDeclarator: p.directAbstractDeclarator2(dad)} case *Declarator: dd := &DirectDeclarator{ Case: DirectDeclaratorDecl, Token: lparen, Declarator: x, Token2: p.must(')'), } r := &Declarator{Pointer: ptr0, DirectDeclarator: p.directDeclarator2(dd, declare)} if declare { r.visible = visible(p.seq) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Name(), r) } return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } case rune(IDENTIFIER): dd := p.directDeclarator(declare) switch p.rune(false) { case ')': dd = &DirectDeclarator{ Case: DirectDeclaratorDecl, Token: lparen, Declarator: &Declarator{ DirectDeclarator: dd, }, Token2: p.must(')'), } r := &Declarator{Pointer: ptr0, DirectDeclarator: p.directDeclarator2(dd, declare)} if declare { r.visible = visible(p.seq) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Name(), r) } return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } case '*': ptr := p.pointer(false) switch p.rune(false) { case ')', '[': dad := &DirectAbstractDeclarator{ Case: DirectAbstractDeclaratorDecl, Token: lparen, AbstractDeclarator: p.abstractDeclarator(ptr, false), Token2: p.must(')'), } return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr0, DirectAbstractDeclarator: p.directAbstractDeclarator2(dad)} case rune(IDENTIFIER): dd := p.directDeclarator(declare) switch p.rune(false) { case ')': dd = &DirectDeclarator{ Case: DirectDeclaratorDecl, Token: lparen, Declarator: &Declarator{ Pointer: ptr, DirectDeclarator: dd, }, Token2: p.must(')'), } r := &Declarator{Pointer: ptr0, DirectDeclarator: p.directDeclarator2(dd, declare)} if declare { r.visible = visible(p.seq) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Name(), r) } return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } case '(': switch x := p.declaratorOrAbstractDeclarator(false).(type) { case *Declarator: x.Pointer = ptr dd := &DirectDeclarator{Case: DirectDeclaratorDecl, Token: lparen, Declarator: x, Token2: p.must(')')} r := &Declarator{Pointer: ptr0, DirectDeclarator: dd} if declare { r.visible = visible(p.seq) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Name(), r) } return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } case '^': ptr := p.pointer(false) switch p.rune(false) { case ')': dad := &DirectAbstractDeclarator{ Case: DirectAbstractDeclaratorDecl, Token: lparen, AbstractDeclarator: p.abstractDeclarator(ptr, false), Token2: p.must(')'), } return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr0, DirectAbstractDeclarator: p.directAbstractDeclarator2(dad)} case rune(IDENTIFIER): dd := p.directDeclarator(declare) switch p.rune(false) { case ')': dd = &DirectDeclarator{ Case: DirectDeclaratorDecl, Token: lparen, Declarator: &Declarator{ Pointer: ptr, DirectDeclarator: dd, }, Token2: p.must(')'), } r := &Declarator{Pointer: ptr0, DirectDeclarator: p.directDeclarator2(dd, declare)} if declare { r.visible = visible(p.seq) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Name(), r) } return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } case '[': dad := &DirectAbstractDeclarator{ Case: DirectAbstractDeclaratorDecl, Token: lparen, AbstractDeclarator: p.abstractDeclarator(nil, false), Token2: p.must(')'), } return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr0, DirectAbstractDeclarator: p.directAbstractDeclarator2(dad)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } case '[': return p.abstractDeclarator(ptr0, false) case rune(IDENTIFIER): return p.declarator(ptr0, nil, declare) default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected declarator or abstract declarator", t.Position(), runeName(t.Ch)) return nil } } func (p *parser) in(ch rune, set ...rune) bool { for _, v := range set { if ch == v { return true } } return false } // type-qualifier-list: // type-qualifier // type-qualifier-list type-qualifier // type-qualifier-list func (p *parser) typeQualifierList(opt, acceptAttributes bool) (r *TypeQualifiers) { switch ch := p.rune(true); { case p.isTypeQualifier(ch): r = &TypeQualifiers{Case: TypeQualifiersTypeQual, TypeQualifier: p.typeQualifier(false)} case p.in(ch, ':', ')', ',', '[', ']', rune(STATIC)) || p.isExpression(ch) || ch == rune(TYPENAME): if opt { return nil } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type qualifier", t.Position(), runeName(t.Ch)) case ch == rune(ATTRIBUTE): if acceptAttributes { r = &TypeQualifiers{Case: TypeQualifiersTypeQual, TypeQualifier: p.typeQualifier(true)} break } fallthrough default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type qualifier", t.Position(), runeName(t.Ch)) } for { switch ch := p.rune(false); { case p.in(ch, ':', ')', ',', '[', ']', rune(STATIC)) || p.isExpression(ch) || ch == rune(TYPENAME): return r case p.isTypeQualifier(ch): r = &TypeQualifiers{Case: TypeQualifiersTypeQual, TypeQualifiers: r, TypeQualifier: p.typeQualifier(acceptAttributes)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type qualifier", t.Position(), runeName(t.Ch)) } } } func (p *parser) isTypeQualifier(ch rune) bool { switch ch { case rune(ATOMIC), rune(CONST), rune(NONNULL), rune(RESTRICT), rune(VOLATILE): return true } return false } // pointer: // * type-qualifier-list_opt // * type-qualifier-list_opt pointer // ^ type-qualifier-list_opt func (p *parser) pointer(opt bool) (r *Pointer) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '*': r = &Pointer{Case: PointerTypeQual, Token: p.shift(false), TypeQualifiers: p.typeQualifierList(true, true)} case '^': return &Pointer{Case: PointerBlock, Token: p.shift(false), TypeQualifiers: p.typeQualifierList(true, true)} default: if opt { return nil } t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type pointer", t.Position(), runeName(t.Ch)) } prev := r for p.rune(false) == '*' { p := p.pointer(false) prev.Pointer = p prev.Case = PointerPtr prev = p } return r } // declaration-specifiers: // storage-class-specifier declaration-specifiers_opt // type-specifier declaration-specifiers_opt // type-qualifier declaration-specifiers_opt // function-specifier declaration-specifiers_opt // alignment-specifier declaration-specifiers_opt func (p *parser) declarationSpecifiers() (r *DeclarationSpecifiers, ok bool) { var ds, prev *DeclarationSpecifiers var isTypedef bool acceptTypeName := true for { switch ch := p.rune(false); { case ch == eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil, false case p.isTypeSpecifier(ch, false): ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()} acceptTypeName = false case ch == rune(IDENTIFIER): if !acceptTypeName || !p.checkTypeName(&p.toks[0]) { return r, true } ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()} acceptTypeName = false case ch == rune(ATOMIC): switch p.peek(1, false).Ch { case '(': ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()} acceptTypeName = false default: ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeQual, TypeQualifier: p.typeQualifier(false)} } case ch == rune(TYPEDEF): isTypedef = true fallthrough case p.isStorageClassSpecifier(ch): ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersStorage, StorageClassSpecifier: p.storageClassSpecifier()} case p.isTypeQualifier(ch): ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeQual, TypeQualifier: p.typeQualifier(false)} case p.in(ch, rune(INLINE), rune(NORETURN)): ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersFunc, FunctionSpecifier: p.functionSpecifier()} case ch == rune(ATTRIBUTE): ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersAttr, AttributeSpecifierList: p.attributeSpecifierListOpt()} case ch == rune(ALIGNAS): ds = &DeclarationSpecifiers{Case: DeclarationSpecifiersAlignSpec, AlignmentSpecifier: p.alignmentSpecifier()} default: return r, true } switch { case r == nil: r = ds default: prev.DeclarationSpecifiers = ds } prev = ds r.isTypedef = isTypedef } } func (p *parser) isDeclarationSpecifier(ch rune, typenameOk bool) bool { return p.isTypeSpecifier(ch, typenameOk) || p.isTypeQualifier(ch) || p.isStorageClassSpecifier(ch) || ch == rune(ATTRIBUTE) || ch == rune(ALIGNAS) || p.isFunctionSpecifier(ch) } // [2], 6.7.5 Alignment specifier // // alignment-specifier: // _Alignas ( type-name ) // _Alignas ( constant-expression ) func (p *parser) alignmentSpecifier() *AlignmentSpecifier { switch ch := p.peek(2, true).Ch; { case p.isTypeSpecifier(ch, true): return &AlignmentSpecifier{Case: AlignmentSpecifierType, Token: p.must(rune(ALIGNAS)), Token2: p.must('('), TypeName: p.typeName(), Token3: p.must(')')} case p.isExpression(ch): return &AlignmentSpecifier{Case: AlignmentSpecifierExpr, Token: p.must(rune(ALIGNAS)), Token2: p.must('('), ConstantExpression: p.constantExpression(), Token3: p.must(')')} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected alignment specifier", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.7.4 Function specifiers // // function-specifier: // inline // _Noreturn func (p *parser) functionSpecifier() *FunctionSpecifier { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(INLINE): return &FunctionSpecifier{Case: FunctionSpecifierInline, Token: p.shift(false)} case rune(NORETURN): return &FunctionSpecifier{Case: FunctionSpecifierNoreturn, Token: p.shift(false)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected function specifier", t.Position(), runeName(t.Ch)) return nil } } func (p *parser) isFunctionSpecifier(ch rune) bool { return ch == rune(INLINE) || ch == rune(NORETURN) } // [0], 6.7.3 Type qualifiers // // type-qualifier: // const // restrict // volatile // _Atomic // __attribute__ func (p *parser) typeQualifier(acceptAttributes bool) *TypeQualifier { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(CONST): return &TypeQualifier{Case: TypeQualifierConst, Token: p.shift(false)} case rune(RESTRICT): return &TypeQualifier{Case: TypeQualifierRestrict, Token: p.shift(false)} case rune(VOLATILE): return &TypeQualifier{Case: TypeQualifierVolatile, Token: p.shift(false)} case rune(ATOMIC): return &TypeQualifier{Case: TypeQualifierAtomic, Token: p.shift(false)} case rune(NONNULL): return &TypeQualifier{Case: TypeQualifierNonnull, Token: p.shift(false)} case rune(ATTRIBUTE): if acceptAttributes { return &TypeQualifier{Case: TypeQualifierAttr, AttributeSpecifierList: p.attributeSpecifierListOpt()} } fallthrough default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type qualifier", t.Position(), runeName(t.Ch)) return nil } } // [0], 6.7.1 Storage-class specifiers // // storage-class-specifier: // typedef // extern // static // auto // register // __declspec ( ... ) func (p *parser) storageClassSpecifier() (r *StorageClassSpecifier) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(AUTO): return &StorageClassSpecifier{Case: StorageClassSpecifierAuto, Token: p.shift(false)} case rune(EXTERN): return &StorageClassSpecifier{Case: StorageClassSpecifierExtern, Token: p.shift(false)} case rune(REGISTER): return &StorageClassSpecifier{Case: StorageClassSpecifierRegister, Token: p.shift(false)} case rune(STATIC): return &StorageClassSpecifier{Case: StorageClassSpecifierStatic, Token: p.shift(false)} case rune(TYPEDEF): return &StorageClassSpecifier{Case: StorageClassSpecifierTypedef, Token: p.shift(false)} case rune(THREADLOCAL): return &StorageClassSpecifier{Case: StorageClassSpecifierThreadLocal, Token: p.shift(false)} case rune(DECLSPEC): r = &StorageClassSpecifier{Case: StorageClassSpecifierDeclspec, Token: p.shift(false), Token2: p.must('(')} out: for lvl := 0; ; { switch p.rune(false) { case '(': lvl++ case ')': if lvl == 0 { break out } lvl-- case eof: break out } r.Declspecs = append(r.Declspecs, p.shift(false)) } r.Token3 = p.must(')') return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected storage class specifier", t.Position(), runeName(t.Ch)) return nil } } func (p *parser) isStorageClassSpecifier(ch rune) bool { switch ch { case rune(AUTO), rune(DECLSPEC), rune(EXTERN), rune(REGISTER), rune(STATIC), rune(THREADLOCAL), rune(TYPEDEF): return true } return false } // [0], 6.7.2 Type specifiers // // type-specifier: // atomic-type-specifier // _Bool // _Complex // _Decimal128 // _Decimal32 // _Decimal64 // _Float128 // _Float16 // _Float32 // _Float64 // __float80 // __fp16 // __m256d // char // double // enum-specifier // float // int // long // short // signed // struct-or-union-specifier // typedef-name // typeof ( expression ) // typeof ( type-name ) // unsigned // void func (p *parser) typeSpecifier() *TypeSpecifier { switch p.rune(true) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(CHAR): return &TypeSpecifier{Case: TypeSpecifierChar, Token: p.shift(false)} case rune(DOUBLE): return &TypeSpecifier{Case: TypeSpecifierDouble, Token: p.shift(false)} case rune(ENUM): return &TypeSpecifier{Case: TypeSpecifierEnum, EnumSpecifier: p.enumSpecifier(), lexicalScope: (*lexicalScope)(p.scope)} case rune(FLOAT): return &TypeSpecifier{Case: TypeSpecifierFloat, Token: p.shift(false)} case rune(INT): return &TypeSpecifier{Case: TypeSpecifierInt, Token: p.shift(false)} case rune(LONG): return &TypeSpecifier{Case: TypeSpecifierLong, Token: p.shift(false)} case rune(SIGNED): return &TypeSpecifier{Case: TypeSpecifierSigned, Token: p.shift(false)} case rune(SHORT): return &TypeSpecifier{Case: TypeSpecifierShort, Token: p.shift(false)} case rune(TYPENAME): return &TypeSpecifier{Case: TypeSpecifierTypeName, Token: p.shift(true), lexicalScope: (*lexicalScope)(p.scope)} case rune(UNSIGNED): return &TypeSpecifier{Case: TypeSpecifierUnsigned, Token: p.shift(false)} case rune(STRUCT), rune(UNION): return &TypeSpecifier{Case: TypeSpecifierStructOrUnion, StructOrUnionSpecifier: p.structOrUnionSpecifier()} case rune(VOID): return &TypeSpecifier{Case: TypeSpecifierVoid, Token: p.shift(false)} case rune(BOOL): return &TypeSpecifier{Case: TypeSpecifierBool, Token: p.shift(false)} case rune(COMPLEX): return &TypeSpecifier{Case: TypeSpecifierComplex, Token: p.shift(false)} case rune(IMAGINARY): return &TypeSpecifier{Case: TypeSpecifierImaginary, Token: p.shift(false)} case rune(FLOAT16): return &TypeSpecifier{Case: TypeSpecifierFloat16, Token: p.shift(false)} case rune(FLOAT32): return &TypeSpecifier{Case: TypeSpecifierFloat32, Token: p.shift(false)} case rune(FLOAT32X): return &TypeSpecifier{Case: TypeSpecifierFloat32x, Token: p.shift(false)} case rune(FLOAT64): return &TypeSpecifier{Case: TypeSpecifierFloat64, Token: p.shift(false)} case rune(FLOAT64X): return &TypeSpecifier{Case: TypeSpecifierFloat64x, Token: p.shift(false)} case rune(FLOAT128): return &TypeSpecifier{Case: TypeSpecifierFloat128, Token: p.shift(false)} case rune(FLOAT128X): return &TypeSpecifier{Case: TypeSpecifierFloat128x, Token: p.shift(false)} case rune(ATOMIC): return &TypeSpecifier{Case: TypeSpecifierAtomic, AtomicTypeSpecifier: p.atomicTypeSpecifier()} case rune(UINT128): return &TypeSpecifier{Case: TypeSpecifierUint128, Token: p.shift(false)} case rune(INT128): return &TypeSpecifier{Case: TypeSpecifierInt128, Token: p.shift(false)} case rune(DECIMAL32): return &TypeSpecifier{Case: TypeSpecifierDecimal32, Token: p.shift(false)} case rune(DECIMAL64): return &TypeSpecifier{Case: TypeSpecifierDecimal64, Token: p.shift(false)} case rune(DECIMAL128): return &TypeSpecifier{Case: TypeSpecifierDecimal128, Token: p.shift(false)} case rune(TYPEOF): switch ch := p.peek(2, true).Ch; { case p.isTypeSpecifier(ch, true): return &TypeSpecifier{Case: TypeSpecifierTypeofType, Token: p.shift(false), Token2: p.must('('), TypeName: p.typeName(), Token3: p.must(')')} case p.isExpression(ch): return &TypeSpecifier{Case: TypeSpecifierTypeofExpr, Token: p.shift(false), Token2: p.must('('), ExpressionList: p.expression(false), Token3: p.must(')')} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type specifier", t.Position(), runeName(t.Ch)) return nil } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected type specifier", t.Position(), runeName(t.Ch)) return nil } } func (p *parser) isTypeSpecifier(ch rune, typenameOk bool) bool { switch ch { case rune(BOOL), rune(CHAR), rune(COMPLEX), rune(DECIMAL128), rune(DECIMAL32), rune(DECIMAL64), rune(DOUBLE), rune(ENUM), rune(FLOAT), rune(FLOAT128), rune(FLOAT128X), rune(FLOAT16), rune(FLOAT32), rune(FLOAT32X), rune(FLOAT64), rune(FLOAT64X), rune(IMAGINARY), rune(INT), rune(INT128), rune(LONG), rune(SHORT), rune(SIGNED), rune(STRUCT), rune(TYPEOF), rune(UINT128), rune(UNION), rune(UNSIGNED), rune(VOID): return true case rune(TYPENAME): return typenameOk } return false } // [2], 6.7.2.4 Atomic type specifiers // // atomic-type-specifier: // _Atomic ( type-name ) func (p *parser) atomicTypeSpecifier() (r *AtomicTypeSpecifier) { return &AtomicTypeSpecifier{Token: p.must(rune(ATOMIC)), Token2: p.must('('), TypeName: p.typeName(), Token3: p.must(')')} } // [0], 6.7.2.2 Enumeration specifiers // // enum-specifier: // enum identifier_opt { enumerator-list } // enum identifier_opt { enumerator-list , } // enum identifier func (p *parser) enumSpecifier() (r *EnumSpecifier) { switch p.peek(1, false).Ch { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(IDENTIFIER): switch p.peek(2, true).Ch { case '{': r = &EnumSpecifier{Case: EnumSpecifierDef, Token: p.shift(false), Token2: p.shift(false), Token3: p.shift(false), EnumeratorList: p.enumeratorList(), lexicalScope: (*lexicalScope)(p.scope)} r.visible = visible(r.Token.seq + 1) // [0]6.2.1,7 p.scope.declare(p.cpp.eh, r.Token2.SrcStr(), r) default: return &EnumSpecifier{Case: EnumSpecifierTag, Token: p.shift(false), Token2: p.shift(false), lexicalScope: (*lexicalScope)(p.scope)} } case '{': r = &EnumSpecifier{Case: EnumSpecifierDef, Token: p.shift(false), Token3: p.shift(false), EnumeratorList: p.enumeratorList(), lexicalScope: (*lexicalScope)(p.scope)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected enum specifier", t.Position(), runeName(t.Ch)) return nil } switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ',': r.Token4 = p.shift(false) r.Token5 = p.must('}') return r case '}': r.Token5 = p.shift(false) return r default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected enum specifier", t.Position(), runeName(t.Ch)) return nil } } // enumerator-list: // enumerator // enumerator-list , enumerator func (p *parser) enumeratorList() (r *EnumeratorList) { r = &EnumeratorList{Enumerator: p.enumerator()} prev := r for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '}': return r case ',': switch p.peek(1, true).Ch { case rune(IDENTIFIER): e := &EnumeratorList{Token: p.shift(false), Enumerator: p.enumerator()} prev.EnumeratorList = e prev = e default: return r } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected enumerator", t.Position(), runeName(t.Ch)) } } } // enumerator: // enumeration-constant // enumeration-constant = constant-expression func (p *parser) enumerator() (r *Enumerator) { switch p.peek(1, false).Ch { case '}', ',': r = &Enumerator{Case: EnumeratorIdent, Token: p.must(rune(IDENTIFIER))} case '=': r = &Enumerator{Case: EnumeratorExpr, Token: p.must(rune(IDENTIFIER)), Token2: p.shift(false), ConstantExpression: p.constantExpression()} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected enumerator", t.Position(), runeName(t.Ch)) return nil } r.visible = visible(r.Token.seq + 1) p.scope.declare(p.cpp.eh, r.Token.SrcStr(), r) return r } // [0], 6.7.2.1 Structure and union specifiers // // struct-or-union-specifier: // struct-or-union identifier_opt { struct-declaration-list } // struct-or-union identifier func (p *parser) structOrUnionSpecifier() (r *StructOrUnionSpecifier) { sou := p.structOrUnion() attrs := p.attributeSpecifierListOpt() switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '{': return &StructOrUnionSpecifier{Case: StructOrUnionSpecifierDef, StructOrUnion: sou, AttributeSpecifierList: attrs, Token2: p.shift(false), StructDeclarationList: p.structDeclarationList(), Token3: p.must('}'), AttributeSpecifierList2: p.attributeSpecifierListOpt(), lexicalScope: (*lexicalScope)(p.scope)} case rune(IDENTIFIER): r = &StructOrUnionSpecifier{StructOrUnion: sou, AttributeSpecifierList: attrs, Token: p.shift(false), lexicalScope: (*lexicalScope)(p.scope)} r.visible = visible(r.Token.seq + 1) // [0]6.2.1,7 switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '{': p.scope.declare(p.cpp.eh, r.Token.SrcStr(), r) r.Case = StructOrUnionSpecifierDef r.Token2 = p.shift(false) r.StructDeclarationList = p.structDeclarationList() r.Token3 = p.must('}') r.AttributeSpecifierList = p.attributeSpecifierListOpt() return r default: r.Case = StructOrUnionSpecifierTag return r } default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected struct or union specifier", t.Position(), runeName(t.Ch)) return nil } } // struct-declaration-list: // struct-declaration // struct-declaration-list struct-declaration func (p *parser) structDeclarationList() (r *StructDeclarationList) { var prev *StructDeclarationList for { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case '}': return r default: sdl := &StructDeclarationList{StructDeclaration: p.structDeclaration()} switch { case r == nil: r = sdl default: prev.StructDeclarationList = sdl } prev = sdl } } } // struct-declaration: // specifier-qualifier-list struct-declarator-list_opt ; // static-assert-declaration ; func (p *parser) structDeclaration() (r *StructDeclaration) { if p.rune(false) == rune(STATICASSERT) { r = &StructDeclaration{Case: StructDeclarationAssert, StaticAssertDeclaration: p.staticAssertDeclaration()} switch p.rune(false) { case ';': r.Token = p.shift(false) default: t := p.toks[0] p.cpp.eh("%v: unexpected %v, expected ';'", t.Position(), runeName(t.Ch)) } return r } r = &StructDeclaration{Case: StructDeclarationDecl, SpecifierQualifierList: p.specifierQualifierList(), StructDeclaratorList: p.structDeclaratorListOpt(), AttributeSpecifierList: p.attributeSpecifierListOpt()} switch p.rune(false) { case ';': r.Token = p.shift(false) return r case '}': return r default: t := p.toks[0] p.cpp.eh("%v: unexpected %v, expected ';'", t.Position(), runeName(t.Ch)) return r } } // struct-declarator-list: // struct-declarator // struct-declarator-list , struct-declarator func (p *parser) structDeclaratorListOpt() (r *StructDeclaratorList) { switch p.rune(false) { case '(', '*', ':', rune(IDENTIFIER): // ok case ';': return nil default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected struct declarator list", t.Position(), runeName(t.Ch)) return nil } r = &StructDeclaratorList{StructDeclarator: p.structDeclarator()} prev := r for p.rune(false) == ',' { sdl := &StructDeclaratorList{Token: p.shift(false), StructDeclarator: p.structDeclarator()} prev.StructDeclaratorList = sdl prev = sdl } return r } // struct-declarator: // declarator // declarator_opt : constant-expression func (p *parser) structDeclarator() (r *StructDeclarator) { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case ':': return &StructDeclarator{Case: StructDeclaratorBitField, Token: p.shift(false), ConstantExpression: p.constantExpression()} default: r = &StructDeclarator{Case: StructDeclaratorDecl, Declarator: p.declarator(nil, nil, false)} if p.rune(false) == ':' { r.Case = StructDeclaratorBitField r.Token = p.shift(false) r.ConstantExpression = p.constantExpression() } return r } } // [0], 6.6 Constant expressions // // constant-expression: // conditional-expression func (p *parser) constantExpression() (r *ConstantExpression) { r = &ConstantExpression{} r.ConditionalExpression, _ = p.conditionalExpression(true) return r } // struct-or-union: // struct // union func (p *parser) structOrUnion() *StructOrUnion { switch p.rune(false) { case eof: p.cpp.eh("%v: unexpected EOF", p.toks[0].Position()) return nil case rune(STRUCT): return &StructOrUnion{Case: StructOrUnionStruct, Token: p.shift(false)} case rune(UNION): return &StructOrUnion{Case: StructOrUnionUnion, Token: p.shift(false)} default: t := p.shift(false) p.cpp.eh("%v: unexpected %v, expected 'struct' or 'union'", t.Position(), runeName(t.Ch)) return nil } } // Scope binds names to declaring nodes. // // The dynamic type of a Node in the Nodes map is one of // // Node type Note // ----------------- ---- // *Declarator // *EnumSpecifier binds the tag // *Enumerator // *LabelDeclaration // *LabeledStatement case LabeledStatementLabel // *Parameter // *StructOrUnionSpecifier binds the tag type Scope struct { Children []*Scope Nodes map[string][]Node Parent *Scope } func newScope(parent *Scope) (r *Scope) { r = &Scope{Parent: parent} if parent != nil { parent.Children = append(parent.Children, r) } return r } func (s *Scope) declare(eh interface{}, nm string, n Node) { // trc("%v: %q@%p %T, visible %v (scope %p) '%s' (%v: %v: %v:)", n.Position(), nm, n, n, n.(interface{ Visible() int }).Visible(), s, NodeSource(n), origin(4), origin(3), origin(2)) if s.Nodes != nil { s.Nodes[nm] = append(s.Nodes[nm], n) return } s.Nodes = map[string][]Node{nm: {n}} } func (s *Scope) ident(t Token) (r Node) { // defer func() { trc("%v: %s -> %v:", pos(t), t.SrcStr(), pos(r)) }() a := s.idents(t) switch len(a) { case 1: return a[0] case 0: return nil } if p, ok := a[0].(*Parameter); ok { return p.Declarator } d, ok := a[0].(*Declarator) if !ok { return a[0] } if d.Type().Kind() == Function { // trc("%v: %q@%p %s %v %v", d.Position(), d.Name(), d, d.Type(), d.isFuncDef, len(a)) f := d.Type().(*FunctionType) for _, v := range a { x, ok := v.(*Declarator) if !ok { continue } // trc("%v: %q@%p %s %v", d.Position(), d.Name(), d, d.Type(), d.isFuncDef) if d.isFuncDef { return d } g, ok := x.Type().(*FunctionType) if !ok { continue } if lessFunctionType(f, g) { return v } } return a[0] } for _, v := range a { if x, ok := v.(*Declarator); ok && !x.Type().IsIncomplete() { return x } } return a[0] } func (s *Scope) idents(t Token) (r []Node) { nm := t.Src() for ; s != nil; s = s.Parent { for _, v := range s.Nodes[string(nm)] { switch x := v.(type) { case *Declarator: if t.seq >= int32(x.visible) { x.resolved = s r = append(r, x) switch { case x.isExtern: for s := s.Parent; s != nil; s = s.Parent { for _, v := range s.Nodes[string(nm)] { if x, ok := v.(*Declarator); ok && x.isExtern { x.resolved = s r = append(r, x) } } } case x.Type().Kind() == Function && !x.isFuncDef: for s := s.Parent; s != nil; s = s.Parent { for _, v := range s.Nodes[string(nm)] { if x, ok := v.(*Declarator); ok && x.Type().Kind() == Function && x.isFuncDef { x.resolved = s r = append(r, x) } } } } } case *Enumerator: if t.seq >= int32(x.visible) { x.resolved = s r = append(r, x) } case *Parameter: if t.seq >= int32(x.visible) { x.resolved = s r = append(r, x) } } } if len(r) != 0 { return r } } return nil } func (s *Scope) builtin(t Token) *Declarator { nm := "__builtin_" + t.SrcStr() for ; s != nil; s = s.Parent { for _, v := range s.Nodes[nm] { switch x := v.(type) { case *Declarator: if t.seq >= int32(x.visible) { return x } } } } return nil } func (s *Scope) enum(t Token) *EnumSpecifier { for ; s != nil; s = s.Parent { for _, v := range s.Nodes[string(t.Src())] { switch x := v.(type) { case *EnumSpecifier: return x } } } return nil } func (s *Scope) structOrUnion(t Token) *StructOrUnionSpecifier { for ; s != nil; s = s.Parent { for _, v := range s.Nodes[string(t.Src())] { switch x := v.(type) { case *StructOrUnionSpecifier: return x } } } return nil } type visible int32 // Visible reports the token sequence number where the visibility of a name starts. func (v visible) Visible() int { return int(v) } type lexicalScope Scope // LexicalScope provides the scope a node appears in. func (n *lexicalScope) LexicalScope() *Scope { return (*Scope)(n) }