Skip to content

Commit

Permalink
Continued: Loki string parser based on pymbolic parser
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelSt98 committed Apr 4, 2024
1 parent 6489ed5 commit 41c130d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 18 deletions.
40 changes: 22 additions & 18 deletions loki/expression/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -27,31 +28,33 @@ 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):
return sym.Sum(tuple(self.rec(child, *args, **kwargs) for child in expr.children))
map_Add = map_sum

def map_power(self, expr, *args, **kwargs):

Check failure on line 38 in loki/expression/parser.py

View workflow job for this annotation

GitHub Actions / code checks (3.11)

W0613: Unused argument 'args' (unused-argument)

Check failure on line 38 in loki/expression/parser.py

View workflow job for this annotation

GitHub Actions / code checks (3.11)

W0613: Unused argument 'kwargs' (unused-argument)
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):

Check failure on line 45 in loki/expression/parser.py

View workflow job for this annotation

GitHub Actions / code checks (3.11)

W0613: Unused argument 'args' (unused-argument)

Check failure on line 45 in loki/expression/parser.py

View workflow job for this annotation

GitHub Actions / code checks (3.11)

W0613: Unused argument 'kwargs' (unused-argument)
# 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):

Check failure on line 56 in loki/expression/parser.py

View workflow job for this annotation

GitHub Actions / code checks (3.11)

W0613: Unused argument 'args' (unused-argument)

Check failure on line 56 in loki/expression/parser.py

View workflow job for this annotation

GitHub Actions / code checks (3.11)

W0613: Unused argument 'kwargs' (unused-argument)
return sym.LogicalNot(expr.children)
return sym.LogicalNot(self.rec(expr.child))

def map_constant(self, expr, *args, **kwargs):
return sym.Literal(expr)
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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({
Expand Down
8 changes: 8 additions & 0 deletions tests/test_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)}")

0 comments on commit 41c130d

Please sign in to comment.