Skip to content
Snippets Groups Projects
Commit 95e4cd3c authored by Hugo Hörnquist's avatar Hugo Hörnquist
Browse files

Add parser.

parent 1c58af77
No related branches found
No related tags found
No related merge requests found
main
main.hs 0 → 100644
import Text.ParserCombinators.Parsec
import Text.Parsec
import Data.Char (ord, chr)
data Expression = Negate Expression
| Not Expression
| StringToInt Expression
| IntToString Expression
| Add Expression Expression
| Sub Expression Expression
| Mul Expression Expression
| Div Expression Expression
| Mod Expression Expression
| Gt Expression Expression
| Lt Expression Expression
| Eq Expression Expression
| Or Expression Expression
| And Expression Expression
| Concat Expression Expression
| Take Expression Expression
| Drop Expression Expression
| Apply Expression Expression
| If Expression Expression Expression
| Lambda Integer Expression
| Variable Integer
| Boolean Bool
| Number Integer
| Str String
deriving (Show)
parseBool :: GenParser Char () Expression
parseBool
= (char 'T' >> (return $ Boolean True))
<|> (char 'F' >> (return $ Boolean False))
decodeInteger :: String -> Integer
decodeInteger str = foldl ((+) . (* 94)) 0 [toInteger $ ord c - 33 | c <- str]
parseInteger :: GenParser Char () Expression
parseInteger = do
char 'I'
Number . decodeInteger <$> many (oneOf [chr 33..chr 126])
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`|~ \n"
decodeString :: String -> String
decodeString msg = [alphabet !! (ord c - 33) | c <- msg]
parseString :: GenParser Char () Expression
parseString = do
char 'S'
s <- many (oneOf [chr 33..chr 126])
return . Str $ decodeString s
parseUnary :: GenParser Char () Expression
parseUnary = do
char 'U'
c <- oneOf "-!#$"
operand <- ws >> parseExpression
case c of
'-' -> return $ Negate operand
'!' -> return $ Not operand
'#' -> return $ StringToInt operand
'$' -> return $ IntToString operand
parseBinary :: GenParser Char () Expression
parseBinary = do
char 'B'
operation <- oneOf "+-*/%<>=|&.TD$"
op1 <- ws >> parseExpression
op2 <- ws >> parseExpression
case operation of
'+' -> return $ Add op1 op2
'-' -> return $ Sub op1 op2
'*' -> return $ Mul op1 op2
'/' -> return $ Div op1 op2
'%' -> return $ Mod op1 op2
'<' -> return $ Lt op1 op2
'>' -> return $ Gt op1 op2
'=' -> return $ Eq op1 op2
'|' -> return $ Or op1 op2
'&' -> return $ And op1 op2
'.' -> return $ Concat op1 op2
'T' -> return $ Take op1 op2
'D' -> return $ Drop op1 op2
'$' -> return $ Apply op1 op2
parseIf :: GenParser Char () Expression
parseIf = do
char '?'
op <- ws >> parseExpression
e1 <- ws >> parseExpression
e2 <- ws >> parseExpression
return $ If op e1 e2
parseLambda :: GenParser Char () Expression
parseLambda = do
char 'L'
arg <- decodeInteger <$> many (oneOf [chr 33..chr 126])
expr <- ws >> parseExpression
return $ Lambda arg expr
parseVariable :: GenParser Char () Expression
parseVariable = do
char 'v'
arg <- decodeInteger <$> many (oneOf [chr 33..chr 126])
return $ Variable arg
ws = many space
parseExpression = parseBool
<|> parseInteger
<|> parseString
<|> parseUnary
<|> parseBinary
<|> parseIf
<|> parseLambda
<|> parseVariable
<?> "Expression"
parseExpression' = do
res <- parseExpression
ws
return res
main = do
msg <- getContents
let result = parse (many parseExpression') "" msg
-- let result = parse (many $ ws >> parseExpression) "" msg
print result
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment