就目前而言,作为解析器,这有点过于简单化了。整个事情可以写成一个简单的正则表达式:“[ab]?c”。如果您真的坚持将其编写为解析器,则代码可能类似于:
Boolean parseA() {
// an A is a B followed by a `c`:
return parseB() && (get_token() == Token.c);
}
Boolean parseB {
// Get a token.
// If it's an `a` or a `b`, consume it.
// Otherwise, throw it back (match null string by consuming nothing).
// Either way, return true (successful match).
//
token current_token = get_token();
if (token != Token.a && token != Token.b)
push_back(current_token);
return true;
}
编辑(回应对另一个答案的评论):不,当你匹配 B 时,你不应该寻找Token.c。就 B 而言,存在三种可能性:匹配“a”、匹配“b”或什么都不匹配。然后由解析 A 的部分来检查它是否有一个 B 后跟一个 Token.c。
例如,如果您要将语法更改为:
A ::= 公元前
B ::= 一个 | 乙 | ε
C ::= c | d
由于“B”仍然具有相同的定义,因此您不必仅仅因为其他一些定义发生更改而对其进行更改。同样,您可以添加到语法中以允许(例如)任意字符串 B 后跟 C。