簡體   English   中英

PyParsing中的簡單遞歸下降

[英]Simple recursive descent in PyParsing

我已經嘗試使用這段代碼並將其轉換為我正在編寫的用於編程語言處理的項目,但我遇到了一個簡化版本的問題:

op = oneOf( '+ - / *')
lparen, rparen = Literal('('), Literal(')')

expr = Forward()
expr << ( Word(nums) | ( expr + op + expr ) | ( lparen + expr + rparen) )

我已經玩過這個簡單設置的許多不同的修改。 通常,嘗試以下方式:

print(expr.parseString('1+2'))

將返回['1'] 雖然我陷入了深度遞歸中,例如:

print(expr.parseString('(1+2)'))

關於我無法解析任意算術表達式的簡單遞歸,我缺少什么,例如1+(2 * 3-(4*(5+6)-(7))...

哇,我猜pyparsing真的在地圖上! 感謝Alex和John踩到這個問題。 你的回答都是你的標記。 但是,讓我添加一兩條評論:

  1. 如果我們抑制左括號和右括號,並使用Group對帶括號的表達式進行分組,則pyparsing將是一個更接近AST的結構化結果。

     from pyparsing import Literal,Word,ZeroOrMore,Forward,nums,oneOf,Group def Syntax(): op = oneOf('+ -') lpar = Literal( '(' ).suppress() rpar = Literal( ')' ).suppress() num = Word(nums) expr = Forward() atom = num | Group(lpar + expr + rpar) expr << atom + ZeroOrMore(op + atom) return expr if __name__ == "__main__": expr = Syntax() def test(s): results = expr.parseString(s) print s,'->', results test( "(9 + 3)" ) test( "(9 + 3) * (4 / 5)" ) 

    贈送:

     (9 + 3) -> [['9', '+', '3']] (9 + 3) * (4 / 5) -> [['9', '+', '3'], '*', ['4', '/', '5']] 

    否則,pyparsing只是標記化,你必須遍歷解析的標記列表才能找到嵌套的表達式。

  2. 由於op被定義為oneOf(“+ - * /”),因此沒有優先級的操作。 有關pyparsing repo的示例,請參閱https://github.com/pyparsing/pyparsing/tree/master/examples定義此方法(fourFn.py)或使用infixNotation幫助程序的更新方法(simpleArith。 PY)。 同樣,這使得pyparsing增加了比標記化更多的價值。

對於OP,請查看這些示例,我認為它們將幫助您推進項目。

- 保羅

這或多或少是你想要的......?

from pyparsing import Literal,Word,ZeroOrMore,Forward,nums,oneOf

def Syntax():
    op = oneOf( '+ - / *')
    lpar  = Literal( '(' )
    rpar  = Literal( ')' )
    num = Word(nums)

    expr = Forward()
    atom = num | ( lpar + expr + rpar )
    expr << atom + ZeroOrMore( op + expr )
    return expr


if __name__ == "__main__":

    expr = Syntax()

    def test(s):
        results = expr.parseString( s )
        print s,'->', results

    test( "(9 + 3)" )
    test( "(9 + 3) * (4 / 5)" )

發光

(9 + 3) -> ['(', '9', '+', '3', ')']
(9 + 3) * (4 / 5) -> ['(', '9', '+', '3', ')', '*', '(', '4', '/', '5', ')']

這通過將“原子”(數字或帶括號的表達式)與“表達式”(一個或多個“原子”與中間的運算符)分開來“錨定”遞歸。

語法如:

expr :: expr op expr

很難處理,因為遞歸只是潛入左側。

正常的算術語法看起來像:

expr :: mulxp | mulxp '+' expr
mulxp :: atom | atom '*' expr
atom :: Word(nums) | '(' + expr + ')'

基本上,你永遠不會得到S :: S ; 任何時候非終結符出現在語法的一行的左側和右側,中間必須有一些文字供解析器使用。

使用operatorPrecedence構建表達式。 它將構建正確的表達式,並在它處理運算符優先級時:

num = Word(nums)
plusop = oneOf( '+ -')
multop = oneOf('/ *')
expr = operatorPrecedence(num,
                          [(multop, 2, opAssoc.LEFT),(plusop, 2, opAssoc.LEFT)])

例:

>> print parsetime.expr.parseString("1+(2 * 3-(4*(5+6)-(7)))")
[['1', '+', [['2', '*', '3'], '-', [['4', '*', ['5', '+', '6']], '-', '7']]]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM