OCAML解释器:为什么我的解释器仅在文件中只执行一行



我正在写一个解释器,使用ocamlyacc和ocamllex来编译我的解析器和lexer。

我的问题是,我有一个文件调用测试,包含2个在lexer中定义的命令:

print a
print b

但是,解释器仅执行行print a!我知道问题主要在解析器中,需要递归。我将其定为这样(下面的代码),但仍然不起作用。

%{  
    open Path
%}
%token <int> INT
%token <string> STRING
%token EOL
%token EOF
%token GET_LINE
%token PRINT
%start main
%type <Path.term> main
%%
main:
    | expr EOL  {$1}
    | expr EOF  {$1}
;

str:
    | STRING { $1 }
    ;
intger:
    | INT {$1 }
    ;
expr:
    | PRINT str  { Print $2 }
    | PRINT str expr  { Print $2 }
    | GET_LINE INT str  { Print_line_in_file ($2, $3) } 
    | GET_LINE INT str expr  { Print_line_in_file ($2, $3) }        
    ;

编辑

这是我的词法,我试图尽可能简化它以发现错误。

(* File lexer.mll *)
{
    open Parser
}
rule main = parse
    | [' ''t''n']     { main lexbuf }
    | "print_line_in_file" { GET_LINE }
    | "print" { PRINT}
    | ['1' - '9']+ as lxm { INT(int_of_string lxm) }
    | ['a'-'z''A'-'Z'] ['a'-'z''A'-'Z''0'-'9']* as lxm { STRING lxm  }
    | eof  {EOF}

main.ml

open Path
let _ =
    try
    let filename = Sys.argv.(1) 
    in
        let lexbuf = Lexing.from_channel (open_in filename)
        in 
            let result = Parser.main Lexer.main lexbuf
            in
                command result;
                flush stdout
    with Parsing.Parse_error -> print_string "Error! Check syntax";
    flush stdout

要扩展Gasche的答案,您需要更改解析器的定义:

%type <Path.term list> main
%%
main:
    | expr EOL main {$1::$3}
    | expr EOF      {[$1]}
    | EOF           {[]}  /* if you want to allow a redundant EOL at the end */
;

使用您的原始定义,单行被认为是main的完整解析,这就是为什么您的解析器在此之后停止的原因。

每次打电话给解析器时,它将仅解析一个表达式(这是您的起始规则的类型);它将停在线路末端(考虑到您在语法中使用EOL的方式)。如果要解析几个表达式,则需要在循环中几次调用它。

最新更新