规则空缺右侧的符号

时间:2013-02-01 13:08:18

标签: bison yacc parser-generator

当用一个空的右侧规则写一个(“理论”)语法时,总是使用一个符号,如ε(或1)来使这个空虚显式:

A → ε | a A

Yacc和其他人的这种语法看起来像

a: | 'a' a

或“更糟糕”

a:       { $$ = new_list(); }
 | a 'a' { $$ = $1; $$->append($1); }
 ;

事实上,在“真实世界语法”(Yacc,Bison等)这个空的右侧的规则没有明确标记为空的麻烦我:很容易错过rhs是的事实空或更糟:忘记插入|并实际使用中规则操作:

a:       { $$ = new_list(); }
   a 'a' { $$ = $1; $$->append($1); }
 ;

1)我不知道有任何工具可以提供显式空rhs的方法。有没有?

Bison的未来版本可能支持专用符号,在非空rhs中使用时会出现错误,而在留下隐式空rhs时会出现警告。

2)人们认为这有用吗?

3)你建议的符号是什么?

目前,候选人是$empty

a: $empty { $$ = new_list(); }
 | a 'a'  { $$ = $1; $$->append($1); }
 ;

修改

所选语法为%empty

a: %empty { $$ = new_list(); }
 | a 'a'  { $$ = $1; $$->append($1); }
 ;

确实$empty看起来像一个伪符号,例如Bison为初始规则生成的$accept,或用于中规则操作的$@n伪符号,或{{ 1}} for,well,end-of-file。但它绝对不是象征,而恰恰是没有符号。

另一方面,$eof清楚地表示指令(某种属性/元数据),如%

所以这是语法的一个细微差别,但它与整体语法更加一致。归功于Joel E. Denny。

5 个答案:

答案 0 :(得分:5)

我通常只是使用评论:

a: /*epsilon*/ { $$ = new_list(); }
 | a 'a'  { $$ = $1; $$->append($1); }
 ;

在没有任何变化的情况下正常工作并使意图明确......

国际海事组织,这标题是“如果没有破产,请不要修理”

答案 1 :(得分:3)

我建议如下:

定义声明:

%empty ID

其语义是双重的:

1)ID可以用作RHS中唯一的非规则令牌,以表明RHS是epsilon产品;和

2)未标有ID的epsilon作品被视为语法错误。

因此,声明:

%empty epsilon

epsilon 必须用于标记空RHS;在没有任何%empty声明的情况下,现状仍然存在,其中空RHS未标记(除非有注释)。

这将允许喜欢明确标记空RHS的用户立即这样做,而不会对现有语法文件或不希望以这种方式明确标记空RHS的用户产生任何影响。

就个人而言,我可能会使用这样的声明,虽然说实话我已经习惯使用评论来标记空的RHS,但我不相信我曾经不小心制作了一个空的RHS。所以我不会将它标记为优先功能请求,但我也不会反对它的实现。

答案 2 :(得分:0)

我自己使用epsilon,以及marker的变体用于空制作,我在括号中附加了一些代码。

野牛语法中的保留符号会很有用;我喜欢建议的$前缀以避免与用户命名的符号冲突。

答案 3 :(得分:0)

1)嗯,有明显的

e: a 'b'
a: 'a'
 | empty
empty:

2)是的,这将非常有帮助。

3)始终定义$accept$end$undefined符号,并专门为Bison的内部使用保留(例如,它们不能出现在语法中)。 Bison为中规则操作生成$@n,但这些也不能用于用户的语法。

如果我没有弄错的话,用户可以在语法中使用的唯一预定义标记是error。那你为什么不建议empty这个专用的符号呢?这似乎相当合理。或者您是否建议引入$error

您考虑过nothing了吗?我可能宁愿那样。

答案 4 :(得分:0)

当然,如果它包含一个动作,那么制作在某种意义上并不是真正的“空”,因为Yacc / Bison很难不知道动作在幕后变成可以为空的非终端。如果你(或书)在课堂上所有学期都说“epsilon”,也许“%epsilon”比“%empty”更具真实性。

我认为将其归入更一般的断言机制:

lines : %assert(epsilon)
      | %assert(on WORD) lines line ;

line : WORD '\n' ;

%assert(nullable(lines))
%assert(!nullable(line))
%assert(WORD in FIRST(lines))
/* etc. */

这个想法是稍微减少了在所有启发式算法开始之后确切地确定yacc / bison实际执行的语言的痛苦。其余的将按照您的指定或多或少地工作,警告“空”的选项规则,除非“空”规则包含%assert(epsilon)。

就优先级而言,我认为当bison可证实地创建了一个无法接受输入语法的解析器时(例如,一个或多个制作永远不会触发),报告的优先级要高得多。至少,这种能力不是最后我看的,但我有一个非常古老的野牛:-)。是否仍然无法用英语解释具有通过嵌入式操作而有所不同的常见左前缀的制作问题?除非它变得更好,否则我认为还有很多解释性的改进,除了检查无意的空规则之外还有什么帮助。

看到学生遇到的最常见错误的一些数据会很有趣(我想我不会选择这个作为竞争者!)。这将是一个有趣的实验:破解学生的野牛副本,以便将每次运行发送到数据库,使用一些软件进行清理并分析最常见的误解。