我有以下语法:
IdentifierName ::
IdentifierStart
IdentifierName IdentifierPart
应使用单词git
解析为以下解析树:
IdentifierName
/ \
IdentifierName IdentifierPart
/ \ |
IdentifierName IdentifierPart 't'
| |
IdentiiferStart 'i'
|
'g'
我想写一个递归下降算法来做到这一点。现在我有两种方法可以编写带有回溯的递归下降解析器或预测递归下降解析器。这两者都是不表驱动器解析器。但是,我已经读过,对于带有回溯的递归下降,我需要消除左递归。问题中的语法似乎是递归的。
我是对的,我要么需要重构语法还是使用预测算法?
答案 0 :(得分:3)
是的,语法是左递归的,因此不是LL。回溯和预测LL解析器都不能处理这样的语法。因此,您需要更改语法或使用其他算法,例如LR解析算法。
请注意,这个语法是规则的,因此它实际上可以转换为正则表达式或直接转换为有限自动机。
在编写JavaScript的实际实现时,词法规则(例如这个)将在词法分析器中处理,只有其他规则将由解析器处理(但是那些指定的左递归也是如此,所以它们' d也必须被重写以由LL解析器解析。)
答案 1 :(得分:0)
这往往是词法分析器的工作,而不是解析器。通常情况下,词法分析器一次循环使用一个大开关语句(或等效的"初始字符表"如果是数据驱动的话),一次进行一个字符。
// near the end of the big "switch (ch) {" statement ...
default:
if (!isIdentifierStart(chInit))
{
log(Severity.ERROR, ILLEGAL_CHAR, new Object[]{quotedChar(chInit)},
lInitPos, source.getPosition());
}
// fall through
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':
case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':
case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':
case 'V':case 'W':case 'X':case 'Y':case 'Z':
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':
case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':
case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':
case 'v':case 'w':case 'x':case 'y':case 'z':
case '_':
{
while (source.hasNext())
{
if (!isIdentifierPart(nextChar()))
{
source.rewind();
break;
}
}
String name = source.toString(lInitPos, source.getPosition());
// ...
}
如果手工构建,我发现拥有专用词法分析器(从字符流生成标记)和解析器(从标记流生成AST)要比尝试将它们组合成一个解析器要容易得多。 / p>