2012-08-03 43 views
2

我已經實現了用於在我的代碼中讀入/打印類型的詞法分析器/分析器/漂亮打印機的常用組合。當涉及到普通字符串正則表達式時,我發現在詞法分析器和漂亮打印機之間存在冗餘,通常用於符號,標點符號或分隔符。ocamllex正則表達式的外部定義

比如我現在有

rule token = parse 
    | "|-" { TURNSTILE } 

在我lexer.mll文件,並像一個函數:

let pp fmt (l,r) = 
    Format.fprintf fmt "@[%a |[email protected] %[email protected]]" Form.pp l Form.pp r 

爲漂亮的印刷。如果我決定改變TURNSTILE的字符串,我必須在代碼中編輯兩個地方,我覺得這不太理想。

顯然,OCaml詞法分析器支持某種定義正則表達式的能力,然後在mll文件內引用它們。所以lexer.mll可以寫成

let symb_turnstile = "|-" 

rule token = parse 
    | symb_turnstile { TURNSTILE } 

但這不會讓我從外部訪問,symb_turnstile,從我的漂亮的打印功能說。事實上,運行ocamllex後,也有lexer.ml沒有symb_turnstile出現次數。我甚至無法在lexer.mll的OCaml後記中提及這些標識符。

是否有實現這一目標的方法嗎?

回答

4

最後,我去了以下的風格,我偷了ocamllex本身的來源(所以我猜這是標準做法)。從字符串到令牌的圖(這裏的關聯列表)中的lexer.mll

let symbols = 
    [ 
    ... 
    (Symb.turnstile, TURNSTILE); 
    ... 
    ] 

其中Symb是定義turnstile作爲字符串的模塊的前序部分所定義。然後,lexer.mll的詞法分析部分是故意過於一般:

rule token = parse 
    ... 
    | punctuation 
    { 
     try 
     List.assoc (Lexing.lexeme lexbuf) symbols 
     with Not_found -> lex_error lexbuf 
    } 
    ... 

其中punctuation是一個正則表達式匹配的符號序列。

漂亮的打印機現在可以這樣寫。

let pp fmt (l,r) = 
    Format.fprintf fmt "@[%a %[email protected] %[email protected]]" Form.pp Symb.turnstile l Form.pp r 
1

儘管兩個標記看起來都像字符串,但它們確實非常不同。我不認爲有一種方便的類型可以讓ocamllex和Printf.printf使用它們。這可能是ocamllex不支持這種外部定義的原因。你可能會得到你想要的宏觀設施(文本包含)的效果。