Presentation is loading. Please wait.

Presentation is loading. Please wait.

Case Study: A Recursive Descent Interpreter Implementation in C++ (Source Code Courtesy of Dr. Adam Drozdek) Payap University ICS220 - Data Structures.

Similar presentations


Presentation on theme: "Case Study: A Recursive Descent Interpreter Implementation in C++ (Source Code Courtesy of Dr. Adam Drozdek) Payap University ICS220 - Data Structures."— Presentation transcript:

1 Case Study: A Recursive Descent Interpreter Implementation in C++ (Source Code Courtesy of Dr. Adam Drozdek) Payap University ICS220 - Data Structures and Algorithm Analysis Instructor: Dr. Ken Cosh Analysis and Presentation by Rob Agle

2 First, lets clear up some terminology…

3 Interpreter Examples of Interpreted Languages Python Pearl JavaScript Ruby Smalltalk Java In general, a compiler is a program that converts an entire program from high level source code into some lower level representation (assembly or machine code for example). An interpreter on the other hand, traditionally translates high level instructions and executes them on the fly (at runtime). The lines between these two concepts are blurring however…

4 Interpreter For our purposes – we can simply say that our interpreter will be used to translate and execute one instruction statement at a time.

5 Interpreter For our purposes – we can simply say that our interpreter will be used to translate and execute one instruction statement at a time.

6 Interpreter For our purposes – we can simply say that our interpreter will be used to translate and execute one instruction statement at a time.

7 Interpreter Things our interpreter understands: Variable Names: Any alphanumeric string Operators: + - / * = Commands: Print, Status, End

8 Recursive Descent A process that allows us to descend – or go down to lower and lower levels of complexity via recursion, and then work backwards towards a solution once all the pieces are in place.

9 Recursive Descent A process that allows us to descend – or go down to lower and lower levels of complexity via recursion, and then work backwards towards a solution once all the pieces are in place.

10 Recursive Descent For Example: var = 2*(3+5);

11 Recursive Descent For Example: var = 2*(3+5);

12 Recursive Descent For Example: The statement: var = 2*(3+5); can be parsed and broken down into its individual pieces using recursion.

13 Recursive Descent For Example: The statement: var = 2*(3+5); can be parsed and broken down into its individual pieces using recursion.

14 Recursive Descent var = 2*(3+5); Dont worry about how, just imagine we magically use some combination of direct and indirect recursion to break down the above statement into the following…

15 Recursive Descent var = 2*(3+5); Dont worry about how, just imagine we magically use some combination of direct and indirect recursion to break down the above statement into the following…

16 var = 2 * ( ) ;

17 ID

18 var = 2 * ( ) ; ID Operator

19 var = 2 * ( ) ; ID Operator Factor Operator Factor

20 var = 2 * ( ) ; ID Operator Factor Operator Factor Term

21 var = 2 * ( ) ; ID Operator Factor Operator Factor Term Expression

22 var = 2 * ( ) ; ID Operator Factor Operator Factor Term Expression

23 What do we need (object wise) to accomplish this? Data: a list of all IDs (variables) An array of characters to store an input statement Functionality: A way to get the input statement from the user A way to parse the input, get values for expressions (if any) and its composite parts (terms, factors – if any) and perform indicated operations. A few black boxes…

24 Data

25 Data: a list of all IDs (variables) An array of characters to store an input statement Functionality: A way to get the input statement from the user A way to parse the input, get values for expressions (if any) and its composite parts (terms, factors – if any) and perform indicated operations. A few black boxes… What do we need (object wise) to accomplish this?

26 Functionality

27 So – lets go back to our concrete example and trace the program…

28 Trace: Input -> var = 2*(3+5);

29

30 statement.idList = Statement.ch =

31 Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement()

32 Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR var

33 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? =var

34 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? = t = R term() ?

35 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? = t = R term() ? R factor() f =?

36 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? = t = R term() ? R factor() f =? var = minus = id = 1.0

37 statement.idList = Statement.ch = = 2 R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =? var = minus = id = 1.0

38 2 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =? var = minus = id = 1.0

39 2 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =? var = minus = id = 1.0

40 * statement.idList = Statement.ch = R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =? var = minus = id = 1.0

41 statement.idList = Statement.ch = * R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =? var = minus = id = 1.0

42 statement.idList = Statement.ch = 2 R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? f = * R factor() * ?

43 R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? * t = R term() ? R factor() f =2 var = minus = id = 1.0 * ?

44 ( R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? * t = R term() ? R factor() f =2 var = minus = id = 1.0 * ?

45 ( R expression() Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ?

46 ? R expression() ( Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ?

47 ? R expression() ( Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? Here, we have our first recursive function call…

48 ? R expression() ( Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? This conveniently allows us to naturally follow mathematical precedence …

49 ? R expression() ( Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? A series of additional indirect recursive calls will determine the value of (3+5)… R term()

50 ? R expression() ( Trace: Input -> var = 2*(3+5); statement.idList = Statement.ch = Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? A series of additional indirect recursive calls will determine the value of (3+5)… R term() R factor()

51 3 statement.idList = Statement.ch = ? R expression() ( Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? A series of additional indirect recursive calls will determine the value of (3+5)… R term() R factor()

52 + statement.idList = Statement.ch = 3 ? R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? A series of additional indirect recursive calls will determine the value of (3+5)… R term()

53 + statement.idList = Statement.ch = ? R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ?

54 ) statement.idList = Statement.ch = 8 + ? R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? R factor() f =2 var = minus = id = 1.0 * ? We now see the same chain of recursive calls to term and factor… Which eventually sets t = 8 in expression(). This value will be returned to factor…

55 ; statement.idList = Statement.ch = R factor() * 8 2 * ? ) 8 R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? f = var = minus = id = 1.0 factor() can now return 8 to term()

56 16 statement.idList = Statement.ch = R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t = R term() ? f =2 * 8 factor() can now return 8 to term() term() can return 2*8 =16 to expression() ;

57 16 statement.idList = Statement.ch = R expression() Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ? t =16 factor() can now return 8 to term() term() can return 2*8 =16 to expression() expression() also returns 16 to getStatement… ;

58 16 statement.idList = Statement.ch = Trace: Input -> var = 2*(3+5); Runtime Stack e = id = command = getStatement() var VAR ; var => 16

59 Control is returned to the main function, where once again getStatement will be called…

60 Final Thoughts For the sake of time – a lot of the non-recursive functions were overlooked and treated as black boxes. Tracing your own input through the functions carefully will leave you with a solid understanding of recursion. Recursive descent was once a popular way to build a parser. These days more complex parsers can be built by parser generators. For more information (and a solid headache), google: LR parsers.


Download ppt "Case Study: A Recursive Descent Interpreter Implementation in C++ (Source Code Courtesy of Dr. Adam Drozdek) Payap University ICS220 - Data Structures."

Similar presentations


Ads by Google