Reputation: 537
I am working on an simple parser to handle expression such as:
"""
FOO*1.5
+
BAR*3
"""
To get an end numeric result, where FOO
and BAR
are replaced at runtime by the values returned by external function executions. For example: FOO ---> def foo():return 2
and BAR ---> def bar():return 4
. Which in our example would yield (2*1.5)+(4*3) = 3+12 = 14
.
This is what I have so far:
from pyparsing import *
from decimal import Decimal
WEIGHT_OPERATORS = ['*', '/']
NUMERIC_OPERATORS = ['+', '-']
def make_score(input):
if input[0] == 'FOO':
return 5
elif input[0] == 'BAR':
return 10
return 1
def make_decimal(input):
try:
return Decimal(input[0])
except ValueError:
pass
return 0
SCORE = Word(alphanums + '_').setParseAction(make_score)
WEIGHT_OPERATOR = oneOf(WEIGHT_OPERATORS)
WEIGHT = Word(nums+'.').setParseAction(make_decimal)
INDIVIDUAL_EXPRESSION = SCORE('score') \
+ WEIGHT_OPERATOR('weight_operator') \
+ WEIGHT('weight')
print INDIVIDUAL_EXPRESSION
print INDIVIDUAL_EXPRESSION.parseString(expression).dump()
Up to here, all works well.
What I miss is the ability to "chain" INDIVIDUAL_EXPRESSIONs together to add/substract them together, as in the simple example above. I have tried:
GLOBAL_EXPRESSION = infixNotation(
INDIVIDUAL_EXPRESSION,
[
(NUMERIC_OPERATORS, 2, opAssoc.RIGHT,)
# or (NUMERIC_OPERATORS, 1, opAssoc.LEFT,), etc... :(
]
)
print GLOBAL_EXPRESSION
print GLOBAL_EXPRESSION.parseString(expression).dump()
Nope.
And:
INDIVIDUAL_EXPRESSION = SCORE('score') \
+ WEIGHT_OPERATOR('weight_operator') \
+ WEIGHT('weight')
+ ZeroOrMore(NUMERIC_OPERATORS)
To get the final list or dict that would easy to compute, to no avail. I am doing something wrong, but what?
Upvotes: 2
Views: 134
Reputation: 108
Try this:
GLOBAL_EXPRESSION = OneOrMore(Group(INDIVIDUAL_EXPRESSION) + Optional(oneOf(NUMERIC_OPERATORS)))
GE_LIST = Group(delimitedList(GLOBAL_EXPRESSION))
print GE_LIST.parseString(expression)
Upvotes: 1