0

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?

baris.aydinoz
  • 1,902
  • 2
  • 18
  • 28
  • 2
    I don't see what dijkstra's algorithm has to do with parsing an expression. Do you want to know the distance between nodes in the parse tree? If so, what for? – sepp2k Jun 01 '10 at 12:49
  • @sepp2K: It is not related with parsing, I will parse using recursive descent, but the problem is the execution of this function with variable inputs. – baris.aydinoz Jun 01 '10 at 12:52
  • @baris_a, after you've constructed the syntax tree, you can evaluate it with a (usually) recursive `eval` function. – Nick Dandoulakis Jun 01 '10 at 12:54
  • 1
    @baris_a: I still don't see what Dijkstra's algorithm has to do with this. Dijkstra's algorithm calculates distances between nodes in a graph. This is not related to evaluating arithmetic expressions at all. – sepp2k Jun 01 '10 at 12:59
  • 1
    Actually, the problem is evaluation of function, how should I change Dijkstra’s algorithm during the evaluation after parsing function into a data structure. – baris.aydinoz Jun 01 '10 at 13:56
  • 3
    Guys! Dijkstra has a lot more algorithms to his name than just shortest paths... –  Jun 01 '10 at 14:24

3 Answers3

3

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/

  • 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.aydinoz Jun 01 '10 at 15:11
  • @Baris_a: I have edited the answer to add another link. Recursive descent and Shunting yard are two separate techniques for parsing. –  Jun 01 '10 at 16:03
  • @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.aydinoz Jun 02 '10 at 06:55
  • @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. –  Jun 02 '10 at 14:00
  • @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.aydinoz Jun 03 '10 at 06:33
0

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
  • 131,802
  • 30
  • 241
  • 343
0

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.

INS
  • 10,594
  • 7
  • 58
  • 89