Download presentation

Presentation is loading. Please wait.

Published byDestiny Cornett Modified over 3 years ago

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, let’s clear up some terminology…**

3
**Interpreter Examples of “Interpreted” Languages**

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… Examples of “Interpreted” Languages Python Ruby Pearl Smalltalk JavaScript Java

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);**

Don’t 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);**

Don’t 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
var = 2 * ( ) ; ID

18
var = 2 * ( ) ; ID Operator Operator Operator

19
**var = 2 * ( 3 + 5 ) ; ID Factor Factor Factor Operator Operator**

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

21
**var = 2 * ( 3 + 5 ) ; ID Expression Expression Term Term Factor Factor**

Operator Operator Operator

22
**var = 2 * ( 3 + 5 ) ; ID Expression Expression Term Term Factor Factor**

Operator Operator Operator

23
**What do we need (object wise) to accomplish this?**

Data: a list of all ID’s (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
**What do we need (object wise) to accomplish this?**

Data: a list of all ID’s (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”…

26
Functionality

27
**So – let’s go back to our concrete example and trace the program…**

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

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

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

statement.idList = Statement.ch =

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

statement.idList = Statement.ch = Runtime Stack getStatement() e = id = command =

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

statement.idList = Statement.ch = var Runtime Stack getStatement() e = id = command = var VAR

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

statement.idList = Statement.ch = = var Runtime Stack R expression() getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = = Runtime Stack R term() R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = = Runtime Stack R factor() R term() f = ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = = Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = 2 = Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = 2 Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = 2 Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = 2 * Runtime Stack R factor() var = 1.0 2.0 minus = 1.0 id = R term() f = ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = * Runtime Stack R factor() var = 2.0 minus = 1.0 id = R term() f = 2 ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = * Runtime Stack R factor() R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = * Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = * ( Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ( Runtime Stack R factor() var = 1.0 minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ( R expression() Runtime Stack R factor() var = ? 1.0 minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ( R expression() Runtime Stack R factor() var = ? Here, we have our first recursive function call… minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ( R expression() Runtime Stack R factor() var = ? This conveniently allows us to naturally follow mathematical precedence … minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

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

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

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

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

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

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

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

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

statement.idList = Statement.ch = + R expression() Runtime Stack R factor() var = ? minus = 1.0 id = R term() f = 2 * ? R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = + ) R expression() Runtime Stack R factor() var = ? 8 minus = 1.0 id = R term() f = 2 * ? 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… R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ; ) Runtime Stack R factor() factor() can now return 8 to term() var = 8 minus = 1.0 id = R term() f = 2 * ? * 8 R expression() t = ? getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ; Runtime Stack factor() can now return 8 to term() term() can return 2*8 =16 to expression() R term() f = 2 * 8 R expression() t = ? 16 getStatement() e = id = command = ? var VAR

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

statement.idList = Statement.ch = ; Runtime Stack factor() can now return 8 to term() term() can return 2*8 =16 to expression() expression() also returns 16 to getStatement… R expression() t = 16 getStatement() e = id = command = ? 16 var VAR

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

statement.idList = Statement.ch = var => 16 ; Runtime Stack getStatement() e = id = command = 16 var VAR

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.

Similar presentations

OK

10/1/2015© 2002-09 Hal Perkins & UW CSEG-1 CSE P 501 – Compilers Intermediate Representations Hal Perkins Autumn 2009.

10/1/2015© 2002-09 Hal Perkins & UW CSEG-1 CSE P 501 – Compilers Intermediate Representations Hal Perkins Autumn 2009.

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google