module Lexer (Lexeme(..), lexer) where import Char -- 1.3 -- lexeme data Lexeme = Ide String | Evar String | Op String | Num String | Lparen | Rparen | Comma deriving Eq -- lexical analyzer returns a Bool indicating whether scanning is successful. lexer :: String -> ([Lexeme], Bool) lexer "" = ([], True) lexer r@(c:s) = if isSpace c then lexer (dropWhile isSpace s) else if isAlpha c then let (str1,str2) = span isAlphaNum r in current_lexeme (Ide str1) str2 else if isDigit c then let (lexeme, rest) = (lexerNum r) in current_lexeme lexeme rest else if isOp c then let (op, rest) = getOp (c:s) in current_lexeme (Op op) rest else if c == '(' then current_lexeme Lparen s else if c == ')' then current_lexeme Rparen s else if c == ',' then current_lexeme Comma s else if c == '$' then let (str1,str2) = span isAlphaNum s in current_lexeme (Evar ('$':str1)) str2 else (consume s, False) where current_lexeme clex rest = (clex : rlex, succ) where (rlex, succ) = lexer rest isOp c = c `elem` "+-*/^='><" getOp (c:s) = if c `elem` "+-*^" then ([c], s) else case s of ('=':ss) -> case c of '=' -> ("==",ss) '>' -> (">=",ss) '<' -> ("<=",ss) '/' -> ("/=",ss) _ -> ([c],s) _ -> ([c],s) lexerNum r = ((Num (ds++f)), t) where (ds,s) = span isDigit r (f,t) = lexFracExp s lexFracExp ('.':r) = ('.':ds, s) where (ds, s) = span isDigit r lexFracExp s = ("",s) consume [] = [] consume (s:ss) = consume ss