content: module Lexer (Operator(..), Token(..), tokenize, lookAhead, accept) where
  
  import Data.Char
  
  data Operator = Plus | Minus | Times | Div
      deriving (Show, Eq)
  
  data Token = TokOp Operator
             | TokAssign
             | TokLParen
             | TokRParen
             | TokIdent String
             | TokNum Double
             | TokEnd
      deriving (Show, Eq)
  
  lookAhead :: [Token] -> Token
  lookAhead [] = TokEnd
  lookAhead (t:ts) = t
  
  accept :: [Token] -> [Token]
  accept [] = error "Nothing to accept"
  accept (t:ts) = ts
  
  tokenize :: String -> [Token]
  tokenize [] = []
  tokenize (c : cs) 
      | elem c "+-*/" = TokOp (operator c) : tokenize cs
      | c == '='  = TokAssign : tokenize cs
      | c == '('  = TokLParen : tokenize cs
      | c == ')'  = TokRParen : tokenize cs
      | isDigit c = number c cs
      | isAlpha c = identifier c cs
      | isSpace c = tokenize cs
      | otherwise = error $ "Cannot tokenize " ++ [c]
  
  identifier :: Char -> String -> [Token]
  identifier c cs = let (name, cs') = span isAlphaNum cs in
                    TokIdent (c:name) : tokenize cs'
  
  number :: Char -> String -> [Token]
  number c cs = 
     let (digs, cs') = span isDigit cs in
     TokNum (read (c : digs)) : tokenize cs'
  
  operator :: Char -> Operator
  operator c | c == '+' = Plus
             | c == '-' = Minus
             | c == '*' = Times
             | c == '/' = Div
  