aboutsummaryrefslogtreecommitdiff
path: root/ProgramParser.hs
diff options
context:
space:
mode:
Diffstat (limited to 'ProgramParser.hs')
-rw-r--r--ProgramParser.hs107
1 files changed, 67 insertions, 40 deletions
diff --git a/ProgramParser.hs b/ProgramParser.hs
index a71d07e..411e063 100644
--- a/ProgramParser.hs
+++ b/ProgramParser.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TupleSections #-}
+
module ProgramParser(parseProgram) where
import Control.Monad
@@ -19,20 +21,32 @@ parseProgram s = case parse pProgram "" s of
Right p -> Right p
pProgram :: Parser Program
-pProgram = do
- pWhiteComment
- decls <- many pDecl
- eof
- return $ Program (lefts decls) (rights decls)
-
-pDecl :: Parser (Either DVar DFunc)
-pDecl = (Right <$> pDFunc) <|> (Left <$> pDVar)
+pProgram = between pWhiteComment eof go
+ where
+ go :: Parser Program
+ go = (pDTypedef >>= \d -> addTypedef d <$> go) <|>
+ (pDFunc >>= \d -> addFunc d <$> go) <|>
+ (pDVar >>= \d -> addVar d <$> go) <|>
+ return (Program [] [] [])
+
+ addTypedef d (Program a b c) = Program (d:a) b c
+ addVar d (Program a b c) = Program a (d:b) c
+ addFunc d (Program a b c) = Program a b (d:c)
+
+pDTypedef :: Parser DTypedef
+pDTypedef = do
+ symbol "type"
+ n <- pName
+ symbol ":="
+ t <- pType
+ symbol ";"
+ return $ DTypedef n t
pDFunc :: Parser DFunc
pDFunc = do
symbol "func"
- rt <- (Just <$> pType) <|> return Nothing
- n <- pName
+ (rt,n) <- (try $ pType >>= \t -> (Just t,) <$> pName) <|>
+ ((Nothing,) <$> pName)
symbol "("
args <- sepBy pTypeAndName (symbol ",")
symbol ")"
@@ -41,8 +55,7 @@ pDFunc = do
pDVar :: Parser DVar
pDVar = do
- t <- pType
- n <- pName
+ (t,n) <- try pTypeAndName
symbol ":="
e <- pExpression
symbol ";"
@@ -52,16 +65,27 @@ pTypeAndName :: Parser (Type, Name)
pTypeAndName = (,) <$> pType <*> pName
pType :: Parser Type
-pType = do
- t <- pBasicType
- (do
- symbol "["
- msz <- optionMaybe pInteger
- symbol "]"
- return $ TArr t msz) <|> return t
+pType = (flip label "type") $
+ pStruct <|> do
+ t <- pBasicType
+ (do
+ symbol "["
+ msz <- optionMaybe pInteger
+ symbol "]"
+ return $ TArr t msz) <|> return t
+
+pStruct :: Parser Type
+pStruct = do
+ symbol "struct"
+ symbol "{"
+ ms <- many $ pTypeAndName <* symbol ";"
+ symbol "}"
+ return $ TStruct ms
pBasicType :: Parser Type
-pBasicType = (symbol "int" >> return TInt) <|> (symbol "char" >> return TChar)
+pBasicType = (symbol "int" >> return TInt) <|>
+ (symbol "char" >> return TChar) <|>
+ (TName <$> pName)
pBlock :: Parser Block
pBlock = do
@@ -134,7 +158,7 @@ pSExpr = do
return $ SExpr e
pExpression :: Parser Expression
-pExpression = E.buildExpressionParser optable litparser
+pExpression = E.buildExpressionParser optable litparser <?> "expression"
where
optable =
[[E.Infix (symbol "**" >> return (mkEBin BOPow)) E.AssocRight],
@@ -163,11 +187,14 @@ pExpression = E.buildExpressionParser optable litparser
litparser :: Parser Expression
litparser = do
- pops <- many pPrefixOp
- e <- pParenExpr <|> pENew <|> pCastExpr <|> (mkELit <$> pLiteral)
- subs <- many $ between (symbol "[") (symbol "]") pExpression
- let e' = foldl (\ex sub -> ESubscript ex sub Nothing) e subs
- e'' = foldl (\ex pop -> EUn pop ex Nothing) e' pops
+ preops <- many pPrefixOp
+ e <- pParenExpr <|> pENew <|> (mkELit <$> pLiteral)
+ postops <- many pPostfixOp
+ let e' = foldl (\ex op -> case op of
+ Left sub -> ESubscript ex sub Nothing
+ Right n -> EGet ex n Nothing)
+ e postops
+ e'' = foldl (\ex pop -> EUn pop ex Nothing) e' preops
return e''
pAsExpression :: Parser AsExpression
@@ -180,6 +207,12 @@ pPrefixOp :: Parser UnaryOp
pPrefixOp = (symbol "!" >> return UONot) <|>
(symbol "-" >> return UONeg)
+-- Left: subscript; Right: dot-index
+pPostfixOp :: Parser (Either Expression Name)
+pPostfixOp =
+ (Left <$> between (symbol "[") (symbol "]") pExpression) <|>
+ (Right <$> (symbol "." >> pName))
+
pParenExpr :: Parser Expression
pParenExpr = do
symbol "("
@@ -187,13 +220,6 @@ pParenExpr = do
symbol ")"
return e
-pCastExpr :: Parser Expression
-pCastExpr = do
- t <- try $ pType <* symbol "("
- e <- pExpression
- symbol ")"
- return $ ECast t e
-
pENew :: Parser Expression
pENew = do
symbol "new"
@@ -206,7 +232,7 @@ pENew = do
pLiteral :: Parser Literal
pLiteral =
(LInt <$> pInteger) <|> (LChar <$> pCharLit) <|> (LStr <$> pString) <|>
- pLCall <|> (LVar <$> pName)
+ pLStruct <|> pLCall <|> (LVar <$> pName)
pCharLit :: Parser Char
pCharLit = do
@@ -237,6 +263,13 @@ pString = do
void $ char '"'
return s
+pLStruct :: Parser Literal
+pLStruct = do
+ symbol "{"
+ ms <- sepBy (pName >>= \n -> symbol "=" >> pExpression >>= \e -> return (n,e)) (symbol ",")
+ symbol "}"
+ return $ LStruct ms
+
pLCall :: Parser Literal
pLCall = do
n <- try $ pName <* symbol "("
@@ -310,9 +343,3 @@ pBlockComment = do
void $ sepEndBy (manyTill anyToken (lookAhead $ try (string "/*") <|> try (string "*/")))
pBlockComment
void $ string "*/"
-
-lefts :: [Either a b] -> [a]
-lefts = foldr (\e l -> either (:l) (const l) e) []
-
-rights :: [Either a b] -> [b]
-rights = foldr (\e l -> either (const l) (:l) e) []