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