是否有一种简单的方法可以确定语法是LL(1),LR(0),SLR(1)......只是通过查看语法而不进行任何复杂的分析?
例如:要确定BNF语法是否为LL(1),您必须计算First和Follow集 - 在某些情况下这可能很耗时。
有人知道如何更快地完成这项工作吗? 真的很感激任何帮助!
答案 0 :(得分:34)
首先,有点迂腐。您无法确定语言是LL(1)来检查语法,您只能对语法本身进行声明。完全可以为存在LL(1)语法的语言编写非LL(1)语法。
解决这个问题:
您可以为语法编写解析器并首先计算程序,然后为您设置跟随集和其他属性。毕竟,这是BNF语法的最大优势,它们是机器可理解的。
检查语法并查找各种语法类型约束的违规。例如:LL(1)允许右递归而不是左递归,因此,包含左递归的语法不是LL(1)。 (对于其他语法属性,你将不得不在定义上花费一些时间,因为我现在不记得其他任何事情了。)。
答案 1 :(得分:15)
回答你的主要问题:对于一个非常简单的语法,可以在不构造FIRST和FOLLOW集的情况下确定它是否为LL(1),例如
A→A + A |一个
不是LL(1),而
A→a | B'/ P>
是
但是当你变得比这更复杂时,你需要做一些分析。
A→B |一个
B→A + A
这不是LL(1),但可能不会立即显而易见
算术的语法规则很快变得非常复杂:
expr→term {'+'term}
term→factor {'*'factor}
因素→数量| '('expr')'
这个语法只处理乘法和加法,并且已经不能立即清楚语法是否为LL(1)。通过查看语法仍然可以对其进行评估,但随着语法的增长,它变得不那么可行。如果我们为整个编程语言定义语法,那几乎肯定会进行一些复杂的分析。
也就是说,有一些明显的迹象表明语法不是LL(1) - 就像上面的A→A + A - 如果你能在语法中找到任何这些,你就会知道它需要如果您正在编写递归下降解析器,则要重写。但是没有捷径可以验证语法是 LL(1)。
答案 2 :(得分:9)
一方面,“语言/语法含糊不清”,a known undecidable question就像Post correspondence和halting问题一样。
答案 3 :(得分:9)
直接来自Aho等人的书“Compilers:Principles,Techniques,& Tools”。人
第223页:
语法G是LL(1)当且仅当时A - > alpha | beta 是G的两个不同产品,以下条件成立:
本质上,这是验证语法通过成对不相交测试的问题,也不涉及左递归。或者更简洁的是左递归或模糊的语法G不能是LL(1)。
答案 4 :(得分:2)
检查语法是否含糊不清。如果是,则语法不是LL(1),因为没有歧义语法是LL(1)。
答案 5 :(得分:0)
你有ll(1)语法的快捷方式
1)如果A-> B1 | B2 | ....... | Bn 然后第一个(B1)交叉口第一个(B2)交叉口。第一个(Bn)=空集然后它是ll(1)语法
2)如果A-> B1 |ε 那么B1交点跟随(A)是空集
3)如果G是任何语法,使得每个非终端只得到一个产生,则语法为LL(1)
答案 6 :(得分:-2)
p0 S' → E
p1 E → id
p2 E → id ( E )
p3 E → E + id
id ( id + id )