Stream Ocaml词法分析器/解析器规则

Stream Ocaml词法分析器/解析器规则,stream,ocaml,camlp4,Stream,Ocaml,Camlp4,我用ocaml编写了一个程序,给定一个中缀表达式(如1+2),输出前缀符号:+1+2 我的问题是我没有找到一种方法来制定这样的规则:所有的值、运算符和括号都应该至少用一个空格隔开:1+1是错误的1+1 ok。我不想使用ocamlp4语法 代码如下: open Genlex

我用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"
opengenlex
类型树=
|弦叶
|树的节点*字符串*树
让我的lexer str=
让kwds=[“(“;”)”;“+”;“-”;“*”;“/”]在
制作单词kwds(字符串str的Stream.of)
让我们从溪流中生成树=
让op_解析器运算符更高\u perm=
让rec aux left higher\u perm=解析器
[]->Leaf n
|[<'Int n>]->Leaf(Int n中的字符串)
在里面
低渗透流
让rec绘制树=函数
|叶n->Printf.Printf“%s”n
|节点(fg,r,fd)->Printf.Printf“(%s)”(r);
绘制树fg;
Printf.Printf“;
绘制树fd;
Printf.Printf“”
让()=
让line=在中读取_line()
绘制_树(从_流生成_树(my_lexer线));Printf.Printf“\n”

另外,如果您有一些关于代码的提示,或者您注意到一些prog风格的错误,那么我将非常感谢您让我知道。谢谢

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


如果您想继续编写流解析器,您可以为它编写自己的lexer:定义
令牌
类型,并将
字符流.t
lex到
令牌流.t
,然后您可以根据需要解析它。否则,如果您不想使用Camlp4,您可能需要尝试LR解析器生成器,例如(更好的ocamlyacc)。

我不想使用ocamlp4语法,因为它非常可怕。我对ocaml的语法/哲学非常陌生。当你说你可以编写自己的lexer时,你的意思是我不应该使用make_lexer来编写自己的函数?谢谢你的帮助!是的,如果您想要对空白进行细粒度处理,您应该编写自己的lexer函数。Genlex只是此类函数的一个特定实例。但是你考虑过使用解析器生成器而不是手工编写吗?是的,我考虑过,但我想与ocamlp4的流相适应,所以我只编写了自己的解析器,我认为这应该是一个很好的培训。