代码之家  ›  专栏  ›  技术社区  ›  Trung Bún

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

  •  0
  • Trung Bún  · 技术社区  · 11 年前

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

    我的问题是,我有一个文件calles测试,包含两个在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) }        
        ;
    

    编辑

    这是我的lexer,我试图尽可能简化它以找出错误。

    (* 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}
    

    主.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
    
    2 回复  |  直到 11 年前
        1
  •  2
  •   Andreas Rossberg    11 年前

    要扩展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 ,这就是为什么解析器在此之后停止。

        2
  •  2
  •   gasche    11 年前

    每次调用解析器时,它只会解析一个表达式(这是开始规则的类型);并且它将在行尾停止(给定您如何使用 EOL 在语法中)。如果要解析多个表达式,则需要在循环中多次调用它。