打印AST以显示缩进

时间:2018-01-10 00:57:23

标签: haskell parsec

我想在Haskell中打印一个抽象语法树。目前我可以逐行打印树,但我更喜欢的是为解析后的代码所在的每个块缩进它。

E.g。

要解析的代码:

module test
foo(x,y):
    foo x y
    x + y 

以下是我创建和打印AST的功能。

返回树。

parse :: String -> Either ParseError [Expr]
parse = runParser (many expr <* eof) () "[input]" . indentConfig

打印树。

printTree :: String -> IO ()
printTree line = do
    let res = parse line
    case res of
        Left err -> print err
        Right ex -> mapM_ print ex

当前输出:

Function "foo" ["x","y"] (FunctionCall "foo" [Variable "x",Variable "y"])
BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])

期望的输出:

Function "foo" ["x","y"] 
    (FunctionCall "foo" [Variable "x",Variable "y"])
    BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])

实现这一目标的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

Hackage上有几个软件包可以让你以“缩进”的方式显示这样的树结构。以前,我使用了Iavor Diatchki的pretty-show包,它做得非常好。您可能想尝试一下:https://hackage.haskell.org/package/pretty-show

答案 1 :(得分:1)

您可以创建自己的prettyPrint函数,该函数接收AST和缩进级别,然后以递归方式打印AST中的节点,根据需要递增缩进级别。

在此函数中,您需要专门处理增加缩进级别的AST节点。

这是一个这样的功能的例子。

data AST =
    Function String [String] [AST]
  | BinOp AST AST AST
  | Plus
  | FunctionCall String [AST]
  | Variable String
  deriving (Show)

prettyPrint :: Int -> AST -> String
prettyPrint n (Function a b c) = "Function " ++ show a ++ " " ++ show b ++
    foldl (++) "" (map (\x -> "\n" ++ take (n + 1) (repeat '\t') ++
    prettyPrint (n + 1) x) c)
prettyPrint n a = show a

请注意,编写此函数的方法可能更为简洁,但此版本显示了该功能。

如果我们在你给出的示例AST上运行它,我们得到以下结果。

λ ~ let a = (Function "foo" ["x","y"] [FunctionCall "foo" [Variable "x",Variable "y"], BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])])
λ ~ putStrLn (prettyPrint 0 a)
Function "foo" ["x","y"]
    FunctionCall "foo" [Variable "x",Variable "y"]
    BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])

这也适用于多级缩进。

λ ~ let b = (Function "foo" ["x","y"] [FunctionCall "foo" [Variable "x",Variable "y"], BinOp Plus (FunctionCall "x" []) (FunctionCall "y" []), Function "bar" ["x"] [BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])]])
b :: AST
λ ~ putStrLn (prettyPrint 0 b)
Function "foo" ["x","y"]
    FunctionCall "foo" [Variable "x",Variable "y"]
    BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])
    Function "bar" ["x"]
        BinOp Plus (FunctionCall "x" []) (FunctionCall "y" [])

请注意,仅当您想要自己实现此功能时才会这样做。从长远来看,使用漂亮的打印库来处理这个问题可能是一个更好的举措。