【问题标题】:How to convert BNF to EBNF如何将 BNF 转换为 EBNF
【发布时间】:2013-02-17 14:42:43
【问题描述】:

如何将此 BNF 转换为 EBNF?

<vardec> ::= var <vardeclist>;
<vardeclist> ::= <varandtype> {;<varandtype>}
<varandtype> ::= <ident> {,<ident>} : <typespec>
<ident> ::= <letter> {<idchar>}
<idchar> ::= <letter> | <digit> | _

【问题讨论】:

  • 你到底有什么问题?
  • “可能重复”问题有一个答案,其中包含两个指向 SO 材料的链接。它当然提出了一个大致相同的问题;但是,它没有一个很好的答案,所以它不是一个好的副本。

标签: bnf ebnf


【解决方案1】:

EBNF 或 Extended Backus-Naur FormISO 14977:1996,可从 ISO 免费获得 PDF*。它没有被计算机语言标准广泛使用。还有一个 paper 对其进行了描述,并且该论文包含此表总结 EBNF 表示法。

         Table 1: Extended BNF
Extended BNF    Operator  Meaning
-------------------------------------------------------------
unquoted words            Non-terminal symbol
" ... "                   Terminal symbol
' ... '                   Terminal symbol
( ... )                   Brackets
[ ... ]                   Optional symbols
{ ... }                   Symbols repeated zero or more times
{ ... }-                  Symbols repeated one or more times†
=               in        Defining symbol
;               post      Rule terminator
|               in        Alternative
,               in        Concatenation
-               in        Except
*               in        Occurrences of
(* ... *)                 Comment
? ... ?                   Special sequence

* 运算符与前面的(无符号)整数一起使用;它似乎不允许可变数量的重复 - 例如在初始字符之后 1-15 个字符使标识符最长为 16 个字符。这是

在标准中,左括号(被称为开始组符号,右括号)被称为结束组符号;左方括号[开始选项符号,右方括号是结束选项符号;左大括号{开始重复符号,右大括号}结束重复符号。单引号' 称为第一个引号,双引号" 称为第二个引号

* 是的,免费的——尽管如果你愿意,你也可以支付 74 瑞士法郎。查看包含收费项目的框下方的注释。


问题试图将这个“BNF”转换为 EBNF:

<vardec> ::= var <vardeclist>;
<vardeclist> ::= <varandtype> {;<varandtype>}
<varandtype> ::= <ident> {,<ident>} : <typespec>
<ident> ::= <letter> {<idchar>}
<idchar> ::= <letter> | <digit> | _

BNF 没有正式定义,因此我们必须对它的含义做出一些(简单的)猜测。翻译是常规的(如果 BNF 被正式定义,它可能是机械的):

vardec     = 'var', vardeclist, ';';
vardeclist = varandtype, { ';', varandtype };
varandtype = ident, { ',', ident }, ':', typespec;
ident      = letter, { idchar };
idchar     = letter | digit | '_';

必须去掉非终结符周围的尖括号;定义符号::= 替换为=;_ 等终端用引号括起来;连接用, 显式标记;每条规则都以; 结尾。原始中的分组和替代操作恰好与标准符号一致。请注意,用逗号显式连接意味着多词非终结符是明确的。


对标准本身的随意研究表明{...}- 符号不是标准的一部分,只是论文的一部分。然而,正如jmmutcomment 中指出的那样,标准确实定义了{…}- 的含义:

§5.8 句法术语

当句法术语是句法因子时,后跟 一个异常符号后跟一个语法异常它 表示任何同时满足的符号序列 条件:

a) 它是由句法因子表示的符号序列,

b) 它不是由 语法异常。

注意 - { "A" } - 表示一个或多个 A 的序列,因为它是一个带有空句法异常的句法项。

【讨论】:

  • 我想指出,符号 {...}- 标准的一部分(第 4 页末尾,在 5.8 句法术语下),只是不直观方式。它显示了如何仅使用{}- 的定义可以制定“一个或多个”规则:ee = {"A"}-,"E"; 定义“AE”、“AAE”、“AAAE”等。 >注意 { "A" } - 表示一个或多个 A 的序列,因为它是一个带有空句法异常的句法项。
  • @jmmut:谢谢。好眼力。这是一个有趣的极简主义。我已经更新了我的答案。我不确定它是否过度杀戮;它可能是。
  • 同意,这与问题没有直接关系,但我想说至少有笔记是好的,在阅读这个答案之前我不知道它是允许的。哦,还有一个细节,逗号(连接)也需要在大括号(重复)等组周围。像例子中的ident这样的定义我认为应该是ident = letter, { idchar };,根据4.5到4.10的标准。
  • @jmmut:是的——已修复。谢谢你。 (如你所知,我没有 EBNF 验证器来验证我写的内容。)
【解决方案2】:

去掉尖括号,把所有的接线端放在引号里:

vardec ::= "var" vardeclist;
vardeclist ::= varandtype { ";" varandtype }
varandtype ::= ident { "," ident } ":" typespec
ident ::= letter { idchar }
idchar ::= letter | digit | "_"

【讨论】:

  • 第一个近似值;您需要修复一些细节。
猜你喜欢
  • 2020-02-05
  • 2011-01-28
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多