Revise interp.js (and, if needed, classes.js) in order to implement an interpreter for the simple language defined below. Your interpreter should pass all the test cases below, and more generally should implement the semantics specified here for the calculator language (we reserve the right to run tests beyond those given). Turn in your files (zip them together if you are updating both) on Canvas by 11:59pm on February 6, 2020. This is an individual assignment. You may start with the OO-style or functional-style starter code developed in class.
In this exercise, you will write an interpreter for a simple calculator language. Let’s begin by taking a look at the syntax of expressions:
Concrete Syntax | JS AST | |
---|---|---|
e ::= |
n
e1
+ e2
e1
- e2
e1
* e2
e1
/ e2
e1
^ e2
|
new Num( n)
new Add( e1, e2)
new Sub( e1, e2)
new Mul( e1, e2)
new Div( e1, e2)
new Pow( e1, e2)
|
n ::= |
42 |
1+2*3
is a valid
expression in our language.
The right-hand column of the table above shows the format of the ASTs that are produced by
our parser. The classes that we use to represent AST nodes (Num
,
Add
, Sub
, etc.) are declared in this
file.
1+2*3
, we evaluate
the JavaScript expression
new Add(new Num(1), new Mul(new Num(2), new Num(3)))
. The resulting tree
is shown on the right. Note that the table at the top of this page provides the names
of the fields that can be used to access the components of each AST node: Add
nodes have fields called e1
and e2
, Num
nodes
have a field called n
, and so on. These fields are the edges in the tree
diagram.
To make our calculator language a little more interesting, let’s extend it with support for variables. We can do this by defining a program to be a sequence of expressions, and adding new syntax for referencing and assigning to variables:
JS AST | Semantics | ||
---|---|---|---|
; e2; …;
en
|
new Prog([ e1, e2,
…, en]) |
|
|
e ::= |
n
e1
+ e2
…
x
x
= e |
new Num( n)
new Add( e1, e2)
…
new Ref( x)
new Assign( x, e)
|
0 if |
sum |
"sum" |
8
.
The AST for this example program is shown on the right. Note that the Prog
node has a single field whose value is an array of expression ASTs —
Assign
s, Add
s, etc. That field is called es
because
in our description of the abstract syntax (in the table above) that array was written as
[
e1,
e2,
…,
en]
e
”s. Similarly, if it had been an array of identifiers,
[
x1,
x2,
…,
xn]
xs
. We will use this convention throughout the course.
Your job is to write an interpreter for our calculator language. The entry-point to
your interpreter will be a function called interp
that takes the AST of
a program and returns the value that it produces:
We have included a file called interp.js where you should do all your work. Also, at the bottom of this page, you will see some unit tests for your implementation — these will run automatically every time you refresh the page. Last but not least, we have also provided a “playground” where you can type in programs, see their corresponding ASTs, and see what value your interpreter produces.
Here are a few unit tests to get you started. You can (and should!) add your own test cases, too. How? Just edit tests.js; the format is pretty self-explanatory.