On this page:
2.1 C Language Grammar
2.1.1 Expressions
2.1.2 Declarations
2.1.3 Statements
2.1.4 Programs
2.2 Abstract Syntax
2.2.1 Source Locations
src
src-start
src-end
build-src
position-min
position-max
src-range
src->syntax
id->syntax
primitive-type-specifier?
unary-operator?
binary-operator?
assignment-operator?
increment-operator?
2.2.2 Identifiers
id
id:  var
id:  label
id:  qualifier
id:  op
id:  storage
id:  inline
id:  ellipsis
id:  star
2.2.3 Expressions
expr
expr:  ref
expr:  int
expr:  float
expr:  char
expr:  string
expr:  compound
expr:  array-ref
expr:  call
expr:  member
expr:  pointer-member
expr:  postfix
expr:  prefix
expr:  cast
expr:  sizeof
expr:  unop
expr:  binop
expr:  assign
expr:  begin
expr:  if
2.2.4 Statements
stmt
stmt:  label
stmt:  case
stmt:  default
stmt:  block
stmt:  expr
stmt:  if
stmt:  switch
stmt:  while
stmt:  do
stmt:  for
stmt:  goto
stmt:  continue
stmt:  break
stmt:  return
stmt:  empty
2.2.5 Declarations
decl
decl:  typedef
decl:  vars
decl:  formal
decl:  function
decl:  declarator
declarator-context?
complete-declarator?
decl:  member-declarator
member-declarator-context?
complete-member-declarator?
decl:  member
2.2.6 Initializers
init
init:  compound
init:  expr
2.2.7 Designators
dtor
dtor:  array
dtor:  member
2.2.8 Types
type
type:  primitive
type:  ref
type:  struct
type:  union
type:  enum
type:  array
type:  pointer
type:  function
type:  qualified
2.2.9 Type Contexts
type-context?
complete-type?
apply-type-context
apply-declarator-context
apply-declarator-contexts
apply-member-declarator-context
apply-member-declarator-contexts

2 The C Language

This library provides data types representing C abstract syntax, a C parser, and macros for constructing C abstract syntax with a convenient parenthesized syntax. It can be required via:

2.1 C Language Grammar

The grammar provided in the ISO/IEC 9899:TC3 standard is mum about when typedef-name tokens can be used as identifier tokens. For example, all C parsers admit programs such as:

typedef int T;

void proc(char T) { }

despite the fact that T is a typedef-name and the grammar for procedure arguments requires argument declarator names to be identifier tokens.

The following is a more detailed (and slightly reorganized) grammar than the one in the C99 standard which explicitly specifies when tokens bound as typedef names can be used as identifiers.

 

ListX

 ::= 

X {"," ListX}*

 

AnyIdentifier

 ::= 

Identifier

 

  |  

TypedefName

2.1.1 Expressions

 

PrimaryExpression

 ::= 

Identifier

 

  |  

Constant

 

  |  

StringLiteral

 

  |  

"(" Expression ")"

 

PostfixExpression

 ::= 

PrimaryExpression

 

  |  

PostfixExpression "[" Expression "]"

 

  |  

PostfixExpression "(" [‹ListAssignmentExpression] ")"

 

  |  

PostfixExpression "." AnyIdentifier

 

  |  

PostfixExpression "->" AnyIdentifier

 

  |  

PostfixExpression "++"

 

  |  

PostfixExpression "–"

 

  |  

"(" TypeName ")" "{" ListInitializer [","] "}"

 

UnaryExpression

 ::= 

"++" UnaryExpression

 

  |  

"–" UnaryExpression

 

  |  

{"&"  |  "*"  |  "+"  |  "-"  |  "~"  |  "!"} CastExpression

 

  |  

"sizeof" UnaryExpression

 

  |  

"sizeof" "(" TypeName ")"

 

CastExpression

 ::= 

UnaryExpression

 

  |  

"(" TypeName ")" CastExpression

 

BinaryExpression(E,Op)

 ::= 

E

 

  |  

BinaryExpression(E,Op) Op E

 

MultiplicativeExpression

 ::= 

BinaryExpression(‹CastExpression›,{"*" | "/" | "%"})

 

AdditiveExpression

 ::= 

BinaryExpression(‹MultiplicativeExpression›,{"+" | "-"})

 

ShiftExpression

 ::= 

BinaryExpression(‹AdditiveExpression›,{"<<" | ">>"})

 

RelationalExpression

 ::= 

BinaryExpression(‹ShiftExpression›,{"<" | ">" | "<=" | ">="})

 

EqualityExpression

 ::= 

BinaryExpression(‹RelationalExpression›,{"==" | "!="})

 

ANDExpression

 ::= 

BinaryExpression(‹EqualityExpression›,"&")

 

ExclusiveORExpression

 ::= 

BinaryExpression(‹ANDExpression›,"^")

 

InclusiveORExpression

 ::= 

BinaryExpression(‹ExclusiveORExpression›,"|")

 

LogicalANDExpression

 ::= 

BinaryExpression(‹LogicalORExpression›,"||")

 

ConditionalExpression

 ::= 

LogicalORExpression

 

  |  

LogicalORExpression "?" Expression ":" ConditionalExpression

 

AssignmentExpression

 ::= 

ConditionalExpression

 

  |  

UnaryExpression AssignmentOperator AssignmentExpression

 

AssignmentOperator

 ::= 

"="  |  "*="  |  "/="  |  "%="  |  "+="  |  "-="

 

  |  

"<<="  |  ">>="  |  "&="  |  "^="  |  "|="

 

Expression

 ::= 

ListAssignmentExpression

 

ConstantExpression

 ::= 

ConditionalExpression

2.1.2 Declarations

 

Declaration

 ::= 

DeclarationModifier+ [‹ListInitDeclaratorIdentifier] ";"

 

  |  

DeclarationSpecifiers [‹ListInitDeclaratorAnyIdentifier] ";"

 

DeclarationSpecifiers

 ::= 

DeclarationModifier›* TaggedTypeSpecifier DeclarationModifier›*

 

  |  

DeclarationModifier›* TypedefName DeclarationModifier›*

 

  |  

DeclarationModifier›* {‹PrimTypeSpecifier DeclarationModifier›*}+

 

DeclarationModifier

 ::= 

StorageClassSpecifier

 

  |  

TypeQualifier

 

  |  

FunctionSpecifier

 

InitDeclaratorX

 ::= 

DeclaratorX ["=" Initializer›]

 

StorageClassSpecifier

 ::= 

"typedef"  |  "extern"  |  "static"  |  "auto"  |  "register"

 

TypeSpecifier

 ::= 

PrimTypeSpecifier

 

  |  

TaggedTypeSpecifier

 

  |  

TypedefName

 

PrimTypeSpecifier

 ::= 

"void"

 

  |  

"char"  |  "short"  |  "int"  |  "long"

 

  |  

"float"  |  "double"

 

  |  

"signed"  |  "unsigned"

 

  |  

"_Bool"  |  "_Complex"

 

TaggedTypeSpecifier

 ::= 

{"struct"  |  "union"} [‹Tag›] "{" StructDeclaration+ "}"

 

  |  

{"struct"  |  "union"} Tag

 

  |  

EnumSpecifier

 

Tag

 ::= 

Identifier

 

  |  

TypedefName

 

StructDeclaration

 ::= 

TypeQualifier+ [‹ListStructDeclaratorIdentifier] ";"

 

  |  

StructSpecifiers [‹ListStructDeclaratorAnyIdentifier] ";"

 

StructSpecifiers

 ::= 

TypeQualifier›* TaggedTypeSpecifier TypeQualifier›*

 

  |  

TypeQualifier›* TypedefName TypeQualifier›*

 

  |  

TypeQualifier›* {‹PrimTypeSpecifier TypeQualifier›*}+

 

StructDeclaratorX

 ::= 

DeclaratorX

 

  |  

[‹DeclaratorX] ":" ConstantExpression

 

EnumSpecifier

 ::= 

"enum" [‹Tag›] "{" ListEnumerator [","] "}"

 

  |  

"enum" Tag

 

Enumerator

 ::= 

AnyIdentifier ["=" ConstantExpression›]

 

TypeQualifier

 ::= 

"const"  |  "restrict"  |  "volatile"

 

FunctionSpecifier

 ::= 

"inline"

 

DeclaratorX

 ::= 

[‹Pointer›] DirectDeclaratorX

 

DirectDeclaratorX

 ::= 

X

 

  |  

"(" DeclaratorX ")"

 

  |  

DirectDeclaratorX "[" TypeQualifier›* [‹AssignmentExpression›] "]"

 

  |  

DirectDeclaratorX "[" "static" TypeQualifier›* AssignmentExpression "]"

 

  |  

DirectDeclaratorX "[" TypeQualifier+ "static" AssignmentExpression "]"

 

  |  

DirectDeclaratorX "[" TypeQualifier›* "*" "]"

 

  |  

DirectDeclaratorX "(" ParameterTypeList ")"

 

  |  

DirectDeclaratorX "(" [‹ListIdentifier] ")"

 

Pointer

 ::= 

{"*" TypeQualifier›*}+

 

ParameterTypeList

 ::= 

ListParameterDeclaration ["," "..."]

 

ParameterDeclaration

 ::= 

DeclarationModifier+ [‹DeclaratorIdentifier]

 

  |  

DeclarationSpecifiers [‹DeclaratorAnyIdentifier]

 

  |  

DeclarationModifier+ AbstractDeclarator

 

  |  

DeclarationSpecifiers AbstractDeclarator

 

TypeName

 ::= 

{‹TypeSpecifier  |  TypeQualifier›}+ [‹AbstractDeclarator›]

 

AbstractDeclarator

 ::= 

Pointer

 

  |  

[‹Pointer›] DirectAbstractDeclarator

 

DirectAbstractDeclarator

 ::= 

"(" AbstractDeclarator ")"

 

  |  

[‹DirectAbstractDeclarator›] "[" TypeQualifier›* [‹AssignmentExpression›] "]"

 

  |  

[‹DirectAbstractDeclarator›] "[" "static" TypeQualifier›* AssignmentExpression "]"

 

  |  

[‹DirectAbstractDeclarator›] "[" TypeQualifier+ "static" AssignmentExpression "]"

 

  |  

[‹DirectAbstractDeclarator›] "[" "*" "]"

 

  |  

[‹DirectAbstractDeclarator›] "(" [‹ParameterTypeList›] ")"

 

Initializer

 ::= 

AssignmentExpression

 

  |  

"{" List{[‹ListDesignator "="] Initializer›} [","] "}"

 

Designator

 ::= 

"[" ConstantExpression "]"

 

  |  

"." AnyIdentifier

2.1.3 Statements

The parameterized statement non-terminals such as ‹StatementX take a flag indicating whether the productions may be right-terminated by a one-armed if statement (i.e., an if statement with no else clause). This is used to avoid the “dangling else” ambiguity.

 

StatementX

 ::= 

LabeledStatementX

 

  |  

CompoundStatement

 

  |  

ExpressionStatement

 

  |  

SelectionStatementX

 

  |  

IterationStatementX

 

  |  

JumpStatement

 

LabeledStatementX

 ::= 

AnyIdentifier ":" StatementX

 

  |  

"case" ConstantExpression ":" StatementX

 

  |  

"default" ":" StatementX

 

CompoundStatement

 ::= 

"{" BlockItem›* "}"

 

BlockItem

 ::= 

Declaration

 

  |  

Statement#t

 

ExpressionStatement

 ::= 

[‹Expression›] ";"

 

SelectionStatementX

 ::= 

IfStatementX

 

  |  

"switch" "(" Expression ")" StatementX

 

IfStatement#t

 ::= 

"if" "(" Expression ")" Statement#t ["else" Statement#t]

 

IfStatement#f

 ::= 

"if" "(" Expression ")" Statement#t "else" Statement#f

 

IterationStatementX

 ::= 

"while" "(" Expression ")" StatementX

 

  |  

"do" Statement#t "while" "(" Expression ")" ";"

 

  |  

"for" "(" [‹Expression›] ";" [‹Expression›] ";" [‹Expression›] ")" StatementX

 

  |  

"for" "(" Declaration [‹Expression›] ";" [‹Expression›] ")" StatementX

 

JumpStatement

 ::= 

"goto" AnyIdentifier ";"

 

  |  

"continue" ";"

 

  |  

"break" ";"

 

  |  

"return" [‹Expression›] ";"

2.1.4 Programs

 

TranslationUnit

 ::= 

ExternalDefinition+

 

ExternalDefinition

 ::= 

FunctionDefinition

 

  |  

Declaration

 

FunctionDefinition

 ::= 

FunctionHead [‹ListDeclaration] FunctionBody

 

FunctionHead

 ::= 

DeclarationModifier+ DeclaratorIdentifier

 

  |  

DeclarationSpecifiers DeclaratorAnyIdentifier

 

FunctionBody

 ::= 

CompoundStatement

2.2 Abstract Syntax

The abstract syntax of C is represented as structs. All of the structure definitions are provided by the package

 (require c/ast) package: c-utils

All of the structs defined in this library are prefab structs, and consist entirely of read-able and write-able data.

2.2.1 Source Locations

Source location information is stored with the following struct type.

struct

(struct src (start-offset
    start-line
    start-col
    end-offset
    end-line
    end-col
    path)
    #:extra-constructor-name make-src)
  start-offset : exact-nonnegative-integer?
  start-line : exact-positive-integer?
  start-col : exact-nonnegative-integer?
  end-offset : exact-nonnegative-integer?
  end-line : exact-positive-integer?
  end-col : exact-nonnegative-integer?
  path : any

procedure

(src-start src)  position?

  src : src?
Extracts a source location’s start position as a position struct.

procedure

(src-end src)  position?

  src : src?
Extracts a source location’s end position as a position struct.

procedure

(build-src start end path)  src?

  start : position?
  end : position?
  path : any
Builds a source location struct from position structs.

procedure

(position-min p ...+)  position?

  p : position?
Returns the least of the given positions p, i.e. the p with the least position-offset.

procedure

(position-max p ...+)  position?

  p : position?
Returns the greatest of the given positions p, i.e. the p with the greatest position-offset.

procedure

(src-range src ...+)  src?

  src : src?
Returns the smallest range that spans all the given source locations src.

procedure

(src->syntax x [datum original?])  syntax?

  x : src?
  datum : any = '...
  original? : boolean? = #t
Converts a source location to a syntax object, using datum as the syntax object’s underlying datum. If original? is #t, the generated syntax object has the syntax-original? property.

procedure

(id->syntax id [original?])  syntax?

  id : id?
  original? : boolean? = #t
Converts an identifier to a syntax object, using the identifier name as the syntax object’s underlying datum. If original? is #t, the generated syntax object has the syntax-original? property.

procedure

(primitive-type-specifier? x)  boolean?

  x : symbol?
Indicates whether x is a primitive type specifier, which is one of the symbols 'void, 'char, 'short, 'int, 'long, 'float, 'double, 'signed, 'unsigned, '_Bool, or '_Complex.

procedure

(unary-operator? x)  boolean?

  x : symbol?
Indicates whether x is a unary operator symbol, which is one of the symbols '&, '*, '+, '-, '~, or '!.

procedure

(binary-operator? x)  boolean?

  x : symbol?
Indicates whether x is a binary operator symbol, which is one of the symbols '*, '/, '%, '+, '-, '<<, '>>, '<, '>, '<=, '>=, '==, '!=, '&, '^, '\|, '&&, or '\|\|.

procedure

(assignment-operator? x)  boolean?

  x : symbol?
Indicates whether x is an assignment operator symbol, which is one of the symbols '=, '*=, '/=, '%=, '+=, '-=, '<<=, '>>=, '&=, '^=, or '\|=.

procedure

(increment-operator? x)  boolean?

  x : symbol?
Indicates whether x is an increment/decrement operator symbol, which is one of the symbols '++ or '--.

2.2.2 Identifiers

struct

(struct id (src)
    #:extra-constructor-name make-id)
  src : (or/c src? #f)
A C identifier, i.e., a variable name, type name, label name, or keyword.

struct

(struct id:var id (name)
    #:extra-constructor-name make-id:var)
  name : symbol?
A variable or type name.

struct

(struct id:label id (name)
    #:extra-constructor-name make-id:label)
  name : symbol?
A struct, union, or enum tag, a statement label, or a struct or union member name.

struct

(struct id:qualifier id (name)
    #:extra-constructor-name make-id:qualifier)
  name : (or/c 'const 'restrict 'volatile)
A type qualifier.

struct

(struct id:op id (name)
    #:extra-constructor-name make-id:op)
  name : (or/c unary-operator? binary-operator? assignment-operator? increment-operator?)
A unary, binary, assignment, or increment/decrement operator.

struct

(struct id:storage id (class)
    #:extra-constructor-name make-id:storage)
  class : (or/c 'typedef 'extern 'static 'auto 'register)
A storage class specifier.

struct

(struct id:inline id ()
    #:extra-constructor-name make-id:inline)
The inline keyword.

struct

(struct id:ellipsis id ()
    #:extra-constructor-name make-id:ellipsis)
The varargs keyword “...”.

struct

(struct id:star id ()
    #:extra-constructor-name make-id:star)
The array-type modifier keyword “*”.

2.2.3 Expressions

struct

(struct expr (src)
    #:extra-constructor-name make-expr)
  src : (or/c src? #f)
A C expression.

struct

(struct expr:ref expr (id)
    #:extra-constructor-name make-expr:ref)
  id : id:var?
A variable reference.

struct

(struct expr:int expr (value qualifiers)
    #:extra-constructor-name make-expr:int)
  value : integer?
  qualifiers : (listof id:qualifier?)
An integer literal.

struct

(struct expr:float expr (value qualifiers)
    #:extra-constructor-name make-expr:float)
  value : inexact-real?
  qualifiers : (listof id:qualifier?)
A floating-point literal.

struct

(struct expr:char expr (source wide?)
    #:extra-constructor-name make-expr:char)
  source : string?
  wide? : boolean?
A character literal. Character literals are stored as uninterpreted source, i.e., with escape sequences left in.

Example:
> (parse-expression "'\\n'")

'#s((expr:char expr 1) #s(src 1 1 0 5 1 4 #f) "\\n" #f)

struct

(struct expr:string expr (source wide?)
    #:extra-constructor-name make-expr:string)
  source : string?
  wide? : boolean?
A string literal. String literals are stored as uninterpreted source, i.e., with escape sequences left in.

Example:
> (parse-expression "\"foo\\nbar\"")

'#s((expr:string expr 1) #s(src 1 1 0 11 1 10 #f) "foo\\nbar" #f)

struct

(struct expr:compound expr (type inits)
    #:extra-constructor-name make-expr:compound)
  type : type?
  inits : (listof (or/c init? (cons (listof dtor?) init?)))
A C99 compound literal.

struct

(struct expr:array-ref expr (expr offset)
    #:extra-constructor-name make-expr:array-ref)
  expr : expr?
  offset : expr?
An array dereference.

struct

(struct expr:call expr (function arguments)
    #:extra-constructor-name make-expr:call)
  function : expr?
  arguments : (listof expr?)
A function call.

struct

(struct expr:member expr (expr label)
    #:extra-constructor-name make-expr:member)
  expr : expr?
  label : id:label?
A struct or union member dereference.

struct

(struct expr:pointer-member expr (expr label)
    #:extra-constructor-name make-expr:pointer-member)
  expr : expr?
  label : id:label?
A struct- or union-pointer member dereference.

struct

(struct expr:postfix expr (expr op)
    #:extra-constructor-name make-expr:postfix)
  expr : expr?
  op : id:op?
A postfix increment or decrement. The id:op-name field of op is an increment-operator? symbol.

struct

(struct expr:prefix expr (op expr)
    #:extra-constructor-name make-expr:prefix)
  op : id:op?
  expr : expr?
A prefix increment or decrement. The id:op-name field of op is an increment-operator? symbol.

struct

(struct expr:cast expr (type expr)
    #:extra-constructor-name make-expr:cast)
  type : type?
  expr : expr?
A type cast.

struct

(struct expr:sizeof expr (term)
    #:extra-constructor-name make-expr:sizeof)
  term : (or/c type? expr?)
A sizeof expression.

struct

(struct expr:unop expr (op expr)
    #:extra-constructor-name make-expr:unop)
  op : id:op?
  expr : expr?
A unary operator expression. The id:op-name field of op is a unary-operator? symbol.

struct

(struct expr:binop expr (left op right)
    #:extra-constructor-name make-expr:binop)
  left : expr?
  op : id:op?
  right : expr?
A binary operator expression. The id:op-name field of op is a binary-operator? symbol.

struct

(struct expr:assign expr (left op right)
    #:extra-constructor-name make-expr:assign)
  left : expr?
  op : id:op?
  right : expr?
An assignment expression. The id:op-name field of op is an assignment-operator? symbol.

struct

(struct expr:begin expr (left right)
    #:extra-constructor-name make-expr:begin)
  left : expr?
  right : expr?
A sequence expression.

struct

(struct expr:if expr (test cons alt)
    #:extra-constructor-name make-expr:if)
  test : expr?
  cons : expr?
  alt : expr?
A conditional expression.

2.2.4 Statements

struct

(struct stmt (src)
    #:extra-constructor-name make-stmt)
  src : (or/c src? #f)
A C statement.

struct

(struct stmt:label stmt (label stmt)
    #:extra-constructor-name make-stmt:label)
  label : id:label?
  stmt : stmt?
A labeled statement.

struct

(struct stmt:case stmt (expr stmt)
    #:extra-constructor-name make-stmt:case)
  expr : expr?
  stmt : stmt?
A case statement.

struct

(struct stmt:default stmt (stmt)
    #:extra-constructor-name make-stmt:default)
  stmt : stmt?
A default statement.

struct

(struct stmt:block stmt (items)
    #:extra-constructor-name make-stmt:block)
  items : (listof (or/c decl? stmt?))
A compound statement.

struct

(struct stmt:expr stmt (expr)
    #:extra-constructor-name make-stmt:expr)
  expr : expr?
An expression statement.

struct

(struct stmt:if stmt (test cons alt)
    #:extra-constructor-name make-stmt:if)
  test : expr?
  cons : stmt?
  alt : (or/c stmt? #f)
An if statement.

struct

(struct stmt:switch stmt (test body)
    #:extra-constructor-name make-stmt:switch)
  test : expr?
  body : stmt?
A switch statement.

struct

(struct stmt:while stmt (test body)
    #:extra-constructor-name make-stmt:while)
  test : expr?
  body : stmt?
A while statement.

struct

(struct stmt:do stmt (body test)
    #:extra-constructor-name make-stmt:do)
  body : stmt?
  test : expr?
A do-while statement.

struct

(struct stmt:for stmt (init test update body)
    #:extra-constructor-name make-stmt:for)
  init : (or/c expr? decl? #f)
  test : (or/c expr? #f)
  update : (or/c expr? #f)
  body : stmt?
A for statement.

struct

(struct stmt:goto stmt (label)
    #:extra-constructor-name make-stmt:goto)
  label : id:label?
A goto statement.

struct

(struct stmt:continue stmt ()
    #:extra-constructor-name make-stmt:continue)
A continue statement.

struct

(struct stmt:break stmt ()
    #:extra-constructor-name make-stmt:break)
A break statement.

struct

(struct stmt:return stmt (result)
    #:extra-constructor-name make-stmt:return)
  result : (or/c expr? #f)
A return statement.

struct

(struct stmt:empty stmt ()
    #:extra-constructor-name make-stmt:empty)
An empty statement.

2.2.5 Declarations

struct

(struct decl (src)
    #:extra-constructor-name make-decl)
  src : (or/c src? #f)
A C declaration.

struct

(struct decl:typedef decl (type declarators)
    #:extra-constructor-name make-decl:typedef)
  type : type?
  declarators : (listof declarator-context?)
A type definition. Note that each of the declarators is a declarator context.

struct

(struct decl:vars decl (storage-class type declarators)
    #:extra-constructor-name make-decl:vars)
  storage-class : (or/c id:storage? #f)
  type : (or/c type? #f)
  declarators : (listof declarator-context?)
A variable declaration. Note that each of the declarators is a declarator context.

struct

(struct decl:formal decl (storage-class type declarator)
    #:extra-constructor-name make-decl:formal)
  storage-class : (or/c id:storage? #f)
  type : (or/c type? #f)
  declarator : (or/c declarator-context? type-context?)
A formal argument declaration.

struct

(struct decl:function decl (storage-class
    inline?
    return-type
    declarator
    preamble
    body)
    #:extra-constructor-name make-decl:function)
  storage-class : (or/c id:storage? #f)
  inline? : (or/c id:inline? #f)
  return-type : type?
  declarator : declarator-context?
  preamble : (or/c (listof decl?) #f)
  body : stmt:block?
A function definition. Note that the declarator is a declarator context. The complete type of the function can be obtained by applying apply-declarator-context to the return-type and declarator.

struct

(struct decl:declarator decl (id type initializer)
    #:extra-constructor-name make-decl:declarator)
  id : (or/c id:var? #f)
  type : (or/c type? #f)
  initializer : (or/c init? #f)
A declarator, i.e., a single variable binding within a variable declaration.

There are two classes of declarator:

procedure

(declarator-context? x)  boolean?

  x : any
Determines whether x is a declarator context, which is a declarator with a type context as its type field.

procedure

(complete-declarator? x)  boolean?

  x : any
Determines whether x is a complete declarator, which is a declarator with a complete type as its type field.

struct

(struct decl:member-declarator decl (id type initializer bit-size)
    #:extra-constructor-name make-decl:member-declarator)
  id : (or/c id:label? #f)
  type : (or/c type? #f)
  initializer : (or/c init? #f)
  bit-size : (or/c expr? #f)
A member declarator, i.e., a single member definition within a struct or union definition.

There are two classes of member declarator:

procedure

(member-declarator-context? x)  boolean?

  x : any
Determines whether x is a member declarator context, which is a member declarator with a type context as its type field.

procedure

(complete-member-declarator? x)  boolean?

  x : any
Determines whether x is a complete member declarator, which is a member declarator with a complete type as its type field.

struct

(struct decl:member decl (type declarators)
    #:extra-constructor-name make-decl:member)
  type : (or/c type? #f)
  declarators : (listof decl:declarator?)
A member declaration within a struct or union definition.

2.2.6 Initializers

struct

(struct init (src)
    #:extra-constructor-name make-init)
  src : (or/c src? #f)
A C initializer.

struct

(struct init:compound init (elements)
    #:extra-constructor-name make-init:compound)
  elements : (listof (or/c init? (cons (listof dtor?) init?)))
A C99 compound initializer.

struct

(struct init:expr init (expr)
    #:extra-constructor-name make-init:expr)
  expr : expr?
An expression initializer.

2.2.7 Designators

struct

(struct dtor (src)
    #:extra-constructor-name make-dtor)
  src : (or/c src? #f)
A C99 designator.

struct

(struct dtor:array dtor (expr)
    #:extra-constructor-name make-dtor:array)
  expr : expr?
An array designator.

struct

(struct dtor:member dtor (label)
    #:extra-constructor-name make-dtor:member)
  label : id:label?
A struct or union member designator.

2.2.8 Types

struct

(struct type (src)
    #:extra-constructor-name make-type)
  src : (or/c src? #f)
A C type.

struct

(struct type:primitive type (name)
    #:extra-constructor-name make-type:primitive)
  name : (or/c primitive-type-specifier? (listof primitive-type-specifier?))
A primitive type. The name field can be one of:
  • 'void, 'char, 'short, 'int, 'long, 'float, 'double, 'signed, 'unsigned, '_Bool, or '_Complex

  • '(signed char)

  • '(unsigned char)

  • '(signed short)

  • '(signed short int)

  • '(unsigned short)

  • '(unsigned short int)

  • '(signed int)

  • '(unsigned int)

  • '(signed long)

  • '(long int)

  • '(signed long int)

  • '(unsigned long)

  • '(unsigned long int)

  • '(long long)

  • '(signed long long)

  • '(long long int)

  • '(signed long long int)

  • '(unsigned long long)

  • '(unsigned long long int)

  • '(long double)

  • '(float _Complex)

  • '(double _Complex)

  • '(long double _Complex)

struct

(struct type:ref type (id)
    #:extra-constructor-name make-type:ref)
  id : id:var?
A reference to a typedef name.

struct

(struct type:struct type (tag fields)
    #:extra-constructor-name make-type:struct)
  tag : id:label?
  fields : (or/c (listof decl:member?) #f)
A struct type.

struct

(struct type:union type (tag variants)
    #:extra-constructor-name make-type:union)
  tag : id:label?
  variants : (or/c (listof decl:member?) #f)
A union type.

struct

(struct type:enum type (tag variants)
    #:extra-constructor-name make-type:enum)
  tag : id:label?
  variants : (or/c (listof (or/c id:var? (cons id:var? expr?))) #f)
An enum type.

struct

(struct type:array type (base static? qualifiers length star?)
    #:extra-constructor-name make-type:array)
  base : type?
  static? : (or/c id:static? #f)
  qualifiers : (listof id:qualifier?)
  length : (or/c expr? #f)
  star? : (or/c id:star? #f)
An array type.

struct

(struct type:pointer type (base qualifiers)
    #:extra-constructor-name make-type:pointer)
  base : type?
  qualifiers : (listof id:qualifier?)
A pointer type.

struct

(struct type:function type (return formals)
    #:extra-constructor-name make-type:function)
  return : type?
  formals : (listof (or/c decl:formal? id:ellipsis?))
A function type.

struct

(struct type:qualified type (type qualifiers)
    #:extra-constructor-name make-type:qualified)
  type : (or/c type? #f)
  qualifiers : (listof id:qualifier?)
A qualified type.

2.2.9 Type Contexts

The peculiar syntax of declarations in C leads to a particular notion of type context. A type context is a type with a “hole,” represented by the value #f. For example, in the C declaration

typedef int A[32], *PA[32];

there are two declared types, A and PA, each of which is formed by plugging the base type int into the respective type contexts __[32] and *__[32].

More precisely, a type context is one of:

procedure

(type-context? x)  boolean?

  x : any
Determines whether x is a type context.

A complete type is a type with no holes.

procedure

(complete-type? x)  boolean?

  x : any
Determines whether x is a complete type.

procedure

(apply-type-context context base)  complete-type?

  context : type-context?
  base : complete-type?
Plugs the type base into the hole of context to obtain a complete type.

procedure

(apply-declarator-context context base)  complete-declarator?

  context : declarator-context?
  base : complete-type?
Plugs the type base into the hole of context to obtain a complete declarator.

procedure

(apply-declarator-contexts contexts base)

  (listof complete-declarator?)
  contexts : (listof declarator-context?)
  base : complete-type?
Plugs the type base into each of the holes of contexts to obtain a list of complete declarators.

procedure

(apply-member-declarator-context context 
  base) 
  complete-member-declarator?
  context : declarator-context?
  base : complete-type?
Plugs the type base into the hole of context to obtain a complete member declarator.

procedure

(apply-member-declarator-contexts contexts 
  base) 
  (listof complete-member-declarator?)
  contexts : (listof member-declarator-context?)
  base : complete-type?
Plugs the type base into each of the holes of contexts to obtain a list of complete member declarators.