CIT 594 Assignment 5: Recognizer for "Bugs" Language
Spring 2008, David Matuszek


General Idea:

In this assignment I define a BNF grammar for a small programming language, which I am calling Bugs.

Your assignment is to write a recognizer (class 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>, defined by

<factor> ::= <function call> | <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.

Supplied files:

This class defines an enum Token.Type with values Token.Type.KEYWORD, Token.Type.NAME, Token.Type.NUMBER, Token.Type.SYMBOL,Token.Type.ERROR, Token.Type.EOL, and Token.Type.EOF; these denote keywords, words, numbers, punctuation marks (including operators), errors, end-of-line, and end-of-file, respectively. It has two fields, Token.Type type and String value which, for easy access, are not private.

This is starter code for your assignment. It recognizes <arithmetic expression>, <factor>, <term>, <add operator>, and <multiply operator>. It has some helper classes which you should get familiar with (generate and read the Javadoc!), and, most importantly, it has methods Token nextToken() and pushBack(), which hide the ugly details of using a StreamTokenizer. You should familiarize yourself with all the "helper" methods--they are useful!

More starter code.

This is just a RuntimeException with a more specific name.



The complete grammar is on a separate page for easy reference.

For each nonterminal xxx in the grammar (excluding <NAME>, <NUMBER>, <SYMBOL>, and <EOL>), you should have one public boolean isXxx() method. Name your methods the same as the nonterminals they recognize, but with the is- prefix. See for examples, which has the required methods for <arithmeticExpression>, <term>, <factor>, <addOperator>, and <multiplyOperator>, plus some very useful (private) utility methods.

Provide complete JUnit tests for all public methods. Write Javadoc comments for all non-private methods.

Caution: Some definitions contains braces { and } as metasymbols, and some definitions use "{" and "}" as terminals. Don't get these confused!

Recommended approach:

The easiest way to do this assignment is as follows:

  1. Create stubs for all the unwritten Recognizer methods, and create JUnit tests for those methods.
  2. Pick some unwritten method that doesn't depend on other unwritten methods, and turn the test method stub for it into an actual test. For example, <comparator> doesn't depend on anything else, but <expression> depends on <comparator>, so write the test code for <comparator> first.
  3. Run the test. It should fail. Make certain that it does. (If it doesn't, there may be a problem with your test.)
  4. Write the code for the method you are testing (that is, fill in the method stub in the Recognizer class).
  5. Test and debug, test and debug, until your test passes. If you wrote adequate tests, you should be done with this method. If your tests pass and you know the method isn't finished, add a test that fails.
  6. Repeat until all methods have been coded.

Due date:

Thursday, February 28, before midnight. Zip up the directory containing your files and submit the .zip file via blackboard.