Skip to content
This repository has been archived by the owner on Jun 6, 2021. It is now read-only.

Note: Preprocessor Directives

alexrp edited this page Mar 12, 2013 · 3 revisions

Preprocessor directives are lexed as:

preprocessor-directive ::= "\\" identifier

Once the preprocessor runs, it processes the token stream according to this grammar:

pp-program ::= { pp-directive | ? any non-directive token ? }

pp-directive ::= pp-if-directive
                 | pp-declaration-directive
                 | pp-error-directive

pp-if-directive ::= "\\if" pp-expression pp-section { pp-elif-directive } [ pp-else-directive ] "\endif"
pp-elif-directive ::= "\\elif" pp-expression pp-section
pp-else-directive ::= "\\else" pp-section

pp-section ::= { pp-directive | ? any non-directive token ? }

pp-expression ::= pp-or-expression
pp-or-expression ::= pp-and-expression | pp-or-expression "||" pp-and-expression
pp-and-expression ::= pp-unary-expression | pp-and-expression "&&" pp-unary-expression
pp-unary-expression ::= "!" pp-unary-expression | pp-primary-expression
pp-primary-expression ::= pp-literal-expression | pp-identifier-expression | pp-parenthesized-expression
pp-literal-expression ::= "true" | "false"
pp-identifier-expression ::= identifier
pp-parenthesized-expression ::= "(" pp-expression ")"

pp-declaration-directive ::= pp-define-directive
                             | pp-undef-directive
pp-define-directive ::= "\\define" identifier
pp-undef-directive ::= "\\undef" identifier

pp-error-directive ::= "\\error" string-literal

First a few rules that must be checked regardless of whether a directive is live:

  • Unknown preprocessor directives shall be flagged as errors.
  • Attempts to define or undefine identifiers starting with Flect_ shall be flagged as errors.

The following rules shall be checked only if the directive they pertain to is live:

  • Attempts to define already-defined identifiers shall be flagged as errors.
  • Attempts to undefine already-undefined identifiers shall be flagged as errors.

Now, all nested directives in a skipped section shall be ignored unless they belong to the outer directive (e.g. an \else that belongs to the outer \if).

Condition expressions are evaluated according to these semantics:

  • pp-or-expression: Performs a short-circuiting conditional OR of the two operands.
  • pp-and-expression: Performs a short-circuiting conditional AND of the two operands.
  • pp-unary-expression: If the operand is true, results in false; otherwise, true.
  • pp-literal-expression: Results in the value true or the value false.
  • pp-identifier-expression: If the identifier is defined, results in true; otherwise, false.
  • pp-parenthesized-expression: Used to override default precedence as encoded in the grammar.

It is generally easiest to implement a Flect preprocessor as a parser combined with an AST evaluator.

Clone this wiki locally