import Text.Parsec
import qualified Text.Parsec.Token as P
import Text.Parsec.Language
import Control.Applicative hiding ((<|>))
import Control.Arrow
data T
= N
Double | T :
* T
| T :
/ T
| T :
+ T
| T :
- T
| B
Bool | T :
> T
| T :
< T
| T :
== T
| If T T T
a --> b = (a, b <$ rOp a)
-- Operators: from lowest to highest precedence
ops = [ [">" --> (:>), "<" --> (:<), "==" --> (:==)]
, ["+" --> (:+), "-" --> (:-)]
, ["*" --> (:*), "/" --> (:/)]
]
myL = P.makeTokenParser $ javaStyle {
, P.reservedNames = ["if", "else", "true", "false"]
}
rOp = P.reservedOp myL
rW = P.reserved myL
parens = P.parens myL
braces = P.braces myL
bool = B <$> ((True <$ rW "true")
<|> (False <$ rW "false"))
num = N <$> P.float myL
if_ = If <$> (rW "if" *> expr)
<*> (braces expr)
<*> (rW "else" *> braces expr)
infix_ x@(l:t) = do
a <- math t
b <- math x
math' = parens $ math ops
math [] = try num <|> try bool <|> parens expr
math l@(_:t) = try math' <|> try (infix_ l) <|> math t
test1 = "1.3 + 1.0 * (2.1 + 3.1) + 1.5"
test2 = "if (2.0 + 2.0 * 1.5== 4.0) { \
\ if(true == false) { \
\ true \
\ } else { \
\ 2.1 \
\ } \
\} else { \
\ 1.0 \
\} "
expr = try if_ <|> try bool <|> math ops
main
= mapM (print . parse
(expr
<* eof
) "") [test1
, test2
, "2.1 == 1.1"]
aW1wb3J0IFRleHQuUGFyc2VjCmltcG9ydCBxdWFsaWZpZWQgVGV4dC5QYXJzZWMuVG9rZW4gYXMgUAppbXBvcnQgVGV4dC5QYXJzZWMuTGFuZ3VhZ2UKaW1wb3J0IENvbnRyb2wuQXBwbGljYXRpdmUgaGlkaW5nICgoPHw+KSkKaW1wb3J0IENvbnRyb2wuQXJyb3cKCmRhdGEgVCA9IE4gRG91YmxlIHwgVCA6KiBUIHwgVCA6LyBUIHwgVCA6KyBUIHwgVCA6LSBUCiAgICAgICB8IEIgQm9vbCB8IFQgOj4gVCB8IFQgOjwgVCB8IFQgOj09IFQKICAgICAgIHwgSWYgVCBUIFQKICBkZXJpdmluZyAoU2hvdykKCmEgLS0+IGIgPSAoYSwgYiA8JCByT3AgYSkKCi0tIE9wZXJhdG9yczogZnJvbSBsb3dlc3QgdG8gaGlnaGVzdCBwcmVjZWRlbmNlCm9wcyA9IFsgWyI+IiAtLT4gKDo+KSwgIjwiIC0tPiAoOjwpLCAiPT0iIC0tPiAoOj09KV0KICAgICAgLCBbIisiIC0tPiAoOispLCAiLSIgLS0+ICg6LSldCiAgICAgICwgWyIqIiAtLT4gKDoqKSwgIi8iIC0tPiAoOi8pXQogICAgICBdCgpteUwgPSBQLm1ha2VUb2tlblBhcnNlciAkIGphdmFTdHlsZSB7CgkJICBQLnJlc2VydmVkT3BOYW1lcyA9IG1hcCBmc3QgJCBjb25jYXQgb3BzCgkJLCBQLnJlc2VydmVkTmFtZXMgPSBbImlmIiwgImVsc2UiLCAidHJ1ZSIsICJmYWxzZSJdCiAgICAgICAgfQpyT3AgPSBQLnJlc2VydmVkT3AgbXlMCnJXID0gUC5yZXNlcnZlZCBteUwKcGFyZW5zID0gUC5wYXJlbnMgbXlMCmJyYWNlcyA9IFAuYnJhY2VzIG15TApib29sID0gQiA8JD4gKChUcnVlIDwkIHJXICJ0cnVlIikgCiAgICAgICAgIDx8PiAoRmFsc2UgPCQgclcgImZhbHNlIikpCm51bSA9IE4gPCQ+IFAuZmxvYXQgbXlMCmlmXyA9IElmIDwkPiAoclcgImlmIiAqPiBleHByKSAKICAgICAgICAgPCo+IChicmFjZXMgZXhwcikgCiAgICAgICAgIDwqPiAoclcgImVsc2UiICo+IGJyYWNlcyBleHByKQoKaW5maXhfIHhAKGw6dCkgPSBkbwogIGEgPC0gbWF0aCB0CiAgZiA8LSBjaG9pY2UgJCBtYXAgc25kIGwKICBiIDwtIG1hdGggeAogIHJldHVybiAkIGYgYSBiCgptYXRoJyA9IHBhcmVucyAkIG1hdGggb3BzCm1hdGggW10gPSB0cnkgbnVtIDx8PiB0cnkgYm9vbCA8fD4gcGFyZW5zIGV4cHIKbWF0aCBsQChfOnQpID0gdHJ5IG1hdGgnIDx8PiB0cnkgKGluZml4XyBsKSA8fD4gbWF0aCB0Cgp0ZXN0MSA9ICIxLjMgKyAxLjAgKiAoMi4xICsgMy4xKSArIDEuNSIKCnRlc3QyID0gImlmICgyLjAgKyAyLjAgKiAxLjU9PSA0LjApIHsgXAogICAgICAgIFwgIGlmKHRydWUgPT0gZmFsc2UpIHsgICAgICAgIFwgCiAgICAgICAgXCAgICB0cnVlICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIFwgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgIFwgCiAgICAgICAgXCAgICAyLjEgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIFwgIH0gICAgICAgICAgICAgICAgICAgICAgICAgIFwgCiAgICAgICAgXH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgXCAKICAgICAgICBcICAxLjAgICAgICAgICAgICAgICAgICAgICAgICBcIAogICAgICAgIFx9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICIKCmV4cHIgPSB0cnkgaWZfIDx8PiB0cnkgYm9vbCA8fD4gbWF0aCBvcHMKCm1haW4gPSBtYXBNIChwcmludCAuIHBhcnNlIChleHByIDwqIGVvZikgIiIpIFt0ZXN0MSwgdGVzdDIsICIyLjEgPT0gMS4xIl0K