101 lines
2.6 KiB
Haskell
101 lines
2.6 KiB
Haskell
module Parser where
|
|
|
|
import qualified Lexer as L
|
|
import Control.Applicative as Applicative
|
|
import Data.Void as Void
|
|
|
|
type CST = Expr
|
|
|
|
data Expr = Add Term Expr
|
|
| Sub Term Expr
|
|
| ETerm Term
|
|
deriving Show
|
|
|
|
data Term = Mult Factor Term
|
|
| Div Factor Term
|
|
| TFactor Factor
|
|
deriving Show
|
|
|
|
data Factor = Integer Int
|
|
| Parantheses Expr
|
|
| NegFactor Factor
|
|
deriving Show
|
|
|
|
type Tokens = [L.Token]
|
|
newtype Parser a = Parser {
|
|
runParser :: Tokens -> Maybe (Tokens, a)
|
|
}
|
|
|
|
instance Functor Parser where
|
|
fmap f (Parser p) = Parser $ \input -> case p input of
|
|
Nothing -> Nothing
|
|
Just (rest, a) -> Just (rest, f a)
|
|
|
|
instance Applicative Parser where
|
|
pure x = Parser $ \input -> Just (input, x)
|
|
(<*>) (Parser fParser) (Parser a) = Parser $ \input -> case fParser input of
|
|
Nothing -> Nothing
|
|
Just (rest, f) -> case a rest of
|
|
Nothing -> Nothing
|
|
Just (rest', x) -> Just (rest', f x)
|
|
|
|
instance Alternative Parser where
|
|
empty = Parser $ const Nothing
|
|
(<|>) (Parser p1) (Parser p2) = Parser $ \input -> case p1 input of
|
|
Nothing -> p2 input
|
|
result -> result
|
|
|
|
|
|
parse :: Tokens -> Maybe CST
|
|
parse tokens = case runParser parseExpression tokens of
|
|
Just ([], cst) -> Just cst
|
|
_ -> Nothing
|
|
|
|
|
|
parseAdd :: Parser Expr
|
|
parseAdd = liftA2 Add (parseTerm <* expect L.Plus) parseExpression
|
|
|
|
parseSub :: Parser Expr
|
|
parseSub = liftA2 Sub (parseTerm <* expect L.Hyphen) parseExpression
|
|
|
|
parseETerm :: Parser Expr
|
|
parseETerm = ETerm <$> parseTerm
|
|
|
|
parseExpression :: Parser Expr
|
|
parseExpression = parseAdd <|> parseSub <|> parseETerm
|
|
|
|
|
|
parseMult :: Parser Term
|
|
parseMult = liftA2 Mult (parseFactor <* expect L.Asterisk) parseTerm
|
|
|
|
parseDiv :: Parser Term
|
|
parseDiv = liftA2 Div (parseFactor <* expect L.ForwardSlash) parseTerm
|
|
|
|
parseTFactor :: Parser Term
|
|
parseTFactor = TFactor <$> parseFactor
|
|
|
|
parseTerm :: Parser Term
|
|
parseTerm = parseMult <|> parseDiv <|> parseTFactor
|
|
|
|
|
|
parseFactor :: Parser Factor
|
|
parseFactor = parseInt <|> parseParatheses <|> parseNegFactor
|
|
|
|
parseInt :: Parser Factor
|
|
parseInt = Parser $ \(token:rest) -> case token of
|
|
L.Integer i -> Just (rest, Integer i)
|
|
_ -> Nothing
|
|
|
|
parseNegFactor :: Parser Factor
|
|
parseNegFactor = NegFactor <$> (expect L.Hyphen *> parseFactor)
|
|
|
|
parseParatheses :: Parser Factor
|
|
parseParatheses = Parantheses <$> (expect L.LBrace *> parseExpression <* expect L.RBrace)
|
|
|
|
|
|
expect :: L.Token -> Parser (Maybe Void)
|
|
expect token = Parser $ \stream -> case stream of
|
|
(t:rest) -> if t == token
|
|
then Just (rest, Nothing)
|
|
else Nothing
|
|
_ -> Nothing
|