c_parse.pl
The C parser (milestone 4a): it turns the tokens from c_lex into a syntax tree.
The only semantic state is the set of typedef names in scope, which the grammar needs to tell declarations from expressions. It is the assoc Env, from each name to t, threaded through the nonterminals. Types, constants and tags are resolved later, in c_types and c_lower.
Translation unit
A translation unit is a list of these items:
| Item | Is |
|---|---|
declLoc, Specs, Inits | a declaration; Inits is a list of initDcl, Init, Init none, an expression or listEntries |
fundefLoc, Specs, Dcl, Body | a function definition |
static_assertLoc, Expr, Message | Message the string's bytes, or [] without one |
Entries are entryDesignators, Init terms, each designator fieldName or indexExpr.
Declarators
A declarator is dclName, Type, Asm. Name is someIdentifier, or none in abstract declarators; Asm is asmSymbol or none. Type is built around the atom base, which stands for the type the Specs give:
| Type | Means |
|---|---|
base | the type of the specifiers |
ptrT, Quals | a pointer to T, Quals a list of qualifiers |
arrayT, Size | Size none or an expression |
funcT, Params | Params unspecified, or paramsPs, Variadic |
In paramsPs, Variadic, Ps is a list of paramSpecs, Dcl and Variadic is fixed or variadic.
Specifiers
Specs is a list of:
| Specifier | Means |
|---|---|
storageS | S is typedef, extern, static, auto, register or thread_local |
tspecK | a type specifier keyword such as int or unsigned |
qualQ | a qualifier: const, volatile, restrict or atomic |
fspecF | inline or noreturn |
tnameName | a typedef name |
suKind, Tag, Members, Attrs | Kind struct or union |
enumTag, Enumerators | an enum |
attrTokens | an attribute |
alignastypeTypeName alignasexprE | _Alignas |
typeoftypeTypeName typeofexprE | typeof |
A Tag is someIdentifier or none. Members is none, or a list of fieldSpecs, Dcl, Width and static_assert terms, Width none or an expression. Enumerators is none, or a list of enumeratorName, Value, Value an expression or none.
Statements
A statement is atLoc, S, with S one of:
| S | Notes |
|---|---|
blockItems | Items are statements, decl and static_assert terms |
exprE | |
null | the empty statement |
ifC, Then, Else | Else none without an else |
whileC, S doS, C | |
forInit, C, Step, S | Init none, exprE or a decl term; C and Step may be none |
switchE, S caseE, S defaultS | |
break continue | |
returnE | E may be none |
gotoL labelL, S |
Expressions
| Expression | Means |
|---|---|
idN | an identifier |
numV, Suffix−Radix | an integer constant, as c_lex gives it |
chrV floatChars | character and floating constants |
strBytes | a string literal |
wstrElemType, Codes | a wide string literal |
binOp, A, B | a binary operator |
assignOp, A, B | Op is = for plain assignment |
unOp, A | Op neg, plus, bnot, not, deref, addr, preinc, predec, postinc or postdec |
condC, A, B | C ? A : B |
gcondC, B | GNU C's C ?: B |
commaA, B | |
callF, Args indexA, I | |
memberA, F arrowA, F | A.F and A->F |
castTypeName, E | |
sizeof_typeTypeName sizeof_exprE alignofTypeName | |
complitTypeName, Init | a compound literal |
offsetofTypeName, Path | Path a list of fieldF and indexE |
va_argA, TypeName | __builtin_va_arg |
stmtexprBlock | a GNU statement expression |
genericControl, Associations | _Generic, Associations a list of assocTypeName, E and assocdefault, E |
A TypeName is typeSpecs, Type.
Expr is the constant expression, a conditional expression, that the c_lex Tokens are, as #if reads them. No name is a typedef. Throws nanofil_error/1 on a syntax error.
the external declarations up to the end of input. The cut commits to the first parse of each declaration.
Tokens
Lookahead: the next token, left in the input.
the punctuator P, or a syntax error.
throw a syntax error at the next token.
External declarations
one external declaration; Items is Items1 with its item in front, or Items1 itself for a stray ';'. Env is Env0 with its typedef names.
a _Static_assert after its keyword.
Env is Env0 with the typedef names the declaration adds or (for ordinary names) hides.
Env is Env0 with typedef Name.
Env is Env0 for a function body, where parameter names hide typedefs.
Inits are the init(Dcl, Init) of the declarator list whose first declarator Dcl is already read. The declarators' attributes are collected into Attrs and apply to the whole declaration.
Declaration specifiers
nonempty declaration specifiers.
once a type specifier is seen, an identifier is the declarator, not a typedef name.
TypeSeen is yes if Spec is a type specifier, else TypeSeen0.
| 286 | storage_ | TypeSeen | TypeSeen |
| 287 | tspec_ | _ | yes |
| 288 | qual_ | TypeSeen | TypeSeen |
| 289 | fspec_ | TypeSeen | TypeSeen |
| 290 | attr_ | TypeSeen | TypeSeen |
| 291 | alignas_ | TypeSeen | TypeSeen |
| 292 | su_, _, _, _ | _ | yes |
| 293 | enum_, _ | _ | yes |
| 294 | typeof_ | _ | yes |
| 295 | tname_ | _ | yes |
__attribute__((...)), Tokens its balanced//1 contents.
Like their GNU spellings, layout-changing attributes cannot be ignored. Reject here also at positions (e.g. pointers) whose attributes we discard.
the member declarations of a struct or union up to its '}'.
Fields-Rest is the difference list of fields one member declaration declares.
the enumerators up to the '}'.
Declarators
a declarator with its GNU suffix. Attributes after a declarator come back as attr(Tokens) specifiers in Attrs.
a declarator of Name; Type is built around Base.
like declarator//4 without a name. A '(' starts a nested declarator only before a '*'; otherwise it is a parameter list.
array and function suffixes, applied inside out: Type is Base with them.
the size between '[' and ']', or none; the ']' stays in the input.
a type name, type(Specs, Type).
lookahead: the next token begins a type name. __extension__ can prefix either a type or an expression. Look past it without consuming it, rather than misreading glibc's ({...}) as a type.
Initializers
the entries of a braced initializer after its '{', through '}'.
Statements
the items of a block through its '}'.
a declaration or statement in a block; Env is Env0 with the declaration's typedef names.
lookahead only: the next tokens begin a declaration, not a label.
label_start//: lookahead: the next tokens are an identifier and ':'.
a declaration in a block or for.
a statement at(Loc, S). The cut commits to the first parse; if there is none, it is a syntax error.
Expressions
an expression, commas included.
Spelling is the compound assignment of the arithmetic or shift operator Op: its spelling followed by = (C11 6.5.16.2).
binary operators of precedence Level and up; level 11 is a cast expression.
C's binary operators (C11 6.5.5-6.5.14): Spelling is Op, of precedence Level (1 binds loosest). Kind says what it does to its operands: arith(Domain) converts integer or arithmetic operands to their common type, shift promotes each, compare converts and compares, and logical tests each for truth.
| 921 | '||' | 1 | lor | logical |
| 922 | && | 2 | land | logical |
| 923 | ('|') | 3 | or | arithinteger |
| 924 | ^ | 4 | xor | arithinteger |
| 925 | & | 5 | and | arithinteger |
| 926 | == | 6 | eq | compare |
| 927 | '!=' | 6 | ne | compare |
| 928 | < | 7 | lt | compare |
| 929 | > | 7 | gt | compare |
| 930 | <= | 7 | le | compare |
| 931 | >= | 7 | ge | compare |
| 932 | << | 8 | shl | shift |
| 933 | >> | 8 | shr | shift |
| 934 | + | 9 | add | aritharithmetic |
| 935 | - | 9 | sub | aritharithmetic |
| 936 | * | 10 | mul | aritharithmetic |
| 937 | / | 10 | div | aritharithmetic |
| 938 | '%' | 10 | mod | arithinteger |
E is A with the postfix operators that follow.
a primary expression.
one or more adjacent string literals, each str(Bytes) or wstr(Type, Codes). They concatenate; if one is wide, all are, and a plain one's bytes become elements (exact for ASCII).
adjacent plain string literals as one list of bytes.
S is the string literal Parts concatenate.
S is the literal of Elements: plain if no part is wide, else of the one wide type.