gpt4 book ai didi

python - pyparsing如何使用infixNotation来表示iif(cond, if true, if false)

转载 作者:行者123 更新时间:2023-12-01 07:47:11 25 4
gpt4 key购买 nike

我需要使用pyparsing来解析它:iif(condition,value if true,value if false),但是这种三元比较应该有另一个比较,我的意思是:

`iif(iif(condition1,value1,value2)>iif(condition2,value1,value2),value3,value4)`

我发现了这个:

integer = Word(nums)
variable = Word(alphas, alphanums)
boolLiteral = oneOf("true false")
operand = boolLiteral | variable | integer
comparison_op = oneOf("== <= >= != < >")
QM,COLON = map(Literal,"?:")
expr = infixNotation(operand,
[
(comparison_op, 2, opAssoc.LEFT),
((QM,COLON), 3, opAssoc.LEFT),
])

它能够解析这个:expr.parseString("(x==1? true: (y == 10? 100 : 200) )")

但我无法修改此代码以满足我的需要。我怎样才能实现这个目标?

更新

感谢 Paul 先生,我想出了这个解决方案:

arith_expr = Forward()

iif = CaselessKeyword("iif")
open = Literal("(")
close = Literal(")")

var_name = pyparsing_common.identifier()
fn_call = Group(iif + open - Group(Optional(delimitedList(arith_expr))) + close)
arith_operand = fn_call | num

rel_comparison_operator = oneOf("< > <= >=")
eq_comparison_operator = oneOf("== !=")
plus_minus_operator = oneOf("+ -")
mult_div_operator = oneOf("* / %")

arith_expr <<= infixNotation(arith_operand,
[
# add other operators here - in descending order of precedence
# http://www.tutorialspoint.com/cprogramming/c_operators_precedence.htm
('-', 1, opAssoc.RIGHT),
(mult_div_operator, 2, opAssoc.LEFT,),
(plus_minus_operator, 2, opAssoc.LEFT,),
(rel_comparison_operator, 2, opAssoc.LEFT,),
(eq_comparison_operator, 2, opAssoc.LEFT,),
]
)

我正在使用我以前的一些规则。现在我投票结束这篇文章。

最佳答案

正如 @sepp2k 在他的评论中提到的,您尝试解析的字符串不是中缀表示法,尽管您最终可能会用作中缀表示法的操作数。并且传递给 iif 的参数本身可能是中缀表示法表达式。因此中缀表示法肯定会成为该解析器的一部分,但它不会是解析您的 iif 函数调用的部分。

这是函数调用在 pyparsing 中的样子:

fn_call = pp.Group(var_name + LPAREN - pp.Group(pp.Optional(pp.delimitedList(arith_expr))) + RPAREN)

用于定义算术表达式的操作数本身可以包含函数调用,因此解析器的递归将要求您使用 pyparsing 的 Forward 类。

arith_expr = pp.Forward()

这将允许您在完全定义 arith_expr 的外观之前在其他子表达式中使用 arith_expr(就像我们刚刚在 fn_call 中所做的那样)。

言归正传,这是一个用于解析 iif 函数的最小解析器:

import pyparsing as pp

# for recursive infix notations, or those with many precedence levels, it is best to enable packrat parsing
pp.ParserElement.enablePackrat()
LPAREN, RPAREN = map(pp.Suppress, "()")

arith_expr= pp.Forward()

var_name = pp.pyparsing_common.identifier()
integer = pp.pyparsing_common.integer()
fn_call = pp.Group(var_name + LPAREN - pp.Group(pp.Optional(pp.delimitedList(arith_expr))) + RPAREN)
arith_operand = fn_call | var_name | integer

rel_comparison_operator = pp.oneOf("< > <= >=")
eq_comparison_operator = pp.oneOf("== !=")
plus_minus_operator = pp.oneOf("+ -")
mult_div_operator = pp.oneOf("* / %")

arith_expr <<= pp.infixNotation(arith_operand,
[
# add other operators here - in descending order of precedence
# http://www.tutorialspoint.com/cprogramming/c_operators_precedence.htm
(mult_div_operator, 2, pp.opAssoc.LEFT,),
(plus_minus_operator, 2, pp.opAssoc.LEFT,),
(rel_comparison_operator, 2, pp.opAssoc.LEFT,),
(eq_comparison_operator, 2, pp.opAssoc.LEFT,),
]
)

使用 runTests,我们可以针对一些测试用例进行尝试:

tests = """\
cos(60)
sqrt(1 - sin(60) * sin(60))
divmod(a, 100)
iif(iif(condition1,value1,value2)>iif(condition2,value1,value2),value3,value4)
"""
arith_expr.runTests(tests)

打印:

cos(60)
[['cos', [60]]]
[0]:
['cos', [60]]
[0]:
cos
[1]:
[60]


sqrt(1 - sin(60) * sin(60))
[['sqrt', [[1, '-', [['sin', [60]], '*', ['sin', [60]]]]]]]
[0]:
['sqrt', [[1, '-', [['sin', [60]], '*', ['sin', [60]]]]]]
[0]:
sqrt
[1]:
[[1, '-', [['sin', [60]], '*', ['sin', [60]]]]]
[0]:
[1, '-', [['sin', [60]], '*', ['sin', [60]]]]
[0]:
1
[1]:
-
[2]:
[['sin', [60]], '*', ['sin', [60]]]
[0]:
['sin', [60]]
[0]:
sin
[1]:
[60]
[1]:
*
[2]:
['sin', [60]]
[0]:
sin
[1]:
[60]


divmod(a, 100)
[['divmod', ['a', 100]]]
[0]:
['divmod', ['a', 100]]
[0]:
divmod
[1]:
['a', 100]


iif(iif(condition1,value1,value2)>iif(condition2,value1,value2),value3,value4)
[['iif', [[['iif', ['condition1', 'value1', 'value2']], '>', ['iif', ['condition2', 'value1', 'value2']]], 'value3', 'value4']]]
[0]:
['iif', [[['iif', ['condition1', 'value1', 'value2']], '>', ['iif', ['condition2', 'value1', 'value2']]], 'value3', 'value4']]
[0]:
iif
[1]:
[[['iif', ['condition1', 'value1', 'value2']], '>', ['iif', ['condition2', 'value1', 'value2']]], 'value3', 'value4']
[0]:
[['iif', ['condition1', 'value1', 'value2']], '>', ['iif', ['condition2', 'value1', 'value2']]]
[0]:
['iif', ['condition1', 'value1', 'value2']]
[0]:
iif
[1]:
['condition1', 'value1', 'value2']
[1]:
>
[2]:
['iif', ['condition2', 'value1', 'value2']]
[0]:
iif
[1]:
['condition2', 'value1', 'value2']
[1]:
value3
[2]:
value4

关于python - pyparsing如何使用infixNotation来表示iif(cond, if true, if false),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56408430/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com