On this page:
3.1 Parsing
parse-program
parse-declaration
parse-statement
parse-expression
parse-type-expression
3.2 Embedding C in Scheme
3.2.1 Scribble Reader
3.2.2 Avoid Using Here Strings
3.2.3 Embedding C
program
declaration
statement
expression
type-expression
3.3 Including C Externally
make-program-reader

3 Parsing and Reading C

 (require (planet dherman/c:3:3/parse))

Each of the parsing operations takes three optional keyword arguments. The #:typedef argument takes a list of type names to bind as though by typedef in the parser’s initial environment. The #:source argument is used to identify the source of the input in the source location information. The #:offset argument is used as the base offset of source location information. This is useful for parsing source extracted from the middle of a file or input port. If this argument is ommitted or #f, the parsed text is assumed to appear at the beginning of the input source.

3.1 Parsing

(parse-program in    
  [#:typedef typedef    
  #:source source    
  #:offset offset])  (listof decl?)
  in : (or/c input-port? string? path?)
  typedef : (or/c (listof symbol?) #f) = #f
  source : any = #f
  offset : (or/c position? #f) = #f
Parses a C program (‹TranslationUnit›).
(parse-declaration in    
  [#:typedef typedef    
  #:source source    
  #:offset offset])  decl?
  in : (or/c input-port? string? path?)
  typedef : (or/c (listof symbol?) #f) = #f
  source : any = #f
  offset : (or/c position? #f) = #f
Parses a C declaration (‹ExternalDeclaration›).
(parse-statement in    
  [#:typedef typedef    
  #:source source    
  #:offset offset])  stmt?
  in : (or/c input-port? string? path?)
  typedef : (or/c (listof symbol?) #f) = #f
  source : any = #f
  offset : (or/c position? #f) = #f
Parses a C statement (‹Statement›).
(parse-expression in    
  [#:typedef typedef    
  #:source source    
  #:offset offset])  expr??
  in : (or/c input-port? string? path?)
  typedef : (or/c (listof symbol?) #f) = #f
  source : any = #f
  offset : (or/c position? #f) = #f
Parses a C expression (‹Expression›).
(parse-type-expression in    
  [#:typedef typedef    
  #:source source    
  #:offset offset])  type?
  in : (or/c input-port? string? path?)
  typedef : (or/c (listof symbol?) #f) = #f
  source : any = #f
  offset : (or/c position? #f) = #f
Parses a C type expression (‹TypeName›).

3.2 Embedding C in Scheme

+ See Scribble: Racket Documentation Tool for more information about Scribble.

This library includes macros for embedding C source in Scheme to be parsed at compile time. These macros are designed to work with the Scribble @-reader to make this embedding convenient.

The following example defines a list of C declaration nodes, parsed at compile time and bound at runtime to decls:

#lang at-exp scheme/base
;  ...
(define decls
  @program[#:typedef (word)]{
      struct tm {
          word tm_sec;
          word tm_min;
          word tm_hour;
          word tm_mday;
          word tm_mon;
          word tm_year;
          word tm_wday;
          word tm_yday;
          word tm_isdst;
      };
  })

Notice the use of the at-exp language to add @-reader support to the specified scheme/base language.

3.2.1 Scribble Reader

The Scribble @-reader does not itself recognize C syntax; it simply treats free-form text enclosed between { } pairs as string literals. It does match delimiters such as braces, parentheses and brackets, however, which works well with the syntax of C.

The special forms defined in this library work in conjunction with the Scribble reader to allow embedding C as string literals. The reader simply determines the end of the input, and parsing occurs as part of macro expansion.

The forms defined in this library accept only string literals, so in particular nested @-expressions are disallowed.

Since the syntax of C requires parsers to maintain a type environment to distinguish variable names and type names (as bound by typedef), all type names must be declared before they are used. For convenience, each of the special forms in this library accepts an optional #:typedef argument to pre-declare type names.

3.2.2 Avoid Using Here Strings

Technically, it is possible to use the special forms in this library without the Scribble reader by using here strings instead. However, the library is unable to extract accurate source location information with here strings, so this is not recommended.

3.2.3 Embedding C

(program #:typedef (type-id ...) src-string ...+)
(program src-string ...+)
Parses the concatenated src-string fragments with parse-program and expands into a list of decl nodes.

(declaration #:typedef (type-id ...) src-string ...+)
(declaration src-string ...+)
Parses the concatenated src-string fragments with parse-declaration and expands into a decl node.

(statement #:typedef (type-id ...) src-string ...+)
(statement src-string ...+)
Parses the concatenated src-string fragments with parse-statement and expands into a stmt node.

(expression #:typedef (type-id ...) src-string ...+)
(expression src-string ...+)
Parses the concatenated src-string fragments with parse-expression and expands into an expr node.

(type-expression #:typedef (type-id ...) src-string ...+)
(type-expression src-string ...+)
Parses the concatenated src-string fragments with parse-type-expression and expands into an type node.

3.3 Including C Externally

(make-program-reader [#:typedef typedef])
  (any input-port? -> (or/c (listof decl?) eof-object?))
  typedef : (listof symbol?) = '()
Produces a procedure that reads an entire input port as a C program. The resulting procedure is suitable for use as the expansion-time argument to include/reader.

Using include/reader, this makes it relatively convenient to include C source code from an external file:

(require scheme/include
         (for-syntax scheme/base)
         (for-syntax (planet dherman/c:3:3/parse)))
;  ...
(define fnord.h
  (include/reader
   "fnord.h"
   (make-program-reader #:typedef '(BOOL WORD UINT32))))

Notice that the relevant bindings must be available in the transformer environment in order to apply make-program-reader in the expansion-time argument to include/reader.