Recursion BNF中的递归定义

Recursion BNF中的递归定义,recursion,bnf,formal-languages,Recursion,Bnf,Formal Languages,我最近开始学习编程语言,并试图更好地理解BNF中的递归定义 例如,如果我们将标识符看作是由字母和数字组成的任何东西,但总是以字母开头,这样的标识符的定义将是 <identifier> ::= <letter> | <identifier> <character> <character> ::= <digit> | <letter> ::=| ::= | 当我们考虑数字的定义时,它会变得有趣。应该是这个吗

我最近开始学习编程语言,并试图更好地理解BNF中的递归定义

例如,如果我们将标识符看作是由字母和数字组成的任何东西,但总是以字母开头,这样的标识符的定义将是

<identifier> ::= <letter> | <identifier> <character>
<character>  ::= <digit> | <letter>
::=|
::=  | 
当我们考虑数字的定义时,它会变得有趣。应该是这个吗

<number> ::= <digit> | <number> <digit>
::=|
还是这个

<number> ::= <digit> | <digit> <number>
::=|

–从语法上看,它们似乎都是正确的,但我敢说它们的语义会有所不同–一个数字是0123456789,另一个数字是9876543210。我错了吗?如果允许数字以前导零开头,两个数字定义都是正确的。由于我们通常不允许这样做,因此更常见的定义是:

<non-zero-number> ::= <non-zero-digit> | <non-zero-number> <digit>
<number> ::= 0 | <non-zero-number>
::=|
::= 0 | 
此定义和
定义都是左递归的,因为它们描述的字符串最左边的字符是特殊的(因为其可能的值是有限的)。如果我们试图描述一组最后(最右边)字符受限制的字符串,我们可能会使用正确的递归

因为我们从左到右阅读,所以最左边的元素是特殊的语法比最右边的元素是特殊的语法多得多。(解析算法也是从左到右运行的,针对这种常见情况往往会进行优化。)

(我完全知道,并非所有人都是从左到右阅读。我们中的许多人都是从右到左阅读,我并不想说其中一个更好。谈论“从头到尾”的阅读或解析,区分“前导递归”和“后继递归”,在文化上更为中立。)。事实上,在与语言关系不大的另一个CS上下文中,谈论“尾部递归”是很常见的;也就是说,递归是在函数的最末端完成的。但是负责现代解析理论的数学家用英语写作,术语中出现了从左到右的偏见。)

由于左递归和右递归都同样擅长描述字符位置不明显的字符串集,因此我们可以使用其中一种来描述数字,如您的问题所示。我们甚至可以使用右递归语法来描述左可分辨字符串,方法是分离第一个位置,然后将其重新粘贴:

<suffix> ::=  <empty> | <letter> <suffix> | <digit> <suffix>
<identifier> ::= <letter> <suffix>
::=||
::=  

但这感觉很不自然,因为标识符实际上只是一个单独的东西。

谢谢,这更有意义。您的第一个语法不允许前导零:
-->-->0