summaryrefslogtreecommitdiffstats
path: root/vendor/modernc.org/cc/v3/parser.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/modernc.org/cc/v3/parser.go')
-rw-r--r--vendor/modernc.org/cc/v3/parser.go4292
1 files changed, 4292 insertions, 0 deletions
diff --git a/vendor/modernc.org/cc/v3/parser.go b/vendor/modernc.org/cc/v3/parser.go
new file mode 100644
index 00000000..d73b2c6b
--- /dev/null
+++ b/vendor/modernc.org/cc/v3/parser.go
@@ -0,0 +1,4292 @@
+// Copyright 2019 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/v3"
+
+import (
+ "bytes"
+ "fmt"
+ "hash/maphash"
+ "strings"
+)
+
+const (
+ unicodePrivateAreaFirst = 0xe000
+ unicodePrivateAreaLast = 0xf8ff
+)
+
+var (
+ noDeclSpecs = &DeclarationSpecifiers{}
+ panicOnParserError bool //TODOOK
+
+ idChar = dict.sid("char")
+ idComma = dict.sid(",")
+ idConst = dict.sid("const")
+ idEq = dict.sid("=")
+ idFFlush = dict.sid("fflush")
+ idFprintf = dict.sid("fprintf")
+ idFunc = dict.sid("__func__")
+ idLBracket = dict.sid("[")
+ idLParen = dict.sid("(")
+ idRBracket = dict.sid("]")
+ idRParen = dict.sid(")")
+ idSemicolon = dict.sid(";")
+ idStatic = dict.sid("static")
+ idStderr = dict.sid("stderr")
+)
+
+// Values of Token.Rune for lexemes.
+const (
+ _ = iota + unicodePrivateAreaFirst //TODOOK
+
+ ACCUM // _Accum
+ ADDASSIGN // +=
+ ALIGNAS // _Alignas
+ ALIGNOF // _Alignof
+ ANDAND // &&
+ ANDASSIGN // &=
+ ARROW // ->
+ ASM // __asm__
+ ATOMIC // _Atomic
+ ATTRIBUTE // __attribute__
+ AUTO // auto
+ BOOL // _Bool
+ BREAK // break
+ BUILTINCHOOSEEXPR // __builtin_choose_expr
+ BUILTINTYPESCOMPATIBLE // __builtin_types_compatible_p
+ CASE // case
+ CHAR // char
+ CHARCONST // 'a'
+ COMPLEX // _Complex
+ CONST // const
+ CONTINUE // continue
+ DDD // ...
+ DEC // --
+ DECIMAL128 // _Decimal128
+ DECIMAL32 // _Decimal32
+ DECIMAL64 // _Decimal64
+ DEFAULT // default
+ DIVASSIGN // /=
+ DO // do
+ DOUBLE // double
+ ELSE // else
+ ENUM // enum
+ ENUMCONST // foo in enum x { foo, bar };
+ EQ // ==
+ EXTERN // extern
+ FLOAT // float
+ FLOAT128 // _Float128
+ FLOAT16 // __fp16
+ FLOAT32 // _Float32
+ FLOAT32X // _Float32x
+ FLOAT64 // _Float64
+ FLOAT64X // _Float64x
+ FLOAT80 // __float80
+ FLOATCONST // 1.23
+ FOR // for
+ FRACT // _Fract
+ GEQ // >=
+ GOTO // goto
+ IDENTIFIER // foo
+ IF // if
+ IMAG // __imag__
+ INC // ++
+ INLINE // inline
+ INT // int
+ INT8 // __int8
+ INT16 // __int16
+ INT32 // __int32
+ INT64 // __int64
+ INT128 // __int128
+ INTCONST // 42
+ LABEL // __label__
+ LEQ // <=
+ LONG // long
+ LONGCHARCONST // L'a'
+ LONGSTRINGLITERAL // L"foo"
+ LSH // <<
+ LSHASSIGN // <<=
+ MODASSIGN // %=
+ MULASSIGN // *=
+ NEQ // !=
+ NORETURN // _Noreturn
+ ORASSIGN // |=
+ OROR // ||
+ PPNUMBER // .32e.
+ PPPASTE // ##
+ PRAGMASTDC // __pragma_stdc
+ REAL // __real__
+ REGISTER // register
+ RESTRICT // restrict
+ RETURN // return
+ RSH // >>
+ RSHASSIGN // >>=
+ SAT // _Sat
+ SHORT // short
+ SIGNED // signed
+ SIZEOF // sizeof
+ STATIC // static
+ STRINGLITERAL // "foo"
+ STRUCT // struct
+ SUBASSIGN // -=
+ SWITCH // switch
+ THREADLOCAL // _Thread_local
+ TYPEDEF // typedef
+ TYPEDEFNAME // int_t in typedef int int_t;
+ TYPEOF // typeof
+ UNION // union
+ UNSIGNED // unsigned
+ VOID // void
+ VOLATILE // volatile
+ WHILE // while
+ XORASSIGN // ^=
+
+ lastTok
+)
+
+var (
+ tokNames = map[rune]StringID{
+ ACCUM: dict.sid("ACCUM"),
+ ADDASSIGN: dict.sid("ADDASSIGN"),
+ ALIGNAS: dict.sid("ALIGNAS"),
+ ALIGNOF: dict.sid("ALIGNOF"),
+ ANDAND: dict.sid("ANDAND"),
+ ANDASSIGN: dict.sid("ANDASSIGN"),
+ ARROW: dict.sid("ARROW"),
+ ASM: dict.sid("ASM"),
+ ATOMIC: dict.sid("ATOMIC"),
+ ATTRIBUTE: dict.sid("ATTRIBUTE"),
+ AUTO: dict.sid("AUTO"),
+ BOOL: dict.sid("BOOL"),
+ BREAK: dict.sid("BREAK"),
+ BUILTINCHOOSEEXPR: dict.sid("BUILTINCHOOSEEXPR"),
+ BUILTINTYPESCOMPATIBLE: dict.sid("BUILTINTYPESCOMPATIBLE"),
+ CASE: dict.sid("CASE"),
+ CHAR: dict.sid("CHAR"),
+ CHARCONST: dict.sid("CHARCONST"),
+ COMPLEX: dict.sid("COMPLEX"),
+ CONST: dict.sid("CONST"),
+ CONTINUE: dict.sid("CONTINUE"),
+ DDD: dict.sid("DDD"),
+ DEC: dict.sid("DEC"),
+ DECIMAL128: dict.sid("DECIMAL128"),
+ DECIMAL32: dict.sid("DECIMAL32"),
+ DECIMAL64: dict.sid("DECIMAL64"),
+ DEFAULT: dict.sid("DEFAULT"),
+ DIVASSIGN: dict.sid("DIVASSIGN"),
+ DO: dict.sid("DO"),
+ DOUBLE: dict.sid("DOUBLE"),
+ ELSE: dict.sid("ELSE"),
+ ENUM: dict.sid("ENUM"),
+ ENUMCONST: dict.sid("ENUMCONST"),
+ EQ: dict.sid("EQ"),
+ EXTERN: dict.sid("EXTERN"),
+ FLOAT128: dict.sid("FLOAT128"),
+ FLOAT16: dict.sid("FLOAT16"),
+ FLOAT32: dict.sid("FLOAT32"),
+ FLOAT32X: dict.sid("FLOAT32X"),
+ FLOAT64: dict.sid("FLOAT64"),
+ FLOAT64X: dict.sid("FLOAT64X"),
+ FLOAT80: dict.sid("FLOAT80"),
+ FLOAT: dict.sid("FLOAT"),
+ FLOATCONST: dict.sid("FLOATCONST"),
+ FOR: dict.sid("FOR"),
+ FRACT: dict.sid("FRACT"),
+ GEQ: dict.sid("GEQ"),
+ GOTO: dict.sid("GOTO"),
+ IDENTIFIER: dict.sid("IDENTIFIER"),
+ IF: dict.sid("IF"),
+ IMAG: dict.sid("IMAG"),
+ INC: dict.sid("INC"),
+ INLINE: dict.sid("INLINE"),
+ INT8: dict.sid("INT8"),
+ INT16: dict.sid("INT16"),
+ INT32: dict.sid("INT32"),
+ INT64: dict.sid("INT64"),
+ INT128: dict.sid("INT128"),
+ INT: dict.sid("INT"),
+ INTCONST: dict.sid("INTCONST"),
+ LABEL: dict.sid("LABEL"),
+ LEQ: dict.sid("LEQ"),
+ LONG: dict.sid("LONG"),
+ LONGCHARCONST: dict.sid("LONGCHARCONST"),
+ LONGSTRINGLITERAL: dict.sid("LONGSTRINGLITERAL"),
+ LSH: dict.sid("LSH"),
+ LSHASSIGN: dict.sid("LSHASSIGN"),
+ MODASSIGN: dict.sid("MODASSIGN"),
+ MULASSIGN: dict.sid("MULASSIGN"),
+ NEQ: dict.sid("NEQ"),
+ NORETURN: dict.sid("NORETURN"),
+ ORASSIGN: dict.sid("ORASSIGN"),
+ OROR: dict.sid("OROR"),
+ PPNUMBER: dict.sid("PPNUMBER"),
+ PPPASTE: dict.sid("PPPASTE"),
+ PRAGMASTDC: dict.sid("PPPRAGMASTDC"),
+ REAL: dict.sid("REAL"),
+ REGISTER: dict.sid("REGISTER"),
+ RESTRICT: dict.sid("RESTRICT"),
+ RETURN: dict.sid("RETURN"),
+ RSH: dict.sid("RSH"),
+ RSHASSIGN: dict.sid("RSHASSIGN"),
+ SAT: dict.sid("SAT"),
+ SHORT: dict.sid("SHORT"),
+ SIGNED: dict.sid("SIGNED"),
+ SIZEOF: dict.sid("SIZEOF"),
+ STATIC: dict.sid("STATIC"),
+ STRINGLITERAL: dict.sid("STRINGLITERAL"),
+ STRUCT: dict.sid("STRUCT"),
+ SUBASSIGN: dict.sid("SUBASSIGN"),
+ SWITCH: dict.sid("SWITCH"),
+ THREADLOCAL: dict.sid("THREADLOCAL"),
+ TYPEDEF: dict.sid("TYPEDEF"),
+ TYPEDEFNAME: dict.sid("TYPEDEFNAME"),
+ TYPEOF: dict.sid("TYPEOF"),
+ UNION: dict.sid("UNION"),
+ UNSIGNED: dict.sid("UNSIGNED"),
+ VOID: dict.sid("VOID"),
+ VOLATILE: dict.sid("VOLATILE"),
+ WHILE: dict.sid("WHILE"),
+ XORASSIGN: dict.sid("XORASSIGN"),
+ }
+
+ keywords = map[StringID]rune{
+
+ // [0], 6.4.1
+ dict.sid("auto"): AUTO,
+ dict.sid("break"): BREAK,
+ dict.sid("case"): CASE,
+ dict.sid("char"): CHAR,
+ dict.sid("const"): CONST,
+ dict.sid("continue"): CONTINUE,
+ dict.sid("default"): DEFAULT,
+ dict.sid("do"): DO,
+ dict.sid("double"): DOUBLE,
+ dict.sid("else"): ELSE,
+ dict.sid("enum"): ENUM,
+ dict.sid("extern"): EXTERN,
+ dict.sid("float"): FLOAT,
+ dict.sid("for"): FOR,
+ dict.sid("goto"): GOTO,
+ dict.sid("if"): IF,
+ dict.sid("inline"): INLINE,
+ dict.sid("int"): INT,
+ dict.sid("long"): LONG,
+ dict.sid("register"): REGISTER,
+ dict.sid("restrict"): RESTRICT,
+ dict.sid("return"): RETURN,
+ dict.sid("short"): SHORT,
+ dict.sid("signed"): SIGNED,
+ dict.sid("sizeof"): SIZEOF,
+ dict.sid("static"): STATIC,
+ dict.sid("struct"): STRUCT,
+ dict.sid("switch"): SWITCH,
+ dict.sid("typedef"): TYPEDEF,
+ dict.sid("union"): UNION,
+ dict.sid("unsigned"): UNSIGNED,
+ dict.sid("void"): VOID,
+ dict.sid("volatile"): VOLATILE,
+ dict.sid("while"): WHILE,
+
+ dict.sid("_Alignas"): ALIGNAS,
+ dict.sid("_Alignof"): ALIGNOF,
+ dict.sid("_Atomic"): ATOMIC,
+ dict.sid("_Bool"): BOOL,
+ dict.sid("_Complex"): COMPLEX,
+ dict.sid("_Noreturn"): NORETURN,
+ dict.sid("_Thread_local"): THREADLOCAL,
+ dict.sid("__alignof"): ALIGNOF,
+ dict.sid("__alignof__"): ALIGNOF,
+ dict.sid("__asm"): ASM,
+ dict.sid("__asm__"): ASM,
+ dict.sid("__attribute"): ATTRIBUTE,
+ dict.sid("__attribute__"): ATTRIBUTE,
+ dict.sid("__complex"): COMPLEX,
+ dict.sid("__complex__"): COMPLEX,
+ dict.sid("__const"): CONST,
+ dict.sid("__inline"): INLINE,
+ dict.sid("__inline__"): INLINE,
+ dict.sid("__int16"): INT16,
+ dict.sid("__int32"): INT32,
+ dict.sid("__int64"): INT64,
+ dict.sid("__int8"): INT8,
+ dict.sid("__pragma_stdc"): PRAGMASTDC,
+ dict.sid("__restrict"): RESTRICT,
+ dict.sid("__restrict__"): RESTRICT,
+ dict.sid("__signed"): SIGNED,
+ dict.sid("__signed__"): SIGNED,
+ dict.sid("__thread"): THREADLOCAL,
+ dict.sid("__typeof"): TYPEOF,
+ dict.sid("__typeof__"): TYPEOF,
+ dict.sid("__volatile"): VOLATILE,
+ dict.sid("__volatile__"): VOLATILE,
+ dict.sid("typeof"): TYPEOF,
+ }
+
+ gccKeywords = map[StringID]rune{
+ dict.sid("_Accum"): ACCUM,
+ dict.sid("_Decimal128"): DECIMAL128,
+ dict.sid("_Decimal32"): DECIMAL32,
+ dict.sid("_Decimal64"): DECIMAL64,
+ dict.sid("_Float128"): FLOAT128,
+ dict.sid("_Float16"): FLOAT16,
+ dict.sid("_Float32"): FLOAT32,
+ dict.sid("_Float32x"): FLOAT32X,
+ dict.sid("_Float64"): FLOAT64,
+ dict.sid("_Float64x"): FLOAT64X,
+ dict.sid("_Fract"): FRACT,
+ dict.sid("_Sat"): SAT,
+ dict.sid("__builtin_choose_expr"): BUILTINCHOOSEEXPR,
+ dict.sid("__builtin_types_compatible_p"): BUILTINTYPESCOMPATIBLE,
+ dict.sid("__float80"): FLOAT80,
+ dict.sid("__fp16"): FLOAT16,
+ dict.sid("__imag"): IMAG,
+ dict.sid("__imag__"): IMAG,
+ dict.sid("__int128"): INT128,
+ dict.sid("__label__"): LABEL,
+ dict.sid("__real"): REAL,
+ dict.sid("__real__"): REAL,
+ }
+)
+
+func init() {
+ for r := rune(0xe001); r < lastTok; r++ {
+ if _, ok := tokNames[r]; !ok {
+ panic(internalError())
+ }
+ }
+ for k, v := range keywords {
+ gccKeywords[k] = v
+ }
+}
+
+func tokName(r rune) string {
+ switch {
+ case r < 0:
+ return "<EOF>"
+ case r >= unicodePrivateAreaFirst && r <= unicodePrivateAreaLast:
+ return tokNames[r].String()
+ default:
+ return fmt.Sprintf("%+q", r)
+ }
+}
+
+type parser struct {
+ block *CompoundStatement
+ ctx *context
+ currFn *FunctionDefinition
+ declScope Scope
+ fileScope Scope
+ hash *maphash.Hash
+ in chan *[]Token
+ inBuf []Token
+ inBufp *[]Token
+ key sharedFunctionDefinitionKey
+ prev Token
+ resolveScope Scope
+ resolvedIn Scope // Typedef name
+ scopes int
+ sepLen int
+ seps []StringID
+ strcatLen int
+ strcats []StringID
+ switches int
+
+ tok Token
+
+ closed bool
+ errored bool
+ ignoreKeywords bool
+ typedefNameEnabled bool
+}
+
+func newParser(ctx *context, in chan *[]Token) *parser {
+ s := Scope{}
+ var hash *maphash.Hash
+ if s := ctx.cfg.SharedFunctionDefinitions; s != nil {
+ hash = &s.hash
+ }
+ return &parser{
+ ctx: ctx,
+ declScope: s,
+ fileScope: s,
+ hash: hash,
+ in: in,
+ resolveScope: s,
+ }
+}
+
+func (p *parser) openScope(skip bool) {
+ p.scopes++
+ p.declScope = p.declScope.new()
+ if skip {
+ p.declScope[scopeSkip] = nil
+ }
+ p.resolveScope = p.declScope
+ // var a []string
+ // for s := p.declScope; s != nil; s = s.Parent() {
+ // a = append(a, fmt.Sprintf("%p", s))
+ // }
+ // trc("openScope(%v) %p: %v", skip, p.declScope, strings.Join(a, " "))
+}
+
+func (p *parser) closeScope() {
+ // declScope := p.declScope
+ p.declScope = p.declScope.Parent()
+ p.resolveScope = p.declScope
+ p.scopes--
+ // var a []string
+ // for s := p.declScope; s != nil; s = s.Parent() {
+ // a = append(a, fmt.Sprintf("%p", s))
+ // }
+ // trc("%p.closeScope %v", declScope, strings.Join(a, " "))
+}
+
+func (p *parser) err0(consume bool, msg string, args ...interface{}) {
+ if panicOnParserError { //TODOOK
+ s := fmt.Sprintf("FAIL: "+msg, args...)
+ panic(fmt.Sprintf("%s\n%s: ", s, PrettyString(p.tok))) //TODOOK
+ }
+ // s := fmt.Sprintf("FAIL: "+p.tok.Position().String()+": "+msg, args...)
+ // caller("%s: %s: ", s, PrettyString(p.tok))
+ p.errored = true
+ if consume {
+ p.tok.Rune = 0
+ }
+ if p.ctx.err(p.tok.Position(), "`%s`: "+msg, append([]interface{}{p.tok}, args...)...) {
+ p.closed = true
+ }
+}
+
+func (p *parser) err(msg string, args ...interface{}) { p.err0(true, msg, args...) }
+
+func (p *parser) rune() rune {
+ if p.tok.Rune == 0 {
+ p.next()
+ }
+ return p.tok.Rune
+}
+
+func (p *parser) shift() (r Token) {
+ if p.tok.Rune == 0 {
+ p.next()
+ }
+ r = p.tok
+ p.tok.Rune = 0
+ // dbg("", shift(r))
+ return r
+}
+
+func (p *parser) unget(toks ...Token) { //TODO injected __func__ has two trailing semicolons, why?
+ p.inBuf = append(toks, p.inBuf...)
+ // fmt.Printf("unget %q\n", tokStr(toks, "|")) //TODO-
+}
+
+func (p *parser) peek(handleTypedefname bool) rune {
+ if p.closed {
+ return -1
+ }
+
+ if len(p.inBuf) == 0 {
+ if p.inBufp != nil {
+ tokenPool.Put(p.inBufp)
+ }
+ var ok bool
+ if p.inBufp, ok = <-p.in; !ok {
+ // dbg("parser: EOF")
+ return -1
+ }
+
+ p.inBuf = *p.inBufp
+ // dbg("parser receives: %q", tokStr(p.inBuf, "|"))
+ // fmt.Printf("parser receives %v: %q\n", p.inBuf[0].Position(), tokStr(p.inBuf, "|")) //TODO-
+ }
+ tok := p.inBuf[0]
+ r := tok.Rune
+ if r == IDENTIFIER {
+ if x, ok := p.ctx.keywords[p.inBuf[0].Value]; ok && !p.ignoreKeywords {
+ return x
+ }
+
+ if handleTypedefname {
+ nm := tok.Value
+ seq := tok.seq
+ for s := p.resolveScope; s != nil; s = s.Parent() {
+ for _, v := range s[nm] {
+ switch x := v.(type) {
+ case *Declarator:
+ if !x.isVisible(seq) {
+ continue
+ }
+
+ if x.IsTypedefName && p.peek(false) != ':' {
+ return TYPEDEFNAME
+ }
+
+ return IDENTIFIER
+ case *Enumerator:
+ return IDENTIFIER
+ case *EnumSpecifier, *StructOrUnionSpecifier, *StructDeclarator, *LabeledStatement:
+ // nop
+ default:
+ panic(internalErrorf("%T", x))
+ }
+ }
+ }
+ }
+ }
+ return r
+}
+
+func (p *parser) next() {
+ if p.closed {
+ // dbg("parser: EOF")
+ p.tok.Rune = -1
+ return
+ }
+
+more:
+ if len(p.inBuf) == 0 {
+ if p.inBufp != nil {
+ tokenPool.Put(p.inBufp)
+ }
+ var ok bool
+ if p.inBufp, ok = <-p.in; !ok {
+ // dbg("parser: EOF")
+ p.closed = true
+ p.tok.Rune = -1
+ return
+ }
+
+ p.inBuf = *p.inBufp
+ // dbg("parser receives: %q", tokStr(p.inBuf, "|"))
+ // fmt.Printf("parser receives %v: %q\n", p.inBuf[0].Position(), tokStr(p.inBuf, "|")) //TODO-
+ }
+ p.tok = p.inBuf[0]
+ switch p.tok.Rune {
+ case STRINGLITERAL, LONGSTRINGLITERAL:
+ switch p.prev.Rune {
+ case STRINGLITERAL, LONGSTRINGLITERAL:
+ p.strcatLen += len(p.tok.Value.String())
+ p.strcats = append(p.strcats, p.tok.Value)
+ p.sepLen += len(p.tok.Sep.String())
+ p.seps = append(p.seps, p.tok.Sep)
+ p.inBuf = p.inBuf[1:]
+ goto more
+ default:
+ p.strcatLen = len(p.tok.Value.String())
+ p.strcats = []StringID{p.tok.Value}
+ p.sepLen = len(p.tok.Sep.String())
+ p.seps = []StringID{p.tok.Sep}
+ p.prev = p.tok
+ p.inBuf = p.inBuf[1:]
+ goto more
+ }
+ default:
+ switch p.prev.Rune {
+ case STRINGLITERAL, LONGSTRINGLITERAL:
+ p.tok = p.prev
+ var b bytes.Buffer
+ b.Grow(p.strcatLen)
+ for _, v := range p.strcats {
+ b.WriteString(v.String())
+ }
+ p.tok.Value = dict.id(b.Bytes())
+ b.Reset()
+ b.Grow(p.sepLen)
+ for _, v := range p.seps {
+ b.WriteString(v.String())
+ }
+ p.tok.Sep = dict.id(b.Bytes())
+ p.prev.Rune = 0
+ default:
+ p.inBuf = p.inBuf[1:]
+ }
+ }
+ p.resolvedIn = nil
+out:
+ switch p.tok.Rune {
+ case IDENTIFIER:
+ nm := p.tok.Value
+ if x, ok := p.ctx.keywords[nm]; ok && !p.ignoreKeywords {
+ p.tok.Rune = x
+ break
+ }
+
+ if p.typedefNameEnabled {
+ seq := p.tok.seq
+ // dbg("checking for typedefname in scope %p", p.resolveScope)
+ for s := p.resolveScope; s != nil; s = s.Parent() {
+ // dbg("scope %p", s)
+ for _, v := range s[nm] {
+ // dbg("%v: %T", nm, v)
+ switch x := v.(type) {
+ case *Declarator:
+ if !x.isVisible(seq) {
+ continue
+ }
+
+ // dbg("", x.isVisible(pos), x.IsTypedefName)
+ if x.IsTypedefName && p.peek(false) != ':' {
+ p.tok.Rune = TYPEDEFNAME
+ p.resolvedIn = s
+ }
+
+ p.typedefNameEnabled = false
+ break out
+ case *Enumerator:
+ if x.isVisible(seq) {
+ break out
+ }
+ case *EnumSpecifier, *StructOrUnionSpecifier, *StructDeclarator, *LabeledStatement:
+ // nop
+ default:
+ panic(internalError())
+ }
+ }
+ }
+ }
+ case PPNUMBER:
+ switch s := p.tok.Value.String(); {
+ case strings.ContainsAny(s, ".+-ijpIJP"):
+ p.tok.Rune = FLOATCONST
+ case strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X"):
+ p.tok.Rune = INTCONST
+ case strings.ContainsAny(s, "Ee"):
+ p.tok.Rune = FLOATCONST
+ default:
+ p.tok.Rune = INTCONST
+ }
+ }
+ if p.ctx.cfg.SharedFunctionDefinitions != nil {
+ p.hashTok()
+ }
+ // dbg("parser.next p.tok %v", PrettyString(p.tok))
+ // fmt.Printf("%s%s/* %s */", p.tok.Sep, p.tok.Value, tokName(p.tok.Rune)) //TODO-
+}
+
+func (p *parser) hashTok() {
+ n := p.tok.Rune
+ for i := 0; i < 4; i++ {
+ p.hash.WriteByte(byte(n))
+ n >>= 8
+ }
+ n = int32(p.tok.Value)
+ for i := 0; i < 4; i++ {
+ p.hash.WriteByte(byte(n))
+ n >>= 8
+ }
+}
+
+// [0], 6.5.1 Primary expressions
+//
+// primary-expression:
+// identifier
+// constant
+// string-literal
+// ( expression )
+// ( compound-statement )
+func (p *parser) primaryExpression() *PrimaryExpression {
+ var kind PrimaryExpressionCase
+ var resolvedIn Scope
+ var resolvedTo Node
+out:
+ switch p.rune() {
+ case IDENTIFIER:
+ kind = PrimaryExpressionIdent
+ nm := p.tok.Value
+ seq := p.tok.seq
+ for s := p.resolveScope; s != nil; s = s.Parent() {
+ for _, v := range s[nm] {
+ switch x := v.(type) {
+ case *Enumerator:
+ if x.isVisible(seq) {
+ resolvedIn = s
+ resolvedTo = x
+ p.tok.Rune = ENUMCONST
+ kind = PrimaryExpressionEnum
+ break out
+ }
+ case *Declarator:
+ if x.IsTypedefName || !x.isVisible(seq) {
+ continue
+ }
+
+ resolvedIn = s
+ resolvedTo = x
+ break out
+ case *EnumSpecifier, *StructOrUnionSpecifier, *StructDeclarator, *LabeledStatement:
+ // nop
+ default:
+ panic(internalError())
+ }
+ }
+ }
+
+ if !p.ctx.cfg.ignoreUndefinedIdentifiers && p.ctx.cfg.RejectLateBinding {
+ p.err0(false, "front-end: undefined: %s", nm)
+ }
+ case INTCONST:
+ kind = PrimaryExpressionInt
+ case FLOATCONST:
+ kind = PrimaryExpressionFloat
+ case ENUMCONST:
+ kind = PrimaryExpressionEnum
+ case CHARCONST:
+ kind = PrimaryExpressionChar
+ case LONGCHARCONST:
+ kind = PrimaryExpressionLChar
+ case STRINGLITERAL:
+ kind = PrimaryExpressionString
+ case LONGSTRINGLITERAL:
+ kind = PrimaryExpressionLString
+ case '(':
+ t := p.shift()
+ switch p.peek(false) {
+ case '{':
+ if p.ctx.cfg.RejectStatementExpressions {
+ p.err0(false, "statement expressions not allowed")
+ }
+ s := p.compoundStatement(nil, nil)
+ var t2 Token
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &PrimaryExpression{Case: PrimaryExpressionStmt, Token: t, CompoundStatement: s, Token2: t2, lexicalScope: p.declScope}
+ default:
+ e := p.expression()
+ var t2 Token
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &PrimaryExpression{Case: PrimaryExpressionExpr, Token: t, Expression: e, Token2: t2, lexicalScope: p.declScope}
+ }
+ default:
+ p.err("expected primary-expression")
+ return nil
+ }
+
+ return &PrimaryExpression{Case: kind, Token: p.shift(), lexicalScope: p.declScope, resolvedIn: resolvedIn, resolvedTo: resolvedTo}
+}
+
+// [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(typ *TypeName) (r *PostfixExpression) {
+ var t, t2, t3, t4, t5 Token
+out:
+ switch {
+ case typ != nil:
+ switch p.rune() {
+ case '{':
+ t3 = p.shift()
+ default:
+ p.err("expected {")
+ return nil
+ }
+
+ var list *InitializerList
+ switch p.rune() {
+ case '}':
+ if p.ctx.cfg.RejectEmptyInitializerList {
+ p.err0(false, "expected initializer-list")
+ }
+ default:
+ list = p.initializerList(nil)
+ if p.rune() == ',' {
+ t4 = p.shift()
+ }
+ }
+ switch p.rune() {
+ case '}':
+ t5 = p.shift()
+ default:
+ p.err("expected }")
+ }
+ r = &PostfixExpression{Case: PostfixExpressionComplit, Token: t, TypeName: typ, Token2: t2, Token3: t3, InitializerList: list, Token4: t4, Token5: t5}
+ break out
+ default:
+ switch p.rune() {
+ case BUILTINCHOOSEEXPR:
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ expr1 := p.assignmentExpression()
+ switch p.rune() {
+ case ',':
+ t3 = p.shift()
+ default:
+ p.err("expected ,")
+ }
+ expr2 := p.assignmentExpression()
+ switch p.rune() {
+ case ',':
+ t4 = p.shift()
+ default:
+ p.err("expected ,")
+ }
+ expr3 := p.assignmentExpression()
+ switch p.rune() {
+ case ')':
+ t5 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &PostfixExpression{Case: PostfixExpressionChooseExpr, Token: t, Token2: t2, Token3: t3, Token4: t4, Token5: t5, AssignmentExpression: expr1, AssignmentExpression2: expr2, AssignmentExpression3: expr3}
+ case BUILTINTYPESCOMPATIBLE:
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ typ := p.typeName()
+ switch p.rune() {
+ case ',':
+ t3 = p.shift()
+ default:
+ p.err("expected ,")
+ }
+ typ2 := p.typeName()
+ switch p.rune() {
+ case ')':
+ t4 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &PostfixExpression{Case: PostfixExpressionTypeCmp, Token: t, Token2: t2, TypeName: typ, Token3: t3, TypeName2: typ2, Token4: t4}
+ case '(':
+ switch p.peek(true) {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE:
+ p.typedefNameEnabled = true
+ t = p.shift()
+ typ := p.typeName()
+ p.typedefNameEnabled = false
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ switch p.rune() {
+ case '{':
+ t3 = p.shift()
+ default:
+ p.err("expected {")
+ }
+ var list *InitializerList
+ switch p.rune() {
+ case '}':
+ if p.ctx.cfg.RejectEmptyInitializerList {
+ p.err0(false, "expected initializer-list")
+ }
+ default:
+ list = p.initializerList(nil)
+ if p.rune() == ',' {
+ t4 = p.shift()
+ }
+ }
+ switch p.rune() {
+ case '}':
+ t5 = p.shift()
+ default:
+ p.err("expected }")
+ }
+ r = &PostfixExpression{Case: PostfixExpressionComplit, Token: t, TypeName: typ, Token2: t2, Token3: t3, InitializerList: list, Token4: t4, Token5: t5}
+ break out
+ }
+
+ fallthrough
+ default:
+ pe := p.primaryExpression()
+ if pe == nil {
+ return nil
+ }
+
+ r = &PostfixExpression{Case: PostfixExpressionPrimary, PrimaryExpression: pe}
+ }
+ }
+
+ for {
+ switch p.rune() {
+ case '[':
+ t = p.shift()
+ e := p.expression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &PostfixExpression{Case: PostfixExpressionIndex, PostfixExpression: r, Token: t, Expression: e, Token2: t2}
+ case '(':
+ t = p.shift()
+ list := p.argumentExpressionListOpt()
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &PostfixExpression{Case: PostfixExpressionCall, PostfixExpression: r, Token: t, ArgumentExpressionList: list, Token2: t2}
+ case '.':
+ t = p.shift()
+ switch p.rune() {
+ case IDENTIFIER:
+ t2 = p.shift()
+ default:
+ p.err("expected identifier")
+ }
+ r = &PostfixExpression{Case: PostfixExpressionSelect, PostfixExpression: r, Token: t, Token2: t2}
+ case ARROW:
+ t = p.shift()
+ switch p.rune() {
+ case IDENTIFIER:
+ t2 = p.shift()
+ default:
+ p.err("expected identifier")
+ }
+ r = &PostfixExpression{Case: PostfixExpressionPSelect, PostfixExpression: r, Token: t, Token2: t2}
+ case INC:
+ r = &PostfixExpression{Case: PostfixExpressionInc, PostfixExpression: r, Token: p.shift()}
+ case DEC:
+ r = &PostfixExpression{Case: PostfixExpressionDec, PostfixExpression: r, Token: p.shift()}
+ default:
+ return r
+ }
+ }
+}
+
+// argument-expression-list:
+// assignment-expression
+// argument-expression-list , assignment-expression
+func (p *parser) argumentExpressionListOpt() (r *ArgumentExpressionList) {
+ if p.rune() == ')' {
+ return nil
+ }
+
+ e := p.assignmentExpression()
+ if e == nil {
+ return nil
+ }
+
+ r = &ArgumentExpressionList{AssignmentExpression: e}
+ for prev := r; ; prev = prev.ArgumentExpressionList {
+ switch p.rune() {
+ case ',':
+ t := p.shift()
+ prev.ArgumentExpressionList = &ArgumentExpressionList{Token: t, AssignmentExpression: p.assignmentExpression()}
+ case ')':
+ return r
+ default:
+ p.err("expected , or )")
+ return r
+ }
+ }
+}
+
+// [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(typ *TypeName) *UnaryExpression {
+ if typ != nil {
+ return &UnaryExpression{Case: UnaryExpressionPostfix, PostfixExpression: p.postfixExpression(typ), lexicalScope: p.declScope}
+ }
+
+ var kind UnaryExpressionCase
+ var t, t2, t3 Token
+ switch p.rune() {
+ case INC:
+ t = p.shift()
+ return &UnaryExpression{Case: UnaryExpressionInc, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ case DEC:
+ t = p.shift()
+ return &UnaryExpression{Case: UnaryExpressionDec, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ case '&':
+ kind = UnaryExpressionAddrof
+ case '*':
+ kind = UnaryExpressionDeref
+ case '+':
+ kind = UnaryExpressionPlus
+ case '-':
+ kind = UnaryExpressionMinus
+ case '~':
+ kind = UnaryExpressionCpl
+ case '!':
+ kind = UnaryExpressionNot
+ case SIZEOF:
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ switch p.peek(true) {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE:
+ p.typedefNameEnabled = true
+ t2 = p.shift()
+ typ := p.typeName()
+ p.typedefNameEnabled = false
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ if p.peek(false) == '{' {
+ return &UnaryExpression{Case: UnaryExpressionSizeofExpr, Token: t, UnaryExpression: p.unaryExpression(typ), lexicalScope: p.declScope}
+ }
+
+ return &UnaryExpression{Case: UnaryExpressionSizeofType, Token: t, Token2: t2, TypeName: typ, Token3: t3, lexicalScope: p.declScope}
+ }
+
+ fallthrough
+ default:
+ return &UnaryExpression{Case: UnaryExpressionSizeofExpr, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ }
+ case ANDAND:
+ t = p.shift()
+ var t2 Token
+ switch p.rune() {
+ case IDENTIFIER:
+ t2 = p.shift()
+ default:
+ p.err("expected identifier")
+ }
+ return &UnaryExpression{Case: UnaryExpressionLabelAddr, Token: t, Token2: t2, lexicalScope: p.declScope}
+ case ALIGNOF:
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ switch p.peek(true) {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE,
+ ALIGNAS:
+ t2 = p.shift()
+ typ := p.typeName()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &UnaryExpression{Case: UnaryExpressionAlignofType, Token: t, Token2: t2, TypeName: typ, Token3: t2, lexicalScope: p.declScope}
+ default:
+ return &UnaryExpression{Case: UnaryExpressionAlignofExpr, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ }
+ default:
+ return &UnaryExpression{Case: UnaryExpressionAlignofExpr, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ }
+ case IMAG:
+ t = p.shift()
+ return &UnaryExpression{Case: UnaryExpressionImag, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ case REAL:
+ t = p.shift()
+ return &UnaryExpression{Case: UnaryExpressionReal, Token: t, UnaryExpression: p.unaryExpression(nil), lexicalScope: p.declScope}
+ default:
+ return &UnaryExpression{Case: UnaryExpressionPostfix, PostfixExpression: p.postfixExpression(nil), lexicalScope: p.declScope}
+ }
+
+ t = p.shift()
+ return &UnaryExpression{Case: kind, Token: t, CastExpression: p.castExpression(), lexicalScope: p.declScope}
+}
+
+// [0], 6.5.4 Cast operators
+//
+// cast-expression:
+// unary-expression
+// ( type-name ) cast-expression
+func (p *parser) castExpression() *CastExpression {
+ var t, t2 Token
+ switch p.rune() {
+ case '(':
+ switch p.peek(true) {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE:
+ p.typedefNameEnabled = true
+ t = p.shift()
+ typ := p.typeName()
+ p.typedefNameEnabled = false
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ if p.peek(false) == '{' {
+ return &CastExpression{Case: CastExpressionUnary, UnaryExpression: p.unaryExpression(typ)}
+ }
+
+ return &CastExpression{Case: CastExpressionCast, Token: t, TypeName: typ, Token2: t2, CastExpression: p.castExpression()}
+ }
+
+ fallthrough
+ default:
+ return &CastExpression{Case: CastExpressionUnary, UnaryExpression: p.unaryExpression(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() (r *MultiplicativeExpression) {
+ r = &MultiplicativeExpression{Case: MultiplicativeExpressionCast, CastExpression: p.castExpression()}
+ for {
+ var kind MultiplicativeExpressionCase
+ switch p.rune() {
+ case '*':
+ kind = MultiplicativeExpressionMul
+ case '/':
+ kind = MultiplicativeExpressionDiv
+ case '%':
+ kind = MultiplicativeExpressionMod
+ default:
+ return r
+ }
+
+ t := p.shift()
+ r = &MultiplicativeExpression{Case: kind, MultiplicativeExpression: r, Token: t, CastExpression: p.castExpression()}
+ }
+}
+
+// [0], 6.5.6 Additive operators
+//
+// additive-expression:
+// multiplicative-expression
+// additive-expression + multiplicative-expression
+// additive-expression - multiplicative-expression
+func (p *parser) additiveExpression() (r *AdditiveExpression) {
+ r = &AdditiveExpression{Case: AdditiveExpressionMul, MultiplicativeExpression: p.multiplicativeExpression()}
+ for {
+ var kind AdditiveExpressionCase
+ switch p.rune() {
+ case '+':
+ kind = AdditiveExpressionAdd
+ case '-':
+ kind = AdditiveExpressionSub
+ default:
+ return r
+ }
+
+ t := p.shift()
+ r = &AdditiveExpression{Case: kind, AdditiveExpression: r, Token: t, MultiplicativeExpression: p.multiplicativeExpression(), lexicalScope: p.declScope}
+ }
+}
+
+// [0], 6.5.7 Bitwise shift operators
+//
+// shift-expression:
+// additive-expression
+// shift-expression << additive-expression
+// shift-expression >> additive-expression
+func (p *parser) shiftExpression() (r *ShiftExpression) {
+ r = &ShiftExpression{Case: ShiftExpressionAdd, AdditiveExpression: p.additiveExpression()}
+ for {
+ var kind ShiftExpressionCase
+ switch p.rune() {
+ case LSH:
+ kind = ShiftExpressionLsh
+ case RSH:
+ kind = ShiftExpressionRsh
+ default:
+ return r
+ }
+
+ t := p.shift()
+ r = &ShiftExpression{Case: kind, ShiftExpression: r, Token: t, AdditiveExpression: p.additiveExpression()}
+ }
+}
+
+// [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() (r *RelationalExpression) {
+ r = &RelationalExpression{Case: RelationalExpressionShift, ShiftExpression: p.shiftExpression()}
+ for {
+ var kind RelationalExpressionCase
+ switch p.rune() {
+ case '<':
+ kind = RelationalExpressionLt
+ case '>':
+ kind = RelationalExpressionGt
+ case LEQ:
+ kind = RelationalExpressionLeq
+ case GEQ:
+ kind = RelationalExpressionGeq
+ default:
+ return r
+ }
+
+ t := p.shift()
+ r = &RelationalExpression{Case: kind, RelationalExpression: r, Token: t, ShiftExpression: p.shiftExpression()}
+ }
+}
+
+// [0], 6.5.9 Equality operators
+//
+// equality-expression:
+// relational-expression
+// equality-expression == relational-expression
+// equality-expression != relational-expression
+func (p *parser) equalityExpression() (r *EqualityExpression) {
+ r = &EqualityExpression{Case: EqualityExpressionRel, RelationalExpression: p.relationalExpression()}
+ for {
+ var kind EqualityExpressionCase
+ switch p.rune() {
+ case EQ:
+ kind = EqualityExpressionEq
+ case NEQ:
+ kind = EqualityExpressionNeq
+ default:
+ return r
+ }
+
+ t := p.shift()
+ r = &EqualityExpression{Case: kind, EqualityExpression: r, Token: t, RelationalExpression: p.relationalExpression()}
+ }
+}
+
+// [0], 6.5.10 Bitwise AND operator
+//
+// AND-expression:
+// equality-expression
+// AND-expression & equality-expression
+func (p *parser) andExpression() (r *AndExpression) {
+ r = &AndExpression{Case: AndExpressionEq, EqualityExpression: p.equalityExpression()}
+ for {
+ switch p.rune() {
+ case '&':
+ t := p.shift()
+ r = &AndExpression{Case: AndExpressionAnd, AndExpression: r, Token: t, EqualityExpression: p.equalityExpression()}
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.5.11 Bitwise exclusive OR operator
+//
+// exclusive-OR-expression:
+// AND-expression
+// exclusive-OR-expression ^ AND-expression
+func (p *parser) exclusiveOrExpression() (r *ExclusiveOrExpression) {
+ r = &ExclusiveOrExpression{Case: ExclusiveOrExpressionAnd, AndExpression: p.andExpression()}
+ for {
+ switch p.rune() {
+ case '^':
+ t := p.shift()
+ r = &ExclusiveOrExpression{Case: ExclusiveOrExpressionXor, ExclusiveOrExpression: r, Token: t, AndExpression: p.andExpression()}
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.5.12 Bitwise inclusive OR operator
+//
+// inclusive-OR-expression:
+// exclusive-OR-expression
+// inclusive-OR-expression | exclusive-OR-expression
+func (p *parser) inclusiveOrExpression() (r *InclusiveOrExpression) {
+ r = &InclusiveOrExpression{Case: InclusiveOrExpressionXor, ExclusiveOrExpression: p.exclusiveOrExpression()}
+ for {
+ switch p.rune() {
+ case '|':
+ t := p.shift()
+ r = &InclusiveOrExpression{Case: InclusiveOrExpressionOr, InclusiveOrExpression: r, Token: t, ExclusiveOrExpression: p.exclusiveOrExpression()}
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.5.13 Logical AND operator
+//
+// logical-AND-expression:
+// inclusive-OR-expression
+// logical-AND-expression && inclusive-OR-expression
+func (p *parser) logicalAndExpression() (r *LogicalAndExpression) {
+ r = &LogicalAndExpression{Case: LogicalAndExpressionOr, InclusiveOrExpression: p.inclusiveOrExpression()}
+ for {
+ switch p.rune() {
+ case ANDAND:
+ t := p.shift()
+ r = &LogicalAndExpression{Case: LogicalAndExpressionLAnd, LogicalAndExpression: r, Token: t, InclusiveOrExpression: p.inclusiveOrExpression()}
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.5.14 Logical OR operator
+//
+// logical-OR-expression:
+// logical-AND-expression
+// logical-OR-expression || logical-AND-expression
+func (p *parser) logicalOrExpression() (r *LogicalOrExpression) {
+ r = &LogicalOrExpression{Case: LogicalOrExpressionLAnd, LogicalAndExpression: p.logicalAndExpression()}
+ for {
+ switch p.rune() {
+ case OROR:
+ t := p.shift()
+ r = &LogicalOrExpression{Case: LogicalOrExpressionLOr, LogicalOrExpression: r, Token: t, LogicalAndExpression: p.logicalAndExpression()}
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.5.15 Conditional operator
+//
+// conditional-expression:
+// logical-OR-expression
+// logical-OR-expression ? expression : conditional-expression
+func (p *parser) conditionalExpression() (r *ConditionalExpression) {
+ lo := p.logicalOrExpression()
+ var t, t2 Token
+ switch p.rune() {
+ case '?':
+ t = p.shift()
+ var e *Expression
+ switch p.rune() {
+ case ':':
+ if p.ctx.cfg.RejectMissingConditionalExpr {
+ p.err("expected expression")
+ }
+ default:
+ e = p.expression()
+ }
+ switch p.rune() {
+ case ':':
+ t2 = p.shift()
+ default:
+ p.err("expected :")
+ }
+ return &ConditionalExpression{Case: ConditionalExpressionCond, LogicalOrExpression: lo, Token: t, Expression: e, Token2: t2, ConditionalExpression: p.conditionalExpression()}
+ default:
+ return &ConditionalExpression{Case: ConditionalExpressionLOr, LogicalOrExpression: lo}
+ }
+}
+
+// [0], 6.5.16 Assignment operators
+//
+// assignment-expression:
+// conditional-expression
+// unary-expression assignment-operator assignment-expression
+//
+// assignment-operator: one of
+// = *= /= %= += -= <<= >>= &= ^= |=
+func (p *parser) assignmentExpression() (r *AssignmentExpression) {
+ ce := p.conditionalExpression()
+ if ce == nil || ce.Case != ConditionalExpressionLOr {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ loe := ce.LogicalOrExpression
+ if loe == nil || loe.Case != LogicalOrExpressionLAnd {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ lae := loe.LogicalAndExpression
+ if lae == nil || lae.Case != LogicalAndExpressionOr {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ ioe := lae.InclusiveOrExpression
+ if ioe == nil || ioe.Case != InclusiveOrExpressionXor {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ eoe := ioe.ExclusiveOrExpression
+ if eoe == nil || eoe.Case != ExclusiveOrExpressionAnd {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ ae := eoe.AndExpression
+ if ae == nil || ae.Case != AndExpressionEq {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ ee := ae.EqualityExpression
+ if ee == nil || ee.Case != EqualityExpressionRel {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ re := ee.RelationalExpression
+ if re == nil || re.Case != RelationalExpressionShift {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ se := re.ShiftExpression
+ if se == nil || se.Case != ShiftExpressionAdd {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ adde := se.AdditiveExpression
+ if adde == nil || adde.Case != AdditiveExpressionMul {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ me := adde.MultiplicativeExpression
+ if me == nil || me.Case != MultiplicativeExpressionCast {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ cast := me.CastExpression
+ if cast == nil || cast.Case != CastExpressionUnary {
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ var kind AssignmentExpressionCase
+ switch p.rune() {
+ case '=':
+ kind = AssignmentExpressionAssign
+ case MULASSIGN:
+ kind = AssignmentExpressionMul
+ case DIVASSIGN:
+ kind = AssignmentExpressionDiv
+ case MODASSIGN:
+ kind = AssignmentExpressionMod
+ case ADDASSIGN:
+ kind = AssignmentExpressionAdd
+ case SUBASSIGN:
+ kind = AssignmentExpressionSub
+ case LSHASSIGN:
+ kind = AssignmentExpressionLsh
+ case RSHASSIGN:
+ kind = AssignmentExpressionRsh
+ case ANDASSIGN:
+ kind = AssignmentExpressionAnd
+ case XORASSIGN:
+ kind = AssignmentExpressionXor
+ case ORASSIGN:
+ kind = AssignmentExpressionOr
+ default:
+ return &AssignmentExpression{Case: AssignmentExpressionCond, ConditionalExpression: ce, lexicalScope: p.declScope}
+ }
+
+ t := p.shift()
+ return &AssignmentExpression{Case: kind, UnaryExpression: cast.UnaryExpression, Token: t, AssignmentExpression: p.assignmentExpression(), lexicalScope: p.declScope}
+}
+
+// [0], 6.5.17 Comma operator
+//
+// expression:
+// assignment-expression
+// expression , assignment-expression
+func (p *parser) expression() (r *Expression) {
+ r = &Expression{Case: ExpressionAssign, AssignmentExpression: p.assignmentExpression()}
+ for {
+ switch p.rune() {
+ case ',':
+ t := p.shift()
+ r = &Expression{Case: ExpressionComma, Expression: r, Token: t, AssignmentExpression: p.assignmentExpression()}
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.6 Constant expressions
+//
+// constant-expression:
+// conditional-expression
+func (p *parser) constantExpression() (r *ConstantExpression) {
+ return &ConstantExpression{ConditionalExpression: p.conditionalExpression()}
+}
+
+// [0], 6.7 Declarations
+//
+// declaration:
+// declaration-specifiers init-declarator-list_opt attribute-specifier-list_opt ;
+func (p *parser) declaration(ds *DeclarationSpecifiers, d *Declarator) (r *Declaration) {
+ defer func() {
+ if cs := p.block; cs != nil && r != nil {
+ cs.declarations = append(cs.declarations, r)
+ }
+ }()
+
+ if ds == nil {
+ ds = p.declarationSpecifiers(nil, nil)
+ }
+ if ds == noDeclSpecs {
+ ds = nil
+ }
+ if d == nil {
+ switch p.rune() {
+ case ';':
+ p.typedefNameEnabled = true
+ return &Declaration{DeclarationSpecifiers: ds, Token: p.shift()}
+ }
+ }
+
+ list := p.initDeclaratorList(d, ds.typedef())
+ p.typedefNameEnabled = true
+ var t Token
+ switch p.rune() {
+ case ';':
+ t = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &Declaration{DeclarationSpecifiers: ds, InitDeclaratorList: list, Token: t}
+}
+
+// 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
+// attribute-specifier declaration-specifiers_opt
+func (p *parser) declarationSpecifiers(extern, inline *bool) (r *DeclarationSpecifiers) {
+ switch p.rune() {
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL:
+ if extern != nil && p.rune() == EXTERN {
+ *extern = true
+ }
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersStorage, StorageClassSpecifier: p.storageClassSpecifier()}
+ if r.StorageClassSpecifier.Case == StorageClassSpecifierTypedef {
+ r.class = fTypedef
+ }
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF:
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ case CONST, RESTRICT, VOLATILE:
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeQual, TypeQualifier: p.typeQualifier()}
+ case INLINE, NORETURN:
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersFunc, FunctionSpecifier: p.functionSpecifier(inline)}
+ case ALIGNAS:
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersAlignSpec, AlignmentSpecifier: p.alignmentSpecifier()}
+ case ATOMIC:
+ switch p.peek(false) {
+ case '(':
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ default:
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeQual, TypeQualifier: p.typeQualifier()}
+ }
+ case ATTRIBUTE:
+ r = &DeclarationSpecifiers{Case: DeclarationSpecifiersAttribute, AttributeSpecifier: p.attributeSpecifier()}
+ default:
+ p.err("expected declaration-specifiers")
+ return nil
+ }
+ r0 := r
+ for prev := r; ; prev = prev.DeclarationSpecifiers {
+ switch p.rune() {
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL:
+ if extern != nil && p.rune() == EXTERN {
+ *extern = true
+ }
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersStorage, StorageClassSpecifier: p.storageClassSpecifier()}
+ if prev.DeclarationSpecifiers.StorageClassSpecifier.Case == StorageClassSpecifierTypedef {
+ r0.class |= fTypedef
+ }
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF:
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ case CONST, RESTRICT, VOLATILE:
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeQual, TypeQualifier: p.typeQualifier()}
+ case INLINE, NORETURN:
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersFunc, FunctionSpecifier: p.functionSpecifier(inline)}
+ case ALIGNAS:
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersAlignSpec, AlignmentSpecifier: p.alignmentSpecifier()}
+ case ATOMIC:
+ switch p.peek(false) {
+ case '(':
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ default:
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersTypeQual, TypeQualifier: p.typeQualifier()}
+ }
+ case ATTRIBUTE:
+ prev.DeclarationSpecifiers = &DeclarationSpecifiers{Case: DeclarationSpecifiersAttribute, AttributeSpecifier: p.attributeSpecifier()}
+ default:
+ return r
+ }
+ }
+}
+
+// init-declarator-list:
+// init-declarator
+// init-declarator-list , attribute-specifier-list_opt init-declarator
+func (p *parser) initDeclaratorList(d *Declarator, isTypedefName bool) (r *InitDeclaratorList) {
+ r = &InitDeclaratorList{InitDeclarator: p.initDeclarator(d, isTypedefName)}
+ for prev := r; ; prev = prev.InitDeclaratorList {
+ switch p.rune() {
+ case ',':
+ t := p.shift()
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ prev.InitDeclaratorList = &InitDeclaratorList{Token: t, AttributeSpecifierList: attr, InitDeclarator: p.initDeclarator(nil, isTypedefName)}
+ default:
+ return r
+ }
+ }
+}
+
+func (p *parser) attributeSpecifierListOpt() (r *AttributeSpecifierList) {
+ if p.rune() == ATTRIBUTE {
+ r = p.attributeSpecifierList()
+ }
+ return r
+}
+
+// init-declarator:
+// declarator attribute-specifier-list_opt
+// declarator attribute-specifier-list_opt = initializer
+func (p *parser) initDeclarator(d *Declarator, isTypedefName bool) *InitDeclarator {
+ if d == nil {
+ d = p.declarator(true, isTypedefName, nil)
+ }
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ switch p.rune() {
+ case '=':
+ t := p.shift()
+ return &InitDeclarator{Case: InitDeclaratorInit, Declarator: d, AttributeSpecifierList: attr, Token: t, Initializer: p.initializer(nil)}
+ }
+
+ return &InitDeclarator{Case: InitDeclaratorDecl, Declarator: d, AttributeSpecifierList: attr}
+}
+
+// [0], 6.7.1 Storage-class specifiers
+//
+// storage-class-specifier:
+// typedef
+// extern
+// static
+// auto
+// register
+func (p *parser) storageClassSpecifier() *StorageClassSpecifier {
+ var kind StorageClassSpecifierCase
+ switch p.rune() {
+ case TYPEDEF:
+ kind = StorageClassSpecifierTypedef
+ case EXTERN:
+ kind = StorageClassSpecifierExtern
+ case STATIC:
+ kind = StorageClassSpecifierStatic
+ case AUTO:
+ kind = StorageClassSpecifierAuto
+ case REGISTER:
+ kind = StorageClassSpecifierRegister
+ case THREADLOCAL:
+ kind = StorageClassSpecifierThreadLocal
+ default:
+ p.err("expected storage-class-specifier")
+ return nil
+ }
+
+ return &StorageClassSpecifier{Case: kind, Token: p.shift()}
+}
+
+// [0], 6.7.2 Type specifiers
+//
+// type-specifier:
+// void
+// char
+// short
+// int
+// long
+// float
+// __fp16
+// __float80
+// double
+// signed
+// unsigned
+// _Bool
+// _Complex
+// _Float128
+// struct-or-union-specifier
+// enum-specifier
+// typedef-name
+// typeof ( expression )
+// typeof ( type-name )
+// atomic-type-specifier
+// _Frac
+// _Sat
+// _Accum
+// _Float32
+func (p *parser) typeSpecifier() *TypeSpecifier {
+ var kind TypeSpecifierCase
+ switch p.rune() {
+ case VOID:
+ kind = TypeSpecifierVoid
+ case CHAR:
+ kind = TypeSpecifierChar
+ case SHORT:
+ kind = TypeSpecifierShort
+ case INT:
+ kind = TypeSpecifierInt
+ case INT8:
+ kind = TypeSpecifierInt8
+ case INT16:
+ kind = TypeSpecifierInt16
+ case INT32:
+ kind = TypeSpecifierInt32
+ case INT64:
+ kind = TypeSpecifierInt64
+ case INT128:
+ kind = TypeSpecifierInt128
+ case LONG:
+ kind = TypeSpecifierLong
+ case FLOAT:
+ kind = TypeSpecifierFloat
+ case FLOAT16:
+ kind = TypeSpecifierFloat16
+ case FLOAT80:
+ kind = TypeSpecifierFloat80
+ case FLOAT32:
+ kind = TypeSpecifierFloat32
+ case FLOAT32X:
+ kind = TypeSpecifierFloat32x
+ case FLOAT64:
+ kind = TypeSpecifierFloat64
+ case FLOAT64X:
+ kind = TypeSpecifierFloat64x
+ case FLOAT128:
+ kind = TypeSpecifierFloat128
+ case DECIMAL32:
+ kind = TypeSpecifierDecimal32
+ case DECIMAL64:
+ kind = TypeSpecifierDecimal64
+ case DECIMAL128:
+ kind = TypeSpecifierDecimal128
+ case DOUBLE:
+ kind = TypeSpecifierDouble
+ case SIGNED:
+ kind = TypeSpecifierSigned
+ case UNSIGNED:
+ kind = TypeSpecifierUnsigned
+ case BOOL:
+ kind = TypeSpecifierBool
+ case COMPLEX:
+ kind = TypeSpecifierComplex
+ case FRACT:
+ kind = TypeSpecifierFract
+ case SAT:
+ kind = TypeSpecifierSat
+ case ACCUM:
+ kind = TypeSpecifierAccum
+ case TYPEDEFNAME:
+ kind = TypeSpecifierTypedefName
+ case STRUCT, UNION:
+ r := &TypeSpecifier{Case: TypeSpecifierStructOrUnion, StructOrUnionSpecifier: p.structOrUnionSpecifier()}
+ p.typedefNameEnabled = false
+ return r
+ case ENUM:
+ r := &TypeSpecifier{Case: TypeSpecifierEnum, EnumSpecifier: p.enumSpecifier()}
+ p.typedefNameEnabled = false
+ return r
+ case TYPEOF:
+ var t, t2, t3 Token
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ switch p.rune() {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE,
+ ALIGNAS:
+ typ := p.typeName()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &TypeSpecifier{Case: TypeSpecifierTypeofType, Token: t, Token2: t2, TypeName: typ, Token3: t3}
+ default:
+ e := p.expression()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &TypeSpecifier{Case: TypeSpecifierTypeofExpr, Token: t, Token2: t2, Expression: e, Token3: t3}
+ }
+ case ATOMIC:
+ return &TypeSpecifier{Case: TypeSpecifierAtomic, AtomicTypeSpecifier: p.atomicTypeSpecifier()}
+ default:
+ p.err("expected type-specifier")
+ return nil
+ }
+
+ p.typedefNameEnabled = false
+ return &TypeSpecifier{Case: kind, Token: p.shift(), resolvedIn: p.resolvedIn}
+}
+
+// [0], 6.7.2.1 Structure and union specifiers
+//
+// struct-or-union-specifier:
+// struct-or-union attribute-specifier-list_opt identifier_opt { struct-declaration-list }
+// struct-or-union attribute-specifier-list_opt identifier
+func (p *parser) structOrUnionSpecifier() *StructOrUnionSpecifier {
+ switch p.rune() {
+ case STRUCT, UNION:
+ default:
+ p.err("expected struct-or-union-specifier")
+ return nil
+ }
+
+ sou := p.structOrUnion()
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ var t, t2, t3 Token
+ switch p.rune() {
+ case IDENTIFIER:
+ t = p.shift()
+ if p.rune() != '{' {
+ return &StructOrUnionSpecifier{Case: StructOrUnionSpecifierTag, StructOrUnion: sou, AttributeSpecifierList: attr, Token: t, lexicalScope: p.declScope}
+ }
+
+ fallthrough
+ case '{':
+ maxAlign := p.ctx.maxAlign
+ p.openScope(true)
+ p.typedefNameEnabled = true
+ p.resolveScope = p.declScope.Parent()
+ t2 = p.shift()
+ var list *StructDeclarationList
+ switch p.peek(false) {
+ case '}':
+ if p.ctx.cfg.RejectEmptyStructs {
+ p.err("expected struct-declarator-list")
+ }
+ default:
+ list = p.structDeclarationList()
+ }
+ p.closeScope()
+ switch p.rune() {
+ case '}':
+ t3 = p.shift()
+ default:
+ p.err("expected }")
+ }
+ r := &StructOrUnionSpecifier{Case: StructOrUnionSpecifierDef, StructOrUnion: sou, AttributeSpecifierList: attr, Token: t, Token2: t2, StructDeclarationList: list, Token3: t3, lexicalScope: p.declScope, maxAlign: maxAlign}
+ if t.Value != 0 {
+ p.declScope.declare(t.Value, r)
+ }
+ return r
+ default:
+ p.err("expected identifier or {")
+ return nil
+ }
+}
+
+// struct-or-union:
+// struct
+// union
+func (p *parser) structOrUnion() *StructOrUnion {
+ var kind StructOrUnionCase
+ switch p.rune() {
+ case STRUCT:
+ kind = StructOrUnionStruct
+ case UNION:
+ kind = StructOrUnionUnion
+ default:
+ p.err("expected struct-or-union")
+ return nil
+ }
+
+ p.typedefNameEnabled = false
+ return &StructOrUnion{Case: kind, Token: p.shift()}
+}
+
+// struct-declaration-list:
+// struct-declaration
+// struct-declaration-list struct-declaration
+func (p *parser) structDeclarationList() (r *StructDeclarationList) {
+ r = &StructDeclarationList{StructDeclaration: p.structDeclaration()}
+ for prev := r; ; prev = prev.StructDeclarationList {
+ switch p.rune() {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE,
+ ALIGNAS:
+ prev.StructDeclarationList = &StructDeclarationList{StructDeclaration: p.structDeclaration()}
+ case ';':
+ p.shift()
+ if p.ctx.cfg.RejectEmptyFields {
+ p.err("expected struct-declaration")
+ }
+ default:
+ return r
+ }
+ }
+}
+
+// struct-declaration:
+// specifier-qualifier-list struct-declarator-list ;
+func (p *parser) structDeclaration() (r *StructDeclaration) {
+ if p.rune() == ';' {
+ if p.ctx.cfg.RejectEmptyStructDeclaration {
+ p.err("expected struct-declaration")
+ }
+ return &StructDeclaration{Empty: true, Token: p.shift()}
+ }
+ sql := p.specifierQualifierList()
+ r = &StructDeclaration{SpecifierQualifierList: sql}
+ switch p.rune() {
+ case ';':
+ if p.ctx.cfg.RejectAnonymousFields {
+ p.err("expected struct-declarator")
+ }
+ default:
+ r.StructDeclaratorList = p.structDeclaratorList(r)
+ }
+ var t Token
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case '}':
+ if p.ctx.cfg.RejectMissingFinalStructFieldSemicolon {
+ p.err0(false, "expected ;")
+ }
+ case ';':
+ t = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ r.Token = t
+ return r
+}
+
+// specifier-qualifier-list:
+// type-specifier specifier-qualifier-list_opt
+// type-qualifier specifier-qualifier-list_opt
+// alignment-specifier-qualifier-list_opt
+func (p *parser) specifierQualifierList() (r *SpecifierQualifierList) {
+ switch p.rune() {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF:
+ r = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ case CONST, RESTRICT, VOLATILE:
+ r = &SpecifierQualifierList{Case: SpecifierQualifierListTypeQual, TypeQualifier: p.typeQualifier()}
+ case ALIGNAS:
+ r = &SpecifierQualifierList{Case: SpecifierQualifierListAlignSpec, AlignmentSpecifier: p.alignmentSpecifier()}
+ case ATOMIC:
+ switch p.peek(false) {
+ case '(':
+ r = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ default:
+ r = &SpecifierQualifierList{Case: SpecifierQualifierListTypeQual, TypeQualifier: p.typeQualifier()}
+ }
+ case ATTRIBUTE:
+ r = &SpecifierQualifierList{Case: SpecifierQualifierListAttribute, AttributeSpecifier: p.attributeSpecifier()}
+ default:
+ p.err("expected specifier-qualifier-list: %s", tokName(p.rune()))
+ return nil
+ }
+ for prev := r; ; prev = prev.SpecifierQualifierList {
+ switch p.rune() {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF:
+ prev.SpecifierQualifierList = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ case CONST, RESTRICT, VOLATILE:
+ prev.SpecifierQualifierList = &SpecifierQualifierList{Case: SpecifierQualifierListTypeQual, TypeQualifier: p.typeQualifier()}
+ case ALIGNAS:
+ prev.SpecifierQualifierList = &SpecifierQualifierList{Case: SpecifierQualifierListAlignSpec, AlignmentSpecifier: p.alignmentSpecifier()}
+ case ATOMIC:
+ switch p.peek(false) {
+ case '(':
+ prev.SpecifierQualifierList = &SpecifierQualifierList{Case: SpecifierQualifierListTypeSpec, TypeSpecifier: p.typeSpecifier()}
+ default:
+ prev.SpecifierQualifierList = &SpecifierQualifierList{Case: SpecifierQualifierListTypeQual, TypeQualifier: p.typeQualifier()}
+ }
+ case ATTRIBUTE:
+ prev.SpecifierQualifierList = &SpecifierQualifierList{Case: SpecifierQualifierListAttribute, AttributeSpecifier: p.attributeSpecifier()}
+ default:
+ return r
+ }
+ }
+}
+
+// struct-declarator-list:
+// struct-declarator
+// struct-declarator-list , struct-declarator
+func (p *parser) structDeclaratorList(decl *StructDeclaration) (r *StructDeclaratorList) {
+ r = &StructDeclaratorList{StructDeclarator: p.structDeclarator(decl)}
+ for prev := r; ; prev = prev.StructDeclaratorList {
+ switch p.rune() {
+ case ',':
+ t := p.shift()
+ prev.StructDeclaratorList = &StructDeclaratorList{Token: t, StructDeclarator: p.structDeclarator(decl)}
+ default:
+ return r
+ }
+ }
+}
+
+// struct-declarator:
+// declarator
+// declarator_opt : constant-expression attribute-specifier-list_opt
+func (p *parser) structDeclarator(decl *StructDeclaration) (r *StructDeclarator) {
+ var d *Declarator
+ if p.rune() != ':' {
+ d = p.declarator(false, false, nil)
+ }
+
+ switch p.rune() {
+ case ':':
+ t := p.shift()
+ r = &StructDeclarator{Case: StructDeclaratorBitField, Declarator: d, Token: t, ConstantExpression: p.constantExpression(), decl: decl}
+ r.AttributeSpecifierList = p.attributeSpecifierListOpt()
+ // if r.AttributeSpecifierList != nil {
+ // trc("%v: ATTRS", r.AttributeSpecifierList.Position())
+ // }
+ default:
+ r = &StructDeclarator{Case: StructDeclaratorDecl, Declarator: d, decl: decl}
+ }
+ if d != nil {
+ p.declScope.declare(d.Name(), r)
+ }
+ return r
+}
+
+// [0], 6.7.2.2 Enumeration specifiers
+//
+// enum-specifier:
+// enum attribute-specifier-list_opt identifier_opt { enumerator-list }
+// enum attribute-specifier-list_opt identifier_opt { enumerator-list , }
+// enum attribute-specifier-list_opt identifier
+func (p *parser) enumSpecifier() *EnumSpecifier {
+ if p.rune() != ENUM {
+ p.err("expected enum")
+ return nil
+ }
+
+ var t, t2, t3, t4, t5 Token
+ p.typedefNameEnabled = false
+ t = p.shift()
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ if p.rune() == IDENTIFIER {
+ t2 = p.shift()
+ if p.rune() != '{' {
+ return &EnumSpecifier{Case: EnumSpecifierTag, AttributeSpecifierList: attr, Token: t, Token2: t2, lexicalScope: p.declScope}
+ }
+ }
+
+ if p.rune() != '{' {
+ p.err("expected identifier or {")
+ return nil
+ }
+
+ p.typedefNameEnabled = false
+ t3 = p.shift()
+ list := p.enumeratorList()
+ if p.rune() == ',' {
+ t4 = p.shift()
+ }
+
+ switch p.rune() {
+ case '}':
+ t5 = p.shift()
+ default:
+ p.err("expected }")
+ }
+ r := &EnumSpecifier{Case: EnumSpecifierDef, AttributeSpecifierList: attr, Token: t, Token2: t2, Token3: t3, EnumeratorList: list, Token4: t4, Token5: t5, lexicalScope: p.declScope}
+ if t2.Value != 0 {
+ p.declScope.declare(t2.Value, r)
+ }
+ return r
+}
+
+// enumerator-list:
+// enumerator
+// enumerator-list , enumerator
+func (p *parser) enumeratorList() *EnumeratorList {
+ r := &EnumeratorList{Enumerator: p.enumerator()}
+ for prev := r; ; prev = prev.EnumeratorList {
+ switch p.rune() {
+ case ',':
+ if p.peek(false) == '}' {
+ return r
+ }
+
+ t := p.shift()
+ prev.EnumeratorList = &EnumeratorList{Token: t, Enumerator: p.enumerator()}
+ default:
+ return r
+ }
+ }
+}
+
+// enumerator:
+// enumeration-constant attribute-specifier-list_opt
+// enumeration-constant attribute-specifier-list_opt = constant-expression
+func (p *parser) enumerator() (r *Enumerator) {
+ if p.rune() != IDENTIFIER {
+ p.err("expected enumeration-constant")
+ return nil
+ }
+
+ t := p.shift()
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ if p.rune() != '=' {
+ r = &Enumerator{Case: EnumeratorIdent, Token: t, AttributeSpecifierList: attr, lexicalScope: p.declScope}
+ p.declScope.declare(t.Value, r)
+ return r
+ }
+
+ t2 := p.shift()
+ r = &Enumerator{Case: EnumeratorExpr, Token: t, AttributeSpecifierList: attr, Token2: t2, ConstantExpression: p.constantExpression(), lexicalScope: p.declScope}
+ p.declScope.declare(t.Value, r)
+ return r
+}
+
+// [2], 6.7.2.4 Atomic type specifiers
+//
+// atomic-type-specifier:
+// _Atomic ( type-name )
+func (p *parser) atomicTypeSpecifier() *AtomicTypeSpecifier {
+ if p.rune() != ATOMIC {
+ p.err("expected _Atomic")
+ return nil
+ }
+
+ t := p.shift()
+ var t2, t3 Token
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ typ := p.typeName()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AtomicTypeSpecifier{Token: t, Token2: t2, TypeName: typ, Token3: t3}
+}
+
+// [0], 6.7.3 Type qualifiers
+//
+// type-qualifier:
+// const
+// restrict
+// volatile
+// _Atomic
+func (p *parser) typeQualifier() *TypeQualifier {
+ switch p.rune() {
+ case CONST:
+ return &TypeQualifier{Case: TypeQualifierConst, Token: p.shift()}
+ case RESTRICT:
+ return &TypeQualifier{Case: TypeQualifierRestrict, Token: p.shift()}
+ case VOLATILE:
+ return &TypeQualifier{Case: TypeQualifierVolatile, Token: p.shift()}
+ case ATOMIC:
+ return &TypeQualifier{Case: TypeQualifierAtomic, Token: p.shift()}
+ default:
+ p.err("expected type-qualifier")
+ return nil
+ }
+}
+
+// [0], 6.7.4 Function specifiers
+//
+// function-specifier:
+// inline
+// _Noreturn
+func (p *parser) functionSpecifier(inline *bool) *FunctionSpecifier {
+ switch p.rune() {
+ case INLINE:
+ if inline != nil {
+ *inline = true
+ }
+ return &FunctionSpecifier{Case: FunctionSpecifierInline, Token: p.shift()}
+ case NORETURN:
+ return &FunctionSpecifier{Case: FunctionSpecifierNoreturn, Token: p.shift()}
+ default:
+ p.err("expected function-specifier")
+ return nil
+ }
+}
+
+// [0], 6.7.5 Declarators
+//
+// declarator:
+// pointer_opt direct-declarator attribute-specifier-list_opt
+func (p *parser) declarator(declare, isTypedefName bool, ptr *Pointer) *Declarator {
+ if ptr == nil && (p.rune() == '*' || p.rune() == '^') {
+ ptr = p.pointer()
+ }
+ r := &Declarator{IsTypedefName: isTypedefName, Pointer: ptr, DirectDeclarator: p.directDeclarator(nil)}
+ r.AttributeSpecifierList = p.attributeSpecifierListOpt()
+ // if r.AttributeSpecifierList != nil {
+ // trc("%v: ATTRS", r.AttributeSpecifierList.Position())
+ // }
+ if declare {
+ p.declScope.declare(r.Name(), r)
+ }
+ return r
+}
+
+// [2], 6.7.5 Alignment specifier
+//
+// alignment-specifier:
+// _Alignas ( type-name )
+// _Alignas ( constant-expression )
+func (p *parser) alignmentSpecifier() *AlignmentSpecifier {
+ if p.rune() != ALIGNAS {
+ p.err("expected _Alignas")
+ return nil
+ }
+
+ t := p.shift()
+ var t2, t3 Token
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ switch p.rune() {
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE,
+ ALIGNAS:
+ typ := p.typeName()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AlignmentSpecifier{Case: AlignmentSpecifierAlignasType, Token: t, Token2: t2, TypeName: typ, Token3: t3}
+ default:
+ e := p.constantExpression()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AlignmentSpecifier{Case: AlignmentSpecifierAlignasExpr, Token: t, Token2: t2, ConstantExpression: e, Token3: t3}
+ }
+}
+
+// direct-declarator:
+// identifier asm_opt
+// ( attribute-specifier-list_opt 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 )
+// direct-declarator ( identifier-list_opt )
+func (p *parser) directDeclarator(d *DirectDeclarator) (r *DirectDeclarator) {
+ switch {
+ case d != nil:
+ r = d
+ default:
+ switch p.rune() {
+ case IDENTIFIER:
+ t := p.shift()
+ var a *Asm
+ if p.rune() == ASM {
+ a = p.asm()
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorIdent, Token: t, Asm: a, lexicalScope: p.declScope}
+ case '(':
+ t := p.shift()
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ d := p.declarator(false, false, nil)
+ var t2 Token
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorDecl, Token: t, AttributeSpecifierList: attr, Declarator: d, Token2: t2, lexicalScope: p.declScope}
+ default:
+ p.err("expected direct-declarator")
+ return nil
+ }
+ }
+
+ var t, t2, t3 Token
+ for {
+ var e *AssignmentExpression
+ switch p.rune() {
+ case '[':
+ t = p.shift()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: t, Token2: t2, lexicalScope: p.declScope}
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC: // type-qualifier
+ list := p.typeQualifierList()
+ switch p.rune() {
+ case STATIC:
+ t2 = p.shift()
+ e = p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorArrStatic, DirectDeclarator: r, Token: t, TypeQualifiers: list, Token2: t2, AssignmentExpression: e, Token3: t3, lexicalScope: p.declScope}
+ case ']':
+ r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: t, TypeQualifiers: list, Token2: p.shift(), lexicalScope: p.declScope}
+ case '*':
+ switch p.peek(false) {
+ case ']':
+ t2 = p.shift()
+ r = &DirectDeclarator{Case: DirectDeclaratorStar, DirectDeclarator: r, Token: t, TypeQualifiers: list, Token2: t2, Token3: p.shift(), lexicalScope: p.declScope}
+ default:
+ e = p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: t, TypeQualifiers: list, AssignmentExpression: e, Token2: t2, lexicalScope: p.declScope}
+ }
+ default:
+ e = p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: t, TypeQualifiers: list, AssignmentExpression: e, Token2: t2, lexicalScope: p.declScope}
+ }
+ case STATIC:
+ t2 := p.shift()
+ var list *TypeQualifiers
+ switch p.peek(false) {
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list = p.typeQualifierList()
+ }
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorStaticArr, DirectDeclarator: r, Token: t, Token2: t2, TypeQualifiers: list, AssignmentExpression: e, Token3: t3, lexicalScope: p.declScope}
+ case '*':
+ if p.peek(false) == ']' {
+ t2 = p.shift()
+ r = &DirectDeclarator{Case: DirectDeclaratorStar, DirectDeclarator: r, Token: t, Token2: t2, Token3: p.shift(), lexicalScope: p.declScope}
+ break
+ }
+
+ fallthrough
+ default:
+ e = p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorArr, DirectDeclarator: r, Token: t, AssignmentExpression: e, Token2: t2, lexicalScope: p.declScope}
+ }
+ case '(':
+ p.openScope(false)
+ p.typedefNameEnabled = true
+ t = p.shift()
+ paramScope := p.declScope
+ switch p.rune() {
+ case IDENTIFIER:
+ list := p.identifierList()
+ p.closeScope()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorFuncIdent, DirectDeclarator: r, Token: t, IdentifierList: list, Token2: t2, paramScope: paramScope, lexicalScope: p.declScope}
+ case ')':
+ p.closeScope()
+ p.typedefNameEnabled = true
+ r = &DirectDeclarator{Case: DirectDeclaratorFuncIdent, DirectDeclarator: r, Token: t, Token2: p.shift(), paramScope: paramScope, lexicalScope: p.declScope}
+ default:
+ list := p.parameterTypeList()
+ p.closeScope()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &DirectDeclarator{Case: DirectDeclaratorFuncParam, DirectDeclarator: r, Token: t, ParameterTypeList: list, Token2: t2, paramScope: paramScope, lexicalScope: p.declScope}
+ }
+ default:
+ return r
+ }
+ }
+}
+
+// pointer:
+// * type-qualifier-list_opt
+// * type-qualifier-list_opt pointer
+// ^ type-qualifier-list_opt
+func (p *parser) pointer() (r *Pointer) {
+ if p.rune() == '^' {
+ t := p.shift()
+ var list *TypeQualifiers
+ switch p.rune() {
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list = p.typeQualifierList()
+ }
+
+ return &Pointer{Case: PointerBlock, Token: t, TypeQualifiers: list}
+ }
+
+ if p.rune() != '*' {
+ p.err("expected * or ^")
+ return nil
+ }
+
+ t := p.shift()
+ var list *TypeQualifiers
+ switch p.rune() {
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list = p.typeQualifierList()
+ }
+
+ switch p.rune() {
+ case '*':
+ return &Pointer{Case: PointerPtr, Token: t, TypeQualifiers: list, Pointer: p.pointer()}
+ default:
+ return &Pointer{Case: PointerTypeQual, Token: t, TypeQualifiers: list}
+ }
+}
+
+// type-qualifier-list:
+// type-qualifier
+// attribute-specifier
+// type-qualifier-list type-qualifier
+// type-qualifier-list attribute-specifier
+func (p *parser) typeQualifierList() (r *TypeQualifiers) {
+ switch p.rune() {
+ case ATTRIBUTE:
+ r = &TypeQualifiers{Case: TypeQualifiersAttribute, AttributeSpecifier: p.attributeSpecifier()}
+ default:
+ r = &TypeQualifiers{Case: TypeQualifiersTypeQual, TypeQualifier: p.typeQualifier()}
+ }
+ for prev := r; ; prev = prev.TypeQualifiers {
+ switch p.rune() {
+ case ATTRIBUTE:
+ prev.TypeQualifiers = &TypeQualifiers{Case: TypeQualifiersAttribute, AttributeSpecifier: p.attributeSpecifier()}
+ case CONST, RESTRICT, VOLATILE, ATOMIC:
+ prev.TypeQualifiers = &TypeQualifiers{TypeQualifier: p.typeQualifier()}
+ default:
+ return r
+ }
+ }
+}
+
+// parameter-type-list:
+// parameter-list
+// parameter-list , ...
+func (p *parser) parameterTypeList() *ParameterTypeList {
+ list := p.parameterList()
+ switch p.rune() {
+ case ',':
+ t := p.shift()
+ var t2 Token
+ switch p.rune() {
+ case DDD:
+ t2 = p.shift()
+ default:
+ p.err("expected ...")
+ }
+ return &ParameterTypeList{Case: ParameterTypeListVar, ParameterList: list, Token: t, Token2: t2}
+ default:
+ return &ParameterTypeList{Case: ParameterTypeListList, ParameterList: list}
+ }
+}
+
+// parameter-list:
+// parameter-declaration
+// parameter-list , parameter-declaration
+func (p *parser) parameterList() (r *ParameterList) {
+ r = &ParameterList{ParameterDeclaration: p.parameterDeclaration()}
+ for prev := r; ; prev = prev.ParameterList {
+ switch p.rune() {
+ case ';':
+ if p.ctx.cfg.RejectParamSemicolon {
+ p.err0(false, "expected ,")
+ }
+ fallthrough
+ case ',':
+ if p.peek(false) == DDD {
+ return r
+ }
+
+ p.typedefNameEnabled = true
+ t := p.shift()
+ prev.ParameterList = &ParameterList{Token: t, ParameterDeclaration: p.parameterDeclaration()}
+ default:
+ return r
+ }
+ }
+}
+
+// parameter-declaration:
+// declaration-specifiers declarator attribute-specifier-list_opt
+// declaration-specifiers abstract-declarator_opt
+func (p *parser) parameterDeclaration() *ParameterDeclaration {
+ ds := p.declarationSpecifiers(nil, nil)
+ switch p.rune() {
+ case ',', ')':
+ r := &ParameterDeclaration{Case: ParameterDeclarationAbstract, DeclarationSpecifiers: ds}
+ return r
+ default:
+ switch x := p.declaratorOrAbstractDeclarator(ds.typedef()).(type) {
+ case *AbstractDeclarator:
+ return &ParameterDeclaration{Case: ParameterDeclarationAbstract, DeclarationSpecifiers: ds, AbstractDeclarator: x}
+ case *Declarator:
+ p.declScope.declare(x.Name(), x)
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ return &ParameterDeclaration{Case: ParameterDeclarationDecl, DeclarationSpecifiers: ds, Declarator: x, AttributeSpecifierList: attr}
+ default:
+ panic(internalError())
+ }
+ }
+}
+
+func (p *parser) declaratorOrAbstractDeclarator(isTypedefName bool) (r Node) {
+ var ptr *Pointer
+ switch p.rune() {
+ case '*', '^':
+ ptr = p.pointer()
+ }
+ switch p.rune() {
+ case IDENTIFIER:
+ return p.declarator(false, isTypedefName, ptr)
+ case '[':
+ return p.abstractDeclarator(ptr)
+ case '(':
+ switch p.peek(true) {
+ case ')':
+ t := p.shift()
+ t2 := p.shift()
+ return &AbstractDeclarator{
+ Case: AbstractDeclaratorDecl,
+ Pointer: ptr,
+ DirectAbstractDeclarator: p.directAbstractDeclarator(
+ &DirectAbstractDeclarator{
+ Case: DirectAbstractDeclaratorFunc,
+ Token: t,
+ Token2: t2,
+ },
+ ),
+ }
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL,
+ VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ CONST, RESTRICT, VOLATILE,
+ INLINE, NORETURN, ATTRIBUTE,
+ ALIGNAS:
+ p.openScope(false)
+ paramScope := p.declScope
+ p.typedefNameEnabled = true
+ t := p.shift()
+ list := p.parameterTypeList()
+ p.closeScope()
+ p.typedefNameEnabled = true
+ var t2 Token
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AbstractDeclarator{
+ Case: AbstractDeclaratorDecl,
+ Pointer: ptr,
+ DirectAbstractDeclarator: p.directAbstractDeclarator(
+ &DirectAbstractDeclarator{
+ Case: DirectAbstractDeclaratorFunc,
+ Token: t,
+ ParameterTypeList: list,
+ Token2: t2,
+ paramScope: paramScope,
+ },
+ ),
+ }
+ }
+
+ t := p.shift()
+ switch x := p.declaratorOrAbstractDeclarator(isTypedefName).(type) {
+ case *AbstractDeclarator:
+ var t2 Token
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AbstractDeclarator{
+ Case: AbstractDeclaratorDecl,
+ Pointer: ptr,
+ DirectAbstractDeclarator: p.directAbstractDeclarator(
+ &DirectAbstractDeclarator{
+ Case: DirectAbstractDeclaratorDecl,
+ Token: t,
+ AbstractDeclarator: x,
+ Token2: t2,
+ },
+ ),
+ }
+ case *Declarator:
+ var t2 Token
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &Declarator{
+ Pointer: ptr,
+ DirectDeclarator: p.directDeclarator(
+ &DirectDeclarator{
+ Case: DirectDeclaratorDecl,
+ Token: t,
+ Declarator: x,
+ Token2: t2,
+ },
+ ),
+ }
+ default:
+ panic(internalError())
+ }
+ case ')', ',':
+ return p.abstractDeclarator(ptr)
+ default:
+ p.err("unexpected %s", p.tok.Value)
+ return p.abstractDeclarator(ptr)
+ }
+}
+
+// identifier-list:
+// identifier
+// identifier-list , identifier
+func (p *parser) identifierList() (r *IdentifierList) {
+ switch p.rune() {
+ case IDENTIFIER:
+ r = &IdentifierList{Token: p.shift(), lexicalScope: p.declScope}
+ default:
+ p.err("expected identifier")
+ return nil
+ }
+
+ for prev := r; p.rune() == ','; prev = prev.IdentifierList {
+ t := p.shift()
+ var t2 Token
+ switch p.rune() {
+ case IDENTIFIER:
+ t2 = p.shift()
+ default:
+ p.err("expected identifier")
+ }
+ prev.IdentifierList = &IdentifierList{Token: t, Token2: t2, lexicalScope: p.declScope}
+ }
+ return r
+}
+
+// [0], 6.7.6 Type names
+//
+// type-name:
+// specifier-qualifier-list abstract-declarator_opt
+func (p *parser) typeName() *TypeName {
+ p.typedefNameEnabled = true
+ list := p.specifierQualifierList()
+ switch p.rune() {
+ case ')', ',':
+ return &TypeName{SpecifierQualifierList: list}
+ case '*', '(', '[':
+ return &TypeName{SpecifierQualifierList: list, AbstractDeclarator: p.abstractDeclarator(nil)}
+ default:
+ p.err("expected ) or * or ( or [ or ,")
+ return &TypeName{SpecifierQualifierList: list}
+ }
+}
+
+// abstract-declarator:
+// pointer
+// pointer_opt direct-abstract-declarator
+func (p *parser) abstractDeclarator(ptr *Pointer) *AbstractDeclarator {
+ if ptr == nil && (p.rune() == '*' || p.rune() == '^') {
+ ptr = p.pointer()
+ }
+ switch p.rune() {
+ case '[', '(':
+ return &AbstractDeclarator{Case: AbstractDeclaratorDecl, Pointer: ptr, DirectAbstractDeclarator: p.directAbstractDeclarator(nil)}
+ default:
+ return &AbstractDeclarator{Case: AbstractDeclaratorPtr, Pointer: ptr}
+ }
+}
+
+// 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(d *DirectAbstractDeclarator) (r *DirectAbstractDeclarator) {
+ var t, t2, t3 Token
+ switch {
+ case d != nil:
+ r = d
+ default:
+ switch p.rune() {
+ case '[':
+ t = p.shift()
+ switch p.rune() {
+ case '*':
+ t2 = p.shift()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArrStar, Token: t, Token2: t2, Token3: t3}
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list := p.typeQualifierList()
+ switch p.rune() {
+ case STATIC:
+ t2 = p.shift()
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArrStatic, Token: t, TypeQualifiers: list, Token2: t2, AssignmentExpression: e, Token3: t3}
+ default:
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: t, TypeQualifiers: list, AssignmentExpression: e, Token2: t2}
+ }
+ case STATIC:
+ t2 = p.shift()
+ var list *TypeQualifiers
+ switch p.rune() {
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list = p.typeQualifierList()
+ }
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorStaticArr, Token: t, Token2: t2, TypeQualifiers: list, AssignmentExpression: e, Token3: t3}
+ case ']':
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: t, Token2: p.shift()}
+ default:
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, Token: t, AssignmentExpression: e, Token2: t2}
+ }
+ case '(':
+ switch p.peek(true) {
+ case ')':
+ t := p.shift()
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, Token: t, Token2: p.shift()}
+ case VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ ATTRIBUTE, CONST, RESTRICT, VOLATILE,
+ ALIGNAS:
+ p.openScope(false)
+ paramScope := p.declScope
+ p.typedefNameEnabled = true
+ t = p.shift()
+ list := p.parameterTypeList()
+ p.closeScope()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, Token: t, ParameterTypeList: list, Token2: t2, paramScope: paramScope}
+ default:
+ p.openScope(false)
+ paramScope := p.declScope
+ p.typedefNameEnabled = true
+ t = p.shift()
+ d := p.abstractDeclarator(nil)
+ p.closeScope()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorDecl, Token: t, AbstractDeclarator: d, Token2: t2, paramScope: paramScope}
+ }
+ default:
+ panic(internalError())
+ }
+ }
+
+ for {
+ switch p.rune() {
+ case '(':
+ if p.peek(false) == ')' {
+ t = p.shift()
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, DirectAbstractDeclarator: r, Token: t, Token2: p.shift()}
+ break
+ }
+
+ p.openScope(false)
+ p.typedefNameEnabled = true
+ t = p.shift()
+ paramScope := p.declScope
+ list := p.parameterTypeList()
+ p.closeScope()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ')':
+ t2 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorFunc, DirectAbstractDeclarator: r, Token: t, ParameterTypeList: list, Token2: t2, paramScope: paramScope}
+ case '[':
+ t = p.shift()
+ switch p.rune() {
+ case '*':
+ t2 = p.shift()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArrStar, DirectAbstractDeclarator: r, Token: t, Token2: t2, Token3: t3}
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list := p.typeQualifierList()
+ switch p.rune() {
+ case STATIC:
+ t2 = p.shift()
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArrStatic, DirectAbstractDeclarator: r, Token: t, TypeQualifiers: list, Token2: t2, AssignmentExpression: e, Token3: t3}
+ default:
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, DirectAbstractDeclarator: r, Token: t, TypeQualifiers: list, AssignmentExpression: e, Token2: t2}
+ }
+ case STATIC:
+ t2 = p.shift()
+ var list *TypeQualifiers
+ switch p.rune() {
+ case ATTRIBUTE, CONST, RESTRICT, VOLATILE, ATOMIC:
+ list = p.typeQualifierList()
+ }
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t3 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorStaticArr, DirectAbstractDeclarator: r, Token: t, Token2: t2, TypeQualifiers: list, AssignmentExpression: e, Token3: t3}
+ case ']':
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, DirectAbstractDeclarator: r, Token: t, Token2: p.shift()}
+ default:
+ e := p.assignmentExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ r = &DirectAbstractDeclarator{Case: DirectAbstractDeclaratorArr, DirectAbstractDeclarator: r, Token: t, AssignmentExpression: e, Token2: t2}
+ }
+ default:
+ return r
+ }
+ }
+}
+
+// [0], 6.7.8 Initialization
+//
+// initializer:
+// assignment-expression
+// { initializer-list }
+// { initializer-list , }
+func (p *parser) initializer(parent *Initializer) *Initializer {
+ switch p.rune() {
+ case '{':
+ t := p.shift()
+ if p.peek(false) == '}' {
+ if p.ctx.cfg.RejectEmptyInitializerList {
+ p.err("expected initializer-list")
+ }
+ return &Initializer{Case: InitializerInitList, Token: t, Token3: p.shift()}
+ }
+
+ r := &Initializer{Case: InitializerInitList, Token: t, parent: parent}
+ r.InitializerList = p.initializerList(r)
+ if p.rune() == ',' {
+ r.Token2 = p.shift()
+ }
+ switch p.rune() {
+ case '}':
+ r.Token3 = p.shift()
+ default:
+ p.err("expected }")
+ }
+ return r
+ default:
+ return &Initializer{Case: InitializerExpr, AssignmentExpression: p.assignmentExpression(), parent: parent}
+ }
+}
+
+// initializer-list:
+// designation_opt initializer
+// initializer-list , designation_opt initializer
+func (p *parser) initializerList(parent *Initializer) (r *InitializerList) {
+ var d *Designation
+ switch p.rune() {
+ case '[', '.':
+ d = p.designation()
+ case IDENTIFIER:
+ if p.peek(false) == ':' {
+ d = p.designation()
+ }
+ }
+ r = &InitializerList{Designation: d, Initializer: p.initializer(parent)}
+ for prev := r; ; prev = prev.InitializerList {
+ switch p.rune() {
+ case ',':
+ t := p.tok
+ prev.Initializer.trailingComma = &t
+ if p.peek(false) == '}' {
+ return r
+ }
+
+ t = p.shift()
+ d = nil
+ switch p.rune() {
+ case '[', '.':
+ d = p.designation()
+ case IDENTIFIER:
+ if p.peek(false) == ':' {
+ d = p.designation()
+ }
+ }
+ prev.InitializerList = &InitializerList{Token: t, Designation: d, Initializer: p.initializer(parent)}
+ default:
+ return r
+ }
+ }
+}
+
+// designation:
+// designator-list =
+func (p *parser) designation() *Designation {
+ var t Token
+ list, colon := p.designatorList()
+ if !colon {
+ switch p.rune() {
+ case '=':
+ t = p.shift()
+ default:
+ p.err("expected =")
+ }
+ }
+ return &Designation{DesignatorList: list, Token: t}
+}
+
+// designator-list:
+// designator
+// designator-list designator
+func (p *parser) designatorList() (r *DesignatorList, colon bool) {
+ d, isCol := p.designator(true)
+ if isCol {
+ return &DesignatorList{Designator: d}, true
+ }
+
+ r = &DesignatorList{Designator: d}
+ for prev := r; ; prev = prev.DesignatorList {
+ switch p.rune() {
+ case '[', '.':
+ d, _ = p.designator(false)
+ prev.DesignatorList = &DesignatorList{Designator: d}
+ default:
+ return r, false
+ }
+ }
+}
+
+// designator:
+// [ constant-expression ]
+// . identifier
+// identifier :
+func (p *parser) designator(acceptCol bool) (*Designator, bool) {
+ var t, t2 Token
+ switch p.rune() {
+ case '[':
+ t = p.shift()
+ e := p.constantExpression()
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ return &Designator{Case: DesignatorIndex, Token: t, ConstantExpression: e, Token2: t2, lexicalScope: p.declScope}, false
+ case '.':
+ t = p.shift()
+ switch p.rune() {
+ case IDENTIFIER:
+ t2 = p.shift()
+ default:
+ p.err("expected identifier")
+ }
+ return &Designator{Case: DesignatorField, Token: t, Token2: t2, lexicalScope: p.declScope}, false
+ case IDENTIFIER:
+ if acceptCol && p.peek(false) == ':' {
+ t = p.shift()
+ return &Designator{Case: DesignatorField2, Token: t, Token2: p.shift(), lexicalScope: p.declScope}, true
+ }
+
+ p.err("expected designator")
+ return nil, false
+ default:
+ p.err("expected [ or .")
+ return nil, false
+ }
+}
+
+// [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() *Statement {
+ switch p.rune() {
+ case IDENTIFIER:
+ if p.peek(false) == ':' {
+ return &Statement{Case: StatementLabeled, LabeledStatement: p.labeledStatement()}
+ }
+
+ return &Statement{Case: StatementExpr, ExpressionStatement: p.expressionStatement()}
+ case '{':
+ return &Statement{Case: StatementCompound, CompoundStatement: p.compoundStatement(nil, nil)}
+ case IF, SWITCH:
+ return &Statement{Case: StatementSelection, SelectionStatement: p.selectionStatement()}
+ case WHILE, DO, FOR:
+ return &Statement{Case: StatementIteration, IterationStatement: p.iterationStatement()}
+ case GOTO, BREAK, CONTINUE, RETURN:
+ return &Statement{Case: StatementJump, JumpStatement: p.jumpStatement()}
+ case CASE, DEFAULT:
+ return &Statement{Case: StatementLabeled, LabeledStatement: p.labeledStatement()}
+ case ASM:
+ return &Statement{Case: StatementAsm, AsmStatement: p.asmStatement()}
+ default:
+ return &Statement{Case: StatementExpr, ExpressionStatement: p.expressionStatement()}
+ }
+}
+
+// [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 r != nil {
+ p.block.labeledStmts = append(p.block.labeledStmts, r)
+ }
+ }()
+
+ var t, t2, t3 Token
+ switch p.rune() {
+ case IDENTIFIER:
+ t = p.shift()
+ switch p.rune() {
+ case ':':
+ t2 = p.shift()
+ default:
+ p.err("expected :")
+ return nil
+ }
+
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ p.block.hasLabel()
+ r = &LabeledStatement{
+ Case: LabeledStatementLabel, Token: t, Token2: t2, AttributeSpecifierList: attr,
+ Statement: p.statement(), lexicalScope: p.declScope, block: p.block,
+ }
+ p.declScope.declare(t.Value, r)
+ return r
+ case CASE:
+ if p.switches == 0 {
+ p.err("case label not within a switch statement")
+ }
+ t = p.shift()
+ e := p.constantExpression()
+ switch p.rune() {
+ case DDD:
+ if p.ctx.cfg.RejectCaseRange {
+ p.err0(false, "expected :")
+ }
+ t2 = p.shift()
+ e2 := p.constantExpression()
+ switch p.rune() {
+ case ':':
+ t3 = p.shift()
+ default:
+ p.err("expected :")
+ }
+ return &LabeledStatement{
+ Case: LabeledStatementRange, Token: t, ConstantExpression: e,
+ Token2: t2, ConstantExpression2: e2, Token3: t3,
+ Statement: p.statement(), lexicalScope: p.declScope,
+ block: p.block,
+ }
+ case ':':
+ t2 = p.shift()
+ default:
+ p.err("expected :")
+ }
+ return &LabeledStatement{
+ Case: LabeledStatementCaseLabel, Token: t, ConstantExpression: e,
+ Token2: t2, Statement: p.statement(), lexicalScope: p.declScope,
+ block: p.block,
+ }
+ case DEFAULT:
+ if p.switches == 0 {
+ p.err("'deafult' label not within a switch statement")
+ }
+ t = p.shift()
+ switch p.rune() {
+ case ':':
+ t2 = p.shift()
+ default:
+ p.err("expected :")
+ }
+ return &LabeledStatement{
+ Case: LabeledStatementDefault, Token: t, Token2: t2, Statement: p.statement(),
+ lexicalScope: p.declScope, block: p.block,
+ }
+ default:
+ p.err("expected labeled-statement")
+ return nil
+ }
+}
+
+// [0], 6.8.2 Compound statement
+//
+// compound-statement:
+// { block-item-list_opt }
+func (p *parser) compoundStatement(s Scope, inject []Token) (r *CompoundStatement) {
+ if p.rune() != '{' {
+ p.err("expected {")
+ return nil
+ }
+
+ r = &CompoundStatement{parent: p.block}
+ if fn := p.currFn; fn != nil {
+ fn.compoundStatements = append(fn.compoundStatements, r)
+ }
+ sv := p.block
+ if sv != nil {
+ sv.children = append(sv.children, r)
+ }
+ p.block = r
+ switch {
+ case s != nil:
+ p.declScope = s
+ p.resolveScope = s
+ p.scopes++
+ // var a []string
+ // for s := p.declScope; s != nil; s = s.Parent() {
+ // a = append(a, fmt.Sprintf("%p", s))
+ // }
+ // dbg("using func scope %p: %v", s, strings.Join(a, " "))
+ default:
+ p.openScope(false)
+ }
+ s = p.declScope
+ p.typedefNameEnabled = true
+ t := p.shift()
+ if len(inject) != 0 {
+ p.unget(inject...)
+ }
+ list := p.blockItemList()
+ var t2 Token
+ p.closeScope()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case '}':
+ t2 = p.shift()
+ default:
+ p.err("expected }")
+ }
+ r.Token = t
+ r.BlockItemList = list
+ r.Token2 = t2
+ r.scope = s
+ p.block = sv
+ return r
+}
+
+// block-item-list:
+// block-item
+// block-item-list block-item
+func (p *parser) blockItemList() (r *BlockItemList) {
+ var prev *BlockItemList
+ for p.rune() != '}' && p.rune() > 0 {
+ n := &BlockItemList{BlockItem: p.blockItem()}
+ if r == nil {
+ r = n
+ prev = r
+ continue
+ }
+
+ prev.BlockItemList = n
+ prev = n
+ }
+ return r
+}
+
+// block-item:
+// declaration
+// statement
+// label-declaration
+// declaration-specifiers declarator compound-statement
+func (p *parser) blockItem() *BlockItem {
+ switch p.rune() {
+ case
+ TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL,
+ VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ CONST, RESTRICT, VOLATILE,
+ ALIGNAS,
+ INLINE, NORETURN, ATTRIBUTE:
+ ds := p.declarationSpecifiers(nil, nil)
+ switch p.rune() {
+ case ';':
+ r := &BlockItem{Case: BlockItemDecl, Declaration: p.declaration(ds, nil)}
+ p.typedefNameEnabled = true
+ return r
+ }
+
+ d := p.declarator(true, ds.typedef(), nil)
+ switch p.rune() {
+ case '{':
+ if p.ctx.cfg.RejectNestedFunctionDefinitions {
+ p.err0(false, "nested functions not allowed")
+ }
+ r := &BlockItem{Case: BlockItemFuncDef, DeclarationSpecifiers: ds, Declarator: d, CompoundStatement: p.compoundStatement(d.ParamScope(), p.fn(d.Name()))}
+ p.typedefNameEnabled = true
+ return r
+ default:
+ r := &BlockItem{Case: BlockItemDecl, Declaration: p.declaration(ds, d)}
+ return r
+ }
+ case LABEL:
+ p.block.hasLabel()
+ return &BlockItem{Case: BlockItemLabel, LabelDeclaration: p.labelDeclaration()}
+ case PRAGMASTDC:
+ return &BlockItem{Case: BlockItemPragma, PragmaSTDC: p.pragmaSTDC()}
+ default:
+ return &BlockItem{Case: BlockItemStmt, Statement: p.statement()}
+ }
+}
+
+// label-declaration
+// __label__ identifier-list ;
+func (p *parser) labelDeclaration() *LabelDeclaration {
+ if p.rune() != LABEL {
+ p.err("expected __label__")
+ return nil
+ }
+
+ t := p.shift()
+ list := p.identifierList()
+ p.typedefNameEnabled = true
+ var t2 Token
+ switch p.rune() {
+ case ';':
+ t2 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &LabelDeclaration{Token: t, IdentifierList: list, Token2: t2}
+}
+
+// [0], 6.8.3 Expression and null statements
+//
+// expression-statement:
+// expression_opt attribute-specifier-list_opt;
+func (p *parser) expressionStatement() *ExpressionStatement {
+ switch p.rune() {
+ case '}':
+ p.typedefNameEnabled = true
+ return &ExpressionStatement{}
+ case ';':
+ p.typedefNameEnabled = true
+ return &ExpressionStatement{Token: p.shift()}
+ case ATTRIBUTE:
+ p.typedefNameEnabled = true
+ attr := p.attributeSpecifierList()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ var t Token
+ switch p.rune() {
+ case ';':
+ t = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &ExpressionStatement{AttributeSpecifierList: attr, Token: t}
+ }
+
+ e := p.expression()
+ var t Token
+ p.typedefNameEnabled = true
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ switch p.rune() {
+ case ';':
+ t = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &ExpressionStatement{Expression: e, AttributeSpecifierList: attr, Token: t}
+}
+
+// [0], 6.8.4 Selection statements
+//
+// selection-statement:
+// if ( expression ) statement
+// if ( expression ) statement else statement
+// switch ( expression ) statement
+func (p *parser) selectionStatement() *SelectionStatement {
+ var t, t2, t3, t4 Token
+ switch p.rune() {
+ case IF:
+ p.openScope(false)
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ e := p.expression()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ p.openScope(false)
+ s := p.statement()
+ if p.peek(false) != ELSE {
+ r := &SelectionStatement{Case: SelectionStatementIf, Token: t, Token2: t2, Expression: e, Token3: t3, Statement: s}
+ p.closeScope()
+ p.closeScope()
+ return r
+ }
+
+ p.closeScope()
+ p.openScope(false)
+ t4 = p.shift()
+ r := &SelectionStatement{Case: SelectionStatementIfElse, Token: t, Token2: t2, Expression: e, Token3: t3, Statement: s, Token4: t4, Statement2: p.statement()}
+ p.closeScope()
+ p.closeScope()
+ return r
+ case SWITCH:
+ p.switches++
+ p.openScope(false)
+ t = p.shift()
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ e := p.expression()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ p.openScope(false)
+ s := p.statement()
+ p.closeScope()
+ p.closeScope()
+ p.switches--
+ return &SelectionStatement{Case: SelectionStatementSwitch, Token: t, Token2: t2, Expression: e, Token3: t3, Statement: s}
+ default:
+ p.err("expected selection-statement")
+ 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) {
+ var t, t2, t3, t4, t5 Token
+ var e, e2, e3 *Expression
+ switch p.rune() {
+ case WHILE:
+ p.openScope(false)
+ t = p.shift()
+ if p.rune() != '(' {
+ p.err("expected (")
+ p.closeScope()
+ return nil
+ }
+
+ t2 = p.shift()
+ e = p.expression()
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ p.openScope(false)
+ r = &IterationStatement{Case: IterationStatementWhile, Token: t, Token2: t2, Expression: e, Token3: t3, Statement: p.statement()}
+ p.closeScope()
+ p.closeScope()
+ return r
+ case DO:
+ t := p.shift()
+ p.openScope(false)
+ p.openScope(false)
+ s := p.statement()
+ p.closeScope()
+ switch p.rune() {
+ case WHILE:
+ t2 = p.shift()
+ default:
+ p.err("expected while")
+ p.closeScope()
+ return nil
+ }
+
+ if p.rune() != '(' {
+ p.err("expected (")
+ p.closeScope()
+ return nil
+ }
+
+ t3 = p.shift()
+ e = p.expression()
+ switch p.rune() {
+ case ')':
+ t4 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ';':
+ t5 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ r = &IterationStatement{Case: IterationStatementDo, Token: t, Statement: s, Token2: t2, Token3: t3, Expression: e, Token4: t4, Token5: t5}
+ p.closeScope()
+ return r
+ case FOR:
+ p.openScope(false)
+ t = p.shift()
+ if p.rune() != '(' {
+ p.err("expected (")
+ p.closeScope()
+ return nil
+ }
+
+ t2 = p.shift()
+ var d *Declaration
+ switch p.rune() {
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL,
+ VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ CONST, RESTRICT, VOLATILE,
+ ALIGNAS,
+ INLINE, NORETURN, ATTRIBUTE:
+ d = p.declaration(nil, nil)
+ if p.rune() != ';' {
+ e = p.expression()
+ }
+ switch p.rune() {
+ case ';':
+ t3 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ if p.rune() != ')' {
+ e2 = p.expression()
+ }
+ switch p.rune() {
+ case ')':
+ t4 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ p.openScope(false)
+ r = &IterationStatement{Case: IterationStatementForDecl, Token: t, Token2: t2, Declaration: d, Expression: e, Token3: t3, Expression2: e2, Token4: t4, Statement: p.statement()}
+ p.closeScope()
+ p.closeScope()
+ return r
+ default:
+ if p.rune() != ';' {
+ e = p.expression()
+ }
+ switch p.rune() {
+ case ';':
+ t3 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ if p.rune() != ';' {
+ e2 = p.expression()
+ }
+ switch p.rune() {
+ case ';':
+ t4 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ if p.rune() != ')' {
+ e3 = p.expression()
+ }
+ switch p.rune() {
+ case ')':
+ t5 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ p.openScope(false)
+ r = &IterationStatement{Case: IterationStatementFor, Token: t, Token2: t2, Expression: e, Token3: t3, Expression2: e2, Token4: t4, Expression3: e3, Token5: t5, Statement: p.statement()}
+ p.closeScope()
+ p.closeScope()
+ return r
+ }
+ default:
+ p.err("expected iteration-statement")
+ return nil
+ }
+}
+
+// [0], 6.8.6 Jump statements
+//
+// jump-statement:
+// goto identifier ;
+// goto * expression ;
+// continue ;
+// break ;
+// return expression_opt ;
+func (p *parser) jumpStatement() *JumpStatement {
+ var t, t2, t3 Token
+ var kind JumpStatementCase
+ switch p.rune() {
+ case GOTO:
+ p.typedefNameEnabled = false
+ t = p.shift()
+ switch p.rune() {
+ case IDENTIFIER:
+ t2 = p.shift()
+ case '*':
+ t2 = p.shift()
+ p.typedefNameEnabled = true
+ e := p.expression()
+ switch p.rune() {
+ case ';':
+ t3 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &JumpStatement{Case: JumpStatementGotoExpr, Token: t, Token2: t2, Expression: e, Token3: t3, lexicalScope: p.declScope}
+ default:
+ p.err("expected identifier or *")
+ }
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ';':
+ t3 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &JumpStatement{Case: JumpStatementGoto, Token: t, Token2: t2, Token3: t3, lexicalScope: p.declScope}
+ case CONTINUE:
+ kind = JumpStatementContinue
+ case BREAK:
+ kind = JumpStatementBreak
+ case RETURN:
+ t = p.shift()
+ var e *Expression
+ if p.rune() != ';' {
+ e = p.expression()
+ }
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ';':
+ t2 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &JumpStatement{Case: JumpStatementReturn, Token: t, Expression: e, Token2: t2, lexicalScope: p.declScope}
+ default:
+ p.err("expected jump-statement")
+ return nil
+ }
+
+ t = p.shift()
+ p.typedefNameEnabled = true
+ switch p.rune() {
+ case ';':
+ t2 = p.shift()
+ default:
+ p.err("expected ;")
+ }
+ return &JumpStatement{Case: kind, Token: t, Token2: t2, lexicalScope: p.declScope}
+}
+
+// [0], 6.9 External definitions
+//
+// translation-unit:
+// external-declaration
+// translation-unit external-declaration
+func (p *parser) translationUnit() (r *TranslationUnit) {
+ p.typedefNameEnabled = true
+ var prev *TranslationUnit
+ for p.rune() >= 0 {
+ ed := p.externalDeclaration()
+ if ed == nil {
+ continue
+ }
+
+ t := &TranslationUnit{ExternalDeclaration: ed}
+ switch {
+ case r == nil:
+ r = t
+ default:
+ prev.TranslationUnit = t
+ }
+ prev = t
+ }
+ if r != nil {
+ return r
+ }
+
+ return &TranslationUnit{}
+}
+
+// external-declaration:
+// function-definition
+// declaration
+// asm-function-definition
+// ;
+func (p *parser) externalDeclaration() *ExternalDeclaration {
+ var ds *DeclarationSpecifiers
+ var inline, extern bool
+ if p.ctx.cfg.SharedFunctionDefinitions != nil {
+ p.rune()
+ p.hash.Reset()
+ p.key = sharedFunctionDefinitionKey{pos: dict.sid(p.tok.Position().String())}
+ p.hashTok()
+ }
+ switch p.rune() {
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL,
+ VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ CONST, RESTRICT, VOLATILE,
+ INLINE, NORETURN, ATTRIBUTE,
+ ALIGNAS:
+ ds = p.declarationSpecifiers(&extern, &inline)
+ case ';':
+ if p.ctx.cfg.RejectEmptyDeclarations {
+ p.err("expected external-declaration")
+ return nil
+ }
+
+ return &ExternalDeclaration{Case: ExternalDeclarationEmpty, Token: p.shift()}
+ case ASM:
+ return &ExternalDeclaration{Case: ExternalDeclarationAsmStmt, AsmStatement: p.asmStatement()}
+ case PRAGMASTDC:
+ return &ExternalDeclaration{Case: ExternalDeclarationPragma, PragmaSTDC: p.pragmaSTDC()}
+ default:
+ if p.ctx.cfg.RejectMissingDeclarationSpecifiers {
+ p.err("expected declaration-specifiers")
+ }
+ }
+ if p.rune() == ';' {
+ return &ExternalDeclaration{Case: ExternalDeclarationDecl, Declaration: p.declaration(ds, nil)}
+ }
+
+ p.rune()
+ d := p.declarator(false, ds.typedef(), nil)
+ p.declScope.declare(d.Name(), d)
+ switch p.rune() {
+ case ',', ';', '=', ATTRIBUTE:
+ if ds == nil {
+ ds = noDeclSpecs
+ }
+ r := &ExternalDeclaration{Case: ExternalDeclarationDecl, Declaration: p.declaration(ds, d)}
+ return r
+ case ASM:
+ return &ExternalDeclaration{Case: ExternalDeclarationAsm, AsmFunctionDefinition: p.asmFunctionDefinition(ds, d)}
+ default:
+ fd := p.functionDefinition(ds, d)
+ if sfd := p.ctx.cfg.SharedFunctionDefinitions; sfd != nil {
+ p.key.nm = d.Name()
+ p.key.hash = p.hash.Sum64()
+ if ex := sfd.m[p.key]; ex != nil {
+ sfd.M[ex] = struct{}{}
+ d := ex.Declarator
+ p.declScope.declare(d.Name(), d)
+ r := &ExternalDeclaration{Case: ExternalDeclarationFuncDef, FunctionDefinition: ex}
+ return r
+ }
+
+ sfd.m[p.key] = fd
+ }
+
+ r := &ExternalDeclaration{Case: ExternalDeclarationFuncDef, FunctionDefinition: fd}
+ return r
+ }
+}
+
+func (p *parser) pragmaSTDC() *PragmaSTDC {
+ if p.rune() != PRAGMASTDC {
+ p.err("expected __pragma_stdc")
+ }
+
+ t := p.shift() // _Pragma
+ t2 := p.shift() // STDC
+ t3 := p.shift() // FOO
+ t4 := p.shift() // Bar
+ return &PragmaSTDC{Token: t, Token2: t2, Token3: t3, Token4: t4}
+}
+
+// [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) {
+ var list *DeclarationList
+ s := d.ParamScope()
+ switch {
+ case p.rune() != '{': // As in: int f(i) int i; { return i; }
+ list = p.declarationList(s)
+ case d.DirectDeclarator != nil && d.DirectDeclarator.Case == DirectDeclaratorFuncIdent: // As in: int f(i) { return i; }
+ d.DirectDeclarator.idListNoDeclList = true
+ for n := d.DirectDeclarator.IdentifierList; n != nil; n = n.IdentifierList {
+ tok := n.Token2
+ if tok.Value == 0 {
+ tok = n.Token
+ }
+ d := &Declarator{
+ IsParameter: true,
+ DirectDeclarator: &DirectDeclarator{
+ Case: DirectDeclaratorIdent,
+ Token: tok,
+ },
+ }
+ s.declare(tok.Value, d)
+ if p.ctx.cfg.RejectMissingDeclarationSpecifiers {
+ p.ctx.errNode(&tok, "expected declaration-specifiers")
+ }
+ }
+ }
+ p.block = nil
+ r = &FunctionDefinition{DeclarationSpecifiers: ds, Declarator: d, DeclarationList: list}
+ sv := p.currFn
+ p.currFn = r
+ r.CompoundStatement = p.compoundStatement(d.ParamScope(), p.fn(d.Name()))
+ p.currFn = sv
+ return r
+}
+
+func (p *parser) fn(nm StringID) (r []Token) {
+ if p.ctx.cfg.PreprocessOnly {
+ return nil
+ }
+
+ pos := p.tok.Position()
+ toks := []Token{
+ {Rune: STATIC, Value: idStatic, Src: idStatic},
+ {Rune: CONST, Value: idConst, Src: idConst},
+ {Rune: CHAR, Value: idChar, Src: idChar},
+ {Rune: IDENTIFIER, Value: idFunc, Src: idFunc},
+ {Rune: '[', Value: idLBracket, Src: idLBracket},
+ {Rune: ']', Value: idRBracket, Src: idRBracket},
+ {Rune: '=', Value: idEq, Src: idEq},
+ {Rune: STRINGLITERAL, Value: nm, Src: nm},
+ {Rune: ';', Value: idSemicolon, Src: idSemicolon},
+ }
+ if p.ctx.cfg.InjectTracingCode {
+ id := dict.sid(fmt.Sprintf("%s:%s\n", pos, nm.String()))
+ toks = append(toks, []Token{
+ {Rune: IDENTIFIER, Value: idFprintf, Src: idFprintf},
+ {Rune: '(', Value: idLParen, Src: idLParen},
+ {Rune: IDENTIFIER, Value: idStderr, Src: idStderr},
+ {Rune: ',', Value: idComma, Src: idComma},
+ {Rune: STRINGLITERAL, Value: id, Src: id},
+ {Rune: ')', Value: idRParen, Src: idRParen},
+ {Rune: ';', Value: idSemicolon, Src: idSemicolon},
+ {Rune: IDENTIFIER, Value: idFFlush, Src: idFFlush},
+ {Rune: '(', Value: idLParen, Src: idLParen},
+ {Rune: IDENTIFIER, Value: idStderr, Src: idStderr},
+ {Rune: ')', Value: idRParen, Src: idRParen},
+ {Rune: ';', Value: idSemicolon, Src: idSemicolon},
+ }...)
+ }
+ for _, v := range toks {
+ v.file = p.tok.file
+ v.pos = p.tok.pos
+ v.seq = p.tok.seq
+ r = append(r, v)
+ }
+ return r
+}
+
+// declaration-list:
+// declaration
+// declaration-list declaration
+func (p *parser) declarationList(s Scope) (r *DeclarationList) {
+ p.declScope = s
+ p.resolveScope = s
+ switch ch := p.rune(); ch {
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL,
+ VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ CONST, RESTRICT, VOLATILE,
+ ALIGNAS,
+ INLINE, NORETURN, ATTRIBUTE:
+ r = &DeclarationList{Declaration: p.declaration(nil, nil)}
+ default:
+ p.err("expected declaration: %s", tokName(ch))
+ return nil
+ }
+
+ for prev := r; ; prev = prev.DeclarationList {
+ switch p.rune() {
+ case TYPEDEF, EXTERN, STATIC, AUTO, REGISTER, THREADLOCAL,
+ VOID, CHAR, SHORT, INT, INT8, INT16, INT32, INT64, INT128, LONG, FLOAT, FLOAT16, FLOAT80, FLOAT32, FLOAT32X, FLOAT64, FLOAT64X, FLOAT128, DECIMAL32, DECIMAL64, DECIMAL128, FRACT, SAT, ACCUM, DOUBLE, SIGNED, UNSIGNED, BOOL, COMPLEX, STRUCT, UNION, ENUM, TYPEDEFNAME, TYPEOF, ATOMIC,
+ CONST, RESTRICT, VOLATILE,
+ ALIGNAS,
+ INLINE, NORETURN, ATTRIBUTE:
+ prev.DeclarationList = &DeclarationList{Declaration: p.declaration(nil, nil)}
+ default:
+ return r
+ }
+ }
+}
+
+// ----------------------------------------------------------------- Extensions
+
+// asm-function-definition:
+// declaration-specifiers declarator asm-statement
+func (p *parser) asmFunctionDefinition(ds *DeclarationSpecifiers, d *Declarator) *AsmFunctionDefinition {
+ return &AsmFunctionDefinition{DeclarationSpecifiers: ds, Declarator: d, AsmStatement: p.asmStatement()}
+}
+
+// asm-statement:
+// asm attribute-specifier-list_opt ;
+func (p *parser) asmStatement() *AsmStatement {
+ a := p.asm()
+ attr := p.attributeSpecifierListOpt()
+ // if attr != nil {
+ // trc("%v: ATTRS", attr.Position())
+ // }
+ var t Token
+ switch p.rune() {
+ case ';':
+ p.typedefNameEnabled = true
+ t = p.shift()
+ default:
+ p.err("expected ';'")
+ }
+
+ return &AsmStatement{Asm: a, AttributeSpecifierList: attr, Token: t}
+}
+
+// asm:
+// asm asm-qualifier-list_opt ( string-literal asm-arg-list_opt )
+func (p *parser) asm() *Asm {
+ var t, t2, t3, t4 Token
+ switch p.rune() {
+ case ASM:
+ t = p.shift()
+ default:
+ p.err("expected asm")
+ }
+
+ var qlist *AsmQualifierList
+ switch p.rune() {
+ case VOLATILE, INLINE, GOTO:
+ qlist = p.asmQualifierList()
+ }
+
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+
+ switch p.rune() {
+ case STRINGLITERAL:
+ t3 = p.shift()
+ default:
+ p.err("expected string-literal")
+ }
+
+ var argList *AsmArgList
+ switch p.rune() {
+ case ':':
+ argList = p.asmArgList()
+ }
+
+ switch p.rune() {
+ case ')':
+ t4 = p.shift()
+ default:
+ p.err("expected )")
+ }
+
+ return &Asm{Token: t, AsmQualifierList: qlist, Token2: t2, Token3: t3, AsmArgList: argList, Token4: t4}
+}
+
+// asm-qualifier-list:
+// asm-qualifier
+// asm-qualifier-list asm-qualifier
+func (p *parser) asmQualifierList() (r *AsmQualifierList) {
+ switch p.rune() {
+ case VOLATILE, INLINE, GOTO:
+ r = &AsmQualifierList{AsmQualifier: p.asmQualifier()}
+ default:
+ p.err("expected asm-qualifier-list")
+ return nil
+ }
+
+ for prev := r; ; prev = prev.AsmQualifierList {
+ switch p.rune() {
+ case VOLATILE, INLINE, GOTO:
+ prev.AsmQualifierList = &AsmQualifierList{AsmQualifier: p.asmQualifier()}
+ default:
+ return r
+ }
+ }
+}
+
+// asm-qualifier:
+// volatile
+// inline
+// goto"
+func (p *parser) asmQualifier() *AsmQualifier {
+ switch p.rune() {
+ case VOLATILE:
+ return &AsmQualifier{Case: AsmQualifierVolatile, Token: p.shift()}
+ case INLINE:
+ return &AsmQualifier{Case: AsmQualifierInline, Token: p.shift()}
+ case GOTO:
+ return &AsmQualifier{Case: AsmQualifierGoto, Token: p.shift()}
+ default:
+ p.err("expected asm-qualifier")
+ return nil
+ }
+}
+
+// asm-arg-list:
+// : ExpressionListOpt
+// asm-arg-list : expression-list_opt
+func (p *parser) asmArgList() (r *AsmArgList) {
+ if p.rune() != ':' {
+ p.err("expected :")
+ return nil
+ }
+
+ t := p.shift()
+ var list *AsmExpressionList
+ switch p.rune() {
+ case ':', ')':
+ default:
+ list = p.asmExpressionList()
+ }
+ r = &AsmArgList{Token: t, AsmExpressionList: list}
+ for prev := r; p.rune() == ':'; prev = prev.AsmArgList {
+ t := p.shift()
+ switch p.rune() {
+ case ':', ')':
+ default:
+ list = p.asmExpressionList()
+ }
+ prev.AsmArgList = &AsmArgList{Token: t, AsmExpressionList: list}
+ }
+ return r
+}
+
+// asm-expression-list:
+// asm-index_opt assignment-expression
+// asm-expression-list , asm-index_opt assignment-expression
+func (p *parser) asmExpressionList() (r *AsmExpressionList) {
+ var x *AsmIndex
+ if p.rune() == '[' {
+ x = p.asmIndex()
+ }
+
+ r = &AsmExpressionList{AsmIndex: x, AssignmentExpression: p.assignmentExpression()}
+ for prev := r; p.rune() == ','; prev = prev.AsmExpressionList {
+ t := p.shift()
+ if p.rune() == '[' {
+ x = p.asmIndex()
+ }
+ prev.AsmExpressionList = &AsmExpressionList{Token: t, AsmIndex: x, AssignmentExpression: p.assignmentExpression()}
+ }
+ return r
+}
+
+// asm-index:
+// [ expression ]
+func (p *parser) asmIndex() *AsmIndex {
+ if p.rune() != '[' {
+ p.err("expected [")
+ return nil
+ }
+
+ t := p.shift()
+ e := p.expression()
+ var t2 Token
+ switch p.rune() {
+ case ']':
+ t2 = p.shift()
+ default:
+ p.err("expected ]")
+ }
+ return &AsmIndex{Token: t, Expression: e, Token2: t2}
+}
+
+// attribute-specifier-list:
+// attribute-specifier
+// attribute-specifier-list attribute-specifier
+func (p *parser) attributeSpecifierList() (r *AttributeSpecifierList) {
+ if p.rune() != ATTRIBUTE {
+ p.err("expected __attribute__")
+ return nil
+ }
+
+ r = &AttributeSpecifierList{AttributeSpecifier: p.attributeSpecifier()}
+ for prev := r; p.rune() == ATTRIBUTE; prev = r.AttributeSpecifierList {
+ prev.AttributeSpecifierList = &AttributeSpecifierList{AttributeSpecifier: p.attributeSpecifier()}
+ }
+ return r
+}
+
+// attribute-specifier:
+// __attribute__ (( attribute-value-list_opt ))
+func (p *parser) attributeSpecifier() (r *AttributeSpecifier) {
+ if p.rune() != ATTRIBUTE {
+ p.err("expected __attribute__")
+ return nil
+ }
+
+ en := p.typedefNameEnabled
+ t := p.shift()
+ var t2, t3, t4, t5 Token
+ p.ignoreKeywords = true
+ switch p.rune() {
+ case '(':
+ t2 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ switch p.rune() {
+ case '(':
+ t3 = p.shift()
+ default:
+ p.err("expected (")
+ }
+ var list *AttributeValueList
+ if p.rune() != ')' {
+ list = p.attributeValueList()
+ }
+ p.ignoreKeywords = false
+ p.typedefNameEnabled = en
+ switch p.rune() {
+ case ')':
+ t4 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ switch p.rune() {
+ case ')':
+ t5 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AttributeSpecifier{Token: t, Token2: t2, Token3: t3, AttributeValueList: list, Token4: t4, Token5: t5}
+}
+
+// attribute-value-list:
+// attribute-value
+// attribute-value-list , attribute-value
+func (p *parser) attributeValueList() (r *AttributeValueList) {
+ r = &AttributeValueList{AttributeValue: p.attributeValue()}
+ for prev := r; p.rune() == ','; prev = prev.AttributeValueList {
+ t := p.shift()
+ prev.AttributeValueList = &AttributeValueList{Token: t, AttributeValue: p.attributeValue()}
+ }
+ return r
+}
+
+// attribute-value:
+// identifier
+// identifier ( expression-list_opt )
+func (p *parser) attributeValue() *AttributeValue {
+ if p.rune() != IDENTIFIER {
+ p.err("expected identifier")
+ return nil
+ }
+
+ t := p.shift()
+ if p.rune() != '(' {
+ return &AttributeValue{Case: AttributeValueIdent, Token: t, lexicalScope: p.declScope}
+ }
+
+ p.ignoreKeywords = false
+ t2 := p.shift()
+ var list *ExpressionList
+ if p.rune() != ')' {
+ list = p.expressionList()
+ }
+ p.ignoreKeywords = true
+ var t3 Token
+ switch p.rune() {
+ case ')':
+ t3 = p.shift()
+ default:
+ p.err("expected )")
+ }
+ return &AttributeValue{Case: AttributeValueExpr, Token: t, Token2: t2, ExpressionList: list, Token3: t3, lexicalScope: p.declScope}
+}
+
+// expression-list:
+// assignment-expression
+// expression-list , assignment-expression
+func (p *parser) expressionList() (r *ExpressionList) {
+ r = &ExpressionList{AssignmentExpression: p.assignmentExpression()}
+ for prev := r; p.rune() == ','; prev = prev.ExpressionList {
+ t := p.shift()
+ prev.ExpressionList = &ExpressionList{Token: t, AssignmentExpression: p.assignmentExpression()}
+ }
+ return r
+}