简体   繁体   中英

Ocaml stringmap calculator AST parse not adding or finding

Very close to getting this to work but having trouble with StringMap from OCaml. Essentially I'm making a calculator which takes in from ocamllex the lexical stream ... so here commas are supposed to separate out our expressions while equal signs means that we will be assigning a value to a variable.

I realized that when assigning variables I'm not able to look them up because I get (Fatal error: exception Not_found) on the lines for not finding the key's I added in the Var case of the function. I don't know where to put the StringMap.empty or how to make it visible in this function... I was wondering why it can't find what I'm adding in the equals case?

Here's my code.

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)

Map is an immutable data structure. Any function that changes the map will return a new modified instance, while leaving the previous one unaltered. Therefore, this expression

StringMap.add v e1 varMap; parser e1

will just throw the new map away, and return whatever the recursive call to parser returns instead. If you want to use Map you have to keep the new instance around. You can do so either by making varMap a ref cell that you update:

let varMap = ref StringMap.empty

...

varMap := StringMap.add v1 !varMap

or by adding a function argument to parser and pass it along:

let rec parser varMap = function

...

parser (StringMap.add v e1 varMap) e1

Another option is to use a Hashtbl instead, which is mutable and works very well with strings.

Maps are immutable. The line

StringMap.add v e1 varMap; parser e1

is thus computing an updated map and then discard it immediately. In other words, the map varMap is always empty.

To avoid discarding the environment map, you should track it in the function parser itself by adding it as an argument of the function — which you might rename to eval :

  let rec eval env = function
  | ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM