Hal
Hal

Reputation: 537

Pyparsing sum of optionally repeated expressions

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

Answers (1)

Arpit Choudhary
Arpit Choudhary

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

Related Questions