Skip to content

Instantly share code, notes, and snippets.

@tiqwab
Created October 16, 2016 23:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiqwab/de848250850126d4f04c68e17216f94a to your computer and use it in GitHub Desktop.
Save tiqwab/de848250850126d4f04c68e17216f94a to your computer and use it in GitHub Desktop.
import System.Environment
import Text.Parsec
import Text.Parsec.Expr
import qualified Text.Parsec.Language as L
import qualified Text.Parsec.Token as T
import Text.ParserCombinators.Parsec hiding (try)
{-
Implement calculator with `Text.Parsec.Expr`.
Use `Text.Parsec.Token` to make parsing simple.
-}
-- Make simple language definition
langCalc = L.emptyDef { T.opLetter = char '+' <|> char '-' <|> char '*' <|> char '/' }
-- Create parser with language definition
calcTokenParser = T.makeTokenParser langCalc
-- Create parser for calculator
expr = buildExpressionParser table term
<?> "expression"
term = T.parens calcTokenParser expr
<|> T.natural calcTokenParser
<?> "simple expression"
-- Table of operators. The list is ordered in descending precedence.
table = [ [prefix "-" negate, prefix "+" id ]
, [postfix "++" (+1)]
, [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]
, [binary "+" (+) AssocLeft, binary "-" (-) AssocLeft ]
]
binary name fun assoc = Infix (do{ T.reservedOp calcTokenParser name; return fun }) assoc
prefix name fun = Prefix (do{ T.reservedOp calcTokenParser name; return fun })
postfix name fun = Postfix (do{ T.reservedOp calcTokenParser name; return fun })
-- :main "(1+2)*(-5+1)++"
-- -> -9
main = do args <- getArgs
parseTest (expr :: CharParser () Integer) (head args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment