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:

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 except the verbose flag from the logging module (used only for debugging).

    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()

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

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]valOptional integer result of the evaluation
Returns
.true. if the expression evaluated successfully to non-zero, .false. otherwise

Remarks

Definition at line 92 of file operators.f90.

◆ parse_additive()

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

Parses additive expressions (+, -).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 445 of file operators.f90.

◆ parse_and()

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

Parses logical AND expressions (&&).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 226 of file operators.f90.

◆ parse_atom()

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

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

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 581 of file operators.f90.

◆ parse_bitwise_and()

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

Parses bitwise AND expressions (&).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 307 of file operators.f90.

◆ parse_bitwise_or()

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

Parses bitwise OR expressions (|).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 253 of file operators.f90.

◆ parse_bitwise_xor()

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

Parses bitwise XOR expressions (^).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 280 of file operators.f90.

◆ parse_conditional()

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

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

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 147 of file operators.f90.

◆ parse_equality()

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

Parses equality/inequality expressions (==, @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 anddefined()` checks.

Returns
Integer value of the parsed expression

Remarks

Definition at line 334 of file operators.f90.

◆ parse_expression()

recursive integer function, public parse_expression ( type(token), dimension(:), intent(in) tokens,
integer, intent(in) ntokens,
integer, intent(inout) pos,
type(macro), dimension(:), intent(in) macros )

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]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
Returns
Integer value of the parsed expression

Remarks

Definition at line 129 of file operators.f90.

◆ parse_multiplicative()

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

Parses multiplicative expressions (*, /, %).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 479 of file operators.f90.

◆ parse_or()

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

Parses logical OR expressions (||).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 200 of file operators.f90.

◆ parse_power()

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

Parses exponentiation (**). Right-associative.

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 517 of file operators.f90.

◆ parse_relational()

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

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

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 368 of file operators.f90.

◆ parse_shifting()

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

Parses shift expressions (<<, >>).

Parameters
[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
Returns
Integer value of the parsed expression

Remarks

Definition at line 411 of file operators.f90.

◆ parse_unary()

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

Parses unary operators ( @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 anddefined()` checks.

Returns
Integer value of the parsed expression

Remarks

Definition at line 545 of file operators.f90.