Loading...
Searching...
No Matches
Operators

Definition

Module implementing a full C-preprocessor-style constant expression evaluator using a top-down recursive descent parser. The module provides the ability to evaluate integer constant expressions of the kind used in classical preprocessor.

This includes support for:

  • All C-style arithmetic, bitwise, logical, relational, and conditional operators
  • Operator precedence and associativity
  • Macro identifier substitution and the special defined(identifier) operator
  • Integer literals in decimal, octal (0...), hexadecimal (0x...), and binary (0b...) bases
  • Parenthesized sub-expressions and proper handling of unary operators

The implementation consists of two major phases:

  1. Tokenization The input string is scanned and converted into a sequence of token objects. The tokenizer recognizes multi-character operators ('&&', '||', '==', '!=', '<=', '>=', '<<', '>>', '**'), the defined operator (with or without parentheses), numbers in all supported bases, identifiers, and parentheses. Whitespace is ignored except as a token separator.
  2. Parsing and evaluation via top-down recursive descent A classic predictive (LL(1)) recursive descent parser is used, where each non-terminal in the grammar is implemented as a separate parsing function with the exact precedence level. The grammar is directly derived from the C standard operator precedence table:

    parse_expression ? parse_conditional parse_conditional ? parse_or (parse_or '?' parse_expression ':' parse_conditional) parse_or ? parse_and ( '||' parse_and )* parse_and ? parse_bitwise_or ( '&&' parse_bitwise_or )* parse_bitwise_or ? parse_bitwise_xor ( '|' parse_bitwise_xor )* parse_bitwise_xor ? parse_bitwise_and ( '^' parse_bitwise_and )* parse_bitwise_and ? parse_equality ( '&' parse_equality )* parse_equality ? parse_relational ( ('==' | '!=') parse_relational )* parse_relational ? parse_shifting ( ('<' | '>' | '<=' | '>=') parse_shifting )* parse_shifting ? parse_additive ( ('<<' | '>>') parse_additive )* parse_additive ? parse_multiplicative ( ('+' | '-') parse_multiplicative )* parse_multiplicative ? parse_power ( ('' | '/' | '') parse_unary ) parse_unary ? ('!' | '-' | '+' | '~') parse_unary | parse_power parse_power ? parse_unary ( '**' parse_unary )* (right-associative) parse_atom ? number | identifier (macro expansion) | 'defined' ( identifier ) | 'defined' identifier | '(' parse_expression ')'

    Each parsing function consumes tokens from the global position pos and returns the integer value of the sub-expression it recognizes. Because the grammar is factored by precedence, left-associativity is achieved naturally via left-recursive loops, while right-associativity for the power operator (**) is handled by calling parse_unary on the right-hand side first.

    Macro expansion occurs lazily inside parse_atom when an identifier token is encountered:

    • If the identifier is defined, its replacement text is recursively evaluated.
    • The special defined operator yields 1 or 0 depending on whether the identifier exists.

    The parser is fully re-entrant and has no global state.

    Public interface:

    This design guarantees correct operator precedence without the need for an explicit abstract syntax tree or stack-based shunting-yard algorithm, while remaining easy to read, maintain, and extend.

Data Types

interface  evaluate_expression
 Evaluates a preprocessor-style expression with macro substitution. Tokenizes the input expression, expands macros where appropriate, parses it according to operator precedence, and computes the integer result. Returns .true. if evaluation succeeded and the result is non-zero. More...
interface  strtol
 Converts a string to integer. More...

Methods

◆ parse_expression()

recursive integer function, public parse_expression ( character(*), intent(in) expr,
type(token), dimension(:), intent(in) tokens,
integer, intent(in) ntokens,
integer, intent(inout) pos,
type(macro), dimension(:), intent(inout), allocatable macros,
type(context), intent(in) ctx )

Parses a sequence of tokens starting at position pos as a full expression. Entry point for the recursive descent parser. Delegates to parse_or().

Parameters
[in]exprExpression to be processed
[in]tokensArray of tokens to parse
[in]ntokensNumber of valid tokens in the array
[in,out]posCurrent parsing position (updated as tokens are consumed)
[in,out]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 195 of file operators.f90.