亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Pyparsing Precedence 打破一元運算符

Pyparsing Precedence 打破一元運算符

慕無忌1623718 2023-04-25 15:46:07
我正在嘗試使用pyparsing. 我有以下代碼實現我的解析器:variable_names = pyparsing.Combine(pyparsing.Literal('$') + pyparsing.Word(pyparsing.alphanums + '_'))integer = pyparsing.Word(pyparsing.nums)double = pyparsing.Combine(pyparsing.Word(pyparsing.nums) + '.' + pyparsing.Word(pyparsing.nums))parser = pyparsing.operatorPrecedence(variable_names | double | integer, [                                ('**', 2, pyparsing.opAssoc.RIGHT),                                ('-', 1, pyparsing.opAssoc.RIGHT),                                (pyparsing.oneOf('* / // %'), 2, pyparsing.opAssoc.LEFT),                                (pyparsing.oneOf('+ -'), 2, pyparsing.opAssoc.LEFT),                                (pyparsing.oneOf('> >= < <= == !='), 2, pyparsing.opAssoc.LEFT),                                ('not', 1, pyparsing.opAssoc.RIGHT),                                ('and', 2, pyparsing.opAssoc.LEFT),                                ('or', 2, pyparsing.opAssoc.LEFT)])在大多數情況下,這工作正常,但有時當我使用一元時它會中斷-。具體來說,我認為(我可能是錯的)如果我-在更高優先級的操作數之后使用它會中斷,在這種情況下就是**. 以下示例顯示了該問題:parsing 5 * 10 * -2             yields: ['5', '*', '10', '*', ['-', '2']]parsing 5 * 10 ** -2            yields: ['5', '*', '10']               # Wrongparsing 5 * 10 ** (-2)          yields: ['5', '*', ['10', '**', ['-', '2']]]parsing 5 and not 8             yields: ['5', 'and', ['not', '8']]parsing 5 and - 8               yields: ['5', 'and', ['-', '8']]發生這種情況有什么原因嗎?我錯過了什么?
查看完整描述

2 回答

?
米琪卡哇伊

TA貢獻1998條經驗 獲得超6個贊

至于我,你應該定義-為更高**


('-', 1, pyparsing.opAssoc.RIGHT),

('**', 2, pyparsing.opAssoc.RIGHT),

這應該可以解決您的問題。


最小的工作代碼


import pyparsing


variable_names = pyparsing.Combine(pyparsing.Literal('$') + pyparsing.Word(pyparsing.alphanums + '_'))


integer = pyparsing.Word(pyparsing.nums)


double = pyparsing.Combine(pyparsing.Word(pyparsing.nums) + '.' + pyparsing.Word(pyparsing.nums))


parser = pyparsing.operatorPrecedence(

? ? ? ? ? ? variable_names | double | integer,

? ? ? ? ? ? [

? ? ? ? ? ? ? ? ('-',? 1, pyparsing.opAssoc.RIGHT),

? ? ? ? ? ? ? ? ('**', 2, pyparsing.opAssoc.RIGHT),

? ? ? ? ? ? ? ? (pyparsing.oneOf('* / // %'), 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? (pyparsing.oneOf('+ -'), 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? (pyparsing.oneOf('> >= < <= == !='), 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? ('not', 1, pyparsing.opAssoc.RIGHT),

? ? ? ? ? ? ? ? ('and', 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? ('or',? 2, pyparsing.opAssoc.LEFT)

? ? ? ? ? ? ]

? ? ? ? )


examples = [

? ? "5 * 10 ** -2",

? ? "5 * 10 * -2",

? ? "5 * 10 ** (-2)",

? ? "5 * -10 ** 2",

? ? "5 * (-10) ** 2",? ??

? ? "5 and not 8",

? ? "5 and -8",

? ? "1 ** -2",

? ? "-1 ** 2",

]


longest = max(map(len, examples))


for ex in examples:

? ? result = parser.parseString(ex)

? ? print(f'{ex:{longest}}? <=>? {result}')

結果:


5 * 10 ** -2? ? <=>? [['5', '*', ['10', '**', ['-', '2']]]]

5 * 10 * -2? ? ?<=>? [['5', '*', '10', '*', ['-', '2']]]

5 * 10 ** (-2)? <=>? [['5', '*', ['10', '**', ['-', '2']]]]

5 * -10 ** 2? ? <=>? [['5', '*', [['-', '10'], '**', '2']]]

5 * (-10) ** 2? <=>? [['5', '*', [['-', '10'], '**', '2']]]

5 and not 8? ? ?<=>? [['5', 'and', ['not', '8']]]

5 and -8? ? ? ? <=>? [['5', 'and', ['-', '8']]]

1 ** -2? ? ? ? ?<=>? [['1', '**', ['-', '2']]]

-1 ** 2? ? ? ? ?<=>? [[['-', '1'], '**', '2']]

順便說一句:為了比較:C 運算符優先級和Python - 運算符優先級

編輯:


我之前保留時可以得到-500( 5 * -10 ** 2)但我使用[[5, '*', ['-', [10, '**', 2]]]]**-


integer = pyparsing.pyparsing_common.signed_integer

import pyparsing


variable_names = pyparsing.Combine(pyparsing.Literal('$') + pyparsing.Word(pyparsing.alphanums + '_'))


#integer = pyparsing.Word(pyparsing.nums)

integer = pyparsing.pyparsing_common.signed_integer


double = pyparsing.Combine(pyparsing.Word(pyparsing.nums) + '.' + pyparsing.Word(pyparsing.nums))


parser = pyparsing.operatorPrecedence(

? ? ? ? ? ? variable_names | double | integer,

? ? ? ? ? ? [

? ? ? ? ? ? ? ? ('**', 2, pyparsing.opAssoc.RIGHT),

? ? ? ? ? ? ? ? ('-',? 1, pyparsing.opAssoc.RIGHT),

? ? ? ? ? ? ? ? (pyparsing.oneOf('* / // %'), 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? (pyparsing.oneOf('+ -'), 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? (pyparsing.oneOf('> >= < <= == !='), 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? ('not', 1, pyparsing.opAssoc.RIGHT),

? ? ? ? ? ? ? ? ('and', 2, pyparsing.opAssoc.LEFT),

? ? ? ? ? ? ? ? ('or',? 2, pyparsing.opAssoc.LEFT)

? ? ? ? ? ? ]

? ? ? ? )


examples = [

? ? "5 * 10 ** -2",

? ? "5 * 10 * -2",

? ? "5 * 10 ** (-2)",

? ? "5 * -10 ** 2",

? ? "5 * (-10) ** 2",? ??

? ? "5 and not 8",

? ? "5 and -8",

? ? "1 ** -2",

? ? "-1 ** 2",

]


longest = max(map(len, examples))


for ex in examples:

? ? result = parser.parseString(ex)

? ? print(f'{ex:{longest}}? <=>? {result}')

結果:


5 * 10 ** -2? ? <=>? [[5, '*', [10, '**', -2]]]

5 * 10 * -2? ? ?<=>? [[5, '*', 10, '*', ['-', 2]]]

5 * 10 ** (-2)? <=>? [[5, '*', [10, '**', ['-', 2]]]]

5 * -10 ** 2? ? <=>? [[5, '*', ['-', [10, '**', 2]]]]

5 * (-10) ** 2? <=>? [[5, '*', [['-', 10], '**', 2]]]

5 and not 8? ? ?<=>? [[5, 'and', ['not', 8]]]

5 and -8? ? ? ? <=>? [[5, 'and', ['-', 8]]]

1 ** -2? ? ? ? ?<=>? [[1, '**', -2]]

-1 ** 2? ? ? ? ?<=>? [['-', [1, '**', 2]]]

Doc forpyparsing_common與其他預定義的表達式


查看完整回答
反對 回復 2023-04-25
?
翻閱古今

TA貢獻1780條經驗 獲得超5個贊

很抱歉帶回這么老的主題,但我正在為我的項目編寫一個非常相似的解析器,它混合了布爾邏輯和數學運算符,我最終得到了一個看起來很合適的相似代碼。


由于此處給出的解析器遇到與我相同的問題,因此我將使用它來說明我的問題。


我無法讓它解析“$true == not $false”,基本上,如果沒有括號,比較后的任何“not”都不會起作用。


$true == $false        <=>  [['$true', '==', '$false']]

$true == not $false    <=>  ['$true']

$true == (not $false)  <=>  [['$true', '==', ['not', '$false']]]

如您所見,沒有“not”或有括號,它解析得很好,但是有一個簡單的“not”,它似乎忽略了“==”之后的所有內容


在 infix_notation(以前的 operatorPrecedence)中先移動“not”運算符是什么修復方法。然后我得到了這些結果:


$true == not $false    <=>  [['$true', '==', ['not', '$false']]]

$true == (not $false)  <=>  [['$true', '==', ['not', '$false']]]

這是偉大的,但當然它打破了諸如“$true and not 10 == 9”之類的運算符優先級,我想像在 python 中那樣解析“$true and not (10 == 9)”而不是解析像那樣:


$true and not 10 == 9  <=>  [['$true', 'and', [['not', 10], '==', 9]]]

我想知道您是否在解析器的實現中遇到過這些用例并找到了解決方法。


查看完整回答
反對 回復 2023-04-25
  • 2 回答
  • 0 關注
  • 163 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號