如何使用ocamllex扫描直到文件结束



我正在尝试实现一个读取正则表达式的解析器。它要求用户输入字符串/整数/浮点的有效输入。如果有效且用户按ctrl^d,则打印号码。否则显示错误。但当我按下ctrl^D时,以下代码中的问题并没有停止。如何实现eof令牌并打印输入?

test.mll:

{ type result = Int of int | Float of float | String of string }
let digit = ['0'-'9']
let digits = digit +
let lower_case = ['a'-'z']
let upper_case = ['A'-'Z']
let letter = upper_case | lower_case
let letters = letter +
rule main = parse
(digits)'.'digits as f  { Float (float_of_string f) }
| digits as n              { Int (int_of_string n) }
| letters as s             { String s}
| _ { main lexbuf }

{ let newlexbuf = (Lexing.from_channel stdin) in
let result = main newlexbuf in
print_endline result }

我认为主要的问题是对main的每次调用都会产生一个令牌,而在您的代码中只有对main的一次调用。因此,它将只处理一个令牌。

您需要有某种重复调用main的迭代。

OCamlex中有一个特殊的模式eof,它与输入文件的末尾相匹配。您可以使用它来返回一个停止迭代的特殊值。

作为附带说明,不能使用结果作为参数来调用print_endline。其参数必须是字符串。您需要编写自己的函数来打印结果。

更新

要获得迭代,请将代码更改为以下内容:

{
let newlexbuf = Lexing.from_channel stdin in
let rec loop () =
match main newlexbuf with
| Int i -> iprint i; loop ()
| Float f -> fprint f; loop ()
| String s -> sprint s; loop ()
| Endfile -> ()
in
loop ()
}

然后在你的模式中添加一条类似这样的规则:

| eof { Endfile }

然后添加Endfile作为您类型的元素。

A假设这是家庭作业。因此,请确保您看到迭代是如何工作的。除了ocamllex的细节之外,这也是你想要掌握的东西(对不请自来的建议表示歉意(。

最新更新