我正在尝试编写一个递归下降解析器而不需要回溯一种类似这样的EBNF:
<a> ::= b [c] | d
,其中
&LT a取代; =非终端
lower-case-string = identifier
[括号内] =括号中的术语是可选的
a | b是a和b之间通常的互斥选择。
目前,我只关心右手边。
按照http://en.wikipedia.org/wiki/Recursive_descent_parser的示例,我最终得到了以下程序(上面评论中的GNU bison语法规则):
/* expression: term optional_or_term */
void expression()
{
term();
if (sym == OR_SYM)
optional_or_term();
}
/* optional_or_term: // empty
| OR_SYM term optional_or_term
*/
void optional_or_term()
{
while (sym == OR_SYM)
{
getsym();
term();
}
}
/* term: factor | factor term */
void term()
{
factor();
if (sym == EOF_SYM || sym == RIGHT_SQUAREB_SYM)
{
;
}
else if (sym == IDENTIFIER_SYM || sym == LEFT_SQUAREB_SYM)
term();
else if (sym == OR_SYM)
optional_or_term();
else
{
error("term: syntax error");
getsym();
}
}
/*
factor: IDENTIFIER_SYM
| LEFT_SQUAREB_SYM expression RIGHT_SQUAREB_SYM
*/
void factor()
{
if (accept(IDENTIFIER_SYM))
{
;
}
else if (accept(LEFT_SQUAREB_SYM))
{
expression();
expect(RIGHT_SQUAREB_SYM);
}
else
{
error("factor: syntax error");
getsym();
}
}
它似乎有效,但我的期望是每个程序都会与相应的规则密切对应。你会注意到term()没有。
我的问题是:在编写程序之前语法是否需要更多转换?
答案 0 :(得分:0)
我不认为你的问题是缺少连接操作符。我认为它不是使用Kleene星(和加号)来列出事物。 Kleene星允许您在实现语法规则的过程中实际编写循环。
我会把你的语法写成:
expression = term (OR_SYM term)*;
term = factor+;
factor = IDENTIFIER_SYM | LEFT_SQUAREB_SYM expression RIGHT_SQUAREB_SYM ;
(这是一种非常经典的语法语法)。
解析器代码如下所示:
boolean function expression()
{ if term()
{ loop
{ if OR_SYM()
{ if term()
{}
else syntax_error();
}
else return true;
}
else return false;
}
boolean term()
{ if factor()
{ loop
{ if factor()
{}
else return true;
}
}
else return false;
}
boolean factor()
{ if IDENTIFIER(SYM)
return true;
else
{ if LEFT_SQUAREB_SYM()
{ if expression()
{ if RIGHT_SQUAREB_SYM()
return true;
else syntax_error();
}
else syntax_error();
else return false;
}
}
我尝试以绝对机械的方式生成这个,你可以做得很好。我的职业生涯早就做了很多。
你不会得到的是每天150条工作规则。首先,对于一门大语言,很难使语法正确;你将反复调整它以获得一个抽象的语法,然后你必须调整你编写的代码。接下来你会发现写词法分析器也有麻烦;试着为Java编写词法分析器。最后,您会发现解析器规则不是整个游戏,甚至不是您努力的最重要部分;你需要很多来处理真正的代码。我称之为“解析后的生活”;看我的生物 了解更多信息。
如果您希望每天获得150个工作规则,请切换到GLR解析器并手动停止编码解析器。这不会解决其他问题,但它确实让你在获得可用的语法方面非常高效。这就是我现在所做的。没有例外。 (我们的DMS软件重组工具包使用了这个,we parse a lot of things that people claim are hard.)