0

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

我的问题是,我有一个名为 test 的文件,其中包含 lexer 中定义的 2 个命令:

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}

主文件

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
4

2 回答 2

2

每次调用解析器时,它只会解析一个表达式(即您的起始规则的类型);它将在行尾停止(考虑到您EOL在语法中的使用方式)。如果要解析多个表达式,则需要在循环中多次调用它。

于 2014-03-06T11:18:55.580 回答
2

要扩展 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,这就是您的解析器在此之后停止的原因。

于 2014-03-06T13:37:01.307 回答