Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.


Takes a token stream from the lexer, and parses it into an abstract syntax tree.

Specification C11


Source cparse.d

class CParser(AST): Parser!AST;
bool addFuncName;
add declaration of _func__ to function symbol table
bool importBuiltins;
seen use of C compiler builtins, so import _importc_builtins;
Array!(void*) typedefTab;
Array of AST.Type[Identifier], typedef's indexed by Identifier
AST.Dsymbols* parseModule();
Parse translation unit. C11 6.9 translation-unit: external-declaration translation-unit external-declaration
external-declaration: function-definition declaration
array of Dsymbols that were declared
AST.Statement cparseStatement(int flags, const(char)** endPtr = null, Loc* pEndloc = null);
Statement Parser
C11 6.8 statement: labeled-statement compound-statement expression-statement selection-statement iteration-statement jump-statement
int flags PSxxxx
const(char)** endPtr store location of closing brace
Loc* pEndloc if { ... statements ... }, store location of closing brace, otherwise loc of last token of statement
parsed statement
AST.Expression cparseExpression();
Expression Parser
C11 6.5.17 expression: assignment-expression expression , assignment-expression
AST.Expression cparsePrimaryExp();
C11 6.5.1 primary-expression: identifier constant string-literal ( expression ) generic-selection _builtin_va_arg(assign_expression, type)
AST.Expression cparseAssignExp();
C11 6.5.16 assignment-expression: conditional-expression unary-expression assignment-operator assignment-expression
assignment-operator: = *= /= %= += -= <<= >>= &= ^= |=
void cparseDeclaration(LVL level);
Declaration Parser
C11 6.7 declaration: declaration-specifiers init-declarator-list (opt) ; static_assert-declaration
init-declarator-list: init-declarator init-declarator-list , init-declarator
init-declarator: declarator declarator = initializer
LVL level declaration context
AST.Dsymbol cparseFunctionDefinition(Identifier id, AST.TypeFunction ft, ref Specifier specifier);
C11 Function Definitions function-definition declaration-specifiers declarator declaration-list (opt) compound-statement
declaration-list: declaration declaration-list declaration
It's already been parsed up to the declaration-list (opt). Pick it up from there.
Identifier id function identifier
AST.TypeFunction ft function type
Specifier specifier function specifiers
Dsymbol for the function
AST.Initializer cparseInitializer();
C11 Initialization initializer: assignment-expression { } // C23 6.7.10 addition { initializer-list } { initializer-list , }
initializer-list: designation (opt) initializer initializer-list , designation (opt) initializer
designation: designator-list =
designator-list: designator designator-list designator
designator: [ constant-expression ] . identifier
MOD cparseTypeQualifierList();
C11 6.7.3 type-qualifier: const restrict volatile Atomic _stdcall
AST.Type cparseTypeName();
C11 6.7.7
AST.Type cparseSpecifierQualifierList(LVL level, ref Specifier specifier);
C11 specifier-qualifier-list: type-specifier specifier-qualifier-list (opt) type-qualifier specifier-qualifier-list (opt)
LVL level declaration context
Specifier specifier specifiers in and out
resulting type, null if not specified
AST.ParameterList cparseParameterList();
C11 ( parameter-type-list ) ( identifier-list (opt) )
void cparseStructDeclaration(AST.Dsymbols* members);
C11 Parse a struct declaration member. struct-declaration: specifier-qualifier-list struct-declarator-list (opt) ; static_assert-declaration
struct-declarator-list: struct-declarator struct-declarator-list , struct-declarator
struct-declarator: declarator declarator (opt) : constant-expression
AST.Dsymbols* members where to put the fields (members)
bool isDeclarationList(ref Token* pt);
See if declaration-list is present.
true if declaration-list is present, even an empty one
enum LVL;
Declaration context
function parameter (declarations for function identifier-list)
function prototype
struct member
enum DTR;
Types of declarator to parse
C11 6.7.6 direct-declarator
C11 6.7.7 abstract-declarator
parameter declarator may be either direct or abstract
enum SCW: uint;
C11 6.7.1 Storage-class specifiers
enum MOD: uint;
C11 6.7.3 Type qualifiers
struct Specifier;
Aggregate for all the various specifiers
bool noreturn;
noreturn attribute
bool naked;
naked attribute
bool _nothrow;
nothrow attribute
bool _pure;
pure attribute
bool dllimport;
dllimport attribute
bool dllexport;
dllexport attribute
bool _deprecated;
deprecated attribute
AST.Expression depMsg;
deprecated message
uint vector_size;
positive power of 2 multipe of base type size
SCW scw;
storage-class specifiers
MOD mod;
type qualifiers
AST.Expressions* alignExps;
structalign_t packalign;
#pragma pack alignment value
StorageClass specifiersToSTC(LVL level, const ref Specifier specifier);
Convert from C specifiers to D storage class
LVL level declaration context
Specifier specifier specifiers, context, etc.
corresponding D storage class
void specifiersToFuncDeclaration(AST.FuncDeclaration fd, const ref Specifier specifier);
Add attributes from Specifier to function
AST.FuncDeclaration fd function to apply them to
Specifier specifier specifiers
void specifiersToVarDeclaration(AST.VarDeclaration vd, const ref Specifier specifier);
Add attributes from Specifier to variable
AST.VarDeclaration vd function to apply them to
Specifier specifier specifiers
void panic();
After encountering an error, scan forward until a right brace or ; is found or the end of the file.
bool isFunctionTypedef(AST.Type t);
typedefTab symbol table
Determines if type t is a function type.
AST.Type t type to test
true if it represents a function
bool isTypedef(Identifier id);
Determine if id is a symbol for a Typedef.
Identifier id possible typedef
true if id is a Type
void insertIdToTypedefTab(Identifier id);
Add id to typedefTab[], but only if it will mask an existing typedef.
Identifier id identifier for non-typedef symbol
void insertTypedefToTypedefTab(Identifier id, AST.Type t);
Add id to typedefTab[]
Identifier id identifier for typedef symbol
AST.Type t type of the typedef symbol
AST.Type* lookupTypedef(Identifier id);
Lookup id in typedefTab[].
if not found, then null. if found, then Type*. Deferencing it will yield null if it is not a typedef, and a type if it is a typedef.
bool parseSpecialTokenSequence();
Directive Parser
void addDefines();
#define Parser
Go through the #define's in the defines buffer and see what we can convert to Dsymbols, which are then appended to symbols[]