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]]]
我想知道您是否在解析器的实现中遇到过这些用例并找到了解决方法。
添加回答
举报