| CIT 594 Notes on Recognizer
Assignment Spring 2004, David Matuszek |
Correction to RecognizerTest.testExpression()
In my RecognizerTest, my method testExpression()
includes the following:
try {
assertFalse(r6.expression()); fail();
assertFalse(r7.expression()); fail();
} catch (ParseException e) {
}
Charlie Chambers points out that if r6.expression() correctly
throws an exception, then r7.expression() will never be tested.
The correct code is:
try {
assertFalse(r6.expression()); fail();
} catch (ParseException e) {
}
try {
assertFalse(r7.expression()); fail();
} catch (ParseException e) {
}
Thanks, Charlie! Extra credit for this.
Name change: ParseException ->
LogoParseException
Before you create your own Exception type, you should always look around to
see if there's a provided one that you can use instead. I should have done that,
but I didn't, and it turns out that there is already a class java.text.ParseException.
Unfortunately we can't use that class, because it's a checked exception (it
extends Exception), and we need an unchecked exception (one that
extends RuntimeException). Also, java.text.ParseException
doesn't have the usual set of constructors, and lacks the one that I use.
While it is perfectly legal to write a class with the same name as a Sun-provided class, it isn't a good idea, so I'm changing the name.
To create this class, use File -> New -> Class, and fill in the
Name LogoParseException. For the Superclass, type
in java.lang.RuntimeException. Make sure Constructors from superclass
is checked, and click Finish. Eclipse generates the entire class for
you. The only thing left to do is to remove the lines that say , otherwise these will show
up in Eclipse's to do list.
Required method names:
Please use these exact method names in your Recognizer.java class:
block()comparator()move()colorName()condition()procedure()command()eol()variable()
I have provided the name() and number() methods for
you. (In one place in the syntax I inconsistently used <integer>
instead of <number>. This won't affect you, because you will
only need the higher-level nonterminal <expression>.)
It is essential to name things exactly as specified, otherwise you aren't fulfilling the assignment requirements, and our JUnit tests won't work with your code.
Minor [optional] improvements to test method:
I have a method to test whether the Tokenizer is in the "correct place"
in the test string--that is, whether subsequent calls to Tokenizer actual
will return the tokens represented by String rest. You call this
method with the Tokenizer and the desired remainder of the String, for example,
.
This can be improved in two ways:
private void remainder(Recognizer recognizer,
String rest) and add the line Tokenizer actual = recognizer.tokenizer; remainder(r6.tokenizer,
"+") with simply remainder(r6, "+") . if (expectedToken.getType() == Token.EOI)
break; remainder(r5, "* ((5 - 3) * 4) / 6 + (8)")
you can abbreviate this to, say, remainder(r5, "* ((") .