EBNF 允许使用整数和乘号表示重复次数.
例如:
seq1 = 2 * ('aa' | 'bb');
符合这个定义的有'aabb','aaaa','bbbb','bbaa'四种情况.
EBNF 允许使用减号表示从一个集合当中减去一些内容.
例如:
seq2 = 'a' | seq1, 'a';
seq3 = seq2 - 'aaa';
这里的 seq3 表示任意个'a'组成的字符串,但是除了'aaa'.
设计总是难免有缺陷. EBNF 为了处理一些通过之前介绍的所有规则都难以定义的情形.使用问号开头,问号结尾的串来表示一个引用串.引用串中的内容可以不符合EBNF语法,它描述性地定义了所有放在这里的东西.比如:
seq4 = 'aaa', ?This is an image?, 'bbb';
再给出一个符合seq4的情况:
EBNF 中的排除的定义其实比较繁琐.甚至用到了引用串.
这种看似简单的语法其实非常麻烦.因为它会涉及到元素是否属于集合的问题.如果不加以限制,就可以写出这样的定义:
seq = 'a' - seq;
然后问你'a'是否符合 seq 这条规则?
为了避免这样的问题,我们可以限制减号后边的内容.要求减号后边的这个名词必须可以在有限次替换后完全变成不包含任何 meta identifier 的一个串.
但是这要又涉及了语义层面的检查,所以就无法用EBNF本身定义.所以必须使用引用串来描述.不过这是ISO的解决方案.
在我后边的定义中,我不会使用引用串来定义排除语句.而是把这个问题留给语义分析去解决.