From 8c8f6155f1b05230c271059c52a503211aec872b Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 16 Mar 2020 14:15:42 +0100 Subject: file Renaming, basic REPL --- src/parser/Assignment.hs | 15 ++++++ src/parser/Core.hs | 117 +++++++++++++++++++++++++++++++++++++++++++++++ src/parser/Expr.hs | 42 +++++++++++++++++ src/parser/Statement.hs | 12 +++++ src/parser/assignment.hs | 15 ------ src/parser/core.hs | 116 ---------------------------------------------- src/parser/expr.hs | 45 ------------------ src/parser/statement.hs | 12 ----- 8 files changed, 186 insertions(+), 188 deletions(-) create mode 100644 src/parser/Assignment.hs create mode 100644 src/parser/Core.hs create mode 100644 src/parser/Expr.hs create mode 100644 src/parser/Statement.hs delete mode 100644 src/parser/assignment.hs delete mode 100644 src/parser/core.hs delete mode 100644 src/parser/expr.hs delete mode 100644 src/parser/statement.hs (limited to 'src/parser') diff --git a/src/parser/Assignment.hs b/src/parser/Assignment.hs new file mode 100644 index 0000000..bb782f5 --- /dev/null +++ b/src/parser/Assignment.hs @@ -0,0 +1,15 @@ +module Parser.Assignment where + +import Control.Applicative +import Parser.Core +import qualified Parser.Expr as E +import Assignment + +variableP :: Parser Assignment +variableP = Variable <$> alphaStringP <* char '=' <*> E.exprP + +functionP :: Parser Assignment +functionP = Function <$> alphaStringP <*> parenthesize alphaStringP <* char '=' <*> E.exprP + +assignmentP :: Parser Assignment +assignmentP = variableP <|> functionP diff --git a/src/parser/Core.hs b/src/parser/Core.hs new file mode 100644 index 0000000..b22bcf4 --- /dev/null +++ b/src/parser/Core.hs @@ -0,0 +1,117 @@ +module Parser.Core where + +import Control.Applicative +import Control.Monad +import Data.Char + +newtype Parser a = Parser { parse :: String -> Maybe (a, String) } + +parseStrict :: Parser a -> String -> Maybe a +parseStrict p input = case parse p input of Just (a, "") -> Just a + _ -> Nothing + +instance Functor Parser where + -- fmap :: (a -> b) -> Parser a -> Parser b + fmap f (Parser p) = Parser new_p + where new_p s = do + (x, s') <- p s + return (f x, s') + +instance Applicative Parser where + -- pure :: a -> Parser a + pure x = Parser (\s -> Just (x, s)) + -- (<*>) :: Parser (a -> b) -> Parser a -> Parser b + (Parser p1) <*> (Parser p2) = Parser new_p + where new_p s = do + (f, s') <- p1 s + (x, s'') <- p2 s' + return (f x, s'') + +instance Alternative Parser where + -- empty :: Parser a + empty = Parser (\_ -> Nothing) + -- (<|>) :: Parser a -> Parser a -> Parser a + (Parser p1) <|> (Parser p2) = Parser new_p + where new_p s = p1 s <|> p2 s + +instance Monad Parser where + -- return :: a -> Parser a + return x = pure x + -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b + (Parser p1) >>= f = Parser new_p + where new_p s = do + (x, s') <- p1 s + parse (f x) s' + + +satisfyChar :: (Char -> Bool) -> Parser Char +satisfyChar f = Parser p + where p [] = Nothing + p (c:cs) = if f c then Just (c, cs) + else Nothing + +sepBy :: Parser b -> Parser a -> Parser [a] +sepBy sep x = (:) <$> x <*> (many (sep *> x)) + +-- sepByMap :: (b -> a -> a) -> Parser b -> Parser a -> Parser [a] +-- sepByMap f sep x = (:) <$> x <*> (many (f <$> sep <*> x)) + +chainl :: Parser a -> Parser (a -> a -> a) -> a -> Parser a +chainl p op a = chainl1 p op <|> pure a + +chainl1 :: Parser a -> Parser (a -> a -> a) -> Parser a +chainl1 p op = p >>= rest + where rest prev = do f <- op + e <- p + rest (f prev e) + <|> return prev + +signed :: Num a => Parser a -> Parser a +signed p = do char '-' + x <- p + return (-x) + <|> p + +readParser :: Read a => Parser String -> Parser a +readParser p = read <$> p + +infixOp :: String -> (a -> a -> a) -> Parser (a -> a -> a) +infixOp opStr f = string opStr *> pure f + +parenthesize :: Parser a -> Parser a +parenthesize p = char '(' *> p <* char ')' + +char :: Char -> Parser Char +char c = satisfyChar (c ==) + +string :: String -> Parser String +string s = sequenceA $ char <$> s + +alphaP :: Parser Char +alphaP = satisfyChar isAlpha + +alphaStringP :: Parser String +alphaStringP = some alphaP + +digitsP :: Parser String +digitsP = some (satisfyChar isDigit) -- at least one digit to avoid read exception + +spacesP :: Parser String +spacesP = many (satisfyChar isSpace) + +unsignedIntP :: Parser Int +unsignedIntP = readParser digitsP + +intP :: Parser Int +intP = signed unsignedIntP + +unsignedFloatP :: Parser Float +unsignedFloatP = readParser p + where p = do pos <- digitsP + char '.' + dec <- digitsP + return (pos ++ "." ++ dec) + <|> digitsP + +floatP :: Parser Float +floatP = signed unsignedFloatP diff --git a/src/parser/Expr.hs b/src/parser/Expr.hs new file mode 100644 index 0000000..5ba4be7 --- /dev/null +++ b/src/parser/Expr.hs @@ -0,0 +1,42 @@ +module Parser.Expr where + +import Control.Applicative + +import Parser.Core +import Expr + + +imaginaryP :: Parser Atom +imaginaryP = Imaginary <$> (floatP <* char 'i') + +rationalP :: Parser Atom +rationalP = Rational <$> floatP + +matrixP :: Parser Atom +matrixP = Matrix <$> (char '[' *> sepBy (char ';') matrixRowP <* char ']') + where matrixRowP = char '[' *> sepBy (char ',') exprP <* char ']' + +exprP :: Parser Expr +exprP = termP `chainl1` termOpP + where termOpP = infixOp "+" Add <|> infixOp "-" Sub + +termP :: Parser Expr +termP = factorP `chainl1` factorOpP + where factorOpP = infixOp "**" Dot <|> infixOp "*" Mul <|> infixOp "/" Div <|> infixOp "%" Mod + +factorP :: Parser Expr +factorP = endpointP `chainl1` expOpP + where expOpP = infixOp "^" Exp + endpointP = parenthesisExprP <|> (EAtom <$> atomP) <|> functionP <|> variableP + +variableP :: Parser Expr +variableP = Variable <$> alphaStringP + +functionP :: Parser Expr +functionP = Function <$> alphaStringP <*> parenthesisExprP + +parenthesisExprP :: Parser Expr +parenthesisExprP = parenthesize exprP + +atomP :: Parser Atom +atomP = imaginaryP <|> rationalP <|> matrixP diff --git a/src/parser/Statement.hs b/src/parser/Statement.hs new file mode 100644 index 0000000..74f7f01 --- /dev/null +++ b/src/parser/Statement.hs @@ -0,0 +1,12 @@ +module Parser.Statement where + +import Control.Applicative +import Parser.Core +import Parser.Expr +import Parser.Assignment +import Statement + + +statementP :: Parser Statement +statementP = SAssignment <$> assignmentP + <|> SExpr <$> exprP <* char '=' <* char '?' diff --git a/src/parser/assignment.hs b/src/parser/assignment.hs deleted file mode 100644 index bb782f5..0000000 --- a/src/parser/assignment.hs +++ /dev/null @@ -1,15 +0,0 @@ -module Parser.Assignment where - -import Control.Applicative -import Parser.Core -import qualified Parser.Expr as E -import Assignment - -variableP :: Parser Assignment -variableP = Variable <$> alphaStringP <* char '=' <*> E.exprP - -functionP :: Parser Assignment -functionP = Function <$> alphaStringP <*> parenthesize alphaStringP <* char '=' <*> E.exprP - -assignmentP :: Parser Assignment -assignmentP = variableP <|> functionP diff --git a/src/parser/core.hs b/src/parser/core.hs deleted file mode 100644 index b622634..0000000 --- a/src/parser/core.hs +++ /dev/null @@ -1,116 +0,0 @@ -module Parser.Core where - -import Control.Applicative -import Control.Monad -import Data.Char - -newtype Parser a = Parser { parse :: String -> Maybe (a, String) } - -parseStrict :: Parser a -> String -> Maybe a -parseStrict p input = case parse p input of Just (a, "") -> Just a - _ -> Nothing - -instance Functor Parser where - -- fmap :: (a -> b) -> Parser a -> Parser b - fmap f (Parser p) = Parser new_p - where new_p s = do - (x, s') <- p s - return (f x, s') - -instance Applicative Parser where - -- pure :: a -> Parser a - pure x = Parser (\s -> Just (x, s)) - -- (<*>) :: Parser (a -> b) -> Parser a -> Parser b - (Parser p1) <*> (Parser p2) = Parser new_p - where new_p s = do - (f, s') <- p1 s - (x, s'') <- p2 s' - return (f x, s'') - -instance Alternative Parser where - -- empty :: Parser a - empty = Parser (\_ -> Nothing) - -- (<|>) :: Parser a -> Parser a -> Parser a - (Parser p1) <|> (Parser p2) = Parser new_p - where new_p s = p1 s <|> p2 s - -instance Monad Parser where - -- return :: a -> Parser a - return x = pure x - -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b - (Parser p1) >>= f = Parser new_p - where new_p s = do - (x, s') <- p1 s - parse (f x) s' - - -satisfyChar :: (Char -> Bool) -> Parser Char -satisfyChar f = Parser p - where p [] = Nothing - p (c:cs) = if f c then Just (c, cs) - else Nothing - --- sepBy :: Parser b -> Parser a -> Parser [a] --- sepBy sep x = (:) <$> x <*> (many (sep *> x)) --- sepByMap :: (b -> a -> a) -> Parser b -> Parser a -> Parser [a] --- sepByMap f sep x = (:) <$> x <*> (many (f <$> sep <*> x)) - -chainl :: Parser a -> Parser (a -> a -> a) -> a -> Parser a -chainl p op a = chainl1 p op <|> pure a - -chainl1 :: Parser a -> Parser (a -> a -> a) -> Parser a -chainl1 p op = p >>= rest - where rest prev = do f <- op - e <- p - rest (f prev e) - <|> return prev - -signed :: Num a => Parser a -> Parser a -signed p = do char '-' - x <- p - return (-x) - <|> p - -readParser :: Read a => Parser String -> Parser a -readParser p = read <$> p - -infixOp :: String -> (a -> a -> a) -> Parser (a -> a -> a) -infixOp opStr f = string opStr *> pure f - -parenthesize :: Parser a -> Parser a -parenthesize p = char '(' *> p <* char ')' - -char :: Char -> Parser Char -char c = satisfyChar (c ==) - -string :: String -> Parser String -string s = sequenceA $ char <$> s - -alphaP :: Parser Char -alphaP = satisfyChar isAlpha - -alphaStringP :: Parser String -alphaStringP = some alphaP - -digitsP :: Parser String -digitsP = some (satisfyChar isDigit) -- at least one digit to avoid read exception - -spacesP :: Parser String -spacesP = many (satisfyChar isSpace) - -unsignedIntP :: Parser Int -unsignedIntP = readParser digitsP - -intP :: Parser Int -intP = signed unsignedIntP - -unsignedFloatP :: Parser Float -unsignedFloatP = readParser p - where p = do pos <- digitsP - char '.' - dec <- digitsP - return (pos ++ "." ++ dec) - <|> digitsP - -floatP :: Parser Float -floatP = signed unsignedFloatP diff --git a/src/parser/expr.hs b/src/parser/expr.hs deleted file mode 100644 index b84362d..0000000 --- a/src/parser/expr.hs +++ /dev/null @@ -1,45 +0,0 @@ -module Parser.Expr where - -import Control.Applicative - -import Parser.Core -import Atom -import Expr - - -imaginaryP :: Parser Atom -imaginaryP = AImaginary <$> (floatP <* char 'i') - -rationalP :: Parser Atom -rationalP = ARational <$> floatP - -termOpP :: Parser (Expr -> Expr -> Expr) -termOpP = infixOp "+" Add <|> infixOp "-" Sub - -factorOpP :: Parser (Expr -> Expr -> Expr) -factorOpP = infixOp "*" Mul <|> infixOp "/" Div <|> infixOp "%" Mod - -expOpP :: Parser (Expr -> Expr -> Expr) -expOpP = infixOp "^" Exp - -exprP :: Parser Expr -exprP = termP `chainl1` termOpP - -termP :: Parser Expr -termP = factorP `chainl1` factorOpP - -variableP :: Parser Expr -variableP = Variable <$> alphaStringP - -functionP :: Parser Expr -functionP = Function <$> alphaStringP <*> parenthesisExprP - -factorP :: Parser Expr -factorP = endpointP `chainl1` expOpP - where endpointP = parenthesisExprP <|> (EAtom <$> atomP) <|> functionP <|> variableP - -parenthesisExprP :: Parser Expr -parenthesisExprP = parenthesize exprP - -atomP :: Parser Atom -atomP = imaginaryP <|> rationalP diff --git a/src/parser/statement.hs b/src/parser/statement.hs deleted file mode 100644 index 74f7f01..0000000 --- a/src/parser/statement.hs +++ /dev/null @@ -1,12 +0,0 @@ -module Parser.Statement where - -import Control.Applicative -import Parser.Core -import Parser.Expr -import Parser.Assignment -import Statement - - -statementP :: Parser Statement -statementP = SAssignment <$> assignmentP - <|> SExpr <$> exprP <* char '=' <* char '?' -- cgit