import junit.framework.TestCase;


/**
 * @author David Matuszek
 * @version Jan 30, 2004.
 */
public class RecognizerTest extends TestCase {

    Recognizer r0, r1, r2, r3, r4, r5, r6, r7, r8;
    /**
     * Constructor for RecognizerTest.
     * @param arg0
     */
    public RecognizerTest(String arg0) {
        super(arg0);
        r0 = new Recognizer("2 + 2");
        r1 = new Recognizer("");
    }

    /*
     * @see TestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        r0 = new Recognizer("");
        r1 = new Recognizer("250");
        r2 = new Recognizer("hello");
        r3 = new Recognizer("(xyz + 3)");
        r4 = new Recognizer("12 * 5 - 3 * 4 / 6 + 8");
        r5 = new Recognizer("12 * ((5 - 3) * 4) / 6 + (8)");
        r6 = new Recognizer("17 +");
        r7 = new Recognizer("22 *");
        r8 = new Recognizer("#");
    }

    public void testRecognizer() {
        r0 = new Recognizer("");
        r1 = new Recognizer("2 + 2");
    }

    public void testExpression() {
        assertTrue(r1.expression());
        assertTrue(r2.expression());
        assertTrue(r3.expression());
        assertTrue(r4.expression());
        assertTrue(r5.expression());

        assertFalse(r0.expression());
        assertFalse(r8.expression());

        try {
            assertFalse(r6.expression());
            fail();
        }
        catch (LogoParseException e) {
        }
        try {
            assertFalse(r7.expression());
            fail();
        }
        catch (LogoParseException e) {
        }
    }

    public void testTerm() {
        assertFalse(r0.term()); // ""

        assertTrue(r1.term()); // "250"

        assertTrue(r2.term()); // "hello"

        assertTrue(r3.term()); // "(xyz + 3)"
        remainder(r3, "");

        assertTrue(r4.term());  // "12 * 5 - 3 * 4 / 6 + 8"
        assertEquals(new Token("-", Token.SYMBOL), nextToken(r4));
        assertTrue(r4.term());
        remainder(r4, "+ 8");

        assertTrue(r5.term());  // "12 * ((5 - 3) * 4) / 6 + (8)"
        assertEquals(new Token("+", Token.SYMBOL), nextToken(r5));
        assertTrue(r5.term());
        remainder(r5, "");
    }

    public void testFactor() {
        assertTrue(r1.factor());
        assertTrue(r2.factor());
        assertTrue(r3.factor());
        assertTrue(r4.factor()); remainder(r4, "* 5 - 3 * 4 / 6 + 8");
        assertTrue(r5.factor()); remainder(r5, "* ((5");
        assertTrue(r6.factor()); remainder(r6, "+");
        assertTrue(r7.factor()); remainder(r7, "*");

        assertFalse(r0.factor());
        assertFalse(r8.factor()); remainder(r8, "#");
    }

    public void testAdd_operator() {
        Recognizer r = new Recognizer("+ - $");
        assertTrue(r.addOperator());
        assertTrue(r.addOperator());
        assertFalse(r.addOperator());
        remainder(r, "$");
    }

    public void testMultiply_operator() {
        Recognizer r = new Recognizer("* / $");
        assertTrue(r.multiplyOperator());
        assertTrue(r.multiplyOperator());
        assertFalse(r.multiplyOperator());
        remainder(r, "$");
    }

//  ----- "Helper" methods

    private void remainder(Recognizer recognizer, String rest) {
        Tokenizer actual = recognizer.tokenizer;
        Tokenizer expected = new Tokenizer(rest);
        while (expected.hasNext()) {
            Token actualToken = actual.next();
            Token expectedToken = expected.next();
            if (expectedToken.getType() == Token.EOI) break;
            assertEquals(expectedToken, actualToken);
        }
    }

    private Token nextToken(Recognizer r) {
        return r.tokenizer.next();
    }
}

