C++ 递归下降解析器问题
关于如何编写递归下降解析器,我有两个问题: 第一个问题是当您有一个非终结符可以匹配几个不同的非终结符中的一个时会发生什么?如何检查哪种方式是正确的 第二,如何构建AST?使用YACC,我可以只编写一段代码来执行非终结符的每个实例,它有一些特殊的变量,这些变量引用规则的“值”。如何在递归下降解析器中执行类似的操作?或如何在一个简单的leasson中给自己一个笔划。 第一个问题是当您有一个非终结符可以匹配几个不同的非终结符中的一个时会发生什么?如何检查哪种方式是正确的 你需要向前看,做出决定。在RDC上很难进行回溯 一个更简单的解决方案是设计语法,这样就不需要向前看(很难) 第二,如何构建AST 函数调用的返回值是调用解析的所有内容的树。将所有子调用包装到另一个动态分配的对象中并返回该对象C++ 递归下降解析器问题,c++,parsing,abstract-syntax-tree,recursive-descent,C++,Parsing,Abstract Syntax Tree,Recursive Descent,关于如何编写递归下降解析器,我有两个问题: 第一个问题是当您有一个非终结符可以匹配几个不同的非终结符中的一个时会发生什么?如何检查哪种方式是正确的 第二,如何构建AST?使用YACC,我可以只编写一段代码来执行非终结符的每个实例,它有一些特殊的变量,这些变量引用规则的“值”。如何在递归下降解析器中执行类似的操作?或如何在一个简单的leasson中给自己一个笔划。 第一个问题是当您有一个非终结符可以匹配几个不同的非终结符中的一个时会发生什么?如何检查哪种方式是正确的 你需要向前看,做出决定。在RD
@约根:混乱,但可能。更新了关于LL和前瞻的说明。(我的背景是NLP,在NLP中,每种语法都是不明确的,因此回溯是我学习解析的第一件事:)ast节点不应该只包含解析的信息,而不主动对其进行处理吗?至少对我来说,将实际逻辑(示例中的实际添加)嵌入到节点本身看起来像是以后许多问题的收据,似乎违反了SRP。@stijn:我承认这不是特别优雅,但是我想展示一个简单的示例,它几乎可以做一些有用的事情,并且仍然比OP所指的Yacc示例更清晰地分离逻辑。@stijn:您还应该将逻辑放在哪里?具有eval方法的节点似乎是一种完美的方式。@mtk:在真正的解释器中,您应该将解析和执行阶段分开,以便在这两个阶段之间进行优化。也许最好使用不同类型的解释器?请参阅
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; }
};