2013-05-06 41 views
0

我写在OCaml的一个程序,给予相同的1 + 2的中缀表达式,输出前缀表示法:+ 1 2ocaml的词法/语法规则

我的问题是我没有找到一种方法,使规则例如:所有的值,运算符和括号至少应该由一个空格隔开:1 + 1将是错误的1 + 1。我想不使用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" 

另外,如果你有一些提示有关代码或如果你注意到的前卫风格的一些错误,那么我会很高兴,你让它我知道。谢谢 !

回答

1

Genlex提供了一个现成的词法分析器,尊重OCaml的词汇约定,特别是忽略你提到的职位空间。我不认为你可以实现你想要的东西(它不是一个灵活的解决方案,而是一个快速获得原型的方法)。

如果你想继续写流解析器,你可以写自己的词法分析器是:定义一个token类型,LEX一个char Stream.ttoken Stream.t,然后你就可以分析你的愿望。否则,如果你不想使用Camlp4,你可能想尝试LR解析器生成器,如menhir(一个更好的ocamlyacc)。

+0

嗯,我不想使用ocamlp4语法,因为它真的很可怕。我对ocaml的语法/哲学非常感兴趣。当你说你可以写自己的词法分析器,你的意思是我不应该使用make_lexer并写我自己的函数?感谢您的帮助! – axzwl 2013-05-06 05:13:56

+0

是的,如果您想要对空格进行细致的处理,您应该编写自己的词法分析器函数。 Genlex只是这种功能的一个特定实例。但是你是否考虑过使用解析器生成器而不是手动编写? – gasche 2013-05-06 06:27:33

+0

是的,我已经考虑过了,但是我想用ocamlp4的流感觉舒适,所以我只写了自己的解析器,并且记住它应该是一个很好的培训。 – axzwl 2013-05-06 15:59:43