CSC 533: Programming Languages
Spring 2015

HW3: Implementing Sequences and Scopes


The SILLY interpreter you wrote for HW2 provides the basic functionality of a scripting language. For this assignment, you will add two additional features to the language, which will involve creating at least one new class and modifying several existing classes. As part of your submission, you must include a text file named changeLog.txt that identifies each class that you created or modified for this assignment, along with a short note describing the modifications. For example, your file might include: AUTHOR your_name_here CREATED DESCRIPTION -------------- ----------------------------------------------------------- VarDeclaration new class that implements the declaration of one or more local variables in the current scope ... MODIFIED DESCRIPTION -------------- ----------------------------------------------------------- Statement added a case to getStatement to recognize a VarDeclaration Token added "var" to the list of keywords ...


Implementing sequences

Recall that the Output statement from HW2 consists of the word output followed by a single expression. Displaying multiple values requires either concatenating the values together (which is somewhat tedious) or using separate Output statements (which breaks the values across separate lines). You are to modify the Output statement so that instead of taking a single expression, it takes a sequence of expressions enclosed in parentheses. The new grammar rule for Output statements, replacing the rule from HW2, is:

<output> --> 'output' '(' { <expression> } ')'

Note that parentheses are now required, even if there is only one expression to be displayed. Also, it is valid to have no expressions between the parentheses, resulting in a blank line being displayed. For example:

SAMPLE CODE (output in red)
  >>> x = 5
  >>> output ( x )
  5
  >>> output ( )
     
  >>> output ( "x=" x "incr=" ( x + 1 ) )
  "x=" 5 "incr=" 6  


Implementing local variables and scopes

Currently, all of the variables in a SILLY program are in the same, global scope. You are to modify the control statements (If, While and Repeat) so that they define new scopes for variables. That is, statements inside an If, While or Repeat statement are considered to be inside a new, nested scope in which local variables can be declared. A VarDeclaration statement, which declares one or more local variables in the current scope, is defined as follows:

<varDecl> --> 'var' ( <identifier | '(' <identifier> <identifier> { <identifier> } ')' )

Note that parentheses appear only if there is more than one variable being declared in the same VarDeclaration statement. For example:

SAMPLE CODE (output in red)
  >>> x = 6
  >>> repeat 4
        var x
        x = "Dolly"
        output ( "Hello" x )
      end
  "Hello" "Dolly" 
  "Hello" "Dolly" 
  "Hello" "Dolly" 
  "Hello" "Dolly"
  >>> output ( x )
  6  

  >>> word1 = "global1"
  >>> word2 = "global2"
  >>> word3 = "global3"
  >>> if ( word1 =/= word2 )
        var ( word2 word3 )
        word2 = "middle2"
        word3 = "middle3"
        if true
          var word3
          word3 = "inner3"
          output ( word1 word2 word3 )
        end
        output ( word1 word2 word3 )
      end
  "global1" "middle2" "inner3" 
  "global1" "middle2" "middle3"        
  >>> output ( word1 word2 word3 )
  "global1" "global2" "global3" 

To implement nested scopes, you will need to modify the MemorySpace class so that a stack of activation records is maintained (as opposed to a single, global activation record). New methods should be added to the MemorySpace class for beginning a new scope (i.e., pushing a new activation record on the stack) and ending the current scope (i.e., popping the current activation record off the stack). These methods should be called to begin and end the nested scopes when executing a control statement. The storeVariable and lookupVariable methods in MemorySpace will also need to be modified so that they properly access variable values from the stack.

Finally, you will need to implement the varDeclaration statement, which declares one or more variables within the current scope (i.e., puts entries for those variables in the current activation record). Note: attempting to declare a variable that already exists in a given scope (e.g., declaring it twice) should result in a runtime error.