loki.expression.parser

Module Attributes

FORTRAN_INTRINSIC_PROCEDURES

list of intrinsic fortran procedure(s) names

parse_expr

An instance of ExpressionParser that allows parsing expression strings into a Loki expression tree.

Classes

ExpressionParser()

String Parser based on pymbolic.parser.Parser for parsing expressions from strings.

LokiEvaluationMapper([strict])

A mapper for evaluating expressions, based on pymbolic.mapper.evaluator.EvaluationMapper.

PymbolicMapper()

Pymbolic expression to Loki expression mapper.

class ExpressionParser

Bases: Parser

String Parser based on pymbolic.parser.Parser for parsing expressions from strings.

The Loki String Parser utilises and extends pymbolic’s parser to incorporate Fortran specific syntax and to map pymbolic expressions to Loki expressions, utilising the mapper PymbolicMapper.

Further, in order to ensure correct ordering of Fortran Statements as documented in ‘WD 1539-1 J3/23-007r1 (Draft Fortran 2023)’, pymbolic’s parsing logic needed to be slightly adapted.

Pymbolic references:

Note

Example:

Using the expression parser and possibly evaluate them

>>> from loki import parse_expr
>>> # parse numerical expressions
>>> ir = parse_expr('3 + 2**4')
>>> ir
Sum((IntLiteral(3, None), Power(IntLiteral(2, None), IntLiteral(4, None))))
>>> # or expressions with variables
>>> ir = parse_expr('a*b')
>>> ir
Product((DeferredTypeSymbol('a', None, None, <SymbolAttributes BasicType.DEFERRED>),                    DeferredTypeSymbol('b', None, None, <SymbolAttributes BasicType.DEFERRED>)))
>>> # and provide a scope e.g, with some routine defining a and b as 'real's
>>> ir = parse_expr('a*b', scope=routine)
>>> ir
Product((Scalar('a', None, None, None), Scalar('b', None, None, None)))
>>> # further, it is possible to evaluate expressions
>>> ir = parse_expr('a*b + 1', evaluate=True, context={'a': 2, 'b': 3})
>>> ir
>>> IntLiteral(7, None)
>>> # even with functions implemented in Python
>>> def add(a, b):
>>>     return a + b
>>> ir = parse_expr('a + add(a, b)', evaluate=True, context={'a': 2, 'b': 3, 'add': add})
>>> ir
>>> IntLiteral(7, None)
__call__(expr_str, scope=None, evaluate=False, strict=False, context=None)

Call Loki String Parser to convert expression(s) represented in a string to Loki expression(s)/IR.

Parameters:
  • expr_str (str) – The expression as a string

  • scope (Scope) – The scope to which symbol names inside the expression belong

  • evaluate (bool, optional) – Whether to evaluate the expression or not (default: False)

  • strict (bool, optional) – Whether to raise exception for unknown variables/symbols when evaluating an expression (default: False)

  • context (dict, optional) – Symbol context, defining variables/symbols/procedures to help/support evaluating an expression

Returns:

The expression tree corresponding to the expression

Return type:

Expression

lex_table = [('f_true', RE(\.true\.)), ('f_false', RE(\.false\.)), ('_f_lessequal', RE(\.le\.)), ('_f_less', RE(\.lt\.)), ('_f_greaterequal', RE(\.ge\.)), ('_f_greater', RE(\.gt\.)), ('_f_equal', RE(\.eq\.)), ('_f_notequal', RE(\.ne\.)), ('and', RE(\.and\.)), ('or', RE(\.or\.)), ('not', RE(\.not\.)), ('f_float', ('|', RE([0-9]+\.[0-9]*([eEdD][+-]?[0-9]+)?(_([\w$]+|[0-9]+))+$))), ('f_int', RE([0-9]+?(_[a-zA-Z]*))), ('f_string', ('|', RE(\".*\"), RE(\'.*\'))), ('openbracket', RE(\(/)), ('closebracket', RE(/\))), ('dot', RE(\%)), ('equal', RE(==)), ('notequal', RE(!=)), ('equal', RE(==)), ('leftshift', RE(\<\<)), ('rightshift', RE(\>\>)), ('lessequal', RE(\<=)), ('greaterequal', RE(\>=)), ('less', RE(\<)), ('greater', RE(\>)), ('assign', RE(=)), ('and', RE(and\b)), ('or', RE(or\b)), ('not', RE(not\b)), ('if', RE(if\b)), ('else', RE(else\b)), ('imaginary', ('float', RE(j))), ('float', ('|', RE([0-9]+\.[0-9]*([eEdD][+-]?[0-9]+)?([a-zA-Z]*)), RE([0-9]+(\.[0-9]*)?[eEdD][+-]?[0-9]+([a-zA-Z]*)\b), RE([0-9]*\.[0-9]+([eEdD][+-]?[0-9]+)?([a-zA-Z]*)), RE([0-9]*\.[0-9]+[eEdD][+-]?[0-9]+([a-zA-Z]*)\b), RE([0-9]+([a-zA-Z]+)))), ('int', RE([0-9]+)), ('plus', RE(\+)), ('minus', RE(-)), ('exp', RE(\*\*)), ('times', RE(\*)), ('floordiv', RE(//)), ('over', RE(/)), ('modulo', RE(%)), ('bitwiseand', RE(\&)), ('bitwiseor', RE(\|)), ('bitwisenot', RE(\~)), ('bitwisexor', RE(\^)), ('openpar', RE(\()), ('closepar', RE(\))), ('openbracket', RE(\[)), ('closebracket', RE(\])), ('True', RE(True)), ('False', RE(False)), ('identifier', RE([@$a-z_A-Z_][@$a-zA-Z_0-9]*)), ('whitespace', RE([  ]*)), ('comma', RE(,)), ('dot', RE(\.)), ('colon', RE(\:))]

Extend pymbolic.parser.Parser.lex_table to accomodate for Fortran specifix syntax/expressions.

parse_prefix(pstate)
parse_postfix(pstate, min_precedence, left_exp)
parse_terminal(pstate)
parse_float(s)

Parse float literals.

Do not cast to float via ‘float()’ in order to keep the original notation, e.g., do not convert 1E-3 to 0.003.

parse_f_float(s)

Parse “Fortran-style” float literals.

E.g., 3.1415_my_real_kind.

parse_f_int(s)

Parse “Fortran-style” int literals.

E.g., 1_my_int_kind.

parse_f_string(s)

Parse string literals.

parse_expr = <loki.expression.parser.ExpressionParser object>

An instance of ExpressionParser that allows parsing expression strings into a Loki expression tree. See ExpressionParser.__call__ for a description of the available arguments.

FORTRAN_INTRINSIC_PROCEDURES = ['ABS', 'AIMAG', 'AINT', 'ANINT', 'CEILING', 'CMPLX', 'CONJG', 'DBLE', 'DIM', 'DPROD', 'FLOOR', 'INT', 'MAX', 'MIN', 'MOD', 'MODULO', 'NINT', 'REAL', 'SIGN', 'ACOS', 'ASIN', 'ATAN', 'ATAN2', 'COS', 'COSH', 'EXP', 'LOG', 'LOG10', 'SIN', 'SINH', 'SQRT', 'TAN', 'TANH', 'ACHAR', 'ADJUSTL', 'ADJUSTR', 'CHAR', 'IACHAR', 'ICHAR', 'INDEX', 'LEN_TRIM', 'LGE', 'LGT', 'LLE', 'LLT', 'REPEAT', 'SCAN', 'TRIM', 'VERIFY', 'KIND', 'SELECTED_CHAR_KIND', 'SELECTED_INT_KIND', 'SELECTED_REAL_KIND', 'LOGICAL', 'TRANSFER', 'DIGITS', 'EPSILON', 'HUGE', 'MAXEXPONENT', 'MINEXPONENT', 'PRECISION', 'RADIX', 'RANGE', 'TINY', 'LBOUND', 'SHAPE', 'SIZE', 'UBOUND', 'ALLOCATED', 'ASSOCIATED', 'BIT_SIZE', 'EXTENDS_TYPE_OF', 'LEN', 'NEW_LINE', 'PRESENT', 'SAME_TYPE_AS', 'BTEST', 'IAND', 'IBCLR', 'IBITS', 'IBSET', 'IEOR', 'IOR', 'ISHFT', 'ISHFTC', 'MVBITS', 'NOT', 'EXPONENT', 'FRACTION', 'NEAREST', 'RRSPACING', 'SCALE', 'SET_EXPONENT', 'SPACING', 'DOT_PRODUCT', 'MATMUL', 'ALL', 'ANY', 'COUNT', 'MAXVAL', 'MINVAL', 'PRODUCT', 'SUM', 'CSHIFT', 'EOSHIFT', 'MERGE', 'PACK', 'RESHAPE', 'SPREAD', 'TRANSPOSE', 'UNPACK', 'MAXLOC', 'MINLOC', 'NULL', 'MOVE_ALLOC', 'RANDOM_NUMBER', 'RANDOM_SEED', 'COMMAND_ARGUMENT_COUNT', 'CPU_TIME', 'DATE_AND_TIME', 'GET_COMMAND', 'GET_COMMAND_ARGUMENT', 'GET_ENVIRONMENT_VARIABLE', 'IS_IOSTAT_END', 'IS_IOSTAT_EOR', 'SYSTEM_CLOCK', 'ALOG', 'ALOG10', 'AMAX0', 'AMAX1', 'AMIN0', 'AMIN1', 'AMOD', 'CABS', 'CCOS', 'CEXP', 'CLOG', 'CSIN', 'CSQRT', 'DABS', 'DACOS', 'DASIN', 'DATAN', 'DATAN2', 'DCOS', 'DCOSH', 'DDIM', 'DEXP', 'DINT', 'DLOG', 'DLOG10', 'DMAX1', 'DMIN1', 'DMOD', 'DNINT', 'DSIGN', 'DSIN', 'DSINH', 'DSQRT', 'DTAN', 'DTANH', 'FLOAT', 'IABS', 'IDIM', 'IDINT', 'IDNINT', 'IFIX', 'ISIGN', 'MAX0', 'MAX1', 'MIN0', 'MIN1', 'SNGL']

list of intrinsic fortran procedure(s) names