0

我有以下代码:

case 1
of 2
    3
of 3
    4
5

我的自定义标记器转换为:

Tokens: [{'case',1},
         {integer,1,1},
         {eol,1},
         {'of',1},
         {integer,1,2},
         {block,[{integer,1,3}]},
         {eol,1},
         {'of',1},
         {integer,1,3},
         {block,[{integer,1,4}]},
         {eol,1},
         {integer,1,5}]

但是我无法使用以下 Yecc 解析它:

Nonterminals
    grammar
    statements statement
    case_def case_conditions condition.


Terminals
    eol block
    integer
    case of.


Rootsymbol grammar.


grammar -> statements : '$1'.


statements -> statement eol statements : ['$1'|'$3'].
statements -> statement : ['$1'].

statement -> case_def : '$1'.
statement -> integer : '$1'.


case_def -> 'case' integer case_conditions : ''.

case_conditions -> case_condition case_conditions : ['$1'|'$2'].
case_conditions -> case_condition : ['$1'].

case_condition -> eol 'of' integer block : ''.

它给了我以下输出:

["syntax error before: ","5"]

非常欢迎任何帮助,谢谢。

4

1 回答 1

1

我认为在非终端列表中,您应该case_condition使用condition.

您的自定义扫描仪会忽略缩进。它必须为INDENT和发出令牌DEDENT。我在 yacc 中找到了示例。然后您可以更改语法以使用这些标记。

您的示例会产生移位/减少冲突。文档说:

如果没有运算符优先级声明,则移位/归约冲突得到解决,有利于移位。

这意味着,当您的解析器位于由|

of 3
    4|
5

并看到新行,可能有两种选择:

  • 这可能是下一个case_condition,因此解析器需要继续“转移”以阅读更多内容
  • 这可能是语句的结尾,因此解析器需要将之前的所有内容都视为语句并将其放入堆栈或简而言之“减少”

因为这些冲突总是被解决转移,你不能在你开始案例后放置下一条语句!你需要改变你的语法。使用它直到yecc:file/1不产生任何警告。

提示:缩进 case 内的所有内容,如下所示:

case 1
    of 2
        3
    of 3
        4
5

这样一来,你就清楚地说,这case是一个陈述,又5是另一个陈述。case_condition我对解析器的了解有点生疏,但我相信,如果您不添加缩进或某种终结符,您将无法编写能够区分statement从左到右解析器的语法。

于 2014-12-04T06:47:06.307 回答