compiler-construction - 构建 AST 时处理错误和释放内存的策略
问题描述
假设我有一个非常简单的语法:表达式 := number '+' number。我编写了一个递归下降解析器(在 C 或其他一些非垃圾收集语言中,我不想使用 Yacc、ANTLR 等),它为这个语法构造了 mini-AST。没有垃圾收集,所以我必须处理所有内存分配和释放。
ASTNode *parse() {
operand1 = parseNumber();
expect (plus);
operand2 = parseNumber();
// Create tree with root (plus) and left and right leaves
return makeNode (operand1, operand2, plus);
}
parseNumber() 将解析一个数字,为节点分配空间,并将节点作为指针返回,例如*ASTNumber,用于增长的 AST。makeNode() 会将所有内容组合在一起并返回 AST 的完成部分。
但是,解析数字时可能会出错,比如说第二个数字。此时我必须优雅地展开树,因为它现在只是部分构建,我们不希望内存泄漏。一种策略是在调用 parseNumber 检测到错误时返回特定的错误节点,例如 ASTError。上面带有错误检测的代码将如下所示:
void parse() {
operand1 = parseNumber();
if (operand1 == ASTError) {
return operand1; // Note its returning ASTError to the caller
}
if (not expect (plus)) {
free (operand1); // Free up the partially constructed AST
return makeASTError(plus);
}
operand2 = parseNumber();
if (operand2 = ASTError) {
free (operand1);
return operand2;
}
// No error, return the finished AST
return makeNode (operand1, operand2, plus);
}
我的问题:这是在 AST 构建过程中处理错误的合理方法吗?我没有在书籍或网上看到任何建议在这里应该做什么。如果一个人正在使用 Java 甚至 Go 进行编程,这不是你会担心的事情,因为你造成的任何混乱都会被垃圾收集器清除。
我想出的另一种策略是拥有两个解析器,一个用于检查语法错误但不执行其他任何操作。如果成功,它将启动第二个解析器,该解析器现在可以安全地构建 AST 而无需担心错误,因此无需担心释放部分构建的树。
我在做什么好吗?还是我错过了一些非常明显的事情?
解决方案
推荐阅读
- html - Div 不适应内容大小
- stripe-payments - Stripe 创建的 Charge 从 Subscription 继承 Metadata
- dataframe - 同一列中的值之间建立差异
- image - TypeError:当我在 Odoo 11 中访问我的自定义看板视图时,dict.record.id 未定义
- d3.js - 在 24 小时时间尺度上计算条的开始位置和宽度(D3 JS)
- c# - Xamarin.Forms 的 Plugin.BLE 未检测到设备
- php - Money\Money 无法转换为字符串
- php - 如何对多维数组的键进行排序?
- java - 在 RHEL 中获取不正确的 LineMetrics (java.awt.font.LineMetrics)
- python - 如何在 Pandas 中提取特定行