上下文无关语法的奇怪问题

Chr*_*son 9 grammar parsing language-design bison

我从语言的一个非常好的(和良好的工作)语法开始.变量,二元运算符,函数调用,列表,循环,条件等.对于这个语法,我想添加我正在调用的object构造:

object
  : object_name ARROW more_objects
  ;

more_objects
  : object_name
  | object_name ARROW more_objects
  ;

object_name
  : IDENTIFIER
  ;
Run Code Online (Sandbox Code Playgroud)

关键是能够访问嵌套在对象中的标量.例如:

car->color
monster->weapon->damage
pc->tower->motherboard->socket_type
Run Code Online (Sandbox Code Playgroud)

我加入objectprimary_expression:

primary_expression
  : id_lookup
  | constant_value
  | '(' expression ')'
  | list_initialization
  | function_call
  | object
  ;
Run Code Online (Sandbox Code Playgroud)

现在这是一个示例脚本:

const list = [ 1, 2, 3, 4 ];
for var x in list {
  send "foo " + x + "!";
}
send "Done!";
Run Code Online (Sandbox Code Playgroud)

在此之前将非终结objectprimary_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!";
Run Code Online (Sandbox Code Playgroud)

然后我明白了 error on line 3: Attempting to use undefined symbol '+' on line 3.

很明显,object语法中的存在正在搞乱解析器的行为方式[SOME],我觉得我忽略了一个相当简单的语言理论原则,可以用jiff解决这个问题,但事实上并没有转移/减少冲突让我感到困惑.

是否有更好的方式(语法上)编写这些规则?我错过了什么?为什么没有冲突?

(这是完整的语法文件,以防它有帮助)


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

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

所以当我用我的语言写作:

player->name
Run Code Online (Sandbox Code Playgroud)

这只能由编译器编纂."播放器"和"名称"不是传统identifier的,因为它们没有添加到符号表中,除了将播放器名称的请求转换为3地址代码之外,在编译时没有对它们进行任何操作.

Gia*_*ian 1

因此,我花了相当多的时间来挑选语法(和野牛输出),但看不出这里有什么明显的错误。如果没有执行它的方法,我无法轻松地通过实验弄清楚发生了什么。因此,以下是我在调试语法时通常会经历的一些具体步骤。希望您可以完成您尚未完成的任何操作,然后也许发布后续内容(或编辑您的问题),并提供可能揭示的任何结果:

  1. 根据您期望应用的规则,设计尽可能小的工作输入(就令牌数量而言)和尽可能小的非工作输入。
  2. 创建语法文件的副本,仅包含麻烦的规则和尽可能少的其他支持规则(即,您想要一种语言,只允许构造由 和object规则组成的序列more_object,并通过箭头连接。这是否可以作为你期望吗?
  3. 它所嵌套的规则是否按您的预期工作?尝试object用其他一些非常简单的规则替换(使用其他地方没有出现的一些标记),看看是否可以包含这些标记而不破坏其他所有内容。
  4. 运行野牛与--report=all. 检查输出以尝试跟踪您添加的规则及其影响的状态。尝试删除这些规则并重复该过程 - 发生了什么变化?这通常非常耗时,并且是一种巨大的痛苦,但它是一个很好的最后手段。我推荐一支铅笔和一些纸。

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

编辑:好的,我研究得越多,我就越相信词法分析器不一定能正常工作。在继续下一步之前,我会仔细检查您从 yylex() 获得的令牌流是否符合您的期望。特别是,看起来您认为特殊的一堆符号(例如“+”和“{”)正在被某些正则表达式捕获,或者至少被允许传递标识符。