【问题标题】:Ocaml lexer / parser rulesOcaml 词法分析器/解析器规则
【发布时间】:2013-04-29 19:25:52
【问题描述】:

我在 ocaml 中编写了一个程序,它给定一个像 1 + 2 这样的中缀表达式,输出前缀表示法:+ 1 2

我的问题是我没有找到一种方法来制定这样的规则:所有值、运算符和括号应始终由至少一个空格分隔:1+1 将是错误的 1+1 ok。我不想使用 ocamlp4 语法。

代码如下:

open Genlex                                                                                                                                                               

type tree =
  | Leaf of string
  | Node of tree * string * tree

let my_lexer str =
  let kwds = ["("; ")"; "+"; "-"; "*"; "/"] in
    make_lexer kwds (Stream.of_string str)

let make_tree_from_stream stream =
  let op_parser operator_l higher_perm =
    let rec aux left higher_perm = parser
        [<'Kwd op when List.mem op operator_l; right = higher_perm; s >]
        -> aux (Node (left, op, right)) higher_perm s
      | [< >]
        -> left
    in
      parser [< left = higher_perm; s >]        -> aux left higher_perm s
  in
  let rec high_perm l = op_parser ["*"; "/"] brackets l
  and low_perm l = op_parser ["+"; "-"] high_perm l
  and brackets = parser
    | [< 'Kwd "("; e = low_perm; 'Kwd ")" >]    -> e
    | [< 'Ident n >]                            -> Leaf n
    | [< 'Int n >]                              -> Leaf (string_of_int n)
  in
    low_perm stream

let rec draw_tree = function
  | Leaf n              -> Printf.printf "%s" n
  | Node(fg, r, fd)     -> Printf.printf "(%s " (r);
      draw_tree fg;
      Printf.printf " ";
      draw_tree fd;
      Printf.printf ")"

let () =
  let line = read_line() in
    draw_tree (make_tree_from_stream (my_lexer line)); Printf.printf "\n"

另外,如果您对代码有一些提示,或者您注意到 prog 样式的一些错误,那么我会很感激您让我知道。谢谢!

【问题讨论】:

    标签: stream ocaml camlp4


    【解决方案1】:

    Genlex 提供了一个现成的词法分析器,它尊重 OCaml 的词法约定,特别是忽略您提到的位置中的空格。我不认为你可以在它之上实现你想要的(它不是一个灵活的解决方案,而是让原型工作的快速方法)。

    如果你想继续编写流解析器,你可以为它编写你自己的词法分析器:定义一个token 类型,并将一个char Stream.t lex 到一个token Stream.t,然后你可以根据需要进行解析。否则,如果您不想使用 Camlp4,您可能想尝试使用 LR 解析器生成器,例如 menhir(更好的 ocamlyacc)。

    【讨论】:

    • 好吧,我不想使用 ocamlp4 语法,因为它真的很吓人。我对 ocaml 的语法/哲学很陌生。当您说您可以编写自己的词法分析器时,您的意思是我不应该使用 make_lexer 并编写自己的函数?感谢您的帮助!
    • 是的,如果您想要对空格进行细粒度处理,您应该编写自己的词法分析器函数。 Genlex 只是这种功能的一个特定实例。但是您是否考虑过使用解析器生成器而不是手动编写?
    • 是的,我已经考虑过了,但我想对 ocamlp4 的流感到舒服,所以我只是编写了自己的解析器,我认为这应该是一个很好的培训。
    猜你喜欢
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多