Applying recursion on 1d-list with parentheses

怎甘沉沦 提交于 2019-12-11 03:51:37

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!