我遇到的一个问题是C必须是上下文敏感的,并且无法使用一个前瞻标记进行解析。例如
int main1;
int main() {}
这是我能想到的最简单的例子,其中函数定义和变量声明都以相同的标记类型开头。你必须一直向前看左边的paren或分号来确定要解析的内容。
我的问题是,这是如何实现的?词法分析器是否有一些技巧可以进行前瞻,并发出一个区分两者的隐形标记?现代解析有很多前瞻性的标记吗?
答案 0 :(得分:8)
您应该阅读LR或shift-reduce解析器。他们自下而上组装解析树。在main
函数的情况下,它就像:
int
作为TYPE终端令牌转移到堆栈中main
作为IDENTIFIER终端令牌转移到堆栈中(
转移到堆栈)
转移到堆栈(
和)
并替换为ARGLIST非终端令牌{
转移到堆栈}
转移到堆栈当然,每次进行替换时,它都会构建一个新的解析树片段并将其附加到新令牌上。 (我编写了这些令牌名称。)
它在有限状态机的控制下工作,该有状态机识别堆栈上的令牌模式,并与下一个(单个)输入令牌一起决定是否移动下一个令牌,或应用其中一个语法规则将堆栈上的一组令牌减少为一个令牌。 FSM由解析器生成器根据语法规则列表构建。
它被称为LR,因为它从左侧读取输入令牌,但是从右侧应用语法规则。它不同于LL或递归下降,它从左侧应用语法规则。 Pascal是一种LL(1)语言。 C不是LL(1),因此需要LR(1)解析器。 例如,它允许C在嵌套括号中嵌入几乎任何东西而不会混淆解析器。
我希望这可以帮助您了解正在发生的事情。