parsing - 上下文无关文法的奇怪问题

标签 parsing language-design grammar bison

我从一种语言的结构良好(运作良好)的语法开始。变量,
二进制运算符,函数调用,列表,循环,条件等。在此语法中,我想添加我称之为object构造的内容:

object
  : object_name ARROW more_objects
  ;

more_objects
  : object_name
  | object_name ARROW more_objects
  ;

object_name
  : IDENTIFIER
  ;

关键是要能够访问嵌套在对象中的标量。例如:
car->color
monster->weapon->damage
pc->tower->motherboard->socket_type

我将object添加为primary_expression:
primary_expression
  : id_lookup
  | constant_value
  | '(' expression ')'
  | list_initialization
  | function_call
  | object
  ;

现在这是一个示例脚本:
const list = [ 1, 2, 3, 4 ];
for var x in list {
  send "foo " + x + "!";
}
send "Done!";

在将非终端object添加为primary_expression之前,所有东西都是阳光和小狗。即使添加了它,Bison也不会提示。没有发生转移和/或减少冲突的报道。并且生成的代码编译时没有声音。但是当我尝试运行上面的示例脚本时,我被告知error on line 2: Attempting to use undefined symbol '{' on line 2.
如果我将脚本更改为:
var list = 0;
for var x in [ 1, 2, 3, 4 ] {
  send "foo " + x + "!";
}
send "Done!";

然后我得到error on line 3: Attempting to use undefined symbol '+' on line 3.
显然,语法中object的存在弄乱了解析器的行为[SOMEhow],我觉得我忽略了一个简单的语言理论原理,可以将其修正为jiff,但是事实是,事实并非如此。任何转变/减少冲突都使我感到困惑。

有没有更好的方法(语法上)来编写这些规则?我想念什么?为什么没有任何冲突?

(这是full grammar file以防万一)

更新:为了澄清起见,这种语言被编译成由虚拟机运行的代码,并被嵌入到另一个系统中,特别是游戏。它具有标量和列表,并且没有复杂的数据类型。当我说我想在语言中添加object时,这实际上是用词不当。我没有在我的语言中添加对用户定义类型的支持。

使用object构造访问的对象实际上是游戏中的对象,我允许语言处理器通过将VM连接到游戏引擎的中间层进行访问。该层旨在将语言定义和虚拟机机制与游戏引擎的实现和细节尽可能地分离。

所以当我用我的语言写的时候:
player->name

编译器只会对此进行整理。 “player”和“name”不是传统的identifier,因为它们没有添加到符号表中,并且在编译时不进行任何处理,只是将对播放器名称的请求转换为3地址代码。

最佳答案

因此,我花了相当多的时间来挑选语法(和野牛输出),并且看不出这里有什么明显的错误。没有执行它的方法,我无法轻易地通过实验弄清楚发生了什么。因此,这里是调试语法时通常要经过的一些具体步骤。希望您可以做所有尚未完成的工作,然后发布后续结果(或编辑您的问题),并给出可能揭示的结果:

  • 根据您希望应用的规则,构造最小的(按 token 数量计)可能的有效输入,以及最小的可能的非有效输入。
  • 创建一个语法文件的副本,其中仅包含麻烦的规则以及您可以避免的其他其他支持规则(即,您需要一种仅允许构造由ROWT加入的objectmore_object规则组成的序列的语言。这项工作符合您的期望?
  • 嵌套规则是否按预期工作?尝试用其他一些非常简单的规则替换object(使用在其他地方未使用的某些标记),看看是否可以包括这些标记而不会破坏其他所有内容。
  • 使用--report=all运行野牛。检查输出以尝试跟踪已添加的规则及其影响的状态。尝试删除这些规则并重复该过程-发生了什么变化?这通常是非常耗时的,并且是一个巨大的痛苦,但这是一个很好的不得已的方法。我推荐一支铅笔和一些纸。

  • 查看错误输出的结构-“+”被识别为标识符标记,因此被查找为符号。可能值得检查您的词法分析器以查看其如何处理标识符 token 。您可能只是不小心捕获了太多东西。作为进一步的调试技术,您可以考虑将某些 token 文字(例如'+','{'等)转换为真实 token ,以便bison的错误报告可以为您提供更多帮助。

    编辑:好的,我投入的越多,我就越相信词法分析器不一定能正常工作。我将再次检查从yylex()获得的 token 流是否符合您的期望,然后再继续进行操作。尤其是看起来像一堆您认为很特殊的符号(例如,“+”和“{”)已被您的某些正则表达式捕获,或者至少被允许传递给标识符。

    关于parsing - 上下文无关文法的奇怪问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3419600/

    相关文章:

    vb6 - DIM 在 Visual Basic 和 BASIC 中代表什么?

    python - 我如何将字符串分成 python 部分

    c++ - 如何在 C++ 中有效地实现异构不可变对象(immutable对象)的不可变图?

    parsing - 在词法输入序列时指定文字的字符名称是什么?

    c# - Double.Parse 用于 native 语言支持

    parsing - 从 torrent 中读取文件集

    c++ - 在 8 位 block 中使用变量的好方法是什么?

    Python PLY解析: definition scope

    java - 从 XML 响应中解析西类牙语字符(á、é、í、ó、ú)时出现问题

    java - 使用ANTLR4解析mysql简单例子