【问题标题】:Why the parser actions, preceding an error, aren't performed?为什么不执行错误之前的解析器操作?
【发布时间】:2021-06-27 19:13:04
【问题描述】:

这个 Packcc 语法只是一个字符串字面量的列表。当发现语法错误时,即使错误出现在文件的最后一项,也会跳过操作。 这是一个问题,因为我想在空间解析期间计算行/列位置。

%source {
#include <stdio.h>
#include <stdlib.h>
}

line <- 
    list _ EOL

list <- 
    list _ ',' _ string 
    / _ string

string <- 
    '"'  ~{puts("unopened string");} (!'"' !EOL .)* '"'   
     # The error action here is not skipped

_ <- 
    [ \t]* {puts("_ match");} 
    # This action doesn't happens if there is an error. In my real project the cursor location is computed here.

EOL <- 
      ('\n'
      / '\r\n' 
      / '\r' ) 

%%

int main(void)
{
  pcc_context_t* ctx = pcc_create(NULL);
  while(pcc_parse(ctx, NULL));
  pcc_destroy(ctx);
  return 0;
}

测试文件“test.txt”只包含 "a", "b", c"

使用packcc theAboveFile.peg 创建解析器 然后编译生成的 .c 文件,然后使用管道将其运行到测试文件,如下所示./a.out &lt; test.txt

如您所见,最后一个字符串中有错误,但我无法执行操作来计算行/列位置,因为由于某种原因跳过了这些操作。

【问题讨论】:

  • Ploum:请使用您正在使用的解析器生成器的标签(在本例中为packcc)标记解析问题,而不是依赖社区为您完成。谢谢。

标签: c parsing packcc


【解决方案1】:

这不应该令人费解,因为这正是文档所说的:

花括号围绕着一个动作。动作是在匹配结束时执行的任意 C 源代码……匹配失败时不执行动作。

为什么它的工作原理可能不在此处,作者可能是最好的来源,但我猜它与回溯的实现有关。除非动作没有副作用,否则在确定不需要撤消之前,您不想运行一个。另一方面,显然以某种方式对 PackCC 的设计做出贡献的 peg/leg 解析器确实包含“谓词”动作,它们总是立即运行(尽管我认为它们应该没有副作用),所以有先例。也许您可以提交功能请求。或者只是使用 peg/leg 来代替 :-) (我也对此一无所知。所以不要将其作为建议。)

我想您真正想问的问题是“我该如何解决这个限制?”虽然我当然不是 PackCC 专家,但我确实阅读了有关错误操作的文档,您已经使用了这些文档。在我看来,因为. 匹配任何东西,!. 应该在任何地方都失败,除了在输入结束时,所以附加一个错误动作应该会导致动作总是运行(多少次,我不知道) .我尝试将您的 _ 规则替换为以下内容:

_ <-
    !.~{puts("_ ran");} / [ \t]* {puts("_ match");}

事实上,这个动作似乎在运行:

$ # Correct input. Note that the "_ ran" predicate runs six times
$ # before the first execution of the "_ match" predicated, consistent
$ # with the error action running immediately while the match action
$ # is deferred.
$ ./test4<<<'"a", "b", "c"'
_ ran
_ ran
_ ran
_ ran
_ ran
_ ran
_ match
_ match
_ match
_ match
_ match
_ match


$ # Invalid input. Error action runs five times, presumably because
$ # it doesn't run after the syntax error is signalled.
$ ./test4<<<'"a", "b", c"'
_ ran
_ ran
_ ran
_ ran
_ ran
unopened string
Syntax error

无论如何,这都不是一个完美的解决方案; !. 模式将在输入结束时匹配这一事实(我认为只有在输入结束之前没有换行符时才会发生这种情况)可能会产生影响。但这可能足以让您入门。

【讨论】:

  • 我很高兴再次读到你 rici !我相信只有与错误相对应的操作会被丢弃,但我误解了文档。看来 peg/leg 不支持递归规则,如果我学会了如何用纯 PEG 替换递归规则,我可以试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
相关资源
最近更新 更多