4

我已经走到了尽头。我无法在 ocamllex 中获得任何工作,这让我发疯。这是我的.mll文件:

{

open Parser

}

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

以下是我作为输入传入的文件的内容:

a=b;

然而,当我编译并运行这个东西时,我在第一个字符上得到一个错误,说它无效。老实说,我不知道发生了什么,谷歌根本没有帮助我。这怎么可能?正如你所看到的,我真的被难住了。

编辑:

我工作了很长时间,以至于我放弃了解析器。现在这是我的主文件中的相关代码:

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

打印出“行:1,列:1”。

4

4 回答 4

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 或 Failure)的标准库异常是一个好主意。原因是它们在整个库中无处不在,因此您通常无法分辨哪个函数引发了异常以及它为什么这样做。

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

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

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

现在,您可以在主文件中捕获新定义的异常,并且与以前不同,该异常特定于语法上无效的输入。因此,您知道异常的来源和原因,让您有机会做一些比以前更有意义的事情。

一个相当随机的 OCaml 开发提示:如果您在启用调试信息的情况下编译程序,则将环境变量OCAMLRUNPARAM设置为“b”(例如 export OCAMLRUNPARAM=b)启用未捕获异常的堆栈跟踪!

于 2011-03-27T15:11:07.453 回答
7

顺便提一句。ocamllex 也可以+在正则表达式中为“一个或多个”做运算符,所以这个

['a'-'z']+

相当于你的

['a'-'z']['a'-'z']*
于 2011-03-28T00:24:04.110 回答
1

我只是在同样的事情上苦苦挣扎(这就是我发现这个问题的方式),最后才意识到我错误地将输入文件的路径指定为Sys.argv.(0)而不是Sys.argv.(1)!大声笑

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

于 2013-01-14T22:37:28.557 回答
-1

看起来您在标识符的正则表达式中有一个空格。这可能会使词法分析器无法识别 a=b,尽管它仍应识别 a = b ;

于 2013-04-02T22:04:10.403 回答