Python pyparsing如何使用infixNotation表示iif(cond,如果为true,如果为false)
我需要使用pyparsing来解析它:Python pyparsing如何使用infixNotation表示iif(cond,如果为true,如果为false),python,python-3.x,pyparsing,Python,Python 3.x,Pyparsing,我需要使用pyparsing来解析它:iif(条件,值如果为真,值如果为假),但是这种三元比较应该有另一个比较,我的意思是: `iif(iif(condition1,value1,value2)>iif(condition2,value1,value2),value3,value4)` 我发现: integer = Word(nums) variable = Word(alphas, alphanums) boolLiteral = oneOf("true false") operand
iif(条件,值如果为真,值如果为假)
,但是这种三元比较应该有另一个比较,我的意思是:
`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),
])
我在使用我以前的一些规则。现在我投票结束这篇文章。正如@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_调用中所做的那样)
切中要害的是,这里有一个最小的解析器来解析您的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,),
]
)
印刷品:
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
iif
不是中缀运算符。它的语法与函数调用相同,因此您应该查看如何解析函数调用的示例,而不是如何解析?:
@sepp2k我没有理解你的意思,我的意思是a)iif
不是中缀运算符(即出现在其操作数之间的运算符),b)iif
的语法是iif(foo,bar,baz)
,这与函数调用的语法非常相似(与foo?bar:baz
的语法根本不相似)三值运算?:
是“中缀”,因为运算符位于操作数->cond\u值之间?真值:假值
。相比之下,iif(cond\u value,true\u value,false\u value)
只是一个函数调用,用3个参数调用iif
函数。谢谢你,PaulMcG先生,你的建议非常有效,但是我想知道如何修复它,以便使用iif
作为关键字。如果iif
是关键字而不是函数调用,语法会是什么?您是否为您正在构建的语言编写了BNF?这将是决定什么应该是关键字以及其各自语法如何工作的一大步。然后编写一些您要解析的示例代码,看看BNF是否可以使用它,或者是否有歧义。在这一点上,转换到pyparsing、PLY或其他包将更加简单。。。您的代码允许我输入iff(…
,iiif(
)。但是没关系。我可以在将输入的文本交给解析器之前检查它。您是否也接受类似x=iif(条件、真值、假值)的代码
?如果是这样,那么我认为iif
实际上更像是一个内置函数,而不是一个关键字。同样,您的BNF和代码示例将帮助您决定如何继续。如果继续使用此语法,您可能应该将iif
定义为关键字(“iif”)+LPAREN+arith_expr+'、“+arith_expr+”、“+arith_expr+RPAREN
强制使用3个参数。我认为您应该能够解析像“iff”或“iif”这样的函数-难道用户不可能在自己的代码中使用这些名称定义函数吗?]此语法不使用标识符,因为在上一步中,我获取标识符并将其替换为其值,因此语法将仅是带有数字和内联条件的数学运算。我使用的唯一关键字是iif
。问题是是可以嵌套的数学运算和条件。
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