2016-11-15 32 views
0

我使用--compile-errors功能menhir,我很滿意。我還使用ocamlbuild來管理我的項目的編譯。由於該項目非常基礎,迄今爲止,構建基礎設施仍然微不足道。如何使用通過OCamlbuild生成Menhir錯誤消息?

我有一個_tags文件和一個簡單的Makefile在項目的根。我還沒有myocamlbuild.ml文件。該_tags文件只包含一個行:

<src/*>: package(ppx_deriving.std) 

在Makefile中的相關部分是

all: src/ParsingErrors.ml 
    ocamlbuild $(OPTIONS) src/Main.native 

src/ParsingErrors.ml: src/Handcrafted.messages src/Parser.mly 
    menhir --compile-errors src/Handcrafted.messages src/Parser.mly > src/ParsingErrors.ml 

OPTIONS = -j 4 -use-menhir -use-ocamlfind -yaccflag --table -pkgs menhirLib,str,unix 

OCamlbuild和巨石通常是很好的整合,但--compile-errors似乎是一個相當新的功能。我的設置並不理想,因爲我不喜歡在我的源代碼目錄中生成自動生成的文件src/ParsingErrors.ml,而不是生成目錄。向OCamlbuild解釋我希望Menhir生成此錯誤消息文件的最佳方式是什麼?更改我的文件的命名約定(例如,src/Parser.messagessrc/Parser.ml)如果它簡化了事情,則不會打擾我。

注意:雖然我在其他項目中有myocamlbuild.ml文件,但我從在線資源中複製它們。我發現他們很難破譯,我真的不知道如何寫這些東西。

回答

2

尋找這個問題的答案最好的地方是在Menhir的發行版中,因爲Menhir在自己的編譯過程中使用了「menhir --compile-errors」和ocamlbuild。

要查找的文件是src/myocamlbuild.mlsource tarball

這裏是一個摘要:

(* This rule generates an .ml file [target] from an .mly file [grammar] and a 
    .messages file [messages]. *) 

(* If the name of a witness file is passed, it is made an additional 
    dependency. This triggers a separate rule (see below) which performs a 
    completeness check, that is, which checks that the .messages file lists 
    every possible syntax error. *) 

let compile_errors grammar messages (witness : string list) target = 
    rule 
    "menhir/compile_errors" 
    ~prod:target 
    ~deps:([ grammar; messages ] @ witness) 
    (fun env _ -> 
     let grammar = env grammar in 
     let tags = tags_of_pathname grammar ++ "ocaml" ++ "menhir" in 
     Cmd(S[ 
     !Options.ocamlyacc; (* menhir *) 
     T tags; 
     P grammar; 
     A "--compile-errors"; P (env messages); 
     Sh ">"; Px (env target); 
     ])) 

(* A generic version of the above rule, with uniform naming. *) 

let generic_compile_errors (check_completeness : bool) = 
    compile_errors 
    (* sources: *) 
    "%.mly" "%Messages.messages" 
    (* if present, this dependency forces a completeness check: *) 
    (if check_completeness then [ "%Messages.witness" ] else []) 
    (* target: *) 
    "%Messages.ml" 

我會很樂意與ocamlbuild維護者巨石的myocamlbuild.ml的某些部件是否可以移到ocamlbuild標準的一套規則進行討論。 (Hi Gabriel!)

+0

除了'!Options.ocamlyacc'是空字符串,所以我不得不用'A「menhir」'替換它。你會猜測爲什麼? – Abdallah

2

當前ocamlbuild版本確實不支持該功能。要將其添加到您的myocamlbuild.ml插件中,您必須定義新的構建規則。如果您對myocamlbuild.ml內部的內容感到害怕,您可能對新的ocamlbuild manual感興趣,特別是its section on plugins

我剛剛在ocamlbuild存儲庫上打開了一個issue report #121來跟蹤這個缺失的功能。您是否有興趣充分了解ocamlbuild爲此編寫適當規則並將其貢獻給下一個ocamlbuild版本?如果是,請隨時諮詢github問題,並開始詢問如何實施它,我會很樂意提供幫助。如果不是的話,我會盡量在有空的時候自己實現。

同時,請注意,定義特定文件的一次性規則比一般規則容易得多。如果你已經準備好對你使用的源文件進行硬編碼,你可以看到與Makefile規則非常相似的東西。我今天沒有時間寫和檢查這條規則,但如果別人之間沒有這樣做,我會盡量明天再來。