import Control. Applicative
import Data. Tree
headOption ( x:xs) = Just x
headOption [ ] = Nothing
parse ( P m) = m
result m s= case headOption ( parse m s) of
Just( res, "" ) -> Just( res)
_ -> Nothing
instance Monad Parser
where ( >>= ) ( P m) f = P( \s -> m s >>= \( a, s) -> parse ( f a) s)
instance MonadPlus Parser where
mzero = P( \s -> [ ] )
mplus ( P a) ( P b) = P( \s -> ( a s) ++ ( b s) )
instance Applicative Parser where
( <*> ) mf ma
= mf
>>= \f
-> ma
>>= \a
-> return $ f a
instance Alternative Parser where
empty = mzero
( <|> ) = mplus
zero' _ _ = []
zero a = P(zero' a)
item' (x:xs) = [(x,xs)]
item' [ ] = [ ]
item = P( item')
term y = P(term' y)
term' y (x:xs) = if(x == y) then [(y,xs)] else []
term' y [ ] = [ ]
digits
= some
$ msum
$ map term
[ '0' .. '9' ] oper op s
= fmap ( const $ BinaryOp op
) $ word s
unary op s
= fmap ( const $ UnaryOp op
) $ word s
type AST = Tree Token
node x = Node x [ ]
unaryMin x = - x
unfolder ( term1, ( ( op, term2) :xs) ) = ( node op, [ ( term1, [ ] ) , ( term2, xs) ] )
unfolder ( term1, [ ] ) = ( term1, [ ] )
tokenToString
( Val x
) = show x
tokenToString _ = "op"
spaces = many $ word " "
between p m
= do { p; r
<- m; p;
return r
}
termAndOperations terms ops = do
spaces
term <- terms
op <- ops
spaces
return $ join
$ unfoldTree unfolder
( term
, op
)
expr
= let unaryAndFactors
= do { op
<- unary unaryMin
"-" ; term
<- eterm;
return $ Node op
[ term
] } <|> eterm;
additionAndSubstruction
= many
$ do { op
<- oper
( + ) "+" <|> oper
( - ) "-" ; other
<- eterm;
return ( op
, other
) } in termAndOperations unaryAndFactors additionAndSubstruction
multAndDiv
= many
$ do { op
<- oper
( * ) "*" <|> oper
( / ) "/" ; f
<- expterm;
return ( op
, f
) } in termAndOperations
exponent multAndDiv
expterm
= let exponentOp
= many
$ do { op
<- oper
( ** ) "^" ; f
<- factor;
return ( op
, f
) } in termAndOperations factor exponentOp
factor
= between spaces
$ ( fmap ( node
. Val
) floatParser
) <|> do { word
"(" ; e
<- expr;word
")" ;
return e;
}
compute ( Node ( BinaryOp( f) ) ( x:y:[ ] ) ) = compute( x) `f` compute( y)
compute ( Node ( UnaryOp( f) ) ( x:[ ] ) ) = f $ compute( x)
compute ( Node ( Val( x) ) [ ] ) = x
eval
= fmap compute
. result expr
data InterpeterTestCases a
= EqualityOf
String ( Maybe a
)
tests
:: [ InterpeterTestCases
Float ] tests = [
EqualityOf "2 + 3" $ Just( 5 ) ,
EqualityOf "4 - 3" $ Just( 1 ) ,
EqualityOf "2 + (-3)" $ Just( - 1 ) ,
EqualityOf "4 * 5" $ Just( 20 ) ,
EqualityOf "6/4" $ Just( 6 / 4 ) ,
EqualityOf "1.2 + 1/2" $ Just( 1.2 + 1 / 2 ) ,
EqualityOf "1/(-3)" $ Just( 1 / ( - 3 ) ) ,
EqualityOf "0.5 + 0.2" $ Just( 0.7 ) ,
EqualityOf "3 ^ 2 ^ 2" $ Just( 81 ) ,
EqualityOf "17654/342" $ Just( 8827 / 171 ) ,
EqualityOf "2/3^2" $ Just( 2 / 9 ) ,
EqualityOf "(2/3)^2" $ Just( 4 / 9 ) ]
main = do
print "(2 + 3) / (2 - 2) == Just(Infinity)" print $ Just
$ Just
( 1 / 0 ) == eval
"(2 + 3) / (2 - 2)" print "2 + 345 + + + + 6 == Nothing" print $ Just
$ Nothing
== eval
"2 + 345 + + + + 6" forM_ tests $ \( EqualityOf expr expected) -> do
let difference = liftA2 ( - ) ( eval expr) expected
aW1wb3J0IENvbnRyb2wuQXBwbGljYXRpdmUKaW1wb3J0IENvbnRyb2wuTW9uYWQKaW1wb3J0IERhdGEuVHJlZQoKZGF0YSBQYXJzZXIgYSA9IFAoU3RyaW5nIC0+IFsoYSxTdHJpbmcpXSkKCmhlYWRPcHRpb24gKHg6eHMpID0gSnVzdCB4CmhlYWRPcHRpb24gW10gPSBOb3RoaW5nCgpwYXJzZSAoUCBtKSA9IG0KCnJlc3VsdCBtIHM9IGNhc2UgaGVhZE9wdGlvbiAocGFyc2UgbSBzKSBvZgoJSnVzdChyZXMsIiIpIC0+IEp1c3QocmVzKQoJXyAtPiBOb3RoaW5nCmluc3RhbmNlIEZ1bmN0b3IgUGFyc2VyIHdoZXJlCglmbWFwIGYgbSA9IG0gPj49IFxhIC0+IHJldHVybiAkIGYgYQoKaW5zdGFuY2UgTW9uYWQgUGFyc2VyIHdoZXJlCglyZXR1cm4gYSA9IFAgKFxzIC0+IFsoYSxzKV0pCgkoPj49KSAoUCBtKSBmID0gUChccyAtPiBtIHMgPj49IFwoYSxzKSAtPiBwYXJzZSAoZiBhKSBzKQoKaW5zdGFuY2UgTW9uYWRQbHVzIFBhcnNlciB3aGVyZQoJbXplcm8gPSBQKFxzIC0+IFtdKQoJbXBsdXMgKFAgYSkgKFAgYikgPSBQKFxzIC0+IChhIHMpICsrIChiIHMpKSAKCmluc3RhbmNlIEFwcGxpY2F0aXZlIFBhcnNlciB3aGVyZQoJcHVyZSA9IHJldHVybgoJKDwqPikgbWYgbWEgPSBtZiA+Pj0gXGYgLT4gbWEgPj49IFxhIC0+IHJldHVybiAkIGYgYQoKaW5zdGFuY2UgQWx0ZXJuYXRpdmUgUGFyc2VyIHdoZXJlCgllbXB0eSA9IG16ZXJvCgkoPHw+KSA9IG1wbHVzCgp6ZXJvJyBfIF8gPSBbXQp6ZXJvIGEgPSBQKHplcm8nIGEpCgppdGVtJyAoeDp4cykgPSBbKHgseHMpXQppdGVtJyBbXSA9IFtdCml0ZW0gPSBQKGl0ZW0nKQoKdGVybSB5ID0gUCh0ZXJtJyB5KQp0ZXJtJyB5ICh4OnhzKSA9IGlmKHggPT0geSkgdGhlbiBbKHkseHMpXSBlbHNlIFtdIAp0ZXJtJyB5IFtdID0gW10KCndvcmQgPSBzZXF1ZW5jZSAuIG1hcCAodGVybSkgCmRpZ2l0cyA9IHNvbWUgJCBtc3VtICQgbWFwIHRlcm0gWycwJy4uJzknXQppbnRlZ2VyUGFyc2VyID0gZm1hcCAocmVhZCA6OiBTdHJpbmcgLT4gSW50ZWdlcikgZGlnaXRzCmZsb2F0UGFyc2VyID0gZm1hcCAocmVhZCA6OiBTdHJpbmcgLT4gRmxvYXQpICQgZm1hcCBqb2luICQgc2VxdWVuY2UgW2RpZ2l0cyxmbWFwIChqb2luKSAoc2VxdWVuY2UgW3dvcmQgIi4iLGRpZ2l0c10pIDx8PiAocmV0dXJuICIiKV0Kb3BlciBvcCBzID0gZm1hcCAoY29uc3QgJCBCaW5hcnlPcCBvcCkgJCB3b3JkIHMKdW5hcnkgb3AgcyA9IGZtYXAgKGNvbnN0ICQgVW5hcnlPcCBvcCkgJCB3b3JkIHMKCmRhdGEgVG9rZW4gPSBWYWwgRmxvYXQgfCBCaW5hcnlPcCAoRmxvYXQgLT4gRmxvYXQgLT4gRmxvYXQpIHwgVW5hcnlPcCAoRmxvYXQgLT4gRmxvYXQpCnR5cGUgQVNUID0gVHJlZSBUb2tlbgoKbm9kZSB4ID0gTm9kZSB4IFtdCnVuYXJ5TWluIHggPSAteAp1bmZvbGRlciAodGVybTEsKChvcCx0ZXJtMik6eHMpKSA9IChub2RlIG9wLFsodGVybTEsW10pLCh0ZXJtMix4cyldKQp1bmZvbGRlciAodGVybTEsW10pID0gKHRlcm0xLFtdKQp0b2tlblRvU3RyaW5nIChWYWwgeCkgPSBzaG93IHgKdG9rZW5Ub1N0cmluZyBfID0gIm9wIgpzcGFjZXMgPSBtYW55ICQgd29yZCAiICIKCmJldHdlZW4gcCBtID0gZG8ge3A7IHIgPC0gbTsgcDsgcmV0dXJuIHIgfQoKdGVybUFuZE9wZXJhdGlvbnMgdGVybXMgb3BzID0gZG8KCXNwYWNlcwoJdGVybSA8LSB0ZXJtcwoJb3AgPC0gb3BzCglzcGFjZXMKCXJldHVybiAkIGpvaW4gJCB1bmZvbGRUcmVlIHVuZm9sZGVyICh0ZXJtLG9wKQoKZXhwciA9IGxldCB1bmFyeUFuZEZhY3RvcnMgPSBkbyB7IG9wIDwtIHVuYXJ5IHVuYXJ5TWluICItIjsgdGVybSA8LSBldGVybTsgcmV0dXJuICQgTm9kZSBvcCBbdGVybV0gfSA8fD4gZXRlcm07CgkJICAgYWRkaXRpb25BbmRTdWJzdHJ1Y3Rpb24gPSBtYW55ICQgZG8geyBvcCA8LSBvcGVyICgrKSAiKyIgPHw+IG9wZXIgKC0pICItIjsgb3RoZXIgPC0gZXRlcm07IHJldHVybiAob3Asb3RoZXIpIH0gCgkJaW4gdGVybUFuZE9wZXJhdGlvbnMgdW5hcnlBbmRGYWN0b3JzIGFkZGl0aW9uQW5kU3Vic3RydWN0aW9uCmV0ZXJtID0gbGV0IGV4cG9uZW50ID0gZXhwdGVybTsKCQkJbXVsdEFuZERpdiA9IG1hbnkgJCBkbyB7IG9wIDwtIG9wZXIgKCopICIqIiA8fD4gb3BlciAoLykgIi8iOyBmIDwtIGV4cHRlcm07IHJldHVybiAob3AsZikgIH0KCQlpbiB0ZXJtQW5kT3BlcmF0aW9ucyBleHBvbmVudCBtdWx0QW5kRGl2IApleHB0ZXJtID0gbGV0IGV4cG9uZW50T3AgPSBtYW55ICQgZG8ge29wIDwtIG9wZXIgKCoqKSAiXiI7IGYgPC0gZmFjdG9yOyByZXR1cm4gKG9wLGYpfQoJCSAgaW4gdGVybUFuZE9wZXJhdGlvbnMgZmFjdG9yIGV4cG9uZW50T3AKZmFjdG9yID0gYmV0d2VlbiBzcGFjZXMgJCAoZm1hcCAobm9kZSAuIFZhbCkgZmxvYXRQYXJzZXIpIDx8PiBkbyB7IHdvcmQgIigiOyBlIDwtIGV4cHI7d29yZCAiKSI7IHJldHVybiBlOyB9CgoKY29tcHV0ZSAoTm9kZSAoQmluYXJ5T3AoZikpICh4Onk6W10pKSA9IGNvbXB1dGUoeCkgYGZgIGNvbXB1dGUoeSkKY29tcHV0ZSAoTm9kZSAoVW5hcnlPcChmKSkgKHg6W10pKSA9IGYgJCBjb21wdXRlKHgpCmNvbXB1dGUgKE5vZGUgKFZhbCh4KSkgW10pID0geAoKZXZhbCA9IGZtYXAgY29tcHV0ZSAuIHJlc3VsdCBleHByCgpkYXRhIEludGVycGV0ZXJUZXN0Q2FzZXMgYSA9IEVxdWFsaXR5T2YgU3RyaW5nIChNYXliZSBhKQoKdGVzdHMgOjogW0ludGVycGV0ZXJUZXN0Q2FzZXMgRmxvYXRdCnRlc3RzID0gWwoJRXF1YWxpdHlPZiAiMiArIDMiICQgSnVzdCg1KSwKCUVxdWFsaXR5T2YgIjQgLSAzIiAkIEp1c3QoMSksCglFcXVhbGl0eU9mICIyICsgKC0zKSIgJCBKdXN0KC0xKSwKCUVxdWFsaXR5T2YgIjQgKiA1IiAkIEp1c3QoMjApLAoJRXF1YWxpdHlPZiAiNi80IiAkIEp1c3QoNi80KSwKCUVxdWFsaXR5T2YgIjEuMiArIDEvMiIgJCBKdXN0KDEuMisxLzIpLAoJRXF1YWxpdHlPZiAiMS8oLTMpIiAkIEp1c3QoMS8oLTMpKSwKCUVxdWFsaXR5T2YgIjAuNSArIDAuMiIgJCBKdXN0KDAuNyksCglFcXVhbGl0eU9mICIzIF4gMiBeIDIiICQgSnVzdCg4MSksCglFcXVhbGl0eU9mICIxNzY1NC8zNDIiICQgSnVzdCg4ODI3LzE3MSksCglFcXVhbGl0eU9mICIyLzNeMiIgJCBKdXN0KDIvOSksCglFcXVhbGl0eU9mICIoMi8zKV4yIiAkIEp1c3QoNC85KV0gCgptYWluID0gZG8KCXByaW50ICIoMiArIDMpIC8gKDIgLSAyKSA9PSBKdXN0KEluZmluaXR5KSIKCXByaW50ICQgSnVzdCAkIEp1c3QoMS8wKSA9PSBldmFsICIoMiArIDMpIC8gKDIgLSAyKSIKCXByaW50ICIyICsgMzQ1ICsgKyArICsgNiA9PSBOb3RoaW5nIgoJcHJpbnQgJCBKdXN0ICQgTm90aGluZyA9PSBldmFsICIyICsgMzQ1ICsgKyArICsgNiIgIAoJZm9yTV8gdGVzdHMgJCBcKEVxdWFsaXR5T2YgZXhwciBleHBlY3RlZCkgLT4gZG8gCgkJcHJpbnQgJCBleHByICsrICIgPT0gIiArKyAoc2hvdyBleHBlY3RlZCkKCQlsZXQgZGlmZmVyZW5jZSA9IGxpZnRBMiAoLSkgKGV2YWwgZXhwcikgZXhwZWN0ZWQKCQlwcmludCAkIGZtYXAgKCg8MC4wMDAxKSAuIGFicykgZGlmZmVyZW5jZQ==