2011-03-27 26 views
5

我在这里结束了我的绳索。我无法在ocamllex中获得任何工作,并且这让我疯狂。这是我的.mll文件:OCaml lex:根本不工作,无论如何

{ 

open Parser 

} 

rule next = parse 
    | (['a'-'z'] ['a'-'z']*) as id { Identifier id } 
    | '=' { EqualsSign } 
    | ';' { Semicolon } 
    | '\n' | ' ' { next lexbuf } 
    | eof { EOF } 

下面是我通过在输入该文件的内容:

a=b; 

然而,当我编译和运行的东西,我就非常得到一个错误第一个字符,说这是无效的。我真的不知道发生了什么事情,而Google根本没有帮助我。这怎么可能呢?正如你所看到的,我真的很难过。

编辑:

我工作了这么久,我放弃了解析器。现在这是我的主文件中的相关代码:

let parse_file filename = 
    let l = Lexing.from_channel (open_in filename) in 
    try 
     Lexer.next l;() 
    with 
     | Failure msg -> 
     printf "line: %d, col: %d\n" l.lex_curr_p.pos_lnum l.lex_curr_p.pos_cnum 

打印出“line:1,col:1”。

+0

你能否提供你定义构造函数如标识符的ML文件?另外,你能否确认ocamllex和ocamlc在编译时没有投诉? – Surikator 2011-03-27 14:34:12

+0

它们在parser.mly中被定义为标准,并且都没有抱怨。 – marsolk 2011-03-27 17:29:10

+1

@marsolk:我很好奇 - 你有没有想过这个?有什么问题? – lebowski 2017-02-17 17:11:34

回答

10

没有相应的ocamlyacc解析器,没有人能够找到你的代码的问题,因为你的词法分析器工作得很好!

我冒昧地编写了构造一系列标识符对的例如下面的小解析器(parser.mly),例如,输入“a = b;”应该给单身人士名单[(“a”,“b”)]。

%{%} 

%token <string> Identifier 
%token EqualsSign 
%token Semicolon 
%token EOF 

%start start 
%type <(string * string) list> start 

%% 

start: 
| EOF {[]} 
| Identifier EqualsSign Identifier Semicolon start {($1, $3) :: $5} 
; 

%% 

为了测试解析器是否做什么,我答应了,我们创建另一个文件(main.ml),其解析字符串“A = B”;并打印结果。

let print_list = List.iter (fun (a, b) -> Printf.printf "%s = %s;\n" a b) 
let() = print_list (Parser.start Lexer.next (Lexing.from_string "a=b;")) 

代码应编译(例如ocamlbuild main.byte),不含任何投诉和程序应输出 “A = B;”按照承诺。


针对最新编辑:

一般情况下,我不相信捕标准库例外是为了表明故障或误操作(如Invalid_argument或失败)是一个好主意。原因在于它们在整个库中无处不在,因此通常无法确定哪个函数会引发异常,以及它为什么会这样做。

此外,你扔掉唯一有用的信息:错误信息!错误消息应该告诉你问题的根源是什么(我最好猜测是与IO相关的问题)。因此,您应该打印错误消息或让异常传播到顶层。就个人而言,我更喜欢后者的选择。

但是,您可能仍然想要以优雅的方式处理语法错误的输入。为此,您可以在词法分析器中定义一个新的异常并添加一个捕获无效令牌的默认情况。现在

{ 
    exception Unexpected_token 
} 
... 
| _ {raise Unexpected_token} 

,你可以赶上新定义的例外在主文件,不像以前,例外是特定于语法上是无效的投入。因此,你知道异常的来源和原因,让你有机会做比以前更有意义的事情。如果您在启用了调试信息的情况下编译程序,将环境变量OCAMLRUNPARAM设置为“b”(例如,导出OCAMLRUNPARAM = b)将为未捕获的异常启用堆栈跟踪!

+1

我想我应该提到,经过这么长时间,我现在只是在没有解析器的情况下测试它,它仍然给我这个错误。我将使用我的主文件中的代码编辑帖子。 – marsolk 2011-03-27 17:22:44

+0

通常情况下,我不会;在这种情况下,我得到了'失败(“lexing:空令牌”)',我抬头看它意味着它看到的字符与词法分析器中的任何内容都不相符。最后,我提出另一个规则:'| _ as c {Printf.printf“无法识别的字符:%c \ n”c; raise(Failure“”)}' ,现在它打印“无法识别的字符:a”。但是,我会尝试使用调试信息来查看发生了什么。 – marsolk 2011-03-27 18:50:55

6

btw。 ocamllex也可以为正则表达式“一个或多个”做+运营商,所以这

['a'-'z']+ 

相当于你

['a'-'z']['a'-'z']* 
1

我只是用同样的事情挣扎(这是我如何发现这个问题),直到最终意识到我错误地指定了输入文件的路径为Sys.argv.(0)而不是Sys.argv.(1)! LOL

我真的希望它有帮助! :)

-1

它看起来像在标识符的正则表达式中有一个空格。这可以防止词法分析器识别a = b,尽管它仍然可以识别a = b;