问题
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!
回答1:
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.
回答2:
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"
来源:https://stackoverflow.com/questions/19941084/applying-recursion-on-1d-list-with-parentheses