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.

176 lines
5.8 KiB

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