我有以下代码:
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"]
非常欢迎任何帮助,谢谢。
答案 0 :(得分:1)
我认为在非终结列表中,您应该case_condition
而不是condition
。
您的自定义扫描程序会忽略缩进。它必须为INDENT
和DEDENT
发出令牌。我找到了example in yacc。然后你可以改变你的语法来使用那些令牌。
您的示例会生成转移/减少冲突。文档说:
转移/减少冲突得到解决,有利于转移,如果有的话 没有运算符优先级声明。
这意味着,当您的解析器位于|
of 3
4|
5
并看到新行,可能有两个选项:
case_condition
所以解析器需要继续“转移”以阅读更多内容因为这些冲突总是被解决才能转移,所以在你开始案例之后你不能放下一个声明!你需要改变你的语法。使用它直到yecc:file/1
没有产生任何警告。
提示:在这种情况下缩进所有内容:
case 1
of 2
3
of 3
4
5
这样,你清楚地说,case
是一个陈述而5
是另一个陈述。我对解析器的了解有点生疏,但我相信,如果你不这样做,你就无法编写能够用左到右解析器区分case_condition
和statement
的语法。添加缩进或某种终结符。