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_power ) parse_power ? parse_unary ( '**' parse_unary )* (right-associative) parse_unary ? ('!' | '-' | '+' | '~') parse_unary | parse_atom 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  strtol
 Converts a string to integer. More...

Methods

◆ evaluate_expression_default()

logical function evaluate_expression_default ( character(*), intent(in) expr,
type(macro), dimension(:), intent(in) macros,
integer, intent(out), optional val )
private

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.

Parameters
[in]exprExpression string to evaluate
[in]macrosArray of defined macros for substitution and defined() checks
[out]val(optional) integer result of the evaluation
Returns
.true. if the expression evaluated successfully to non-zero, .false. otherwise

Remarks

Definition at line 98 of file operators.f90.

◆ evaluate_expression_with_context()

logical function evaluate_expression_with_context ( character(*), intent(in) expr,
type(macro), dimension(:), intent(in) macros,
type(context), intent(in) ctx,
integer, intent(out), optional val )
private

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.

Parameters
[in]exprExpression string to evaluate
[in]macrosArray of defined macros for substitution and defined() checks
[in]ctxContext
[out]val(optional) integer result of the evaluation
Returns
.true. if the expression evaluated successfully to non-zero, .false. otherwise

Remarks

Definition at line 122 of file operators.f90.

◆ parse_additive()

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

Parses additive expressions (+, -).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 515 of file operators.f90.

◆ parse_and()

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

Parses logical AND expressions (&&).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 275 of file operators.f90.

◆ parse_atom()

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

Parses primary expressions: numbers, identifiers, defined(...), parentheses.

Parameters
[in]exprInput expression
[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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 660 of file operators.f90.

◆ parse_bitwise_and()

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

Parses bitwise AND expressions (&).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 365 of file operators.f90.

◆ parse_bitwise_or()

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

Parses bitwise OR expressions (|).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 305 of file operators.f90.

◆ parse_bitwise_xor()

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

Parses bitwise XOR expressions (^).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 335 of file operators.f90.

◆ parse_conditional()

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

Parses conditional expressions (?:). Right-associative.

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 191 of file operators.f90.

◆ parse_equality()

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

Parses equality/inequality expressions (==, @param[in] expr Expression to be processed @param[in] tokens Array of tokens to parse @param[in] ntokens Number of valid tokens in the array @param[inout] pos Current parsing position (updated as tokens are consumed) @param[in] macros Defined macros for expansion and defined()` checks.

Parameters
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 395 of file operators.f90.

◆ parse_expression()

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

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 169 of file operators.f90.

◆ parse_multiplicative()

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

Parses multiplicative expressions (*, /, %).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 552 of file operators.f90.

◆ parse_or()

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

Parses logical OR expressions (||).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 245 of file operators.f90.

◆ parse_power()

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

Parses exponentiation (**). Right-associative.

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 593 of file operators.f90.

◆ parse_relational()

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

Parses relational expressions (<, >, <=, >=).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 432 of file operators.f90.

◆ parse_shifting()

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

Parses shift expressions (<<, >>).

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]macrosDefined macros for expansion and defined() checks
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 478 of file operators.f90.

◆ parse_unary()

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

Parses unary operators ( @param[in] expr Expression to be processed @param[in] tokens Array of tokens to parse @param[in] ntokens Number of valid tokens in the array @param[inout] pos Current parsing position (updated as tokens are consumed) @param[in] macros Defined macros for expansion and defined()` checks.

Parameters
[in]ctxContext
Returns
Integer value of the parsed expression

Remarks

Definition at line 624 of file operators.f90.