2

我正在阅读 Python 文档 2.76

这是 3 种布尔运算的词法语法

or_test  ::=  and_test | or_test "or" and_test
and_test ::=  not_test | and_test "and" not_test
not_test ::=  comparison | "not" not_test

这是比较的词法语法

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
                 | "is" ["not"] | ["not"] "in"

和 or_expr 的词法语法

and_expr ::=  shift_expr | and_expr "&" shift_expr
xor_expr ::=  and_expr | xor_expr "^" and_expr
or_expr  ::=  xor_expr | or_expr "|" xor_expr

文档中的符号在这里解释:

竖线 (|) 用于分隔备选方案;它是这种表示法中约束力最小的运算符。

现在问题来了:

  1. not_test ::= comparison | "not" not_test解析为

    not_test ::= comparison | ("not" not_test)?

  2. 如果1.为真,则有效comparison也是有效的not_test。(例如1 < 2not_test即使其中没​​有 a not。)

  3. 此外,因为 validand_test只能是一个 valid not_test1 < 2所以也是一个 valid and_test。对于or_test.

  4. 那么什么是有效的comparison1 < 2显然符合模式。并且这些按位比较 expr 也是有效的comparison。共同点是至少需要一个运算符('>'、'<' 或按位的东西)。(我不知道。)

  5. 这是奇怪的部分。例如考虑x and y。根据

and_test ::= not_test | and_test "and" not_test

and_test ::= not_test | (and_test "and" not_test) # 我相信这样解析?

如果它是x and y一个有效的and_test(它永远不可能是not_test存在的and),那么它x必须是一个有效的and_test,它只能是一个有效not_test的。并且y必须也是有效的not_test

Anot_test可以是单一的,也可以是前面有 的comparison另一个。所以 a基本上是零个或多个s 后跟一个。现在重要的是.not_testnotnot_testnotcomparisoncomparison

根据4.,一个comparison必须至少有一个运算符。但这与以下示例冲突:

分配 x = 3, y = 4 。3 and 4似乎是一个有效的and_test.

但我不知道如何34可以是有效comparison的。我哪里做错了?

4

4 回答 4

3

“*”表示包含序列的零个或多个实例。Acomparison不需要运算符,可以通过跟踪shift_exprprimaryatom、 和随后的 来显示literal

于 2014-02-27T05:21:58.373 回答
2

除了简单地定义语言的各个部分之外,形式语法还指定了优先级。这就是为什么表达式部分的许多语法节点都包含与节点的实际名称不符的左侧替代项;这些替代方案指定具有次高优先级的语法节点(因此,在扩展树时,您将扩展低优先级操作,然后是高优先级操作)。

这在算术运算符中是最清楚的:

power ::=  primary ["**" u_expr]
u_expr ::=  power | "-" u_expr | "+" u_expr | "~" u_expr
m_expr ::=  u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr
            | m_expr "%" u_expr
a_expr ::=  m_expr | a_expr "+" m_expr | a_expr "-" m_expr
shift_expr ::=  a_expr | shift_expr ( "<<" | ">>" ) a_expr

观察它u_expr作为power它的选择之一,因为power绑定比一元更紧密(至少在左边)。m_expr可以扩展为 a u_expr,因为一元的绑定比乘法运算更紧密,并且a_expr可以扩展为 a m_expr,因为乘法运算的绑定比加法运算更紧密。这些陈述并不试图暗示您应该将该陈述视为实际上是一个加法运算(尽管在语法上x * y它可以被视为一个术语加法中的一个术语)。


基本上,这意味着您可以沿着节点的 LHS 进行跟踪,直到到达解析表达式的节点。

例如,根据语法,表达式3 + 4是有效comparison的(尽管它不是一般语言意义上的“比较”)。这是因为你可以根据链展开

comparison > or_expr > xor_expr > and_expr > shift_expr > a_expr > a_expr + m_expr

并进一步与

a_expr > m_expr > u_expr > power > primary > atom > literal > integer > decimalinteger > etc...

在每个阶段,您基本上都会将优先级链提升一个等级,这提供了一种非常清晰的方法来确定操作顺序是什么。

于 2014-02-27T05:29:54.233 回答
1

让我们解析您的问题陈述:):

1 < 2一个not_test

not_test: 'not' not_test | comparison

# `comparison: expr (comp_op expr)*`
not_test: expr comp_op expr

# `comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'`
not_test: expr < expr

# `expr: xor_expr ('|' xor_expr)*`
not_test: xor_expr < xor_expr

# `xor_expr: and_expr ('^' and_expr)*`
not_test: and_expr < and_expr

# `and_expr: shift_expr ('&' shift_expr)*`
not_test: shift_expr < shift_expr

# shift_expr: arith_expr (('<<'|'>>') arith_expr)*
not_test: arith_expr < arith_expr

# arith_expr: term (('+'|'-') term)*
not_test: term < term

# term: factor (('*'|'/'|'%'|'//') factor)*
not_test: factor < factor

# factor: ('+'|'-'|'~') factor | power
not_test: power < power

# power: atom trailer* ['**' factor]
not_test: atom < atom

#atom: ('(' [yield_expr|testlist_comp] ')' |
#       '[' [listmaker] ']' |
#       '{' [dictorsetmaker] '}' |
#       '`' testlist1 '`' |
#       NAME | NUMBER | STRING+)
not_test: NUMBER < NUMBER
not_test: 1 < 2
于 2014-02-27T06:25:32.650 回答
0
  1. 顺序很重要,所以括号用于分组,所以没有。

  2. 不适用,因为 1 不正确

所以我认为你的逻辑在这里开始崩溃。这里重要的是这些都是逻辑陈述。不仅仅是“如果它的论点是 False 则产生 True,否则产生 False”

因此,将第一个值赋予not_test(通过or_testand and_test),然后将第二个值赋予 the not_test,然后将它们进行比较,返回一个布尔值。

于 2014-02-27T05:29:45.690 回答