2017-03-31 2 views
2

Wie erstellt man einen Parser, der Klammern in arithmetische Priorität in Ausdrücken mit der Bibliothek pyparsing macht? zum Beispiel * hat höhere Priorität als +.Python-Parser, der Klammern entsprechend der arithmetischen Priorität erstellt

Es sollte wie folgt vorgehen:

»> print(wholeexp.parseString('3+5-2')) 
[[['3', '+', '5'], '-', '2']] 
»> print(wholeexp.parseString('3+(5-2)')) 
[['3', '+', ['5', '-', '2']]] 
»> print(wholeexp.parseString('3+5-2*4')) 
[[['3', '+', '5'], '-', ['2', '*', '4']]] 

habe ich versucht, die folgenden, aber es funktioniert nicht sehr gut funktionieren. Wie sollten wir ändern ausdr hier:

from pyparsing import * 

numb = Word(nums) 
leftpar = Suppress('(') 
rightpar = Suppress(')') 

expr = Forward() 
expr << Or([numb, 
    Group(leftpar + expr + "+" + expr + rightpar), 
    Group(leftpar + expr + "-" + expr + rightpar), 
    Group(leftpar + expr + "*" + expr + rightpar)]) 

wholeexp = expr + StringEnd() 
+0

Haben Sie überprüft [diese Dokumentation] (https://pyparsing.wikispaces.com/file/view/SimpleCalc.py)? –

+0

Ein rekursiver Descent-Parser hilft: https://en.wikipedia.org/wiki/Recursive_descent_parser. Oder ein Shunting-Yard-Algorithmus: https://en.wikipedia.org/wiki/Shunting-yard_algorithm. Aber zuerst diese SO Frage zu entscheiden, welche zu wählen: http://stackoverflow.com/questions/28256/equation-expression-parser-with-precedence. – rajah9

Antwort

0

Dieser Artikel scheint vielversprechend: Simple Top-Down Parsing in Python Ich weiß, dass es viel ist, aber nach unten scrollen der „Streamlining Token-Klasse Generation“ Abschnitt und Sie werden es in Aktion sehen. Ich persönlich konnte es wegen eines Fehlers nicht zum Laufen bringen: AttributeError: 'generator' object has no attribute 'next' aber ich bin ziemlich sicher, dass es mit der Tatsache zu tun hat, dass die nächste Methode in Python 3.0 geändert wurde. Der Code ist zu kompliziert für mich, um das Problem zu verstehen und zu beheben, aber Sie könnten mehr Glück haben.

Edit: Gerade lief es in Python 2.7 und es hat funktioniert. Sie können es entweder in einer älteren Version von Python ausführen oder den Code durchgehen und versuchen, ihn zu beheben.

+0

andere Varianten? – parYosef

1

Ihr Ansatz ist ähnlich wie in diesem Beispiel: http://pyparsing.wikispaces.com/file/view/fourFn.py. Aber neuere Versionen von operatorPrecedence eingeführt pyparsing, umbenannt in jüngerer Zeit infixNotation und Ihr 4-Funktion arithmetischen Ausdruck Parser sieht wie folgt aus:

import pyparsing as pp 

integer = pp.pyparsing_common.integer() 

four_fn_arith_expr = pp.infixNotation(integer, 
            [ 
             # leading sign 
             (pp.oneOf("+ -"), 1, pp.opAssoc.RIGHT,), 
             # multiplication and division 
             (pp.oneOf("* /"), 2, pp.opAssoc.LEFT,), 
             # addition and subtraction 
             (pp.oneOf("+ -"), 2, pp.opAssoc.LEFT,), 
            ]) 

Hier sind Ihre Testfälle laufen mit diesem Parser:

tests = """ 
    3+5-2 
    3+(5-2) 
    3+5--2 
    3+5-2*4 
    """ 
four_fn_arith_expr.runTests(tests, fullDump=False) 

gibt:

3+5-2 
[[3, '+', 5, '-', 2]] 

3+(5-2) 
[[3, '+', [5, '-', 2]]] 

3+5--2 
[[3, '+', 5, '-', ['-', 2]]] 

3+5-2*4 
[[3, '+', 5, '-', [2, '*', 4]]] 
+0

Wir brauchen Parser, der von links nach rechts geht und nach arithmetischer Op. wird Klammern nach Priorität machen, z.B. »> drucken (wholeexp.parseString ('3 + 5-2')) [[['3', '+', '5'], '-', '2']] »> drucken (wholeexp .parseString ('3+ (5-2)')) [['3', '+', ['5', '-', '2']]]] »> drucken (whoexexp.parseString (' 3 + 5-2 * 4 ')) [[[' 3 ',' + ',' 5 '],' - ', [' 2 ',' * ',' 4 ']]]] drucken (expr .parseString ('3 + 5-4-2')) [[['3', '+', '5'], '-', '4'], '-', '2']] mit Forward und spezifischen Funktionen. hilf mir bitte, danke! – parYosef

+0

Diese verbleibende Transformation bleibt als Übung für das OP übrig. – PaulMcG

Verwandte Themen