2016-12-05 66 views
4

我正在HaTeX之上建立一個eDSL。我面臨的問題是我想在我的LaTeX文檔中顯示Haskell表達式,並且我想使用相同的Haskell表達式來幫助生成文檔。如何顯式調用haskell語法的quasiquoter?

顯而易見的答案是複製和粘貼表達式,使其顯示爲帶引號和實況。我想避免這種情況,因爲表達可能會發生變化。

我在想象的是一個準標準器,它既能拼接它的內容,又能輸出表示它的字符串。

例如,這裏是我想輸入的內容:

document = do 
    title "this is an example document" 
    paragraph "This is normal text. We will now show the Haskell code that generates a table" 
    [quoted| makeTable ["heading1","heading2"] ["cell1","cell2"] |] 

,我想準報價擴大至:

document = do 
    title "this is an example document" 
    paragraph "This is normal text. We will now show the Haskell code that generates a table" 
    makeTable ["heading1","heading2"] ["cell1","cell2"] 
    listing Haskell "makeTable [\"heading1\",\"heading2\"] [\"cell1\",\"cell2\"]" 

對於這一點,我需要寫一個QuasiQuoter:

quoted :: QuasiQuoter 
quoted = QuasiQuoter 
    { quoteExp = \str -> [e| $(_ str) >> listing Haskell $(lift str) |] } 

我不確定如何在$(_ str)與替換孔。我需要用Haskell表達式準確的報價器替換它,但我不確定如何調用它。如果ee :: QuasiQuoter我可以用$(quoteExp e str)填補這個漏洞,但不幸的是它不起作用。我應該填寫什麼?

回答

5

簡答:沒有簡單的方法。 This question仍然爲未回答的原因。對於Haskell來說,String -> Q Exp很難。最好的方法可能是通過haskell-src-meta,它提供了返回模板Haskell AST的解析器。特別是Language.Haskell.Meta.Parse模塊給了我們parseExp :: String -> Either String Exp

import Language.Haskell.Meta.Parse (parseExp) 

quoted :: QuasiQuoter 
quoted = QuasiQuoter 
    { quoteExp = \str -> 
     case parseExp str of 
      Left msg -> fail "Could not parse expression." 
      Right exp -> [e| $(pure exp) >> listing Haskell $(liftString str) |] } 
+0

很酷,謝謝!它似乎工作得非常好。我假定,因爲parseExp不在Q monad中,它可能無法很好地處理範圍,但它確實如此。軟件包信息並不特定缺少什麼。你對此有更多的瞭解嗎? – simon1505475

+1

@ simon1505475是的,該包需要一些愛。它依賴'haskell-src-exts',它可以讓你指定一個'ParseMode'。 'haskell-src-meta'可能使用['defaultParseMode'](https://hackage.haskell.org/package/haskell-src-exts-1.19.0/docs/Language-Haskell-Exts-Parser.html#v :defaultParseMode)在這種情況下「缺省值是一個未知的文件名,沒有擴展名(即Haskell 98),不要忽略LANGUAGE pragmas,忽略LINE pragmas,並注意Prelude的固定性。 – Alec

+1

@ simon1505475我收回我以前的評論。 [這是使用的分析模式](https://github.com/bmillwood/haskell-src-meta/blob/master/src/Language/Haskell/Meta/Parse.hs#L70-L79) – Alec