我想在C中制作递归下降解析器 鉴于条件如下:
<prg> -> <stmts>
<stmts> -> <stmt> [;stmts]
<stmt> -> <assign> | <if>
<if> -> if '(' <expr> ')' ('{' <stmts> '}' | <stmt>)
<expr> -> <term> {(+ | -) <term>
<term> -> <factor> {(* | / ) <factor>}
<factor> -> <const> | <id> | '(' <expr> ')'
<id> -> <letter> {<letter>|<const>}
<letter> -> a|b|c
<digit> -> 0|1|2
我得到了addChar(),getChar(),lex()函数。 我想知道如何处理&#34;&lt;&#34; stmt&gt;,&#34;&lt;&#34; if&gt;,&#34;&lt;&#34; letter&gt;。 另外,是什么意思 [; stmts]和 {&#34;&LT;&#34;字母GT; |&#34;&LT;&#34;&常量GT;} ?
答案 0 :(得分:2)
在how to write recursive descent parsers上查看我的答案:
你从哪里得到这个语法?不幸的是,人们在BNF中用各种略有不同的符号来编写语法,并且不告诉你他们正在使用什么约定。检查Wikipedia for BNF以查看一些变体。
通常,您必须了解BNF及其变体,以及您对BNF要描述的语言的理解,并解释BNF以猜测它们的实际含义。 [那是愚蠢的; BNF的目的是消除所有猜测]。关于
[;stmts]
并且使用大多数语言允许一系列语句的知识,我猜[ X ]
表示序列中的&#34; 0或更多X&#34;这里的具体解释是指&#34; 0或更多的陈述,每个陈述前面都有一个&#39 ;;&#39;&#34;。
鉴于概念X的BNF规则被引用为<X>
的适当约定,此语法在此处被破坏;作家很草率,应该写[; <stmts>]
。
在这种BNF样式中指示文字字符的惯例似乎是当它不是BNF metasyntax中使用的字符时使用文字字符。使用的BNF metasyntax字符是这个语法似乎是
< > ( ) [ ] { } '
以->
作为特殊标记。不在此集合中的任何文字字符都只是自己写的;必须引用此集合中的任何文字字符。除了-
之外,这种解释似乎解释了大部分语法。这样的规则可能会使语法看起来更清晰(某种程度)给作者,但让读者难以理解。
无论如何,这解释了为什么[; stmts]
不是[ ';' stmts]
。恕我直言,正确的约定是总是引用文字字符;然后读者永远不必猜测。
关于
{<letter>|<const>}
再次使用我们对BNF变体的理解,并且知道标识符通常是字母和数字的序列,我得出结论{ X }
&#34;表示&#34; 0和更多的X&#34;并且这里的意图是&#34; 0或更多字母或数字&#34;。
我将[ X ]
和{ X }
解释为含义&#34; 0或更多&#34;表明我猜错了;为什么用两种不同的符号来表示同一件事?所以也许他们意味着不同的东西也许[ X ]
表示&#34;一个或多个&#34;。我只能通过查看语法来告诉我。
我必须为这么小的语法猜这么多才是坏消息。我认为这个语法作者选择的约定对读者来说是一种伤害。这对于初学者来说尤其是坏消息,因为它增加了一个已经很棘手的主题的混乱。
代表那些写过这个语法并把它交给你的人,我道歉。
但是,请接受教训。在很多情况下,BNF语法都是写得很糟糕。既然你无法修复作者,你需要学会解释你得到的东西。长号。