--- /dev/null
+-------------------------------------------------------------
+-- 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