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