3

我正在尝试为由作业组成的非常简单的语言生成 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"

预先感谢,

安托万。

4

2 回答 2

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。无论如何,您都希望您的词法分析器跟踪准确的行数。

于 2012-03-15T05:12:11.740 回答
0

我对此并没有太多经验,但这会起作用吗?

listvalue : value ,
          | value '\n'
          | value , '\n'

list : listvalue list
于 2012-03-14T05:43:19.010 回答