Final Project: FAQ
Answers to your commonly asked questions.
General Code Questions
- What code can I change?
- Any and all of it. Make sure you understand why you are changing it and use branching and commits judiciously so you can roll back.
- These variable names/method names/... don't make sense to me,
- After you understand their purpose, rename them with a descriptive name that would be more helpful.
- How does a switch statement work?
- Switch statement tutorial
- I'm overwhelmed. Where should I start?
- Try implementing a unary function and its test (in the opposite order -- first the test case, then the unary function).
Tokenization
- I know I need to handle quoted strings for the images, but when I try to get the string, I only get the quote.
- This requires understanding a bit about
the StreamTokenizer
class, which is used by the Tokenizer class. Look what it says in
the
nextToken
aboutttype
and in thettype
documentation about quoted strings. - What does
tokenNameToToken
represent? - First, see where it is updated/used. Right click on the name,
then go to References and select Project. One place
it's being updated in is
the
initBuiltinFunctionTokenMappings
. That name is probably more descriptive than the map's name. It maps the name of the function to the Token class that represents the function. It is used to distinguish between a known function name and an identifier (a variable). - The minus sign is included in the variable name when I try to
evaluate the expression
x-y
. This isn't a problem with the other operators. -
Here is a terrible hack to solve this. I think this should
usually work (and not break something else).
In
Tokenizer
'sparseTokens
method, add this statement (and its comment) as the first line:
// - is seen as a numeric character. If we try to parse, e.g., x-y, // it is seen as one string "x-y". See StreamTokenizer documentation about // handling words. So, our imperfect solution is to always add // a space before a minus sign. Negative numbers will still be // seen as numbers, and the space will mark the end of a word. s = s.replace("-", " -");
Here's what is happening: the
StreamTokenizer
looks at characters and tries to figure out what to do with them. According to the documentation, "A word token consists of a word constituent followed by zero or more word constituents or number constituents." So, when theStreamTokenizer
sees thex
inx-y
, it grabs every word or numeric constituent that follows. We need the minus character to be a number constituent because we want to be able to parse numbers, e.g., -1. If we try to make the minus sign an "ordinary" character, we can no longer parse negative numbers. So, since this really isn't the focus of the assignment, we'll go with the imperfect solution provided above. (Although I am open to hearing proposals of better solutions.)
Parsing
- The order of operations constants don't make sense. GROUPING should have high precedence.
- You're learning to try to read someone else's code. Note that
GROUPING is not yet used, and this is partial code. I am not sure
if it would be used. It seems like it's placed for the parentheses
of a function, but I don't know what the original goals of this
code were. You can and should change this code to be whatever
makes the most sense to you--well, and has good design.
Note that, if you have your automated JUnit tests, you should be able to make changes to this code and confirm that you are getting correct results fairly easily.
- How should parsing an assignment statement work?
-
Consider each part separately for some sample expressions, e.g.,
a=x
anda=floor(x)
. Write appropriate JUnit tests for each step.- Tokenizing: What should the tokens be for each example?
- Parsing: What should the result of infix to postfix be? What analyzers need to be involved? What should the expression tree look like?
- Evaluating: What is the result of evaluating an assignment statement?
Note that you should not handle this specially separately. You have all of this infrastructure, so add to the parser to handle assignments.
Consider what functionality/classes exist that I can use/leverage? You may need to do some refactoring to make it all work together well.
Continuing with the above examples, what should happen when the user enters
a
ora/x
?Finally, what erroneous assignment statements should you handle, i.e., display an error message?
Semantic Analyzer
- I made my code for the negate/inversion (!) operator and updated all the right files, but my code isn't finding its semantic analyzer.
- This one is tricky.
!
is a comment for the properties file. You'll need to escape the character (using the escape character:\
) in the properties file.
Evaluating
- How do I implement evaluate something?
- Make sure you check
ReferenceForExpressionEvaluations
to see if there is anything helpful there. - How should ImageWrap and ImageClip work?
- See if this helps:
You should check out
Pixmap
for its code related to images. (You don't need to use a Pixmap object itself -- that's more than what you need; just copy and adapt the relevant parts in your code.Make sure to write test cases for each part (tokenizing, parsing, evaluation). Make a simple test image that will be easy to test.
- I keep getting errors about not being able to find the image file, but the image file is there.
- One trick to use is to get a
File
object using the filename and check what its path is (getAbsolutePath()). Does that path match what you expected?You can either change the String that you pass in to make it be the appropriate path, or add an image directory in your image code to say where to look for images.
Error Handling
- If there is an error when evaluating an expression, the next [valid] expression evaluated doesn't work either. But, if you press the button again, it works.
- Add some print statements to try to figure out what's happening. Is there something leftover from the erroroneous expression?
Testing
- I wrote my JUnit test, but the test is failing, and the output is a little strange.
- Two things that will make testing easier: overriding
toString
andequals
in the relevant classes that are being compared. - I can't test method X because it's private
- If it's private, is there a method that calls that method that you can test instead?
- How can I test evaluating the ExpressionTreeNodes?
- This should look similar to what we did in class, where we
computed what the resulting RGBColor would be at a specific (x,y)
coordinate. For example:
@Test public void testFloorEvaluation() { Floor myTree = new Floor(new X()); // some straightforward tests assertEquals(new RGBColor(0, 0, 0), myTree.evaluate(.4, -1)); assertEquals(new RGBColor(0, 0, 0), myTree.evaluate(.999, -1)); assertEquals(new RGBColor(-1, -1, -1), myTree.evaluate(-.7, -1)); // test the ints; remember that y's value doesn't matter for (int i = -1; i <= 1; i++) { assertEquals(new RGBColor(i, i, i), myTree.evaluate(i, -i)); assertEquals(new RGBColor(i, i, i), myTree.evaluate(i, i)); } double[] tests = {-.7, -.00001, .000001, .5}; for( double testVal : tests) { double floorOfTestVal = Math.floor(testVal); assertEquals(new RGBColor(floorOfTestVal, floorOfTestVal, floorOfTestVal), myTree.evaluate(testVal, -1)); assertEquals(new RGBColor(floorOfTestVal, floorOfTestVal, floorOfTestVal), myTree.evaluate(testVal, testVal)); } }
GitHub
- Eclipse is saying that there are conflicts in our main branch, and I'm unable to merge my branch.
- Yeah, that happens. Try to resolve the conflicts. You'll need to decide if you want to use that version or your version or maybe do a merge. After resolving the conflicts, stage them for commitment and then commit. Eclipse's User Guide
- My test cases are failing
- Wouldn't it be cool if I could press enter on the text box, and evaluation would happen? How do I do that?
- First, consider that you could enter multiple lines in the text box. But, if you decide to go this route, this links to a simple example of how to make the text field respond to the user pressing enter.