CIT 594 Assignment 6: Simple functional programming language
Spring 2013, David Matuszek
| Minor change in tokenizer: |
|---|
As mentioned in class, you need to enhance the provided What I didn't say is that you also need to add a new type to |
| Minor changes in grammar: |
|---|
Changed from The same error was made in the definition of factor; I've now changed the first alternative from |
Implement a very small programming language. The language needs a name; we'll call it Funl.
You will need a tokenizer. Use this one: tokenizer.zip. You should replace the list of keywords (the language for this assignment has only six). You may make any other necessary modifications to the tokenizer, but try to keep changes to a minimum.
Your first task is to write a program to parse programs in Funl, creating abstract syntax trees (ASTs), according to the BNF below. Use your Tree class from Assignment 3. Name your new class Parser.
| BNF | Tree representation |
|---|---|
<program> ::= <function definition> { <function definition> } |
Do not construct a tree for a <program>. Instead, construct an AST for each <function definition>, then remove the AST from the stack and save it in a . The key will be the function name, and the value will be the entire function definition (including the name). |
<function definition> ::=
"def" <name> { <parameter> } "=" <expressions> "end" |
The constructed AST will have Example: def
/ | \
foo | \
$seq $seq
/ \ |
x y +
/ \
x y |
<parameter> ::= <name> |
The tree consists of a single node whose value is the name found in the Funl program. |
<expressions> ::= <expression> { "," <expression> } |
Parsing <expressions> results in a tree whose root is $seq and whose children are the expressions, in the order of occurrence. This is true even when there is only one expression. |
<expression> ::= <value definition>
| <term> { <add_operator> <term> } |
An <expression> is represented the tree for one of the two alternatives. For the second alternative, if the expression consists of a single term, then use the tree for that term. Otherwise use a tree whose root is the last add operator, the second child is the last term, and the right child is the tree representing the rest of the expression. Example: -
/ \
+ d
/ \
- c
/ \
a b
|
<value definition> ::= "val" <name> = <expression> |
A <value definition> is a tree with root val, first child is the (actual) name, and second child is a tree representing the term.. |
<term> ::= <factor> { <multiply_operator> <factor> } |
If the term is just one factor, it is represented by the tree for that factor. Otherwise it is represented by a tree whose root is the last multiply operator, the second child is the last factor, and the right child is the tree representing the rest of the expression. Example: *
/ \
* c
/ \
a b
|
<factor> ::= <name> [ "(" [ <expressions> ] ")" ] |
The tree is one of:
|
<add_operator> ::= "+" | "-" |
A single node whose value is "+" or "-". |
<multiply_operator> ::= "*" | "/" |
A single node whose value is "*" or "/". |
Some explanations regarding the AST are in order.
25 should be represented as a single node of the AST. It would be silly to represent it as an expression node with a single child term which has a single child factor which has a single child 25. The same goes for variable names. Don't add nodes you don't need.$seq node, even if there is only a single expression. This doesn't add much to the AST and helps to avoid special cases.seq and call for function names or variable names. To avoid confusion with these, we spell the internal nodes $seq and $call with a dollar sign, as these are not legal Funl names. We don't need to add dollar signs to keywords (such as def and if), because the programmer cannot use these as names.double), even if written as integers.Write a REPL and interpreter for Funl. Details are here.
If you want to get an early start on the REPL, here's what it is supposed to do: Repeatedly read an <expression> from the user, parse it, call the interpreter to compute the value of the expression, print the value. The REPL should do very basic error handling (i.e. not crash), and there should be some way to quit.
6am Thursday, March 21 Tuesday, March 26, via Canvas. Zip your entire Java Project, including Tree and Tokenizer and related classes, along with your Parser and Interpreter classes.