Skip to content

Instantly share code, notes, and snippets.

@mwolicki
Last active August 29, 2015 14:21
Show Gist options
  • Save mwolicki/7340f2c33fdd08f68863 to your computer and use it in GitHub Desktop.
Save mwolicki/7340f2c33fdd08f68863 to your computer and use it in GitHub Desktop.
simple calc parser
#if INTERACTIVE
#I @"/Users/kevin/Projects/FSParsec/packages/FParsec.1.0.1/lib/net40-client/"
#r @"FParsecCS.dll"
#r @"FParsec.dll"
#endif
open FParsec
type Expr = Op of string * Expr * Expr | Num of float
let ws = spaces
let isSymbolicOperatorChar = isAnyOf "*+-^/"
let remainingOpChars_ws = manySatisfy isSymbolicOperatorChar .>> ws
let opp = new OperatorPrecedenceParser<Expr, string, unit>()
let expr = opp.ExpressionParser
opp.TermParser <- (pfloat .>> ws |>> Num) <|> between (ws >>.pstring "(" .>> ws) (ws >>.pstring ")" .>> ws) expr
let addSymbolicInfixOperators (prefix, precedence) =
let op = InfixOperator(prefix, remainingOpChars_ws,
precedence, Associativity.Left, (),
fun remOpChars expr1 expr2 ->
Op(prefix + remOpChars, expr1, expr2))
opp.AddOperator(op)
seq [("^",30); ("*",20); ("/", 20); ("+",10); ("-", 10)] |> Seq.iter addSymbolicInfixOperators
let calc str =
let rec calc'=
function
| Num x->x
| Op (op,a,b) ->
let func = match op with | "+" -> (+) | "-" -> (-) | "*" -> (*) | "/" -> (/) | "^" -> ( ** ) | _ -> failwith ("Unknown operator "+ op)
func (calc' a) (calc' b)
match run opp.ExpressionParser str with
| Success (a,_,_) -> calc' a
| Failure(errorMsg, _, _) -> failwith ("Failure: " + errorMsg)
//calc "2^16"
calc "1+2*(2 +3)/3"
calc " (1 +2+3)/6 "
calc "(1*2+3)/6"
calc "(1+2*3-1)/6"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment