使用menhir解析带有变量的算术表达式

问题描述 投票:0回答:1

parser.mly:

%{
  let env=Hashtbl.create 10
%}
%token <int> INT
%token SUB
%token EOL
%token EQUAL
%token NAME
%left SUB EQUAL

%start main             /* the entry point */
%type<int> main
%%
 main:
  expr EOL                { $1 }
;

expr:
   INT                     { $1} 
  | expr SUB expr           { $1 - $3}
  | var EQUAL expr {Hashtbl.add env $1 $3;0}
  | var {Hashtbl.find env $1}
;

var:NAME {$1}

(12 行是:

%type<int> main

使用:

wangkai@wangkai-ThinkPad-X1:~/src/ocaml/lexonlysub$ ./calc
a=1
0
b=2
0
b
2
a
2
^C

我不知道为什么定义b=2后,a也是2,应该是1。为什么是2?

还有这个:

wangkai@wangkai-ThinkPad-X1:~/src/ocaml/lexonlysub$ ./calc
a=1
0
b=2
0
a-b
0

lexer.mll:

{
open Parser
exception Eof
}
rule token = parse
  [' ' '\t']     { token lexbuf }     (* skip blanks *)
| ['\n' ]        { EOL }
 | ['0'-'9']+ as lxm { INT(int_of_string lxm) } 
| '-'            { SUB }
|['a'-'z']+ {NAME}
|'=' {EQUAL}
| eof            { raise Eof }

谢谢!

计算.ml

开放语法

让_ =
  尝试
    让 lexbuf = Lexing.from_channel stdin 中
       虽然是真的
        让结果 = Parser.main Lexer.token lexbuf in
          print_int 结果;
        print_newline();刷新标准输出
        完毕
          与 Lexer.Eof ->
          出口0

生成文件:

calc:lexer.cmo 解析器.cmo 语法.cmo calc.cmo
    ocamlc -o calc lexer.cmo 解析器.cmo 语法.cmo calc.cmo

词法分析器.cmo:词法分析器.mll
    ocamllex 词法分析器.mll
    
解析器.cmo:解析器.mly
    门希尔解析器.mly

语法.cmo:语法.ml
    ocamlc -c 语法.ml

计算.cmo:计算.ml
    ocamlc -c 词法分析器.ml
    ocamlc -c 解析器.mli
    ocamlc -c 解析器.ml
    ocamlc -c calc.ml
parsing ocaml arithmetic-expressions menhir
1个回答
0
投票

您需要向

NAME
添加有效负载。否则,它不会注册词法分析的字符串;相反,它给你的值只是
()
,所以每次你访问哈希表时,你都会访问相同的元素。

您需要将

string
类型添加到
NAME
:

%token<string> NAME

拥有

string
有效负载。您还需要实际记住词法分析器中的有效负载:

| ['a'-'z']+ as name { NAME(name) }

(这两个片段应该替换代码中的等效片段)

您可以通过添加一些注释来确保您拥有合适的类型:

%{
  let env : (string, int) Hashtbl.t = Hashtbl.create 10
%}

(如果您将此注释添加到当前版本,它应该会失败;但如果将适当的有效负载添加到

NAME
,则不会失败)。

© www.soinside.com 2019 - 2024. All rights reserved.