简体   繁体   中英

Pyparsing simple arithmetic grammar does not capture the expression

I am currently writing a parser for simple arithmetic strings with (), {} and [] as balanced brackets and * and + as operations. Somehow my grammar seems to be off though. Does somebody have an idea how to fix that? I tried to be a bit more recursive but always run into recursion depth errors.

from pyparsing import *
enclosed = Forward()
nestedParens = nestedExpr('(', ')', content=enclosed)
nestedBrackets = nestedExpr('[', ']', content=enclosed)
nestedCurlies = nestedExpr('{', '}', content=enclosed)

braexpr = Forward()
parexpr = Forward()
curexpr = Forward()

parexpr << OneOrMore(infixNotation(
    nestedParens | nestedBrackets | nestedCurlies | Word(nums),
    [
        ('*', 2, opAssoc.LEFT),
        ('+', 2, opAssoc.LEFT),
    ]
))

curexpr << OneOrMore(infixNotation(
    nestedParens | nestedBrackets | nestedCurlies | Word(nums),
    [
        ('*', 2, opAssoc.LEFT),
        ('+', 2, opAssoc.LEFT),
    ],
    Suppress('{'),
    Suppress('}')
))
braexpr << OneOrMore(infixNotation(
    nestedParens | nestedBrackets | nestedCurlies | Word(nums),
    [
        ('*', 2, opAssoc.LEFT),
        ('+', 2, opAssoc.LEFT),
    ],
    Suppress('['),
    Suppress(']')
))

enclosed << ( (nestedParens | nestedBrackets | nestedCurlies | Word(nums)) + oneOf("+ *") + (enclosed | nestedParens | nestedBrackets | nestedCurlies | Word(nums)) | parexpr | curexpr | braexpr | nestedParens | nestedBrackets | nestedCurlies | Word(nums) )

print(evaluate("[{1}+5]*({2}+[{1*3}+2] + 2])"))

If you just have the basic arithmetic operators, then I suggest you not use infixNotation, but instead define your own recursive parser, something like:

import pyparsing as pp
ppc = pp.pyparsing_common

operand = ppc.integer()
multop = pp.oneOf("* /")
addop = pp.oneOf("+ -")

expr = pp.Forward()
# here is where to extend the grouping symbols to include (), [], and {}
LPAR, RPAR, LBRACK, RBRACK, LBRACE, RBRACE = map(pp.Suppress, "()[]{}")
atom = operand | LPAR + expr + RPAR | LBRACK + expr + RBRACK | LBRACE + expr + RBRACE
factor = pp.Group('-' + atom) | atom
term = pp.Group(factor + (multop + factor)[1, ...]) | factor
sum = pp.Group(term + (addop + term)[1, ...]) | term
expr <<= sum

Some simple tests:

expr.runTests("""
1+7
1+2+4
-(1+2)*4
3*[11+14]
""", fullDump=False)

Gives:

1+7
[[1, '+', 7]]

1+2+4
[[1, '+', 2, '+', 4]]

-(1+2)*4
[[['-', [1, '+', 2]], '*', 4]]

3*[11+14]
[[3, '*', [11, '+', 14]]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM