36 lines
1.2 KiB
Haskell
36 lines
1.2 KiB
Haskell
module Lexer where
|
|
|
|
data Token = Plus
|
|
| Hyphen
|
|
| Asterisk
|
|
| ForwardSlash
|
|
| Integer Int
|
|
| LBrace
|
|
| RBrace
|
|
deriving 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 ++ ")"
|