packages feed

c0check (empty) → 0.0

raw patch · 5 files changed

+355/−0 lines, 5 filesdep +basedep +c0checkdep +parsecsetup-changed

Dependencies added: base, c0check, parsec

Files

+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ c0check.cabal view
@@ -0,0 +1,25 @@+Name:                c0check+Version:             0.0+Synopsis:            Simple C0 Parser+Description:         The package contains a parser for C0-language that is introduced in the basic programming course \"Algorithmisches Denken und imperative Programmierung\" (WS 2011/12 and later) at the University of Bonn.+                     The program contained in the package will take a C source code file and test the content if it is conform to the C0-language specifications. +                     The answer is simply yes or no.+License:             GPL+Author:              Daniel Seidel+Maintainer:          ds@iai.uni-bonn.de+Build-Type:          Simple+Cabal-Version:       >=1.8+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++Executable c0check+  Main-is:           src/c0check.hs+  Build-Depends:     base >= 3 && < 6,+                     c0check
+ src/Language/C0/Parser/C0Parser.hs view
@@ -0,0 +1,278 @@+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++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 return (V decls) else fail "Doppeldeklaration"++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 <- pStatement+  try (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 
+ src/c0check.hs view
@@ -0,0 +1,22 @@+module Main where++import System.Environment (getArgs)+import Language.C0.Parser.C0Parser (yesNo)++checkFile fn = do+  input <- readFile fn+  putStr "Folgendes Programm wurde gelesen:\n\n"+  putStr input+  putStr "\n\n"+  case yesNo input of+    True  -> putStr "Ihr Programm ist syntaktisch korrektes C0."+    False -> putStr "Das getestete Programm ist *kein* C0-Programm."+  putStr "\n\n"+  ++main = do+  args <- getArgs+  case args of+   []   -> error "Die zu testende Quellcodedatei ist als Argument zu uebergeben."+   [fn] -> checkFile fn+   _    -> error "Zuviele Parameter. Aufruf nur als c0check prog.c"