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.

276 lines
7.7 KiB

  1. {
  2. {-# LANGUAGE FlexibleContexts, FlexibleInstances, ViewPatterns #-}
  3. module Frontend.Autogen.Parser where
  4. import qualified Data.Text as T
  5. import Data.Maybe
  6. import Frontend.Lexer.Wrapper
  7. import Frontend.Lexer.Tokens
  8. import Frontend.Parser.Posn
  9. import Frontend.Syntax
  10. import Frontend.Autogen.Lexer
  11. import qualified Prelude
  12. import Prelude hiding (span)
  13. import Debug.Trace
  14. import Control.Monad
  15. }
  16. %name parseExp Exp
  17. %name parseMod Module
  18. %name parseType Type
  19. %tokentype { Token }
  20. %monad { Alex }
  21. %lexer { lexer } { Token TokEof _ _ }
  22. %errorhandlertype explist
  23. %error { parseError }
  24. %token
  25. VAR { Token (TokUnqual VarId _) _ _ }
  26. CON { Token (TokUnqual ConId _) _ _ }
  27. QVAR { Token (TokQual VarId _ _) _ _ }
  28. QCON { Token (TokQual ConId _ _) _ _ }
  29. STRING { Token (TokString _) _ _ }
  30. 'eof' { Token TokEof _ _ }
  31. '(' { Token TokOParen _ _ }
  32. ')' { Token TokCParen _ _ }
  33. '{' { Token TokOBrace _ _ }
  34. '}' { Token TokCBrace _ _ }
  35. START { Token TokLStart _ _ }
  36. END { Token TokLEnd _ _ }
  37. '[' { Token TokOSquare _ _ }
  38. ']' { Token TokCSquare _ _ }
  39. '{-#' { Token TokOPragma _ _ }
  40. '#-}' { Token TokCPragma _ _ }
  41. '\\' { Token TokLambda _ _ }
  42. '->' { Token TokArrow _ _ }
  43. '_' { Token TokUnder _ _ }
  44. '::' { Token TokDoubleColon _ _ }
  45. ';' { Token TokSemi _ _ }
  46. '=' { Token TokEqual _ _ }
  47. ',' { Token TokComma _ _ }
  48. 'let' { Token TokLet _ _ }
  49. 'in' { Token TokIn _ _ }
  50. 'data' { Token TokData _ _ }
  51. 'case' { Token TokCase _ _ }
  52. 'module' { Token TokModule _ _ }
  53. 'where' { Token TokWhere _ _ }
  54. 'import' { Token TokImport _ _ }
  55. 'as' { Token TokAs _ _ }
  56. 'qualified' { Token TokQualified _ _ }
  57. %%
  58. Exp :: { Exp }
  59. : InfixExp '::' Type { span $1 $3 $ Annot $1 $3 }
  60. | InfixExp { $1 }
  61. InfixExp :: { Exp }
  62. : LeftExp {- ... -} { $1 }
  63. -- | LeftExp qop InfixExp { Infix $1 (getVar $2) $3 }
  64. LeftExp :: { Exp }
  65. : '\\' Apat List(Apat) '->' Exp { span $1 $5 (makeLams ($2:$3) $5) }
  66. | 'let' LaidOutList(Decl) 'in' Exp { span $1 $4 $ Let (thd $2) $4 }
  67. | FuncExp { $1 }
  68. FuncExp :: { Exp }
  69. : FuncExp Aexp { span $1 $2 $ App $1 $2 }
  70. | Aexp { $1 }
  71. Aexp :: { Exp }
  72. : qvar { span $1 $1 $ Ref $1 }
  73. | qcon { span $1 $1 $ Con $1 }
  74. | '(' CommaList(Exp) ')' { span $1 $3 $ makeTuple $2 }
  75. | STRING { span $1 $1 $ Literal (LitString (getString $1)) }
  76. Type :: { Type }
  77. : Btype '->' Type { span $1 $3 $ Tyarr $1 $3 }
  78. | Btype { $1 }
  79. Btype :: { Type }
  80. : Btype Atype { span $1 $2 $ Tyapp $1 $2 }
  81. | Atype { $1 }
  82. Atype :: { Type }
  83. : qvar { span $1 $1 $ Tyvar $1 }
  84. | qcon { span $1 $1 $ Tycon $1 }
  85. | '(' CommaList(Type) ')' { span $1 $3 $ makeTupleType $2 }
  86. Pat :: { Pat }
  87. : Lpat { $1 }
  88. Lpat :: { Pat }
  89. : Apat { $1 }
  90. Apat :: { Pat }
  91. : VAR { span $1 $1 $ Var (getVar $1) }
  92. | '_' { span $1 $1 $ Wildcard }
  93. | '(' CommaList(Pat) ')' { span $1 $3 $ makeTuplePattern $2 }
  94. Decl :: { Decl }
  95. : CommaList1(VAR) '::' Type { TySig (getVar `fmap` $1) $3 (startPosn (head $1)) (endPosn $3) }
  96. | VAR Apat List(Apat) Rhs { FunDecl (getVar $1) ($2:$3) $4 (startPosn $1) (endPosn $4) }
  97. | Pat Rhs { PatDecl $1 $2 (startPosn $1) (endPosn $2) }
  98. Rhs :: { Rhs }
  99. : '=' Exp { BareRhs $2 [] (startPosn $1) (endPosn $2) }
  100. | '=' Exp 'where' LaidOutList(Decl) { BareRhs $2 (thd $4) (startPosn $1) (endPosn $4) }
  101. LaidOutList(p)
  102. : START Opt(Semis) LOLContents(p, END) { (startPosn $1, lolEnd $3, lolList $3) }
  103. | '{' Opt(Semis) LOLContents(p, '}') { (startPosn $1, lolEnd $3, lolList $3) }
  104. LOLContents(p, End)
  105. : p Semis LOLContents(p,End) { lolCons $1 $3 }
  106. | p Opt(Semis) End { lolCons $1 (emptyLol $3) }
  107. | Opt(Semis) End { emptyLol $2 }
  108. Module :: { Module }
  109. : 'module' CON ImportExportList 'where' LaidOutList(ModItem)
  110. {% do { (imports,items) <- spanModuleItems (thd $5)
  111. ; pure $ Module { moduleName = toModId (getVar $2)
  112. , moduleExports = fst $3
  113. , moduleImports = imports
  114. , moduleItems = items }
  115. }
  116. }
  117. ImportExportList :: { (Maybe [NamespacedItem ParsedVar], Maybe Posn) }
  118. : {-empty-} { (Nothing, Nothing) }
  119. | '(' CommaList(NSItem) ')' { (Just $2, Just (endPosn $3)) }
  120. NSItem :: { NamespacedItem ParsedVar }
  121. : VAR { IEVar (getVar $1) }
  122. | CON { IECon (getVar $1) }
  123. | 'module' CON { IEModule (getVar $2) }
  124. ModItem :: { Item }
  125. : Decl { ModDecl $1 (startPosn $1) (endPosn $1) }
  126. | Import { ModImport $1 (startPosn $1) (endPosn $1) }
  127. Import :: { ModuleImport ParsedVar }
  128. : 'import' modid ImportExportList
  129. { Import $2 (fst $3) False Nothing (startPosn $1) (fromMaybe (endPosn $2) (snd $3)) }
  130. | 'import' modid ImportExportList 'as' CON
  131. { Import $2 (fst $3) False (Just (getVar $5)) (startPosn $1) (endPosn $5) }
  132. | 'import' 'qualified' modid ImportExportList
  133. { Import $3 (fst $4) True Nothing (startPosn $1) (fromMaybe (endPosn $3) (snd $4)) }
  134. | 'import' 'qualified' modid ImportExportList 'as' CON
  135. { Import $3 (fst $4) True (Just (getVar $6)) (startPosn $1) (endPosn $6) }
  136. Opt(p)
  137. : { () }
  138. | p { () }
  139. Semis
  140. : ';' Semis { () }
  141. | ';' { () }
  142. -- TODO: qualified names
  143. qvar :: { ParsedVar }
  144. qvar : VAR { getVar $1 }
  145. | QVAR { getVar $1 }
  146. qcon : CON { getVar $1 }
  147. | QCON { getVar $1 }
  148. modid : qcon { toModId $1 }
  149. List(p)
  150. : {-empty-} { [] }
  151. | p List(p) { $1:$2 }
  152. CommaList(p)
  153. : {-empty-} { [] }
  154. | p { [$1] }
  155. | p ',' CommaList(p) { $1:$3 }
  156. CommaList1(p)
  157. : p { [$1] }
  158. | p ',' CommaList(p) { $1:$3 }
  159. Block(p)
  160. : START p END { (startPosn $1, endPosn $3, $2) }
  161. | '{' p '}' { (startPosn $1, endPosn $3, $2) }
  162. {
  163. type Exp = FeExpr ParsedVar
  164. type Pat = FePat ParsedVar
  165. type Decl = FeDecl ParsedVar
  166. type Type = FeType ParsedVar
  167. type Rhs = FeRhs ParsedVar
  168. type Module = FeModule ParsedVar
  169. type Item = ModuleItem ParsedVar
  170. lexer cont = alexMonadScan >>= cont
  171. parseError x = alexError (show x)
  172. makeLams xs b = foldr Lam b xs
  173. getVar :: Token -> ParsedVar
  174. getVar tok@(Token (TokQual _ p s) _ _) = QualVar { varId = s, varPrefix = p, varBegin = startPosn tok, varEnd = endPosn tok }
  175. getVar tok@(Token (TokUnqual _ s) _ _) = UnqualVar { varId = s, varBegin = startPosn tok, varEnd = endPosn tok }
  176. getVar _ = error "getVar non-var"
  177. getString (Token (TokString s) _ _) = s
  178. getString _ = error "getString non-string"
  179. data LOL a = LOL { lolEnd :: Posn, lolList :: [a] }
  180. emptyLol :: HasPosn x => x -> LOL a
  181. emptyLol t = LOL (endPosn t) []
  182. lolCons :: a -> LOL a -> LOL a
  183. lolCons x (LOL p xs) = LOL p (x:xs)
  184. makeTupleType [x] = ParenType x
  185. makeTupleType xs = Tytup xs
  186. makeTuplePattern [x] = ParenPat x
  187. makeTuplePattern xs = TupPat xs
  188. makeTuple [x] = ParenExp x
  189. makeTuple xs = Tuple xs
  190. spanModuleItems xs = do
  191. let
  192. isImport (ModImport _ _ _) = True
  193. isImport _ = False
  194. (imports, items) = Prelude.span isImport xs
  195. forM_ items $ \x -> case x of
  196. ModImport _ start end ->
  197. alexThrow $ \fname ->
  198. ParseError { parseErrorMessage = "all import statements should be at the top of the file."
  199. , parseErrorInlineDesc = Just "unexpected import statement"
  200. , parseErrorFilename = fname
  201. , parseErrorBegin = start
  202. , parseErrorEnd = end
  203. }
  204. _ -> pure ()
  205. pure (map itemImport imports, items)
  206. }