views:

391

answers:

3

Hi guys, the question is: suppose I have an input function like sin(2-cos(3*A/B)^2.5)+0.756*(C*D+3-B) specified with a BNF, I will parse input using recursive descent algorithm, and then how can I use or change Dijkstra’s algorithm to handle this given function? I need to execute it with sin | cos | sqrt | ln, where Dijkstra’s algorithm should do the work.

EDIT: May be I should ask also: What is the best practice or data structure to represent given function?

EDIT: Input set can be acquired as:

C 0.01 .01 .02 .04 .08 .02 .02 .04 
A .016 .008 .116 .124 .147 .155 .039 .023  
D .012 .025 .05 .1 .1 .1 .025 .012000 .012
B .007 .007 .015 .022 .029 .036 .044 .051 .058 .066 .073 .080 

EDIT: Shunting Yard is the algorithm to convert input function to RPN, but how can I extend it to accept another function like sin | cos | sqrt | ln? Does recursive descent provides required extension to Shunting Yard?

A: 

I don't see Dijkstra here, since it is used to find the shortest path in a graph with non negative weights.

In you case you talk about a recursive descent parser, that is of kind LL(k) and it is defined by a grammar similar to

expression ::= term + term | term - term
term ::= factor * factor | factor / factor
factor ::= ident | number

number ::= digit | digit number
digit ::= 0 | 1 | 2 ...

the best data structure to store this kind of information usually is an Abstract Syntax Tree that is a tree which replicates the structure of the code it parses. In you example you would need a different struct or class for various pieces of code: BinaryOperation, Ident, Number, UnaryOperation, FunctionCall ending up having something like

                         BinaryOperation +
                          |            |
                                     BinaryOperation *
                                      |            |
                                    Number       BinaryOperation +
                                      |           |
                                     0.756     BinOp *
                                               |    |
                                             Ident Ident
                                               |    |
                                               C    D

EDIT: Didn't know that shunting-yard was invented by Dijkstra! By the way it's a quite easy algorithm like Moron explained.. you'll never stop learning something new!

Jack
could downvoters be enough kind to explain themselves? thank you, for a better world :)
Jack
Dijkstra has invented a lot of stuff. The rest of us are mere mortals.
Hamish Grubijan
+3  A: 

I presume you are talking about Dijkstra's Shunting Yard algorithm?

To evaluate the reverse polish notation (output of shunting yard), normally a stack is used.

Shunting Yard was devised to do the parsing in Algol I believe, and I believe it is supposed to work with any functions (either fixed or variable number of arguments).

Here is a blog post which explains it in more detail: http://www.kallisti.net.nz/blog/2008/02/extension-to-the-shunting-yard-algorithm-to-allow-variable-numbers-of-arguments-to-functions/

Moron
Shunting Yard is the algorithm to convert input function to RPN, but how can I extend it to accept another function like sin | cos | sqrt | ln? Does recursive descent provides required extension to Shunting Yard?
baris_a
@Baris_a: I have edited the answer to add another link. Recursive descent and Shunting yard are two separate techniques for parsing.
Moron
@Moron: Thanks for the link for variable input, but sin|cos|sqrt|ln problem is different, I just do not get it, do I have to handle this functions in another stack? Since, they are not operators, neither outputs.
baris_a
@baris_a: I presume you mean during evaluation, after RPN is generated (operators are part of the output). You push operators on the stack too. You also tag the operators with the number of arguments they take, so when you need to pop off the arguments for that operator, you know exactly how many to pop off.
Moron
@Moron: I gave sin|cos|sqrt|ln symbols, that are not used in the BNF, and treated them as right-associative operators. No problem so far. Thanks for your help.
baris_a
A: 

Use ANTLR with a grammar similar to the one Jack provided. It should be enough to create a good parser in multiple languages: Java/C/C++/Python/etc. Read some example and tutorials. You should use ANTLRWorks for faster expression verification.

Iulian Şerbănoiu