hscolour:仅着色子表达式

hscolour: Colouring only a sub-expression

假设我想标记一个 monadic 动作的句法结构。 colour 是否有比这个更简单(更清晰)的定义:

import Language.Haskell.HsColour.CSS
import Language.Haskell.HsColour.Classify

colour :: String -> String
colour = concat . map renderToken . unwrap . tokenise . wrap where
    wrap :: String -> String
    wrap = (prefix ++)

    unwrap :: [a] -> [a]
    unwrap = drop (length (tokenise prefix))

    prefix :: String
    prefix = "x = do "

对我来说,hscolour 似乎总是假定从顶级开始。这就是为什么没有 wrap 它将第一个标记标记为 definition 这显然是我不想要的,因为我打算只传递可以在 do 块中出现的表达式。

这是令牌流的不同之处 当您使用 colour 函数时与 tokenise 在输入上:

a <- getLine; return $ words a

with colour          with just tokenise
-----------          ------------------
(Varid,"a")          (Definition,"a")
(Space," ")          (Space," ")
(Keyglyph,"<-")      (Keyglyph,"<-")
(Space," ")          (Space," ")
(Varid,"getLine")    (Varid,"getLine")
(Layout,";")         (Layout,";")
(Space," ")          (Space," ")
(Varid,"return")     (Varid,"return")
(Space," ")          (Space," ")
(Varop,"$")          (Varop,"$")
(Space," ")          (Space," ")
(Varid,"words")      (Varid,"words")
(Space," ")          (Space," ")
(Varid,"a")          (Varid,"a")

所以唯一的区别是第一个 Varid 令牌已更改为 Definition 令牌。

事实上,这正是 markDefs 函数的作用 - 它将前导 Varid 标记更改为 Definition (link):

markDefs :: [(TokenType, String)] -> [(TokenType, String)]
markDefs [] = []
markDefs ((Varid, s) : rest) = (Definition, s) : continue rest
markDefs ((Varop, ">") : (Space, " ") : (Varid, d) : rest) =
    (Varop, ">") : (Space, " ") : (Definition, d) : continue rest
markDefs rest = continue rest

请注意,markDefs 是可以创建 Definition 令牌的唯一方法。出现在行首的任何 Varid 都将更改为 Definition 标记。

所以你的方法的替代方法是只改变所有 Definition 个代币回一个 Varid.

colour' = concat . map renderToken . map fixup . tokenise  where
  where fixup (Definition, d) = (Varid, d)
        fixup t                = t