![]() |
|
CISC323: Introduction to Software Engineering (Winter 2003)
Assignment 3 (Design Patterns)Due Fri, March 14 |
The purpose of this assignment is to give you practise with design patterns, in particular, the visitor pattern. Other concepts that you will learn about along the way are grammars, parsing, and parser generation.
<expr> ::= <sum>The grammar consists of productions. Each production has a left-hand side and a right-hand side, separated by ::=. The right-hand side is a finite, possibly empty sequence of three different kinds of symbols:
<sum> ::= <term> ( ("+" | "-") <term> )*
<term> ::= <atom> ( ("*" | "/") <atom> )*
<atom> ::= <nat> | "(" <sum> ")"
<nat> ::= <digit> ( <digit> )*
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<atom> ::= <nat> | "(" <sum> ")"stands for the two productions
<atom> ::= <nat>The production
<atom> ::= "(" <sum> ")"
<nat> ::= <digit> ( <digit> )*stands for the infinite set of productions
<nat> ::= <digit>The production
<nat> ::= <digit> <digit>
<nat> ::= <digit> <digit> <digit>
...
<sum> ::= <term> ( ("+" | "-") <term> )*stands for the infinite number of productions:
<sum> ::= <term>Every grammar typically contains a non-terminal symbol that is not contained in the right-hand side of any production. That non-terminal is called start symbol. The above grammar has the start symbol <expr>.
<sum> ::= <term> "+" <term>
<sum> ::= <term> "-" <term>
<sum> ::= <term> "+" <term> "+" <term>
<sum> ::= <term> "+" <term> "-" <term>
<sum> ::= <term> "-" <term> "+" <term>
<sum> ::= <term> "-" <term> "-" <term>
<sum> ::= <term> "+" <term> "+" <term> "+" <term>
...
Parse trees, parsing, parsers, and parser generators Given a grammar, we can determine which words the grammar generates. We do that by building a parse-tree. A parse-tree is build from the start symbol of the grammar by choosing a leaf in the tree that contains a non-terminal, finding a production that has that non-terminal on the left-hand side, and then adding the terminal and non-terminal symbols occurring on the right-hand side of that production as new children of that leaf. The parse-tree is complete if all its leaves contain terminal symbols only. In that case, the sequence of leaves read from left to right constitutes the expression generated by the tree. An expression is said to be syntactically correct with respect to some grammar if there is a parse tree for that expression that was built using the grammar. The process of building a parse tree for an expression is also called parsing. The following picture illustrates the process of parsing by creating a parse tree for the expression 2 * 3 + 4.
A parser is a tool that takes a sequence of symbols as input and
then attempts to find a parse tree for it. Every compiler contains a parser.
If program P is contained in file f, the parser opens f, reads in the sequence
of characters in f, and attempts to build a parse tree for P using the grammar
of the programming language. If P is syntactically correct, its parse tree
is handed off to the later stages of the compiler like the optimizer and
code generator. If P is not syntactically correct, an error is reported.
A parser generator is a tool that takes a grammar as input and generates
a parser for the language defined by the grammar. In other words, it outputs
a parser for that language. Parser generators are used a lot in industry.
Examples for parser generators include YACC (generates C code), Cup (generates
Java code), and JavaCC (generates Java code).
Question 1 For each of the following expressions, decide whether it is syntactically correct with respect to the grammar above. If your answer is positive, also draw the parse tree of that expression.
JavaCC In this assignment, you will be given code that you will have to extend. The code contains a parser. That parser was generated using the parser generator JavaCC (Java Compiler Compiler). The parse tree created by the parser supports the visitor pattern. For this assignment, you don't need to run JavaCC. You just use the parser. If you're interested, here's more information on JavaCC.
Question 2 It is your task to extend that driver program ExprMain.java to perform the final 4 actions on the input expression. More precisely, for each of the following tasks you have to write a visitor that implements the interface in Visitor.java and performs that task:
Maximal nesting of parentheses in expression: 2
Number of operators in expression: 4
There are no occurences of division by zero in the expressionHowever, when run on 2 + 4 / 0 - 3 your visitor should print something like
There are occurences of division by zero in the expression
The value of the expression is: 6You should interpret the operators +, -, *, and / by the corresponding Java operators on integers. For instance, the evaluation of 3 / 2 should return 1.
System.out.println("class: " + n.getClass());would print the type of the node n. Java also offers the instanceof infix predicate that returns true if an object has a given type. For instance,
if (n instanceof T) System.out.println("yes");prints "yes" if n is of type T, and "no" otherwise.
else System.out.println("no");
Juergen Dingel
Last modified: Thu Feb 20 09:07:45 EST 2003