CS 152: Programming Language Paradigms April 7 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 2 Conceptual Design (Version 3) A compiler and an interpreter can both use the same front end and intermediate tier.
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 3 Scheme Intermediate Code Scheme programs have a simple structure. Everything is a list. The Scheme parser can translate a list into a binary tree. Example: (1 2 3) The left subtree is the car of the list. The right subtree is the cdr of the list. Each leaf node contains an element of the list. _ 1 2 3
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 4 Scheme Intermediate Code, cont’d Example: ((a b) c (d)) Do a preorder walk of the tree to recreate the list: Visit the root. If the left subtree is not an element node, open a set of parentheses. Visit the left subtree. If the left subtree is a leaf, print its element. Visit the right subtree. c ab d
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 5 How to Build the Intermediate Code Write a list parser method that can read a list and return the root of the binary parse tree. As the scanner returns elements, the parse tree “adopts” them. Example: (1 2 3) The parse tree adopts the elements 1, 2, and 3. If a list element is a nested sublist, recursively call the list parser to build a subtree. The main tree adopts the root of the subtree. _ 1 23 Return this root.
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 6 How to Build the Intermediate Code, cont’d Example: (1 2 3) Example: (a (1 2 3) b) Recursively call the list parser. a1 2 3 b 1 2 3
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 7 Top-Down Recursive-Descent Parser Start with the topmost rule. In our case, the rule that defines a list. Recursively work down to the lower level rules. Rules that define list elements. One token lookahead. Example: If the scanner fetches a ( token, the parser knows that it will parse a list next. The syntax diagram helps you write the parsing method.
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 8 The Symbol Table: Basic Concepts Purpose To store information about certain tokens during the translation process (i.e., parsing and scanning). What information to store? Anything that’s useful! For a symbol: its name how it’s defined (as a variable, procedure name, etc.) Basic operations Enter new information Look up existing information Update existing information
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 9 The Symbol Table: Implementation Each symbol table entry includes the name of a symbol and its attributes. To maintain maximum flexibility, we can implement the attributes as a hash table.
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 10 The Symbol Table: Implementation, cont’d The symbol table itself can be a hash table. Key: The symbol name. Value: The symbol table entry for the symbol.
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 11 The Symbol Table Stack Scheme constructs (and their scopes) can be nested. A lambda expression can be nested inside another lambda expression. A let special form can be nested inside another let special form. Therefore, symbol tables need to be kept on a symbol table stack. The stack handles nested scopes. You can implement the stack as an array list. _
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 12 The Symbol Table Stack, cont’d Whichever symbol table is on top of the stack is the local symbol table. The first symbol table created (the one at the bottom of the stack) is the global symbol table. It stores the predefined symbols, such as entries for the names of the standard Scheme procedures car, cdr, cons, +, -, etc. During the translation process, symbol tables are pushed onto and popped off the stack … … as the parser enters and exits scopes. _ Global symbol table
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 13 The Global Symbol Table Before starting to parse, initialize the global symbol table by populating it with Scheme’s predefined symbols, such as car, cdr, cons, +, -, *, etc. Push the global symbol table onto the symbol table stack, so that it’s at the bottom of the stack. The global symbol table has nesting level 0. Global symbol table
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 14 The Top-Level Symbol Table After initializing the global symbol table, push a new empty symbol table onto the stack. It goes on top of the global symbol table. It has nesting level 1. This is the symbol table for all the top-level names in your program. Top-level names are not nested. This table should contain all the names that are each declared by the define special form. As you parse each define special form, enter the symbol (name) into the top-level symbol table. One of the attributes of a symbol table entry should be a reference to the symbol table that it’s contained in.
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 15 Scope and the Symbol Table Stack Scheme special forms lambda, let, letrec, let*, etc. each creates a new scope. Each scope must have its own symbol table. Each symbol table has a nesting level number according to how deeply nested the scope is. Whenever your parser enters a new scope (i.e., it begins to parse one of the special forms listed above), create a symbol table for the scope and push it onto the symbol table stack. Enter symbols declared by the scope into its symbol table. When the parser is done parsing the scope, pop off the symbol table
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 16 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 17 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 18 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table “a” Level 2 symbol table “b”
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 19 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table “a” Level 2 symbol table “b”“sum” Level 3 symbol table
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 20 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table “a” Level 2 symbol table “b”“sum” Level 3 symbol table
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 21 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table “a” Level 2 symbol table “b” Two ways to search the symbol table stack: 1. Search only the local symbol table (at the top of the stack) to make sure that a symbol isn’t being defined multiple times within a scope. Example: (lambda (a b)...
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 22 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table “a” Level 2 symbol table “b”“sum” Level 3 symbol table Two ways to search the symbol table stack: 2. Search the stack from top to bottom to look for a symbol defined in an outer scope. Example: (+ a b) _
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 23 (define proc (lambda (a b) (let ((sum (+ a b))) sum) )) Scope and the Symbol Table Stack, cont’d “car”“cdr”“+” Level 0 symbol table Symbol table stack “proc” Level 1 symbol table After the define has been parsed, make the entry for “ proc ” point to the parse tree of the lambda expression. Ready to parse the next define special form!
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 24 Scope and the Symbol Table Stack, cont’d After popping a symbol table off the stack, you must still keep a reference to that symbol table. In your parse tree, each lambda node will have a reference to its symbol table. Similarly for each let, letrec, let*, etc. node. The symbol table entry for a defined symbol will point to the root node of the value’s parse tree. Example: If a procedure is being defined, then the symbol table entry for the procedure name will point to the root node of the lambda parse tree. _
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 25 When Parsing is Done At the conclusion of parsing: Each defined symbol will have an entry in the level 1 symbol table. The symbol table entry for each procedure name will point to the lambda expression’s parse tree. _
SJSU Dept. of Computer Science Spring 2014: April 7 CS 152: Programming Language Paradigms © R. Mak 26 (define proc (lambda (a b) (let ((sum (+ a (func b)))) sum))) (define func (lambda (a) (let* ((b 2) (prod (* a b))) prod))) Parse Trees and Symbol Tables lambda a func definelet* prod 2 b b a * lambda b a proc define sum b func a + let sum a b Level 2 sum Level 3 b prod Level 3 a Level 2 (define x 2) (define y 3) (proc x y) Top-Level Symbol Table xy proc func The parse trees and the symbol tables are interlinked.