11. Symbols II

Detailed instructions for creating symbol mappings.

Helper Functions

The parser produces (keyword "int") but you just want "int". Write a function unwrap to extract the strings from keyword and identifier.

(check-expect (unwrap '(keyword "int"))
              "int")
(check-expect (unwrap '(identifier "nums"))
              "nums")

To help find bugs later, you can issue warning if you don’t unwrap anything.

(displayln (format "warning: did not unwrap ~a" var))

You can also use the shortcut ~a function.

The recursive version of this unwrap-recursive applies unwrap recursively every time it finds a list?. Using one of the examples below:

(check-expect (unwrap-recursive VDex)
              '(varDec "int" "a" "b"))

Loading Symbols

Use a single variable to represent an entire symbol table. If you want to hold more than one piece of information, make it a struct or a list. On this page, we will use all-symbols to be the variable that holds the symbol table.

Write a function to update the symbol table based on one line of Jack code.

(update-symbol-table! all-symbols code-line)

Examples:

  • Three variables added to the symbol table in the “class” scope. The variables "x", "y", and "z" are numbered 0, 1, and 2 in the this segment.

      (define cv1
        '(classVarDec (keyword "field") (keyword "int")
                      (identifier "x") (identifier "y") (identifier "z")))
    
  • A single variable “light” is added to the class scope. It is in the static scope and is variable number 0.

     (define cv2
       '(classVarDec (keyword "static") (keyword "boolean") (identifier "light")))
    
  • Variables in a parameterList should go into the args segment.

      (define PLex
        '(parameterList ((keyword "int") (identifier "n"))
                        ((keyword "boolean") (identifier "bv"))))
    
  • Variables in a varDec should go into the local segment.

      (define VDex
        '(varDec (keyword "int") (identifier "a") (identifier "b")))
    

Notes

The list '(varDec (keyword "int") (identifier "cnt")) is internally represented by (list 'varDec (list 'keyword "int") (list 'identifier "cnt")). Use the latter form if using match.

Ways to Match

Here are some ideas for matching.

  1. Write everything out with lists.

     (match '(keyword "int")
       [(list 'keyword type))    type])
     => "int"
    
  2. Use quasiquote and unquote (the backwards single quote and the comma).

     (match '(keyword "int")
       [`(keyword ,type)        type])
     => "int"
    
  3. Ellipses make a list of 0 or more repetitions of the preceding pattern.

     (match VDex
        [`(varDec ,type ,ids ...)  ids])
     => (list (identifier "a") (identifier "b"))
    
  4. Unwrapping everything before matching is also a viable strategy.

     (define uPL (unwrap-recursive PLex))
     (match uPL
       [`(parameterList (t1 v1) (t2 v2))  (list t1 t2)])
     => (list "int" "boolean")
    
Last modified May 31, 2025: Chapter 11 web site updates. (58262d9)