有一段时间我一直在努力学习LL解析器是如何工作的,如果我理解正确的话,当手动编写自上而下的递归下降解析器时,我应该为每个非终端符号创建一个函数。所以对于这个例子:
Imputer()
我必须为每个S,A,B和D创建一个函数,如下所示:
S -> AB
A -> aA|ε
B -> bg|dDe
D -> ab|cd
然后我尝试使用我创建的以下语法来生成相同的语言,以生成与(a | b | c)*正则表达式相同的语言:
Token B()
{
if (Lookahead(1) == 'b')
{
Eat('b');
Eat('g');
}
else if (Lookahead(1) == 'd')
{
Eat('d');
D();
Eat('e');
}
else
{
Error();
}
return B_TOKEN;
}
这给了我以下功能:
S -> Ma
M -> aM|bM|cM|ε
它似乎并不好,因为输入'bbcaa'M将消耗所有内容,之后S将找不到最后一个'a'并报告错误,即使语法接受它。感觉M缺少ε案例,或者可能是以错误的方式处理,但我不知道如何处理它。有人可以帮忙吗?
答案 0 :(得分:2)
自上而下预测解析器的行为与您在问题中记下的完全一样。换句话说,你的第二个语法不适合自上而下的解析(使用一个令牌前瞻)。许多语法不是;其中包括无法根据有限前瞻预测要使用哪种生产的任何语法。
在这种情况下,如果您要预测两个令牌而不是一个令牌,您可以解决冲突; from uitest import Ui_MainWindow
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QLabel, QTreeWidgetItem,
)
MENUS = ...
class window(QMainWindow):
def __init__(self, parent=None):
super(window, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.loadMenus(MENUS)
self.ui.Menutree.itemChanged.connect(self.handleItemChanged)
def loadMenus(self, menus):
def recurse(parent, items):
for text, children in items:
item = QTreeWidgetItem(parent)
item.setText(0, text)
item.setCheckState(0, Qt.Checked)
recurse(item, children)
recurse(self.ui.Menutree, menus)
self.ui.Menutree.expandAll()
def handleItemChanged(self, item, column):
def recurse(parent, state):
for index in range(parent.childCount()):
child = parent.child(index)
# child.setCheckState(0, state)
child.setDisabled(state == Qt.Unchecked)
recurse(child, state)
recurse(item, item.checkState(0))
if __name__ == "__main__":
app = QApplication([''])
gui = window()
gui.show()
app.exec_()
应该预测前瞻 a END 上的M
生成,以及所有其他双令牌前瞻中的ε
生成第一个标记是 a 。