-- ParseCalc.lhs -- Parsing expressions and commands -- (c) Simon Thompson, 1998 module ParseCalc where import Types import ParseLib -- A parser for expressions -- -- -- The parser has three components, corresponding to the three -- clauses in the definition of the syntactic type. -- parseExpr :: Parse Char Expr parseExpr = (litParse `alt` varParse) `alt` opExpParse -- -- Spotting variables. -- varParse :: Parse Char Expr varParse = spot isVar `build` Var isVar :: Char -> Bool isVar x = ('a' <= x && x <= 'z') -- -- Parsing (fully bracketed) operator applications. -- opExpParse = (token '(' >*> parseExpr >*> spot isOp >*> parseExpr >*> token ')') `build` makeExpr makeExpr (_,(e1,(bop,(e2,_)))) = Op (charToOp bop) e1 e2 isOp :: Char -> Bool isOp ch = elem ch "+-*/%" charToOp :: Char -> Ops charToOp ch = case ch of '+' -> Add '-' -> Sub '*' -> Mul '/' -> Div '%' -> Mod -- -- A number is a list of digits with an optional ~ at the front. -- litParse = ((optional (token '~')) >*> (neList (spot isDigit))) `build` (charListToExpr.join) where join = uncurry (++) -- Converting strings representing numbers into numbers -- charListToExpr :: [Char] -> Expr charListToExpr = Lit . charListToInt charListToInt :: [Char] -> Int charListToInt ('~':rest) = - (charListToNat rest) charListToInt other = charListToNat other charListToNat :: [Char] -> Int charListToNat [] = 0 charListToNat (ch:rest) = charToNat ch * 10^(length rest) + charListToNat rest charToNat :: Char -> Int charToNat ch | ord ch < ord '0' + 10 = ord ch - ord '0' | otherwise = ord '0' -- -- The top-level parser -- topLevel :: Parse a b -> [a] -> b topLevel p inp = case results of [] -> error "parse unsuccessful" _ -> head results where results = [ found | (found,[]) <- p inp ] -- A parse for the type of commands. -- parseCommand :: Parse Char Command parseCommand = ((parseExpr `build` Eval) `alt` (((spot isVar) >*> (token ':') >*> parseExpr) `build` makeComm)) `alt` endOfInput Null makeComm (v,(_,e)) = Assign v e -- This is the function which gets used in a top-level interaction..... calcLine :: String -> Command calcLine = topLevel parseCommand --