2012-06-05 38 views
4

是否可以爲OCamlYacc生成的解析器提供一個明確的標記列表供分析?從顯式標記列表中輸入ocamlyacc分析器?

我想使用OCamlLex顯式生成一個令牌列表,然後我使用Yacc生成的分析器進行分析。但是,標準用例會生成一個分析器,爲下一個標記隱式調用詞法分析器。這裏的令牌是在yacc分析期間而不是之前計算的。從概念上講,解析器只能處理令牌,但是Yacc生成的解析器提供了一個依賴於詞法分析器的接口,這在我的情況下並不需要。

回答

4

如果您已經有一個令牌列表,那麼您可以採用醜陋的方式,完全忽略lexing緩衝區。畢竟,您的解析器預計解析 - 從 - lexbuf功能是一個非純函數:

let my_tokens = ref [ (* WHATEVER *) ] 
let token lexbuf = 
    match !my_tokens with 
    | []  -> EOF 
    | h :: t -> my_tokens := t ; h 

let ast = Parser.parse token (Lexbuf.from_string "") 

在另一方面,它看起來與你的意見,你實際上有Lexing.lexbuf -> token list類型,你」的功能重新嘗試適應分析器的Lexing.lexbuf -> token簽名。如果是這樣的話,你可以很容易地使用隊列寫兩種類型之間的轉換器:

let deflate token = 
    let q = Queue.create() in 
    fun lexbuf -> 
    if not (Queue.is_empty q) then Queue.pop q else 
     match token lexbuf with 
     | [ ] -> EOF 
     | [tok] -> tok 
     | hd::t -> List.iter (fun tok -> Queue.add tok q) t ; hd 

let ast = Parser.parse (deflate my_lexer) lexbuf 
+0

yacc生成的解析器提供語義操作訪問隱藏在'lexbuf'狀態中的位置信息。因此,我不確定'放氣'會起作用,但它給了我一個想法。 –

1

OCamlYacc接口看起來很複雜;它似乎需要一個Lexing.lexbuf。也許你可以考慮使用Lexing.from_string來提供一個固定的字符串,而不是固定的令牌序列。你也可以看看Menhir。我沒有使用它,但是當有人提到OCaml解析器生成器時,它會在這裏得到極好的評論。它可能有一個更靈活的lexing接口。

+0

巨石看起來像一個很好的替代OCamlYacc爲很多原因。但是,它似乎與詞法分析器非常緊密地聯繫在一起。 'Lexing.from_string'不是一種替代方案,因爲基本問題是某些詞法分析器動作產生了兩個令牌而不是一個,因爲我只能識別出跟隨任意字符串的令牌,並以字符串令牌和跟隨它的字符串結束。因此,我計劃先建立一個令牌列表。也許我必須引入奇怪的混合標記來解決這個限制。 –

7

已經由Jeffrey提到,Menhir特別提供,其運行時庫的一部分,一個模塊的解析器與任何類型的令牌流(它只是要求一個unit -> token函數):MenhirLib.Convert

(你甚至可以使用此代碼,而無需使用巨石,與ocamlyacc來代替。在實踐中,轉換並不十分複雜,所以你甚至可以自己重新實現它。)

+0

這非常有用。我從來沒有使用過Menhir,但手冊看起來非常有說服力(雖然我忽略了Convert模塊),它的作者在OCaml社區中備受尊敬。 –