this question的可能重复项,但是对我来说不够具体。
python语法为claimed to be LL(1),但是我注意到Python grammar中的某些表达式确实使我感到困惑,例如,以下函数调用中的参数:
foo(a)
foo(a=a)
对应于以下语法:
argument: ( test [comp_for] |
test '=' test |
'**' test |
'*' test )
test
在语法的第一位置出现两次。这意味着仅查看test
的Python就无法确定它是test [comp_for]
还是test '=' test
。
更多示例:
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
请注意'is'
和'is' 'not'
subscript: test | [test] ':' [test] [sliceop]
test
也出现两次。
我对LL(1)的理解是否错误? Python在词法分析或语法分析期间是否对语法做一些变通办法,以使其LL(1)可处理?谢谢大家。
答案 0 :(得分:2)
您是正确的,像'is' | 'is' 'not'
这样的结构不是LL(1)。通过将其更改为'is' notOpt
,其中notOpt: 'not' | ϵ
,或者如果您允许EBNF语法,只需将'is' 'not'?
(或'is' ['not']
EBNF的味道。
因此,语言为LL(1),但语法在技术上并非如此。我认为Python设计人员认为这是可以的,因为在没有太多好处的情况下,左侧分解版本将更难以阅读,并且当前版本仍然可以毫无困难地用作LL(1)解析器的基础。
答案 1 :(得分:2)
grammar presented in the Python documentation(用于生成Python解析器)以扩展BNF的形式编写,其中包括“操作符”,例如可选性([a]
)和Kleene闭包((a b c)*
)。但是,LL(1)是仅适用于不具有此类运算符的简单无上下文语法的类别。因此,询问该特定语法是否为LL(1)是一个类别错误。
为了使问题有意义,必须将语法转换为简单的无上下文语法。当然,这是可能的,但是没有规范的转换,Python文档也没有解释所使用的精确转换。某些转换可能会产生LL(1)语法,而其他转换可能不会。 (实际上,对Kleene星的幼稚翻译很容易导致模棱两可,根据定义,这对任何k都不是LL(k)。)
在实践中,Python解析设备将语法转换为可执行的解析器,而不是上下文无关的语法。出于Python的务实目的,仅需提前一个令牌即可构建预测分析器就足够了。由于预测解析器可以使用条件语句和循环之类的控制结构,因此无需完全转换为无上下文语法。因此,可以使用未完全左分解的EBNF生成物(如已记录的语法),甚至可以使用向LL(1)转换不平凡的EBNF生成物:
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
在上面的生产中,(';' small_stmt)*
的重复后面可能是';'
,这意味着简单的while
循环将无法正确表示生产。我不知道Python解析器生成器如何处理此生成,但是可以在扩展重复之后通过左分解将其转换为CFG:
simple_stmt: small_stmt rest_A
rest_A : ';' ret_B
| NEWLINE
rest_B : small_stmt rest_A
| NEWLINE
类似地,可以将整个EBNF转换为LL(1)语法。之所以没有这样做,是因为该练习对于解析或解释语法都没有用。它将很难阅读,并且EBNF可以直接转换为解析器。
这一点与Python是否为LL(1)的问题无关,因为如果该语言存在LL(1)语法,则该语言就是LL(1)。语言的语法永远都是无限的,包括对于任何k都不是LL(k)的语法,甚至不是上下文无关的语法,但这与 language < / em>为LL(1):即使存在一个LL(1)语法,语言也为LL(1)。 (我知道这不是最初的问题,因此我将不再进一步探讨这个问题。)