c0parser (empty) → 0.1
raw patch · 4 files changed
+343/−0 lines, 4 filesdep +basedep +parsecsetup-changed
Dependencies added: base, parsec
Files
- Setup.hs +2/−0
- c0parser.cabal +19/−0
- src/Language/C0/Parser/C0Parser.hs +294/−0
- src/Language/C0/Types/C0Types.hs +28/−0
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ c0parser.cabal view
@@ -0,0 +1,19 @@+Name: c0parser+Version: 0.1+Synopsis: Simple C0 Parser+Description: The package contains a parser for C0 programs.+ The C0-language is introduced in the basic programming course \"Algorithmisches Denken und imperative Programmierung\" (WS 2011/12 and later) at the University of Bonn.+License: GPL+Author: Daniel Seidel+Maintainer: ds@iai.uni-bonn.de+Build-Type: Simple+Cabal-Version: >=1.2+Category: Language+Stability: Experimental++Library+ hs-source-dirs: src+ Exposed-Modules: Language.C0.Parser.C0Parser,+ Language.C0.Types.C0Types+ Build-Depends: base >= 3 && < 6,+ parsec >= 3 && <4
+ src/Language/C0/Parser/C0Parser.hs view
@@ -0,0 +1,294 @@+module Language.C0.Parser.C0Parser where++import Prelude hiding (Ordering(..))+import Language.C0.Types.C0Types+import Text.Parsec+import Text.ParserCombinators.Parsec.Char+import Text.Parsec.Token (integer)+import Text.Parsec.String (Parser)+import Control.Monad (sequence_)+import Data.List (intersperse, nub, foldl1')++--import Debug.Trace (trace)+trace _ x = x++keywords :: [String]+keywords = [ "auto", "break", "case", "char", "const", "continue"+ , "default", "do", "double", "else", "enum", "extern"+ , "float", "for", "goto", "if", "int", "long"+ , "register", "return", "short", "signed", "sizeof", "static"+ , "struct", "switch", "typdef", "union", "unsigned", "void"+ , "volatile", "while"]++yesNo :: String -> Bool+yesNo input = + case runP pYesNo [] "While Parsing C0 Program ..." input of+ Right b -> b+ Left e -> error "The impossible happened! A never failing parser failed."++pYesNo = (pProgram >> return True) <|> return False++wsOrCmts :: CharParser [String] ()+wsOrCmts = do+ many $ try (spaces >> (try comment1 <|> try comment2))+ spaces+ where+ comment1 = do+ string "//" + manyTill anyChar (char '\n')+ return ()+ comment2 = do+ string "/*"+ manyTill anyChar (string "*/")+ return ()++parseProg :: String -> (Either ParseError Program)+parseProg input = runP pProgram [] "While Parsing C0 Program ..." input++pProgram :: CharParser [Ident] Program+pProgram = do+ wsOrCmts+ string "#include"+ wsOrCmts+ char '<'+ wsOrCmts+ string "stdio.h"+ wsOrCmts+ char '>'+ wsOrCmts+ string "int"+ wsOrCmts+ string "main"+ wsOrCmts+ char '('+ wsOrCmts+ char ')'+ block <- pBlock+ return $ P block++pBlock :: CharParser [String] Block+pBlock = do+ wsOrCmts+ char '{'+ wsOrCmts+ (V decls) <- pVariableDeclaration+ setState(decls)+ (S stmts) <- pStatementSequence+ wsOrCmts+ string "return"+ wsOrCmts+ char '0'+ wsOrCmts+ char ';'+ wsOrCmts+ char '}'+ return $ B (V decls) (S stmts)++pVariableDeclaration :: CharParser [String] VariableDeclaration+pVariableDeclaration = do+ wsOrCmts+ (try (string "int")) <|> return []+ decls <- sepBy1 pIdent (wsOrCmts >> char ',')+ wsOrCmts+ char ';'+ if nub decls == decls + then (if (not $ foldr (||) False $ map isKeyword decls) + then return (V decls) + else fail "C-Schluesselwort als Bezeichner verwendet")+ else fail "Doppeldeklaration"++isKeyword :: String -> Bool+isKeyword ident = ident `elem` keywords++pIdent :: CharParser [String] String+pIdent = do+ trace "try to read ident ...\n" wsOrCmts+ hd <- try letter <|> char '_'+ tl <- many (try letter <|> try digit <|> char '_')+ trace ("return ident " ++ (hd:tl) ++ "\n") (return (hd:tl))++checkIdent :: String -> CharParser [String] ()+checkIdent ident = do+ idents <- trace ("DEBUG: checkIdent " ++ ident ++ "\n") getState+ if ident `elem` idents then trace "DEBUG: ... successful!\n" (return ()) else fail ("unknown identifier " ++ ident)++pStatementSequence :: CharParser [String] StatementSequence+pStatementSequence = + many1 (try pStatement) >>= (\stmts -> return (S stmts))++pStatement :: CharParser [String] Statement+pStatement = foldl1' (<|>) $ map try + [ trace "try pScanf ...\n" pScanf+ , trace "try pPrintf ...\n" pPrintf+ , trace "try pAssignment ...\n" pAssignment+ , trace "try pIfStatement ...\n" pIfStatement+ , trace "try pWhileStatement ...\n" (pWhileStatement <|> trace "DEBUG: WHILE FAILED" (fail "BLUB"))+ , trace "try pStatementSequence' ...\n" pStatementSequence'+ ]+ where pStatementSequence' = do+ wsOrCmts+ trace "DEBUG: try to read {" $ char '{' + wsOrCmts+ stmts <- trace "DEBUG: read statement sequence ...\n" pStatementSequence + wsOrCmts+ char '}'+ return (SSS stmts)++pScanf :: CharParser [String] Statement +pScanf = do+ wsOrCmts+ string "scanf"+ wsOrCmts+ char '('+ wsOrCmts+ string "\"%d\""+ wsOrCmts+ char ','+ wsOrCmts+ char '&'+ wsOrCmts+ ident <- pIdent+ checkIdent ident+ wsOrCmts+ char ')'+ wsOrCmts+ char ';'+ return (SS ident)++pPrintf :: CharParser [String] Statement +pPrintf = do+ wsOrCmts+ string "printf"+ wsOrCmts+ char '('+ wsOrCmts+ string "\"%d\""+ wsOrCmts+ char ','+ wsOrCmts+ ident <- pIdent+ checkIdent ident+ wsOrCmts+ char ')'+ wsOrCmts+ char ';'+ return (SP ident)++pAssignment :: CharParser [String] Statement +pAssignment = do+ wsOrCmts+ ident <- pIdent+ wsOrCmts+ char '='+ checkIdent ident+ wsOrCmts+ sexp <- pSimpleExpression+ wsOrCmts+ char ';'+ return $ SA (A ident sexp)++pIfStatement :: CharParser [String] Statement +pIfStatement = do+ wsOrCmts+ trace "try to read if\n" $ string "if"+ wsOrCmts+ char '('+ wsOrCmts+ bexp <- pBoolExpression+ wsOrCmts + char ')'+ stmt1 <- trace "parsed if part" pStatement+ wsOrCmts+ try (trace "parsed else" (string "else") >> wsOrCmts >> pStatement >>= (\stmt2 -> return $ SI (I bexp stmt1 (Just stmt2)))) <|> return (SI (I bexp stmt1 Nothing))++pWhileStatement :: CharParser [String] Statement +pWhileStatement = (do+ wsOrCmts+ trace "DEBUG: Testing for while\n" (string "while")+ wsOrCmts+ char '('+ bexp <- trace "DEBUG: try to read boolean expression\n" pBoolExpression+ trace "DEBUG: ... successfull!\n" wsOrCmts+ char ')'+ wsOrCmts+ stmt <- trace "DEBUG: try to read whileStatement\n" pStatement+ return $ SW (W bexp stmt))+ <|> (do+ (State s _ u) <- getParserState+ trace ("DEBUG: Simple Expression failed at ParserState:\n" ++ show s ++ "\n") fail "failed"+ )++pBoolExpression :: CharParser [String] BoolExpression +pBoolExpression = do+ sexp1 <- trace "DEBUG: try to read simpleExpression\n" pSimpleExpression+ rel <- trace "DEBUG: try to read relation\n" pRelation+ sexp2 <- trace "DEBUG: try to read second simple expression" pSimpleExpression+ return $ Bool sexp1 rel sexp2++pRelation :: CharParser [String] Relation+pRelation = try $ wsOrCmts >> (foldl1' (<|>) $ map try + [ string "==" >> return EQ+ , string "!=" >> return NE+ , string "<=" >> return LE+ , string ">=" >> return GE+ , char '<' >> return LT+ , char '>' >> return GT+ ])++pSimpleExpression :: CharParser [String] SimpleExpression+pSimpleExpression = (do+ wsOrCmts+ mSign <- trace "Entered simple expression ... \n" (pPlus <|> pMinus <|> return Nothing)+ (State s _ u) <- getParserState+ term <- trace ("DEBUG: try to read term at parser state:\n" ++ s ++ "\nwith user state: " ++ show u ++ " and sign = " ++ show mSign ++ "\n") pTerm+ terms <- trace "DEBUG: try to read more terms\n" pMoreTerms+ return $ Simple mSign term terms) <|> + (do+ (State s _ u) <- getParserState+ trace ("DEBUG: Simple Expression failed at ParserState:\n" ++ show s ++ "\n") fail "failed")+ +pPlus :: CharParser [String] (Maybe Sign)+pPlus = wsOrCmts >> char '+' >> return (Just Plus)++pMinus :: CharParser [String] (Maybe Sign)+pMinus = wsOrCmts >> char '-' >> return (Just Minus)++pTerm :: CharParser [String] Term+pTerm = (do+ trace "entered pTerm\n" (return ())+ (State s _ u) <- getParserState+ fac <- trace ("DEBUG: try to read factor at ParserState:\n" ++ s ++ "\n") pFactor+ facs <- trace ("DEBUG: try to read more factors ...") pMoreFactors+ trace ("read Term " ++ show (T fac facs) ++ "\n") return ()+ (return $ T fac facs)) <|> trace "DEBUG: pTerm failed" (return (T (FI "x") []))++pMoreTerms :: CharParser [String] [(OpAddSub, Term)]+pMoreTerms = many $ try (pOpAddSub >>= (\op->pTerm >>= (\t -> return (op,t))))++pOpAddSub :: CharParser [String] OpAddSub+pOpAddSub = wsOrCmts >> ((char '+' >> return Add) <|> (char '-' >> return Sub))++pFactor :: CharParser [String] Factor+pFactor = wsOrCmts >> (foldl1' (<|>) $ map try+ [ trace "DEBUG pFactor ident? ...\n" (pIdent >>= (\ident -> (checkIdent ident >> return (FI ident))))+ , trace "DEBUG pFactor number? ...\n" (pNumber >>= (\number -> return (FN number)))+ , trace "DEBUG pFactor (simple expression)? ...\n" (char '(' >> wsOrCmts >> pSimpleExpression >>= (\sexp -> (wsOrCmts >> char ')' >> return (FS sexp))))+ ])++pMoreFactors :: CharParser [String] [(OpMulDivMod, Factor)]+pMoreFactors = many (try (do+ op <- pOpMulDivMod + fac <- pFactor+ return (op,fac)))++pOpMulDivMod :: CharParser [String] OpMulDivMod+pOpMulDivMod = do+ op <-trace "try to read mul div mod ops\n" $ wsOrCmts >> ((char '*' >> return Mul) <|> (char '/' >> return Div) <|> (char '%' >> return Mod))+ trace ("read: " ++ show op ++ "\n") $ return op++pNumber :: CharParser [String] Int+pNumber = do+ wsOrCmts+ sign <- char '-' <|> return ' '+ digits <- many1 digit+ if sign == '-' then return ((read (sign:digits))::Int) else return ((read digits)::Int)
+ src/Language/C0/Types/C0Types.hs view
@@ -0,0 +1,28 @@+module Language.C0.Types.C0Types where++newtype Program = P Block deriving (Eq, Show)+data Block = B VariableDeclaration StatementSequence deriving (Eq, Show)+newtype VariableDeclaration = V [Ident] deriving (Eq, Show)+newtype StatementSequence = S [Statement] deriving (Eq, Show)+data Statement = SS Ident --scanf+ | SP Ident --printf+ | SA Assignment+ | SI IfStatement+ | SW WhileStatement+ | SSS StatementSequence+ deriving (Eq, Show)+data Assignment = A Ident SimpleExpression deriving (Eq, Show)+data IfStatement = I BoolExpression Statement (Maybe Statement) deriving (Eq, Show)+data WhileStatement = W BoolExpression Statement deriving (Eq, Show)+data BoolExpression = Bool SimpleExpression Relation SimpleExpression deriving (Eq, Show)+data Relation = EQ | NE | LT | GT | LE | GE deriving (Eq, Show)+data SimpleExpression = Simple (Maybe Sign) Term [(OpAddSub, Term)] deriving (Eq, Show)+data OpAddSub = Add | Sub deriving (Eq, Show)+data OpMulDivMod = Mul | Div | Mod deriving (Eq, Show)+data Sign = Plus | Minus deriving (Eq, Show)+data Term = T Factor [(OpMulDivMod, Factor)] deriving (Eq, Show)+data Factor = FI Ident + | FN Number + | FS SimpleExpression deriving (Eq, Show)+type Ident = String +type Number = Int