我正在OCaml中编写一个简单的递归下降解析器。通常(据我在网上和书中的教程中可以看出),异常用于指示解析失败,例如:
match tok with
TokPlus -> ...
| _ -> raise SyntaxError
但是,我正在考虑使用选项类型,即:
match tok with
TokPlus -> Some(...)
| _ -> None
我想要这样做的主要原因是使用选项类型可以让我优化我的一些组合器以进行尾递归。
使用选项而不是例外是否有任何缺点?当我开始解析更复杂的结构时,这个决定会让我感到困惑吗?
答案 0 :(得分:3)
不,但你可能不得不添加(很多)虚拟规则来将错误传播回语法的根产生。
例外的一点是你不必为每个例程添加异常处理程序;你得到了隐式传播。
您是否有特定原因想要优化尾递归?大多数解析器实际上并不会产生非常深的调用堆栈(对于非常复杂的东西,几百个级别)。而且我怀疑与非解析器部分所做的所有其他工作相比,节省的时间是显着的。
答案 1 :(得分:2)
我认为异常可以优化常见情况 - 成功解析的代码路径更简单。通常在解析它时全部或全部 - 要么一切都解析好,你返回最终结果或者中断 - 你不关心它在哪里中断,因为你无论如何都不打算处理它,除了打印有意义的消息,但是也可以跳过这一步:)所以看起来像是异常的完美匹配。
答案 2 :(得分:1)
关于递归下降解析的好处是你可以以任何你喜欢的方式编写代码(在合理范围内)。我没有看到在有或没有异常的情况下递归写尾的问题,除非您想象在所有中间函数中捕获异常。更可能的是,你的语法顶部附近有一个(或几个)异常处理程序,在这种情况下,下面的所有代码都很容易被尾递归。
所以,我同意ygrek的异常样式对于解析是很自然的,我不认为使用异常必然会排除尾递归样式。