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.

180 lines
6.1 KiB

  1. module Frontend.Lexer.Wrapper where
  2. import Control.Applicative as App (Applicative (..))
  3. import Data.Word (Word8)
  4. import Data.Int (Int64)
  5. import qualified Data.Char
  6. import qualified Data.ByteString.Lazy as ByteString
  7. import qualified Data.ByteString.Internal as ByteString (w2c)
  8. import Frontend.Lexer.Tokens (Token)
  9. import qualified Data.Text as T
  10. import Frontend.Parser.Posn
  11. type Byte = Word8
  12. type AlexInput = ( Posn, -- current position,
  13. Char, -- previous char
  14. ByteString.ByteString, -- current input string
  15. Int64) -- bytes consumed so far
  16. ignorePendingBytes :: AlexInput -> AlexInput
  17. ignorePendingBytes i = i -- no pending bytes when lexing bytestrings
  18. alexInputPrevChar :: AlexInput -> Char
  19. alexInputPrevChar (_,c,_,_) = c
  20. alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)
  21. alexGetByte (p,_,cs,n) =
  22. case ByteString.uncons cs of
  23. Nothing -> Nothing
  24. Just (b, cs') ->
  25. let c = ByteString.w2c b
  26. p' = alexMove p c
  27. n' = n+1
  28. in p' `seq` cs' `seq` n' `seq` Just (b, (p', c, cs',n'))
  29. -- -----------------------------------------------------------------------------
  30. -- Token positions
  31. -- `Posn' records the location of a token in the input text. It has three
  32. -- fields: the address (number of chacaters preceding the token), line number
  33. -- and column of a token within the file. `start_pos' gives the position of the
  34. -- start of the file and `eof_pos' a standard encoding for the end of file.
  35. -- `move_pos' calculates the new position after traversing a given character,
  36. -- assuming the usual eight character tab stops.
  37. alexStartPos :: Posn
  38. alexStartPos = Posn 1 1
  39. alexMove :: Posn -> Char -> Posn
  40. alexMove (Posn l c) '\t' = Posn l (c+8-((c-1) `mod` 8))
  41. alexMove (Posn l _) '\n' = Posn (l+1) 1
  42. alexMove (Posn l c) _ = Posn l (c+1)
  43. data AlexState = AlexState {
  44. alex_pos :: !Posn, -- position at current input location
  45. alex_bpos:: !Int64, -- bytes consumed so far
  46. alex_inp :: ByteString.ByteString, -- the current input
  47. alex_chr :: !Char, -- the character before the input
  48. alex_scd :: !Int -- the current startcode
  49. , alex_ust :: AlexUserState -- AlexUserState will be defined in the user program
  50. , alex_fname :: String
  51. }
  52. runAlex :: String -> ByteString.ByteString -> Alex a -> Either ParseError a
  53. runAlex fname input__ (Alex f) =
  54. case f initState of
  55. Left msg -> Left msg
  56. Right ( _, a ) -> Right a
  57. where
  58. initState = AlexState
  59. { alex_bpos = 0
  60. , alex_pos = alexStartPos
  61. , alex_inp = input__
  62. , alex_chr = '\n'
  63. , alex_ust = alexInitUserState
  64. , alex_scd = 0
  65. , alex_fname = fname
  66. }
  67. newtype Alex a = Alex { unAlex :: AlexState -> Either ParseError (AlexState, a) }
  68. instance Functor Alex where
  69. fmap f a = Alex $ \s -> case unAlex a s of
  70. Left msg -> Left msg
  71. Right (s', a') -> Right (s', f a')
  72. instance Applicative Alex where
  73. pure a = Alex $ \s -> Right (s, a)
  74. fa <*> a = Alex $ \s -> case unAlex fa s of
  75. Left msg -> Left msg
  76. Right (s', f) -> case unAlex a s' of
  77. Left msg -> Left msg
  78. Right (s'', b) -> Right (s'', f b)
  79. instance Monad Alex where
  80. m >>= k = Alex $ \s -> case unAlex m s of
  81. Left msg -> Left msg
  82. Right (s',a) -> unAlex (k a) s'
  83. return = App.pure
  84. alexGetInput :: Alex AlexInput
  85. alexGetInput =
  86. Alex $ \s@AlexState{alex_pos=pos,alex_bpos=bpos,alex_chr=c,alex_inp=inp__} ->
  87. Right (s, (pos,c,inp__,bpos))
  88. alexSetInput :: AlexInput -> Alex ()
  89. alexSetInput (pos,c,inp__,bpos)
  90. = Alex $ \s -> Right ( s { alex_pos = pos
  91. , alex_bpos = bpos
  92. , alex_chr = c
  93. , alex_inp = inp__
  94. }
  95. , ())
  96. alexError :: String -> Alex a
  97. alexError message = Alex $ \s -> Left (ParseError message (alex_fname s) Nothing (alex_pos s) (alex_pos s))
  98. alexErrorPosn :: Posn -> Posn -> String -> Alex a
  99. alexErrorPosn start end message = Alex $ \s -> Left (ParseError message (alex_fname s) Nothing start end)
  100. alexThrow :: (String -> ParseError) -> Alex a
  101. alexThrow err = Alex $ \s -> Left (err (alex_fname s))
  102. alexGetStartCode :: Alex Int
  103. alexGetStartCode = Alex $ \s@AlexState{alex_scd=sc} -> Right (s, sc)
  104. alexSetStartCode :: Int -> Alex ()
  105. alexSetStartCode sc = Alex $ \s -> Right (s{alex_scd=sc}, ())
  106. -- -----------------------------------------------------------------------------
  107. -- Useful token actions
  108. type AlexAction result = AlexInput -> Int64 -> Alex result
  109. -- perform an action for this token, and set the start code to a new value
  110. andBegin :: AlexAction result -> Int -> AlexAction result
  111. (action `andBegin` code) input__ len = do
  112. alexSetStartCode code
  113. action input__ len
  114. token :: (AlexInput -> Int64 -> token) -> AlexAction token
  115. token t input__ len = return (t input__ len)
  116. data LayoutState
  117. = LetLayout { layoutCol :: Int }
  118. | Layout { layoutCol :: Int }
  119. | ExplicitLayout
  120. deriving (Show)
  121. data AlexUserState =
  122. AlexUserState { layoutColumns :: ![LayoutState]
  123. , startCodes :: ![Int]
  124. , leastColumn :: !Int
  125. , pendingLayoutKw :: Maybe (Int -> LayoutState)
  126. , pendingTokens :: ![Token]
  127. , pendingLambdaCase :: !Bool
  128. , stringBuffer :: !T.Text
  129. , stringStartPosn :: Maybe Posn
  130. }
  131. alexInitUserState :: AlexUserState
  132. alexInitUserState = AlexUserState [] [] 0 Nothing [] False T.empty Nothing
  133. data ParseError
  134. = ParseError { parseErrorMessage :: String
  135. , parseErrorFilename :: String
  136. , parseErrorInlineDesc :: Maybe String
  137. , parseErrorBegin :: Posn
  138. , parseErrorEnd :: Posn
  139. }
  140. deriving (Eq, Show)