diff --git a/loki/expression/parser.py b/loki/expression/parser.py index 3a6a05e80..010887878 100644 --- a/loki/expression/parser.py +++ b/loki/expression/parser.py @@ -6,6 +6,7 @@ # nor does it submit to any jurisdiction. from sys import intern +import re import pytools.lex from pymbolic.parser import Parser as ParserBase from pymbolic.mapper import Mapper @@ -27,7 +28,7 @@ def __init__(self, scope=None): super().__init__() def map_product(self, expr, *args, **kwargs): - return sym.Product(expr.children) + return sym.Product(tuple(self.rec(child, *args, **kwargs) for child in expr.children)) map_Mul = map_product def map_sum(self, expr, *args, **kwargs): @@ -35,23 +36,25 @@ def map_sum(self, expr, *args, **kwargs): map_Add = map_sum def map_power(self, expr, *args, **kwargs): - return sym.Power(base=expr.base, exponent=expr.exponent) + return sym.Power(base=self.rec(expr.base), + exponent=self.rec(expr.exponent)) def map_quotient(self, expr, *args, **kwargs): return sym.Quotient(numerator=expr.numerator, denominator=expr.denominator) def map_comparison(self, expr, *args, **kwargs): - # return sym.Comparison(tuple(self.rec(child, *args, **kwargs) for child in expr.children)) - return sym.Comparison(left=self.rec(expr.left), operator=expr.operator, right=self.rec(expr.right)) + return sym.Comparison(left=self.rec(expr.left), + operator=expr.operator, + right=self.rec(expr.right)) def map_logical_and(self, expr, *args, **kwargs): - return sym.LogicalAnd(expr.children) + return sym.LogicalAnd(tuple(self.rec(child, *args, **kwargs) for child in expr.children)) def map_logical_or(self, expr, *args, **kwargs): - return sym.LogicalOr(expr.children) + return sym.LogicalOr(tuple(self.rec(child, *args, **kwargs) for child in expr.children)) def map_logical_not(self, expr, *args, **kwargs): - return sym.LogicalNot(expr.children) + return sym.LogicalNot(self.rec(expr.child)) def map_constant(self, expr, *args, **kwargs): return sym.Literal(expr) @@ -71,7 +74,7 @@ def map_meta_symbol(self, expr, *args, **kwargs): map_array = map_meta_symbol def map_slice(self, expr, *args, **kwargs): - return sym.RangeIndex(expr.children) + return sym.RangeIndex(tuple(self.rec(child, *args, **kwargs) for child in expr.children)) map_range = map_slice map_range_index = map_slice @@ -80,6 +83,7 @@ def map_slice(self, expr, *args, **kwargs): def map_variable(self, expr, *args, **kwargs): return sym.Variable(name=expr.name, scope=self.scope) + # TODO: incomplete ... better approach possible? def map_algebraic_leaf(self, expr, *args, **kwargs): if str(expr).isnumeric(): return self.map_constant(expr) @@ -108,18 +112,18 @@ class LokiParser(ParserBase): _f_notequal = intern('_f_notequal') _f_and = intern("and") _f_or = intern("or") - # _f_not = intern("not") + _f_not = intern("not") lex_table = [ - (_f_lessequal, pytools.lex.RE(r"\.le\.")), - (_f_less, pytools.lex.RE(r"\.lt\.")), - (_f_greaterequal, pytools.lex.RE(r"\.ge\.")), - (_f_greater, pytools.lex.RE(r"\.gt\.")), - (_f_equal, pytools.lex.RE(r"\.eq\.")), - (_f_notequal, pytools.lex.RE(r"\.ne\.")), - (_f_and, pytools.lex.RE(r"\.and\.")), - (_f_and, pytools.lex.RE(r"\.or\.")), - # (_f_and, pytools.lex.RE(r"\.not\.")), + (_f_lessequal, pytools.lex.RE(r"\.le\.", re.IGNORECASE)), + (_f_less, pytools.lex.RE(r"\.lt\.", re.IGNORECASE)), + (_f_greaterequal, pytools.lex.RE(r"\.ge\.", re.IGNORECASE)), + (_f_greater, pytools.lex.RE(r"\.gt\.", re.IGNORECASE)), + (_f_equal, pytools.lex.RE(r"\.eq\.", re.IGNORECASE)), + (_f_notequal, pytools.lex.RE(r"\.ne\.", re.IGNORECASE)), + (_f_and, pytools.lex.RE(r"\.and\.", re.IGNORECASE)), + (_f_or, pytools.lex.RE(r"\.or\.", re.IGNORECASE)), + (_f_not, pytools.lex.RE(r"\.not\.", re.IGNORECASE)), ] + ParserBase.lex_table ParserBase._COMP_TABLE.update({ diff --git a/tests/test_expression.py b/tests/test_expression.py index 4c82850a9..6a60a6f76 100644 --- a/tests/test_expression.py +++ b/tests/test_expression.py @@ -1610,6 +1610,14 @@ def test_parser(frontend): print(f"{parsed} | {type(parsed)} | children: {parsed.children}") parsed = loki_parse('a .or. b') print(f"{parsed} | {type(parsed)} | children: {parsed.children}") + # parsed = loki_parse('.not. a') + parsed = loki_parse('a .or. .not. b') + print(f"{parsed} | {type(parsed)}") # | children: {parsed.child}") + print(f" {fgen(parsed)}") + parsed = loki_parse('a .OR. .NOT. b') + print(f"{parsed} | {type(parsed)}") # | children: {parsed.child}") + print(f" {fgen(parsed)}") parsed = loki_parse('((a + b)/(a - b))**3 + 3.1415', scope=routine) print(f"{parsed} | {type(parsed)}") + print(f" {fgen(parsed)}")