Haskell Ast -> IO () - PullRequest
       36

Haskell Ast -> IO ()

0 голосов
/ 06 октября 2019

Я работал над заданием о разборе в 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.

Кстати, мне не разрешено изменять какие-либо функции

Помощь с благодарностью

1 Ответ

1 голос
/ 06 октября 2019

Новые строки и увеличение расстояния с глубиной - это то, что вам нужно.

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>
...