diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Assignment.hs (renamed from src/assignment.hs) | 0 | ||||
| -rw-r--r-- | src/Expr.hs | 98 | ||||
| -rw-r--r-- | src/Polynomial.hs | 87 | ||||
| -rw-r--r-- | src/Statement.hs (renamed from src/statement.hs) | 0 | ||||
| -rw-r--r-- | src/atom.hs | 49 | ||||
| -rw-r--r-- | src/expr.hs | 43 | ||||
| -rw-r--r-- | src/main.hs | 25 | ||||
| -rw-r--r-- | src/manifest | 96 | ||||
| -rw-r--r-- | src/parser/Assignment.hs (renamed from src/parser/assignment.hs) | 0 | ||||
| -rw-r--r-- | src/parser/Core.hs (renamed from src/parser/core.hs) | 5 | ||||
| -rw-r--r-- | src/parser/Expr.hs (renamed from src/parser/expr.hs) | 29 | ||||
| -rw-r--r-- | src/parser/Statement.hs (renamed from src/parser/statement.hs) | 0 | ||||
| -rw-r--r-- | src/polynomial.hs | 95 |
13 files changed, 226 insertions, 301 deletions
diff --git a/src/assignment.hs b/src/Assignment.hs index c086280..c086280 100644 --- a/src/assignment.hs +++ b/src/Assignment.hs diff --git a/src/Expr.hs b/src/Expr.hs new file mode 100644 index 0000000..e3d8aef --- /dev/null +++ b/src/Expr.hs @@ -0,0 +1,98 @@ +module Expr where + +import Data.List + + +data Atom + = Rational Float + | Imaginary Float + | Matrix [[Expr]] + +data Expr + = EAtom Atom + | Add Expr Expr + | Sub Expr Expr + | Mul Expr Expr + | Div Expr Expr + | Mod Expr Expr + | Exp Expr Expr + | Dot Expr Expr + | Variable String + | Function String Expr + +eval :: Expr -> Maybe Atom +eval (EAtom a) = Just a +eval (Add e1 e2) = evalInfix e1 e2 (+?) +eval (Sub e1 e2) = evalInfix e1 e2 (-?) +eval (Mul e1 e2) = evalInfix e1 e2 (*?) +eval (Div e1 e2) = evalInfix e1 e2 (/?) +eval (Mod e1 e2) = evalInfix e1 e2 (%?) +eval (Exp e1 e2) = evalInfix e1 e2 (^?) +eval (Dot e1 e2) = evalInfix e1 e2 (**?) +eval _ = Nothing + +evalInfix :: Expr -> Expr -> (Atom -> Atom -> Maybe Atom) -> Maybe Atom +evalInfix e1 e2 f = do a <- eval e1 + b <- eval e2 + f a b + +infixl 6 +? +(+?) :: Atom -> Atom -> Maybe Atom +(Rational a) +? (Rational b) = Just $ Rational (a + b) +(Imaginary a) +? (Imaginary b) = Just $ Imaginary (a + b) +_ +? _ = Nothing + +infixl 6 -? +(-?) :: Atom -> Atom -> Maybe Atom +(Rational a) -? (Rational b) = Just $ Rational (a - b) +(Imaginary a) -? (Imaginary b) = Just $ Imaginary (a - b) +_ -? _ = Nothing + +infixl 7 *? +(*?) :: Atom -> Atom -> Maybe Atom +(Rational a) *? (Rational b) = Just $ Rational (a * b) +(Rational a) *? (Imaginary b) = Just $ Imaginary (a * b) +(Imaginary a) *? (Imaginary b) = (Imaginary (a * b)) ^? Rational 2 +_ *? _ = Nothing + +infixl 7 /? +(/?) :: Atom -> Atom -> Maybe Atom +_ /? (Rational 0) = Nothing +(Rational a) /? (Rational b) = Just $ Rational (a / b) +_ /? _ = Nothing + +infixl 7 %? +(%?) :: Atom -> Atom -> Maybe Atom +_ %? _ = Nothing + +infixr 8 ^? +(^?) :: Atom -> Atom -> Maybe Atom +(Rational a) ^? (Rational b) = Just $ Rational (a ** b) +(Imaginary a) ^? (Rational 0) = Just $ Rational a +(Imaginary a) ^? (Rational 1) = Just $ Imaginary a +(Imaginary a) ^? (Rational 2) = Just $ Rational (-a) +(Imaginary a) ^? (Rational 3) = Just $ Imaginary (-a) +(Imaginary a) ^? (Rational b) = Imaginary a ^? (Rational (b - 4)) +_ ^? _ = Nothing + +infixr 8 **? +(**?) :: Atom -> Atom -> Maybe Atom +_ **? _ = Nothing + +instance Show Expr where + show (EAtom a) = show a + show (Add e1 e2) = show e1 ++ " + " ++ show e2 + show (Sub e1 e2) = show e1 ++ " - " ++ show e2 + show (Mul e1 e2) = show e1 ++ " * " ++ show e2 + show (Div e1 e2) = show e1 ++ " / " ++ show e2 + show (Mod e1 e2) = show e1 ++ " % " ++ show e2 + show (Exp e1 e2) = show e1 ++ " ^ " ++ show e2 + show (Dot e1 e2) = show e1 ++ " ** " ++ show e2 + show (Variable name) = name + show (Function name e) = name ++ "(" ++ show e ++ ")" + +instance Show Atom where + show (Rational r) = show r + show (Imaginary i) = show i ++ "i" + show (Matrix m) = intercalate "\n" (map showRow m) + where showRow r = "[ " ++ intercalate ", " (map show r) ++ " ]" diff --git a/src/Polynomial.hs b/src/Polynomial.hs new file mode 100644 index 0000000..cd0da4f --- /dev/null +++ b/src/Polynomial.hs @@ -0,0 +1,87 @@ +module Polynomial where + +-- import Data.List +-- +-- +-- data Equation = Equation { left :: Polynomial, right :: Polynomial } +-- type Polynomial = [Term] +-- data Term = Term { coefficient :: Float, exponent :: Int } +-- +-- instance Eq Term where +-- (Term _ e1) == (Term _ e2) = e1 == e2 +-- +-- instance Ord Term where +-- compare (Term _ e1) (Term _ e2) = compare e1 e2 +-- +-- instance Show Term where +-- show (Term 0 e) = "" +-- show (Term c 0) = show (round c) +-- show (Term c e) = show (round c) ++ " * X^" ++ show e +-- +-- instance Show Equation where +-- show (Equation l r) = showPolynomial (filterNull l) +-- ++ " = " +-- ++ showPolynomial (filterNull r) +-- where showPolynomial [] = "0" +-- showPolynomial p = dropWhile (`elem` " +") $ foldl f "" (map show p) +-- where f s "" = s +-- f s (c:cs) +-- | c == '-' = s ++ " - " ++ cs +-- | otherwise = s ++ " + " ++ (c:cs) +-- +-- +-- filterNull :: Polynomial -> Polynomial +-- filterNull = filter (\t -> coefficient t /= 0) +-- +-- equationMap :: (Polynomial -> Polynomial) -> Equation -> Equation +-- equationMap f (Equation l r) = Equation (f l) (f r) +-- +-- degree :: Polynomial -> Int +-- degree [] = 0 +-- degree p = Equation.exponent (maximum p) +-- +-- reduce :: Equation -> Equation +-- reduce equ = Equation (merge (left stdForm) (right stdForm)) [] +-- where stdForm = equationMap (\a -> (reducePolynomial $ sort a)) equ +-- merge [] rs = rs +-- merge ls [] = ls +-- merge (l:ls) (r:rs) +-- | l == r = (subTerm l r) : merge ls rs +-- | l < r = l : merge ls (r:rs) +-- | r < l = r : merge (l:ls) rs +-- where subTerm (Term c1 e) (Term c2 _) = Term (c1 - c2) e +-- reducePolynomial [] = [] +-- reducePolynomial [t] = [t] +-- reducePolynomial (t1:t2:ts) +-- | t1 == t2 = (addTerm t1 t2) : reducePolynomial ts +-- | otherwise = t1 : reducePolynomial (t2:ts) +-- where addTerm (Term c1 e) (Term c2 _) = Term (c1 + c2) e +-- +-- solveDegree2 :: Float -> Float -> Float -> [Float] +-- solveDegree2 a b c +-- | phi < 0 = [] +-- | phi == 0 = [(-b) / (2.0 * a)] +-- | phi > 0 = [ (-b + mySqrt phi) / (2.0 * a) -- not alowed +-- , (-b - mySqrt phi) / (2.0 * a) +-- ] +-- where phi = b * b - 4.0 * a * c +-- +-- solveDegree1 :: Float -> Float -> Float +-- solveDegree1 b c = -c / b +-- +-- solve :: Polynomial -> [Float] +-- solve [t0] = [] +-- solve [t0, t1] = [solveDegree1 (coefficient t1) (coefficient t0)] +-- solve [t0, t1, t2] = solveDegree2 (coefficient t2) (coefficient t1) (coefficient t0) +-- solve _ = undefined +-- +-- mySqrt :: Float -> Float +-- mySqrt n +-- | n < 0 = undefined +-- | otherwise = mySqrt' (n / 2) +-- where mySqrt' x = if abs (x * x - n) < 0.01 +-- then x +-- else mySqrt' xn +-- where xn = b - (a * a) / (2 * b) +-- where a = (n - x * x) / (2 * x) +-- b = x + a diff --git a/src/statement.hs b/src/Statement.hs index 75dfdb4..75dfdb4 100644 --- a/src/statement.hs +++ b/src/Statement.hs diff --git a/src/atom.hs b/src/atom.hs deleted file mode 100644 index 5f1b42c..0000000 --- a/src/atom.hs +++ /dev/null @@ -1,49 +0,0 @@ -module Atom where - - -data Atom - = ARational Float - | AImaginary Float - -infixl 6 +? -(+?) :: Atom -> Atom -> Maybe Atom -(ARational a) +? (ARational b) = Just $ ARational (a + b) -(AImaginary a) +? (AImaginary b) = Just $ AImaginary (a + b) -_ +? _ = Nothing - -infixl 6 -? -(-?) :: Atom -> Atom -> Maybe Atom -(ARational a) -? (ARational b) = Just $ ARational (a - b) -(AImaginary a) -? (AImaginary b) = Just $ AImaginary (a - b) -_ -? _ = Nothing - -infixl 7 *? -(*?) :: Atom -> Atom -> Maybe Atom -(ARational a) *? (ARational b) = Just $ ARational (a * b) -(ARational a) *? (AImaginary b) = Just $ AImaginary (a * b) -(AImaginary a) *? (AImaginary b) = (AImaginary (a * b)) ^? ARational 2 -_ *? _ = Nothing - -infixl 7 /? -(/?) :: Atom -> Atom -> Maybe Atom -_ /? (ARational 0) = Nothing -(ARational a) /? (ARational b) = Just $ ARational (a / b) -_ /? _ = Nothing - -infixl 7 %? -(%?) :: Atom -> Atom -> Maybe Atom -_ %? _ = Nothing - -infixr 8 ^? -(^?) :: Atom -> Atom -> Maybe Atom -(ARational a) ^? (ARational b) = Just $ ARational (a ** b) -(AImaginary a) ^? (ARational 0) = Just $ ARational a -(AImaginary a) ^? (ARational 1) = Just $ AImaginary a -(AImaginary a) ^? (ARational 2) = Just $ ARational (-a) -(AImaginary a) ^? (ARational 3) = Just $ AImaginary (-a) -(AImaginary a) ^? (ARational b) = AImaginary a ^? (ARational (b - 4)) -_ ^? _ = Nothing - -instance Show Atom where - show (ARational r) = show r - show (AImaginary i) = show i ++ "i" diff --git a/src/expr.hs b/src/expr.hs deleted file mode 100644 index e6f1f25..0000000 --- a/src/expr.hs +++ /dev/null @@ -1,43 +0,0 @@ -module Expr where - -import Atom - - -data Expr - = EAtom Atom - | Add Expr Expr - | Sub Expr Expr - | Mul Expr Expr - | Div Expr Expr - | Mod Expr Expr - | Exp Expr Expr - | Variable String - | Function String Expr - - - -eval :: Expr -> Maybe Atom -eval (EAtom a) = Just a -eval (Add e1 e2) = evalInfix e1 e2 (+?) -eval (Sub e1 e2) = evalInfix e1 e2 (-?) -eval (Mul e1 e2) = evalInfix e1 e2 (*?) -eval (Div e1 e2) = evalInfix e1 e2 (/?) -eval (Mod e1 e2) = evalInfix e1 e2 (%?) -eval (Exp e1 e2) = evalInfix e1 e2 (^?) -eval _ = Nothing - -evalInfix :: Expr -> Expr -> (Atom -> Atom -> Maybe Atom) -> Maybe Atom -evalInfix e1 e2 f = do a <- eval e1 - b <- eval e2 - f a b - -instance Show Expr where - show (EAtom a) = show a - show (Add e1 e2) = show e1 ++ " + " ++ show e2 - show (Sub e1 e2) = show e1 ++ " - " ++ show e2 - show (Mul e1 e2) = show e1 ++ " * " ++ show e2 - show (Div e1 e2) = show e1 ++ " / " ++ show e2 - show (Mod e1 e2) = show e1 ++ " % " ++ show e2 - show (Exp e1 e2) = show e1 ++ " ^ " ++ show e2 - show (Variable name) = name - show (Function name e) = name ++ "(" ++ show e ++ ")" diff --git a/src/main.hs b/src/main.hs new file mode 100644 index 0000000..34a190a --- /dev/null +++ b/src/main.hs @@ -0,0 +1,25 @@ +import System.IO +import Statement +import Parser.Statement +import Parser.Core + + +main = do + line <- prompt + loop line + +loop :: String -> IO () +loop "exit" = return () +loop line = do s <- parseIO line + putStrLn $ show s + main + +prompt :: IO String +prompt = do putStr "> " + hFlush stdout + getLine + +parseIO :: String -> IO Statement +parseIO input = case parseStrict statementP input of + Nothing -> fail "Couldn't parse input" + Just s -> return s diff --git a/src/manifest b/src/manifest deleted file mode 100644 index 7216fa7..0000000 --- a/src/manifest +++ /dev/null @@ -1,96 +0,0 @@ -Data struct: - - expression - - matrix - - complex - - - polynomial - -State Data struct: - - function - - variable - - - -Instruction/line: - if is '?' evaluate label else declare label. - -instruction ::= <label> '=' (<expr> | '?') - - -Declaration: - label is a declaration of function or variable name - -label ::= <funcDecl> | <var> -funcDecl ::= <var> '(' <var> ')' -var ::= [a-zA-Z]+ - - -Expression: - -5. real imag matrix -4. + - -3. * / % ** -2. ^ -1. ( ) -- not an operator - -expr ::= <sum> | <imag> | <matrix> | <real> | <var> | <funcExpr> - -Arithmetic: - -sum ::= <term> (+ | -) <sum> | <term> -term ::= <factor> (* | / | % | **)? <term> | <factor> -- default to '*' -factor ::= <base> '^' <factor> | <base> -base ::= '(' <expr> ')' | <expr> - -Leaf: - -real ::= [0-9]+(\.[0-9]+)? -imag ::= <real> '*'? 'i' -matrix ::= '[' (<matrixRow> ';')* ']' -matrixRow ::= '[' (<expr> ',')* ']' -fundExpr ::= <var> '(' <expr> ')' - -REPL: - -1. read user input -2. parse it into an ast -3. reduce the ast to the minimum possible form -4. - -every expression is a binary tree, except () which can be interpreted by changing the -structure of the tree. - -operators and operand are both expression (tree nodes). - -operators always need 2 operand (not leaf node) -operand need 0 (leaf node) - -evaluation of operand return the operand -evaluation of operator, evaluate his childs, perform the operation on them, return the result - -fold? -!monoid - - + - / \ - * \ - / \ \ 3 * 4 + (5 - 3i) -3 4 - - / \ - 5 3i - -Node + -|_ Node * -| |_ Leaf 3 -| |_ Leaf 4 -| -|_ Node - - |_ Leaf 5 - |_ Leaf 3i - - -i^0 = 1 -i^1 = sqrt(-1) = i -i^2 = -1 -i^3 = -sqrt(-1) = -i -i^4 = 1 diff --git a/src/parser/assignment.hs b/src/parser/Assignment.hs index bb782f5..bb782f5 100644 --- a/src/parser/assignment.hs +++ b/src/parser/Assignment.hs diff --git a/src/parser/core.hs b/src/parser/Core.hs index b622634..b22bcf4 100644 --- a/src/parser/core.hs +++ b/src/parser/Core.hs @@ -50,8 +50,9 @@ satisfyChar f = Parser p 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)) +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)) diff --git a/src/parser/expr.hs b/src/parser/Expr.hs index b84362d..5ba4be7 100644 --- a/src/parser/expr.hs +++ b/src/parser/Expr.hs @@ -3,30 +3,31 @@ module Parser.Expr where import Control.Applicative import Parser.Core -import Atom import Expr imaginaryP :: Parser Atom -imaginaryP = AImaginary <$> (floatP <* char 'i') +imaginaryP = Imaginary <$> (floatP <* char 'i') rationalP :: Parser Atom -rationalP = ARational <$> floatP +rationalP = Rational <$> 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 +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 @@ -34,12 +35,8 @@ 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 +atomP = imaginaryP <|> rationalP <|> matrixP diff --git a/src/parser/statement.hs b/src/parser/Statement.hs index 74f7f01..74f7f01 100644 --- a/src/parser/statement.hs +++ b/src/parser/Statement.hs diff --git a/src/polynomial.hs b/src/polynomial.hs deleted file mode 100644 index f332131..0000000 --- a/src/polynomial.hs +++ /dev/null @@ -1,95 +0,0 @@ -module Equation -( Equation (..) -, Polynomial -, Term (..) -, degree -, reduce -, solve -, filterNull -) where - -import Data.List - - -data Equation = Equation { left :: Polynomial, right :: Polynomial } -type Polynomial = [Term] -data Term = Term { coefficient :: Float, exponent :: Int } - -instance Eq Term where - (Term _ e1) == (Term _ e2) = e1 == e2 - -instance Ord Term where - compare (Term _ e1) (Term _ e2) = compare e1 e2 - -instance Show Term where - show (Term 0 e) = "" - show (Term c 0) = show (round c) - show (Term c e) = show (round c) ++ " * X^" ++ show e - -instance Show Equation where - show (Equation l r) = showPolynomial (filterNull l) - ++ " = " - ++ showPolynomial (filterNull r) - where showPolynomial [] = "0" - showPolynomial p = dropWhile (`elem` " +") $ foldl f "" (map show p) - where f s "" = s - f s (c:cs) - | c == '-' = s ++ " - " ++ cs - | otherwise = s ++ " + " ++ (c:cs) - - -filterNull :: Polynomial -> Polynomial -filterNull = filter (\t -> coefficient t /= 0) - -equationMap :: (Polynomial -> Polynomial) -> Equation -> Equation -equationMap f (Equation l r) = Equation (f l) (f r) - -degree :: Polynomial -> Int -degree [] = 0 -degree p = Equation.exponent (maximum p) - -reduce :: Equation -> Equation -reduce equ = Equation (merge (left stdForm) (right stdForm)) [] - where stdForm = equationMap (\a -> (reducePolynomial $ sort a)) equ - merge [] rs = rs - merge ls [] = ls - merge (l:ls) (r:rs) - | l == r = (subTerm l r) : merge ls rs - | l < r = l : merge ls (r:rs) - | r < l = r : merge (l:ls) rs - where subTerm (Term c1 e) (Term c2 _) = Term (c1 - c2) e - reducePolynomial [] = [] - reducePolynomial [t] = [t] - reducePolynomial (t1:t2:ts) - | t1 == t2 = (addTerm t1 t2) : reducePolynomial ts - | otherwise = t1 : reducePolynomial (t2:ts) - where addTerm (Term c1 e) (Term c2 _) = Term (c1 + c2) e - -solveDegree2 :: Float -> Float -> Float -> [Float] -solveDegree2 a b c - | phi < 0 = [] - | phi == 0 = [(-b) / (2.0 * a)] - | phi > 0 = [ (-b + mySqrt phi) / (2.0 * a) -- not alowed - , (-b - mySqrt phi) / (2.0 * a) - ] - where phi = b * b - 4.0 * a * c - -solveDegree1 :: Float -> Float -> Float -solveDegree1 b c = -c / b - -solve :: Polynomial -> [Float] -solve [t0] = [] -solve [t0, t1] = [solveDegree1 (coefficient t1) (coefficient t0)] -solve [t0, t1, t2] = solveDegree2 (coefficient t2) (coefficient t1) (coefficient t0) -solve _ = undefined - -mySqrt :: Float -> Float -mySqrt n - | n < 0 = undefined - | otherwise = mySqrt' (n / 2) - where mySqrt' x = if abs (x * x - n) < 0.01 - then x - else mySqrt' xn - where xn = b - (a * a) / (2 * b) - where a = (n - x * x) / (2 * x) - b = x + a |
