module Lexer where data Token = Plus | Hyphen | Asterisk | ForwardSlash | Integer Int | LBrace | RBrace deriving (Eq, Show) lex :: String -> [Token] lex source = reverse (lex' source [] (length source)) lex' :: String -> [Token] -> Int -> [Token] lex' "" tokens _ = tokens lex' (' ':xs) tokens orgLength = lex' xs tokens orgLength lex' (x:xs) tokens orgLength = case x of '+' -> lex' xs (Plus:tokens) orgLength '-' -> lex' xs (Hyphen:tokens) orgLength '*' -> lex' xs (Asterisk:tokens) orgLength '/' -> lex' xs (ForwardSlash:tokens) orgLength '(' -> lex' xs (LBrace:tokens) orgLength ')' -> lex' xs (RBrace:tokens) orgLength _ -> lexNumbers (x:xs) tokens orgLength lexNumbers :: String -> [Token] -> Int -> [Token] lexNumbers (x:xs) tokens orgLength | isDigit x = lex' rest ((Integer(read digits::Int)):tokens) orgLength | otherwise = syntaxError x (orgLength - (length (x:xs)) + 1) where digits = takeWhile isDigit (x:xs) rest = dropWhile isDigit (x:xs) isDigit c = c `elem` "0123456789" syntaxError char pos = error $ "Syntax error: " ++ [char] ++ " (" ++ show pos ++ ")"