Last active
August 29, 2015 14:21
-
-
Save mwolicki/7340f2c33fdd08f68863 to your computer and use it in GitHub Desktop.
simple calc parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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