2013-05-06 90 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