我在某个地方看到一个问题,询问LL(0)和LR(0)解析器之间的区别。是否存在LL(0)解析器?如果有,它们如何在不查看任何标记的情况下进行解析?
我在某个地方看到一个问题,询问LL(0)和LR(0)解析器之间的区别。是否存在LL(0)解析器?如果有,它们如何在不查看任何标记的情况下进行解析?
LL(0)解析器确实会查看令牌,但它们不决定要应用哪些产生式。 它们只是确定序列是否属于语言。 这意味着每个非终端符号必须有一个单独的右侧,并且可能没有递归。
G == ID name lastname
name == STRING
lastname == STRING
# lexer rules
# -----------
ID == [0-9]+
STRING == <unicode>+
请注意,如 @280Z28 所提到的,需要一个单独的词法分析器来处理可变长度部分 (ID
和 STRING
),否则语法将不是 LL(0)
。S -> A
A -> B
B -> 'a' | 'b'
B产生式有两个右侧,分别对应输入中的两个独立字符串'a'和'b'。因此,解析器必须查看输入以选择正确的RHS。
然而,S和A产生式都没有任何选择需要做出。因此,尽管它们实际上都有关联的FIRST集合(包含'a'和'b'),但是它们的FIRST集合不需要做出解析决策,这意味着S -> A和A -> B产生式是LL(0)子语法。因此,优化是忽略这两个非终结符的FIRST集合。
为了清楚起见,假设输入是字符串“b”。然后,解析器可以在甚至查看输入之前自动生成自顶向下的派生S -> A a和A -> B(这称为自动机)。然后,对于最内部的派生B,它必须查看输入以决定使用哪种B产生式来完成解析树。
这种优化的好处在于,错误检测(发现没有输入或者输入不是'a'或'b')可以在检查输入的那一点上立即完成,而不是在解析其他产生式时。如果需要的话,错误信息可以不仅参考B产生式,还可以参考A和S产生式,因为它们已经生成了。如果S的FIRST集合没有进行优化,则当尝试S -> A时只知道这些信息,用户的上下文信息就少得多,必须在这时报告错误。