我一直在从事有关Haskell中解析的任务。我已经完成了将字符串解析为抽象语法树的功能,这可以正常工作。
解析器如何与我之前制作的代码一起工作的简短示例:
tokenize :: String -> [String]
tokenize [] = []
tokenize xs @ (x : xs')
| x `elem` t = [x] : tokenize xs'
| isDigit x = [y | y <- takeWhile isDigit xs] : (tokenize (dropWhile isDigit xs))
| otherwise = tokenize xs'
where t = ['+', '-', '*']
--parseExpr recursively goes through list and produces ast
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Error!"
parseExpr (s:ss) | all isDigit s = (Int (read s),ss)
| s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
| s == "*" = (Mult e e',ss'')
| s == "+" = (Sum e e',ss'') where
(e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
-- parse returns the first in the tuple returned from parseExpr
parse :: String -> Ast
parse [] = error "Empty string"
parse str = fst $ parseExpr x
where x = tokenize str
parse "+ 8 * 9 10"
>> Sum (Int 8) (Mult (Int 9) (Int 10))
现在我要做的是编写一个以正确的缩进打印给定ast的函数。
这里是功能:
showw :: Ast -> String
showw ast = ???
show :: Ast -> IO ()
show ast = putStr (showw ast)
所以:
show (parse "+ 8 * 9 10")
Sum
Int 8
Mult
Int 9
Int 10
我需要写showw :: Ast -> String
以便它返回字符串"Sum\n---Int 8\n---Mult\n------Int9\n------Int10"
(仅在此处显示空格是“-”)(我在这里的正确轨道上吗?即使没有一些非常复杂的代码,也可以实现吗?) 。我还必须这样做,以使打印的树增加3个空格的缩进(我将如何去做?)。从我的研究中,我遇到了一种叫做prettyprint的东西,但是问题是除Data.Char之外,我不允许导入其他任何东西。
顺便说一句,我不允许更改任何功能
非常感谢您的帮助
换行并随着深度增加间距是您所需要的。
spacing n = concat $ take n (repeat " ")
showw :: Ast -> String
showw ast = showw2 ast 0
showw2 :: Ast -> Int -> String
showw2 (Mult a a') n = spacing n ++ "Mult" ++ "\n" ++ showw2 a (n+1) ++ showw2 a' (n+1)
showw2 (Sum a a' ) n = spacing n ++ "Sum" ++ "\n" ++ showw2 a (n+1) ++ showw2 a' (n+1)
showw2 (Min a a' ) n = spacing n ++ "Min" ++ "\n" ++ showw2 a (n+1) ++ showw2 a' (n+1)
showw2 (Int i ) n = spacing n ++ "Int " ++ show i ++ "\n"
示例输出
putStr $ showw $ parse "+ 8 * 9 10"
Sum
Int 8
Mult
Int 9
Int 10
*Main>