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
與其他預定義的表達式

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]]]
我想知道您是否在解析器的實現中遇到過這些用例并找到了解決方法。
添加回答
舉報