Question

I am kinda new to F# and I'm trying to write a simple program that reads a mathematical expression and calculates it.

I was successfully able to calculate expressions like: "5+3 *3 - 1/2", "10 + 50 /50" etc. As this is being fairly simple and done by straightforward recursion, I wanted to take it to the next level using other mathematical functions (cos,sin etc.) but . . . I stumbled upon parentheses as i can't get an idea of how to recurse on patterns such as "((5+3) * 5) - (4-5)" because this is 1 deminsional list of the so-called Tokens (I 'tokenize' the input string with Regex") and the list having outer and inner layers of endless expressions!

This is the code I used for the first prototype of calculations:

let rec parseEq (src:Expression) = 
match src with 
| [Int number] -> number
| _ ->
    match decompose src with
    Some(Int head,rest) -> 
        match decompose rest with
            | Some(Plus,  rest) -> head + parseEq rest
            | Some(Minus, rest) -> head - parseEq rest
            | Some(Times, rest) -> head * parseEq rest
            | Some(DevBy, rest) -> head / parseEq rest
            | _ -> failwith "input error"
    | _ -> failwith "input error"

Note the tokens : Plus,Minus, Int etc. this is the same appraoch im trying to use to calculate the more complex expressions.

Update: this is the list I get after tokenization:

"((5+5) - 10)" |> tokenize;;
val it : Token list =
[Open; Open; Digit 5.0; Plus; Digit 5.0; Close; Minus; Digit 10.0; Close]

Update : is there a way that i can 'replace' a segment of the token list to one token of type Token list? like this:

"5 + (3-1)" = [Digit 5; Plus; Open; Digit 3; Minus; Digit 1; Close]

becomes:

"5 + (3-1)" = [Digit 5; Plus; Expr [Digit 3; Minus; Digit 1]]

Any ideas would be helpful, Thanks!

Was it helpful?

Solution

I think to do this you probably need to convert your expression into prefix notation. this requires walking over it and pushing onto stacks until you are ready to take the term, so

for example ((5+5) - 10)

becomes

(+5,5)(-10). then it's simply a matter of going from left to right and evaluating the expressions inline.

OTHER TIPS

The best solution is in your DU you add

|Bracket of Token list

then you change your function to

match decompose src with
|Some(Int head,rest) -> 
    match decompose rest with
        | Some(Plus,  rest) -> head + parseEq rest
        | Some(Minus, rest) -> head - parseEq rest
        | Some(Times, rest) -> head * parseEq rest
        | Some(DevBy, rest) -> head / parseEq rest
        | _ -> failwith "input error"
|Some(Bracket b,rest) ->
    let head = parseEq b
    match decompose rest with
        | Some(Plus,  rest) -> head + parseEq rest
        | Some(Minus, rest) -> head - parseEq rest
        | Some(Times, rest) -> head * parseEq rest
        | Some(DevBy, rest) -> head / parseEq rest
        | _ -> failwith "input error"
| _ -> failwith "input error"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top