594 RoboTalk Recognizer
Spring 2007, David Matuszek
In this assignment I define a BNF grammar for a small programming language, which I am calling "RoboTalk."
Your assignment is to write a recognizer (
for productions (rules) in that grammar. A recognizer is a program that,
given a stream of tokens and a nonterminal, decides whether or not that stream
of tokens is an instance of that nonterminal. The meaning of the production,
if any, is outside the scope of this assignment.
There will be no "main program." Instead, you should have JUnit tests for
every nonterminal, and every definition of that nonterminal, defined in the
grammar. When your test methods can accept every correct input, and
reject every incorrect input (either by reporting
false or throwing an exception),
you are done.
For example, one of the nonterminals is
<factor> ::= <NAME> | <NUMBER> | "(" <expression> ")"
The stream of tokens
SYMBOL:( NUMBER:2 SYMBOL:+ NUMBER:3 SYMBOL:)
(the tokenization of the String
"(2+3)") is recognized
by this production.
There is a nonterminal called
<program>. For this assignment, there is nothing
special about this nonterminal.
This is a very simple class. It defines an enum
Token.Type.EOF; these denote words, integers, punctuation marks, end-of-line, and end-of-file, respectively. It has two fields,
which, for easy access, are not
This is starter code for your assignment. It recognizes
. It has some helper classes which you should get familiar with (generate and read the Javadoc!), and, most importantly, it has methods
pushBack(), which hide the ugly details of using a
More starter code.
This is just a
RuntimeExceptionwith a more specific name.
The complete grammar is on a separate page for easy reference.
For each nonterminal
nt in the grammar (excluding
<EOL>), you should have one
Name your methods the same as the nonterminals they recognize, but with the
is- prefix. See Recognizer.java for
examples, which has the required methods for
<multiplyOperator>, plus some very useful (private)
Provide complete JUnit tests for all public methods. Write Javadoc comments for all non-private methods.
Caution: Some definitions contains braces
} as metasymbols, and
<block> also uses
"}" as terminals. Don't
get these confused!
To get started, do the following:
RecognizerTest.javainto a new project in Eclipse.
Recognizerclass, add stubs for each method you will need. This will be one method stub for every nonterminal (
<move>, etc.). Note that you do not need method stubs for
<EOL>, because your tokenizer provides these. You also don't need stubs for my provided methods.
Recognizerclass. Have it generate all the test method stubs for you.
RecognizerTest.javafile into yours. This may involve replacing some constructors or method stubs.
Here's why I suggest the above. If you start by importing my
class, Eclipse won't add test method stubs to it (or if it will, I haven't
yet discovered how). This would mean you would have to write all the test method
stubs by hand, which is boring and error prone. If instead you let Eclipse generate
RecognizerTest.java class, it will be correct and complete, and you can
add code from the provided RecognizerTest.java class simply by cutting and pasting.
The easiest way to do this assignment is as follows:
RecognizerTest.javainto an actual test. For example,
<comparator>doesn't depend on anything else, but
<comparator>, so write the test code for
Tuesday, February 20, before midnight. Turn in your program via blackboard, and follow these conventions: