How to fix this prog which using ocamlyacc?

46 views Asked by At

parser.mly:

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

%start main             /* the entry point */
%type  main
%%
 main:
  statement_list EOL                { $1 }

statement_list:
  {}
  |statement statement_list {}

statement:
 assign_statement{}
 |print_statement{}

assign_statement:
 var EQUAL expr {Hashtbl.add env $1 $3}

print_statement:
 var {print_int(Hashtbl.find env $1)}

expr:
   INT                     { $1} 
  | expr SUB expr           { $1 - $3}
  
var:NAME {$1}

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']+ as name {NAME(name)}
|'=' {EQUAL}
| eof            { raise Eof }

calc.ml:

open Syntax

let _ =
  try
    let a=open_in "test" in
    let lexbuf = Lexing.from_channel a in
    while true do
        Parser.main Lexer.token lexbuf; 
    done
        with Lexer.Eof ->
        exit 0;

build.sh:

ocamllex lexer.mll
menhir parser.mly
ocamlc -c parser.mli
ocamlc -c lexer.ml
ocamlc -c parser.ml
ocamlc -c calc.ml
ocamlc -o calc lexer.cmo parser.cmo calc.cmo

it can work sometimes,it test is:

a=1

there is no error

it test is:

a=1
1=a

got:

Fatal error: exception Parser.MenhirBasics.Error

so the prog can parse more than 1 lines

if test is

a=1
a

the prog will no print 1

if test is

a=1
b

the prog will no report a error(b not defined)

the prog is first written useing stdio,it works fine.but I want use it not using stdio.It seems I am not understand ocamlyacc very well.

so how to fix it?Thanks!

1

There are 1 answers

0
octachron On BEST ANSWER

Your code should work once the trivial typos are fixed, but you may want to update your printing code to:

print_statement:
 var {Printf.printf "%d\n%!" (Hashtbl.find env $1)}

in order to avoid any buffer flushing issues.