-------------------------------------------------------------
-- 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
|