几乎可以使它正常工作,但是使用OCaml的StringMap遇到麻烦。本质上讲,我正在制作一个从ocamllex引入词法流的计算器...因此,这里的逗号应该分隔出我们的表达式,而等号意味着我们将为变量分配值。
我意识到,在分配变量时,我无法查找它们,因为我在无法找到键的行上遇到(致命错误:Exception Not_found异常),这是我在函数的Var情况下添加的。我不知道将StringMap.empty放在哪里或如何在此函数中使其可见...我想知道为什么在等号情况下为什么找不到我要添加的内容?
这是我的代码。
open Ast
module StringMap = Map.Make(String)
let varMap = StringMap.empty
let rec parser = function
Lit(x) -> x
| Binop(e1, op, e2) -> (
let v1 = parser e1 and v2 = parser e2 in
match op with
Add -> v1 + v2
| Sub -> v1 - v2
| Mul -> v1 * v2
| Div -> v1 / v2
)
| Var(v) -> StringMap.find v varMap
| Statements(e1, e2) -> ignore(parser e1); parser e2
| Equals(v, e1) -> StringMap.add v e1 varMap; parser e1
let _ =
let LexingBuffer = Lexing.from_channel stdin in
let expression = Parser.expression Scanner.token LexingBuffer in
let result = parser expression in
print_endline (string_of_int result)
答案 0 :(得分:3)
Map
是不可变的数据结构。更改映射的任何函数都将返回一个新的修改后的实例,而保留先前的实例不变。因此,这种表达方式
StringMap.add v e1 varMap; parser e1
只会丢弃新地图,并返回对parser
的递归调用返回的任何内容。如果要使用Map
,则必须保留新实例。您可以通过将varMap
设为您要更新的参考单元来完成此操作:
let varMap = ref StringMap.empty
...
varMap := StringMap.add v1 !varMap
或通过向parser
添加一个函数参数并将其传递:
let rec parser varMap = function
...
parser (StringMap.add v e1 varMap) e1
另一种选择是改为使用Hashtbl,它是 可变的,并且可以很好地与字符串配合使用。