Abbie's Haskell compiler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.8 KiB

  1. -- {-# LANGUAGE BlockArguments #-}
  2. module Main where
  3. import Control.Monad ( unless )
  4. import qualified Data.ByteString.Lazy as Lbs
  5. import qualified Data.Text.Encoding as T
  6. import qualified Data.Text as T
  7. import Data.Foldable
  8. import Debug.Trace
  9. import Frontend.Autogen.Parser
  10. import Frontend.Autogen.Lexer
  11. import Frontend.Lexer.Wrapper
  12. import Frontend.Lexer.Tokens
  13. import System.Environment (getArgs)
  14. import Text.Show.Pretty (pPrint)
  15. import Frontend.Parser.Posn
  16. import System.Posix.Internals
  17. import GHC.IO.Handle.FD (stdout, handleToFd)
  18. import GHC.IO.FD
  19. import Data.Maybe (fromMaybe)
  20. main :: IO ()
  21. main = do
  22. args <- getArgs
  23. for_ args $ \str -> do
  24. Main.lex str pPrint parseMod =<< Lbs.readFile str
  25. testParse :: String -> IO ()
  26. testParse s = Main.lex "<interactive>" print parseMod (Lbs.fromStrict (T.encodeUtf8 (T.pack s)))
  27. testLex :: String -> IO ()
  28. testLex s = Main.lex "<interactive>" (const (pure ())) (scan []) (Lbs.fromStrict (T.encodeUtf8 (T.pack s)))
  29. lex :: String -> (a -> IO ()) -> Alex a -> Lbs.ByteString -> IO ()
  30. lex fname show cont arg = do
  31. let x = runAlex fname arg cont
  32. case x of
  33. Left e -> showParseError e
  34. Right x -> show x
  35. showParseError :: ParseError -> IO ()
  36. showParseError pe = do
  37. code <- lines <$> readFile (parseErrorFilename pe)
  38. color <- fmap (1 ==) . c_isatty . fdFD =<< handleToFd GHC.IO.Handle.FD.stdout
  39. let
  40. linum = posnLine (parseErrorBegin pe)
  41. startcol = posnColm (parseErrorBegin pe)
  42. multiline = linum /= posnLine (parseErrorEnd pe)
  43. width
  44. | multiline = 0
  45. | otherwise = max 0 (posnColm (parseErrorEnd pe) - startcol - 1)
  46. linum' = show linum
  47. line = [ show linum ++ sep ++ code !! (linum - 1) | linum <- [ linum .. posnLine (parseErrorEnd pe) ] ]
  48. padding = replicate (length linum') ' ' ++ sep
  49. padding' = replicate (length linum') ' ' ++ " "
  50. caret = replicate (startcol - 1) ' ' ++ red ++ "^"
  51. squiggle = replicate width '~'
  52. (red, bold, reset, sep)
  53. | color = ("\x1b[31m", "\x1b[1m", "\x1b[0m", "\x1b[1;34m \9474 \x1b[0m")
  54. | otherwise = ("", "", "", "")
  55. putStr . unlines $
  56. [ bold
  57. ++ parseErrorFilename pe
  58. ++ ":" ++ show linum ++ ":" ++ show startcol ++ ": "
  59. ++ red ++ "parse error:" ++ reset
  60. , padding'
  61. , init (unlines line)
  62. , padding' ++ caret ++ squiggle ++ reset ++ fromMaybe "" ((" " ++) <$> parseErrorInlineDesc pe)
  63. , ""
  64. , padding' ++ parseErrorMessage pe
  65. ]
  66. scan :: [Token] -> Alex [Token]
  67. scan acc = do
  68. tok <- alexMonadScan
  69. sc <- alexGetStartCode
  70. state <- getUserState
  71. traceM . unlines $
  72. [ "----------------"
  73. , "just lexed: " ++ show tok
  74. , "sc: " ++ show sc
  75. , "sc stack: " ++ show (startCodes state)
  76. , "layout stack: " ++ show (layoutColumns state)
  77. ]
  78. case tokenClass tok of
  79. TokEof -> pure (reverse acc)
  80. _ -> scan (tok:acc)