我有两个关于如何编写递归下降解析器的问题:
第一个问题是,当您有一个非终结符可以匹配几个不同的非终结符时,如何检查哪种方式是正确的?
第二个问题是,如何构建AST?使用YACC,我只需编写一段代码来执行每个非终结符的实例,并且它有特殊变量引用规则的“值”。在递归下降解析器中如何进行类似的操作?
我有两个关于如何编写递归下降解析器的问题:
第一个问题是,当您有一个非终结符可以匹配几个不同的非终结符时,如何检查哪种方式是正确的?
第二个问题是,如何构建AST?使用YACC,我只需编写一段代码来执行每个非终结符的实例,并且它有特殊变量引用规则的“值”。在递归下降解析器中如何进行类似的操作?
E.g.,
class ASTNode {
public:
virtual int eval() = 0;
virtual ~ASTNode() = 0;
};
// construct this when parsing an integer literal
class Value : ASTNode {
int v;
public:
Value(int v_) : v(v_) {}
virtual int eval() { return v; }
virtual ~Value() {}
};
// construct this when parsing "x+y"
class Addition : ASTNode {
ASTNode *left, *right;
public:
Addition(ASTNode *l, ASTNode *r) : left(l), right(r) {}
virtual int eval() { return l->eval() + r->eval(); }
virtual ~Addition() { delete left; delete right; }
};
第一个问题是,当您有一个非终端可以匹配几个不同的非终端时,该怎么办?您如何检查哪种方式是正确的?
您需要向前查看流并做出决策。在 RDC 上进行回溯很困难。
更简单的解决方案是设计语法,使其不需要向前查看(难度较大)。
第二个问题是,如何构建 AST?
函数调用的返回值是由调用解析的所有内容组成的树。您将所有子调用包装到另一个动态分配的对象中并返回它。