1 module Lexer (Lexeme(..), lexer) where 2 3 import Char -- 1.3 4 5 -- lexeme 6 data Lexeme = Ide String 7 | Evar String 8 | Op String 9 | Num String 10 | Lparen 11 | Rparen 12 | Comma 13 deriving Eq 14 15 -- lexical analyzer returns a Bool indicating whether scanning is successful. 16 lexer :: String -> ([Lexeme], Bool) 17 18 lexer "" = ([], True) 19 lexer r@(c:s) = 20 if isSpace c then lexer (dropWhile isSpace s) 21 else if isAlpha c then 22 let (str1,str2) = span isAlphaNum r 23 in current_lexeme (Ide str1) str2 24 else if isDigit c then 25 let (lexeme, rest) = (lexerNum r) 26 in current_lexeme lexeme rest 27 else if isOp c then 28 let (op, rest) = getOp (c:s) 29 in current_lexeme (Op op) rest 30 else if c == '(' then current_lexeme Lparen s 31 else if c == ')' then current_lexeme Rparen s 32 else if c == ',' then current_lexeme Comma s 33 else if c == '$' then let (str1,str2) = span isAlphaNum s 34 in current_lexeme (Evar ('$':str1)) str2 35 else (consume s, False) 36 where 37 current_lexeme clex rest = (clex : rlex, succ) 38 where (rlex, succ) = lexer rest 39 isOp c = c `elem` "+-*/^='><" 40 getOp (c:s) = if c `elem` "+-*^" then ([c], s) 41 else case s of 42 ('=':ss) -> case c of 43 '=' -> ("==",ss) 44 '>' -> (">=",ss) 45 '<' -> ("<=",ss) 46 '/' -> ("/=",ss) 47 _ -> ([c],s) 48 _ -> ([c],s) 49 50 lexerNum r = ((Num (ds++f)), t) where (ds,s) = span isDigit r 51 (f,t) = lexFracExp s 52 lexFracExp ('.':r) = ('.':ds, s) 53 where (ds, s) = span isDigit r 54 lexFracExp s = ("",s) 55 consume [] = [] 56 consume (s:ss) = consume ss