在递归下降解析器中使用第一个集合 我在C++中编写了一个递归下降分析器。在以下情况下,我不知道如何选择正确的产品: statement: labeled-statement | compound-statement | expression-statement | selection-statement | iteration-statement | jump-statement

在递归下降解析器中使用第一个集合 我在C++中编写了一个递归下降分析器。在以下情况下,我不知道如何选择正确的产品: statement: labeled-statement | compound-statement | expression-statement | selection-statement | iteration-statement | jump-statement,c++,c,parsing,C++,C,Parsing,我读到了关于“first”(第一)集的内容,它将前瞻令牌/字符与可能的终端进行比较,后者在产品中是第一位的。目前,我只能在递归下降解析器中使用第一个集合,因为我只有一个函数,没有其他任何东西,每个规则都没有对象,也没有其他任何东西可以用来识别规则/产品。您的语法对于递归下降解析器无效,因为它在左侧是不明确的: 标记语句以标识符开头 复合语句以{开头(这很好) 表达式语句以标识符或数字开头(或() 可以到此为止,标记语句和表达式语句之间存在冲突。您需要转换语法以消除左侧歧义(通过临时语法节点包

我读到了关于“first”(第一)集的内容,它将前瞻令牌/字符与可能的终端进行比较,后者在产品中是第一位的。目前,我只能在递归下降解析器中使用第一个集合,因为我只有一个函数,没有其他任何东西,每个规则都没有对象,也没有其他任何东西可以用来识别规则/产品。

您的语法对于递归下降解析器无效,因为它在左侧是不明确的:

  • 标记语句
    以标识符开头
  • 复合语句
    {
    开头(这很好)
  • 表达式语句
    以标识符或数字开头(或

可以到此为止,标记语句和表达式语句之间存在冲突。您需要转换语法以消除左侧歧义(通过临时语法节点包含公共部分,以便在进行分支时,您可以仅使用“向前看”确定要转到哪个分支).

你的shift键出了什么问题?不,sry。下次我会用它:)谢谢!它只是让这个地方看起来整洁,对那些要帮助你的人来说这是一种小小的礼貌。对于C,纯粹的递归下降(ll(1))是不会成功的解析。您需要能够区分orer中的某些类型才能以这种方式进行解析。关于原因,请参见下面的答案:mhh听起来不错,但如何尝试一个又一个产品并排除这些产品,因为它们与“第一个”集不匹配(为了提高性能)。如果任何生产失败,我可以回溯到最后一个生产或最后一个有效状态?顺便说一句:在我消除了左侧的歧义之后,我仍然不知道选择哪一个生产,因为我仍然没有第一个集合与前瞻进行比较。还有什么好的解决方案吗?回溯编译器永远不会工作,因为它的性能非常糟糕即使是很小的输入文件,性能也很低。假设您确实消除了左侧的歧义,那么构建第一个集合是很容易的(如果繁琐的话):只需遍历每个分支的产品,并构建一组可能的首字母。例如,
语句
的第一个集合是
标识符
(来自表达式和标签),
{
(来自复合语句),
number
(表达式),
goto
for
if
等。在递归函数中,您只需对照每个分支的第一个集合检查前瞻。如果不明显,则单个产生式的分支之间有任何重叠意味着您的语法是不明确的。此外,epsilon产生式在递归下降解析器的语法中没有位置AR,如果有,必须去掉它们。好:我如何在C++代码中实现第一组?在哪里存储不同的第一组等等?我如何防止空的产生,因为它们是通过消除左递归来生成的:(.它们被实现为一个简单的令牌类型数组,你将它们作为局部变量存储在递归函数中。为了删除epsilon产品,只需谷歌搜索一个好的算法,我没有随身携带我的龙书,自从我上一次实现编译器以来已经整整10年了。