我正在尝试为由分配组成的非常简单的语言生成LALR语法。例如:
foo = "bar"
bar = 42
该语言还应处理值列表,例如:
foo = 1, 2, 3
但我也希望在多行上处理列表:
foo = 1, 2
3, 4
尾随逗号(单身人士和语言灵活性):
foo = 1,
foo = 1, 2,
显然,两者同时出现:
foo = 1,
2,
3,
我能用逗号或多行列表写一个语法,但不能同时写两个。
我的语法看起来像这样:
content : content '\n'
: content assignment
| <empty>
assignment : NAME '=' value
| NAME '=' list
value : TEXT
| NUMBER
list : ???
注意:我需要语法中的'\ n'来禁止这种代码:
foo
=
"bar"
先谢谢,
安托。
答案 0 :(得分:2)
看起来您的配置语言基本上是免费的。我会忘记将换行符作为语法中的标记。如果你想要新行限制,你可以将其作为一些词法搭配规则进行破解,解析器调用一个添加到词法分析器的小API来告诉词法分析器它在语法中的位置,词法分析器可以决定是否接受换行或拒绝它们。
试试这个语法。
%token NAME NUMBER TEXT
%%
config_file : assignments
| /* empty */
;
assignments : assignment
| assignments assignment
;
assignment : NAME '=' values comma_opt
comma_opt : ',' | /* empty */;
values : value
| values ',' value
;
value : NUMBER | TEXT ;
它为我构建而没有冲突。我没有运行它,但随便阅读y.output
看起来过渡是理智的。
这个语法当然允许
foo = 1, 2, 3, bar = 4, 5, 6 xyzzy = 7 answer = 42
没有与词法分析者的额外沟通。
您的限制意味着只允许在值中使用换行符。两个NAME标记必须永远不会出现在同一行上,并且=必须与前一个NAME出现在同一行(并且可能还必须是第一个值)。
基本上,当解析器扫描第一个值时,它可以告诉词法分析器“现在正在扫描值,打开换行符”。然后当comma_opt
减少时,可以再次关闭它。当comma_opt
减少时,词法分析者可能已经读取了下一个赋值的NAME
标记,但它可以检查这是否发生在与前一个NAME
不同的行上。无论如何,您都希望词法分析器能够跟踪准确的行数。
答案 1 :(得分:0)
我对此并没有多少经验,但这会有效吗?
listvalue : value ,
| value '\n'
| value , '\n'
list : listvalue list