[project @ 2002-05-31 12:22:33 by panne]
[haskell-directory.git] / Text / ParserCombinators / Parsec / examples / while / While.hs
diff --git a/Text/ParserCombinators/Parsec/examples/while/While.hs b/Text/ParserCombinators/Parsec/examples/while/While.hs
new file mode 100644 (file)
index 0000000..d686edc
--- /dev/null
@@ -0,0 +1,179 @@
+-------------------------------------------------------------
+-- Parser for WHILE from Nielson, Nielson and Hankin
+-- and various other sources.
+-------------------------------------------------------------
+
+module While( prettyWhileFromFile ) where
+
+import WhileAS
+import Text.ParserCombinators.Parsec
+import Text.ParserCombinators.Parsec.Expr
+import qualified Text.ParserCombinators.Parsec.Token as P
+import Text.ParserCombinators.Parsec.Language( javaStyle )
+
+
+prettyWhileFromFile fname
+  = do{ input <- readFile fname
+      ; putStr input
+      ; case parse program fname input of
+           Left err -> do{ putStr "parse error at "
+                           ; print err
+                           }
+           Right x  -> print x
+      }
+
+--renum :: Prog -> Prog
+--renum p = rn (1,p)
+--rn :: (Int, Stat) -> (Int, Stat)
+--rn (x,s) = case s of
+--            Assign vi ae _  -> (x+1,Assign vi ae x)
+--            Skip _          -> (x+1, Skip x)
+--            Seq [Stat]      -> 
+--            If be _ s1 s2   -> do{ (newx, newthen) <- rn (x+1,s1)
+--                                 ; (newerx, newelse) <- rn (newx,s2)
+--                                 ; return (newerx, If be x newthen newelse)
+--                                 }
+--            While be _ s    -> do{ (newx, news) <- rn (x+1,s)
+--                                 ; return (newx, While be x+1 news)
+--                                 }
+
+-----------------------------------------------------------
+-- A program is simply an expression.
+-----------------------------------------------------------
+program 
+    = do{ stats <- semiSep1 stat
+        ; return (if length stats < 2 then head stats else Seq stats)
+        }
+        
+stat :: Parser Stat
+stat = choice 
+       [ do { reserved "skip";
+              return (Skip 0)
+            }
+       , ifStat
+       , whileStat
+       , sequenceStat
+       , try assignStat
+       ]
+
+
+assignStat :: Parser Stat
+assignStat = do{ id <- identifier
+               ; symbol ":="
+               ; s <- aritExpr
+               ; return (Assign id s 0)
+               }
+
+ifStat :: Parser Stat
+ifStat = do{ reserved "if"
+             ; cond <- boolExpr
+             ; reserved "then"
+             ; thenpart <- stat
+             ; reserved "else"
+             ; elsepart <- stat
+             ; return (If cond 0 thenpart elsepart)
+             }
+             
+whileStat :: Parser Stat
+whileStat = do{ reserved "while"
+              ; cond <- boolExpr
+              ; reserved "do"
+              ; body <- stat
+              ; return (While cond 0 body)
+              }
+
+sequenceStat :: Parser Stat
+sequenceStat = do{ stats <- parens (semiSep1 stat)
+                 ; return (if length stats < 2 then head stats else Seq stats)
+                 }
+
+boolExpr:: Parser BExp
+boolExpr = buildExpressionParser boolOperators relExpr
+
+relExpr :: Parser BExp
+relExpr = do{ arg1 <- aritExpr
+            ; op <- choice [string "=", try (string "<>"), try (string "<="), string "<", try (string ">="), string ">"]
+            ; arg2 <- aritExpr
+            ; return (RelOp op arg1 arg2)
+            }
+
+aritExpr :: Parser AExp
+aritExpr = buildExpressionParser aritOperators simpleArit
+
+-- Everything mapping bools to bools
+boolOperators =
+    [ [ prefix "not"]
+    , [ opbb "and" AssocRight ] -- right for shortcircuit
+    , [ opbb "or" AssocRight ] -- right for shortcircuit
+    ]
+    where
+      opbb name assoc   = Infix (do{ reservedOp name
+                                   ; return (\x y -> BOp name x y) 
+                                   }) assoc
+      prefix name       = Prefix  (do{ reservedOp name
+                                  ; return (\x -> BUnOp name x)
+                                  })                                      
+
+-- Everything mapping pairs of ints to ints
+aritOperators =
+    [ [ op "*"  AssocLeft, op "/"  AssocLeft ]
+    , [ op "+"  AssocLeft, op "-"  AssocLeft ]
+    , [ op "&" AssocRight ] -- bitwise and delivering an int
+    , [ op "|" AssocRight ] -- bitwise or delivering an int
+    ]
+    where
+      op name assoc   = Infix (do{ reservedOp name
+                                  ; return (\x y -> AOp name x y) 
+                                  }) assoc
+
+
+simpleArit = choice [ intLiteral
+                    , parens aritExpr
+                    , variable
+                    ]
+
+simpleBool = choice [ boolLiteral
+                    , parens boolExpr
+                    ]
+
+boolLiteral = do{ reserved "false"
+               ; return (BoolLit True)
+               }
+             <|>  
+             do{ reserved "true"
+               ; return (BoolLit False)
+               }
+
+intLiteral = do{ i <- integer; return (IntLit i) }
+variable = do{ id <- identifier
+             ; return (Var id)
+             }
+             
+
+-----------------------------------------------------------
+-- The lexer
+-----------------------------------------------------------
+lexer     = P.makeTokenParser whileDef
+
+whileDef  = javaStyle
+          { -- Kept the Java single line comments, but officially the language has no comments
+            P.reservedNames  = [ "true", "false", "do", "else", "not",
+                               "if", "then", "while", "skip"
+                               -- , "begin", "proc", "is", "end", "val", "res", "malloc" 
+                              ]
+          , P.reservedOpNames= [ "and", "or", "not", "<", "<=", ">", ">=", ":=", "+", "&", "-", "/"]
+          , P.opLetter       = oneOf (concat (P.reservedOpNames whileDef))
+          , P.caseSensitive  = False
+          }
+
+parens          = P.parens lexer    
+braces          = P.braces lexer    
+semiSep1        = P.semiSep1 lexer    
+whiteSpace      = P.whiteSpace lexer    
+symbol          = P.symbol lexer    
+identifier      = P.identifier lexer    
+reserved        = P.reserved lexer    
+reservedOp      = P.reservedOp lexer
+integer         = P.integer lexer    
+charLiteral     = P.charLiteral lexer    
+stringLiteral   = P.stringLiteral lexer