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.

 

‹List›X

 ::= 

X {"," ‹List›X}*

 

‹AnyIdentifier›

 ::= 

‹Identifier›

 

  |  

‹TypedefName›

2.1.1 Expressions🔗ℹ

 

‹PrimaryExpression›

 ::= 

‹Identifier›

 

  |  

‹Constant›

 

  |  

‹StringLiteral›

 

  |  

"(" ‹Expression› ")"

 

‹PostfixExpression›

 ::= 

‹PrimaryExpression›

 

  |  

‹PostfixExpression› "[" ‹Expression› "]"

 

  |  

‹PostfixExpression› "(" [‹List›‹AssignmentExpression›] ")"

 

  |  

‹PostfixExpression› "." ‹AnyIdentifier›

 

  |  

‹PostfixExpression› "->" ‹AnyIdentifier›

 

  |  

‹PostfixExpression› "++"

 

  |  

‹PostfixExpression› "–"

 

  |  

"(" ‹TypeName› ")" "{" ‹List›‹Initializer› [","] "}"

 

‹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›

 ::= 

‹List›‹AssignmentExpression›

 

‹ConstantExpression›

 ::= 

‹ConditionalExpression›

2.1.2 Declarations🔗ℹ

 

‹Declaration›

 ::= 

‹DeclarationModifier›+ [‹List›‹InitDeclarator›‹Identifier›] ";"

 

  |  

‹DeclarationSpecifiers› [‹List›‹InitDeclarator›‹AnyIdentifier›] ";"

 

‹DeclarationSpecifiers›

 ::= 

‹DeclarationModifier›* ‹TaggedTypeSpecifier› ‹DeclarationModifier›*

 

  |  

‹DeclarationModifier›* ‹TypedefName› ‹DeclarationModifier›*

 

  |  

‹DeclarationModifier›* {‹PrimTypeSpecifier› ‹DeclarationModifier›*}+

 

‹DeclarationModifier›

 ::= 

‹StorageClassSpecifier›

 

  |  

‹TypeQualifier›

 

  |  

‹FunctionSpecifier›

 

‹InitDeclarator›X

 ::= 

‹Declarator›X ["=" ‹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›+ [‹List›‹StructDeclarator›‹Identifier›] ";"

 

  |  

‹StructSpecifiers› [‹List›‹StructDeclarator›‹AnyIdentifier›] ";"

 

‹StructSpecifiers›

 ::= 

‹TypeQualifier›* ‹TaggedTypeSpecifier› ‹TypeQualifier›*

 

  |  

‹TypeQualifier›* ‹TypedefName› ‹TypeQualifier›*

 

  |  

‹TypeQualifier›* {‹PrimTypeSpecifier› ‹TypeQualifier›*}+

 

‹StructDeclarator›X

 ::= 

‹Declarator›X

 

  |  

[‹Declarator›X] ":" ‹ConstantExpression›

 

‹EnumSpecifier›

 ::= 

"enum" [‹Tag›] "{" ‹List›‹Enumerator› [","] "}"

 

  |  

"enum" ‹Tag›

 

‹Enumerator›

 ::= 

‹AnyIdentifier› ["=" ‹ConstantExpression›]

 

‹TypeQualifier›

 ::= 

"const"  |  "restrict"  |  "volatile"

 

‹FunctionSpecifier›

 ::= 

"inline"

 

‹Declarator›X

 ::= 

[‹Pointer›] ‹DirectDeclarator›X

 

‹DirectDeclarator›X

 ::= 

X

 

  |  

"(" ‹Declarator›X ")"

 

  |  

‹DirectDeclarator›X "[" ‹TypeQualifier›* [‹AssignmentExpression›] "]"

 

  |  

‹DirectDeclarator›X "[" "static" ‹TypeQualifier›* ‹AssignmentExpression› "]"

 

  |  

‹DirectDeclarator›X "[" TypeQualifier+ "static" ‹AssignmentExpression› "]"

 

  |  

‹DirectDeclarator›X "[" ‹TypeQualifier›* "*" "]"

 

  |  

‹DirectDeclarator›X "(" ‹ParameterTypeList› ")"

 

  |  

‹DirectDeclarator›X "(" [‹List›‹Identifier›] ")"

 

‹Pointer›

 ::= 

{"*" ‹TypeQualifier›*}+

 

‹ParameterTypeList›

 ::= 

‹List›‹ParameterDeclaration› ["," "..."]

 

‹ParameterDeclaration›

 ::= 

‹DeclarationModifier›+ [‹Declarator›‹Identifier›]

 

  |  

‹DeclarationSpecifiers› [‹Declarator›‹AnyIdentifier›]

 

  |  

‹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›{[‹List›‹Designator› "="] ‹Initializer›} [","] "}"

 

‹Designator›

 ::= 

"[" ‹ConstantExpression› "]"

 

  |  

"." ‹AnyIdentifier›

2.1.3 Statements🔗ℹ

The parameterized statement non-terminals such as ‹Statement›X 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.

 

‹Statement›X

 ::= 

‹LabeledStatement›X

 

  |  

‹CompoundStatement›

 

  |  

‹ExpressionStatement›

 

  |  

‹SelectionStatement›X

 

  |  

‹IterationStatement›X

 

  |  

‹JumpStatement›

 

‹LabeledStatement›X

 ::= 

‹AnyIdentifier› ":" ‹Statement›X

 

  |  

"case" ‹ConstantExpression› ":" ‹Statement›X

 

  |  

"default" ":" ‹Statement›X

 

‹CompoundStatement›

 ::= 

"{" ‹BlockItem›* "}"

 

‹BlockItem›

 ::= 

‹Declaration›

 

  |  

‹Statement›#t

 

‹ExpressionStatement›

 ::= 

[‹Expression›] ";"

 

‹SelectionStatement›X

 ::= 

‹IfStatement›X

 

  |  

"switch" "(" ‹Expression› ")" ‹Statement›X

 

‹IfStatement›#t

 ::= 

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

 

‹IfStatement›#f

 ::= 

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

 

‹IterationStatement›X

 ::= 

"while" "(" ‹Expression› ")" ‹Statement›X

 

  |  

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

 

  |  

"for" "(" [‹Expression›] ";" [‹Expression›] ";" [‹Expression›] ")" ‹Statement›X

 

  |  

"for" "(" ‹Declaration› [‹Expression›] ";" [‹Expression›] ")" ‹Statement›X

 

‹JumpStatement›

 ::= 

"goto" ‹AnyIdentifier› ";"

 

  |  

"continue" ";"

 

  |  

"break" ";"

 

  |  

"return" [‹Expression›] ";"

2.1.4 Programs🔗ℹ

 

‹TranslationUnit›

 ::= 

‹ExternalDefinition›+

 

‹ExternalDefinition›

 ::= 

‹FunctionDefinition›

 

  |  

‹Declaration›

 

‹FunctionDefinition›

 ::= 

‹FunctionHead› [‹List›‹Declaration›] ‹FunctionBody›

 

‹FunctionHead›

 ::= 

‹DeclarationModifier›+ ‹Declarator›‹Identifier›

 

  |  

‹DeclarationSpecifiers› ‹Declarator›‹AnyIdentifier›

 

‹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.