package net.ranides.assira.grammar;

import net.ranides.assira.grammar.impl.G4ParserInterpreter;
import net.ranides.assira.io.ResourceUtils;
import org.junit.Test;

import java.io.IOException;
import java.util.NoSuchElementException;

import static net.ranides.assira.junit.NewAssert.assertThrows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class LabelTest {

    @Test
    public void labelForExpressions() throws IOException {
        G4Parser parser = G4Parser.builder().resource("LabelTest.g4").build();

        G4Node expr1 = parser.parse("manyLabels", "! ( 2 3 + 4 + 5 6 !");
        assertEquals("2", expr1.child("@num1").text());
        assertEquals("3", expr1.child("@num2").text());
        assertEquals("5", expr1.child("@num4").text());
        assertEquals("6", expr1.child("@num5").text());

        G4Node expr2 = parser.parse("functionCall", "hello(1,2,3,4)");
        assertEquals("1,2,3,4", expr2.child("@args").text());

        G4Node expr3 = parser.parse("withToken", "((16))");
        assertEquals("16", expr3.child("@value").text());

        testLabelExpression(parser, "withLabels");
        testLabelExpression(parser, "withoutLabels");
        testLabelExpression(parser, "withoutLabelsRecursive");
    }

    private void testLabelExpression(G4Parser parser, String rule) {

        G4Node expr2 = parser.parse(rule, "-5");
        assertEquals("5", expr2.child("@a").text());
        assertThrows(NoSuchElementException.class, () -> {
            expr2.child("@b");
        });

        G4Node expr3 = parser.parse(rule, "(1+5) & 8");
        assertEquals("(1+5)", expr3.child("@a").text());
        assertEquals("8", expr3.child("@b").text());

        G4Node expr4 = parser.parse(rule, "(1+5) * 8");
        assertEquals("(1+5)", expr4.child("@b").text());
        assertEquals("8", expr4.child("@a").text());

        G4Node expr5 = parser.parse(rule, "(1+5) + 8");
        assertEquals("(1+5)", expr5.child("@x").text());
        assertEquals("8", expr5.child("@y").text());

        G4Node expr6 = parser.parse(rule, "? 1 2 3");
        assertEquals("1", expr6.child("@p").text());
        assertEquals("2", expr6.child("@q").text());
        assertEquals("3", expr6.child("@r").text());
    }

    // @todo G4Parser should have "coverage mode" for each rule and rule branch


}