Skip to content
Snippets Groups Projects
ExpressionParserTest.java 5.73 KiB
package fr.insarennes.nperier.minichamo.parsing;

import fr.insarennes.nperier.minichamo.errors.ParsingException;
import fr.insarennes.nperier.minichamo.language.Context;
import fr.insarennes.nperier.minichamo.language.definition.ValueDef;
import fr.insarennes.nperier.minichamo.language.expressions.ConditionExpression;
import fr.insarennes.nperier.minichamo.language.expressions.Expression;
import fr.insarennes.nperier.minichamo.language.expressions.NameExpression;
import fr.insarennes.nperier.minichamo.language.expressions.VarExpression;
import fr.insarennes.nperier.minichamo.language.expressions.base.*;
import fr.insarennes.nperier.minichamo.language.typing.BuiltinType;
import fr.insarennes.nperier.minichamo.language.typing.GenericType;
import fr.insarennes.nperier.minichamo.lexing.Lexer;
import fr.insarennes.nperier.minichamo.lexing.tokens.TokenType;
import fr.insarennes.nperier.minichamo.utils.SymbolPosition;
import fr.insarennes.nperier.minichamo.utils.TokenPeekIterator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class ExpressionParserTest {

    private Context ctx;

    @BeforeEach
    public void before() {
        ctx = new Context();
    }

    @Test
    public void baseTypesTest() {
        TokenPeekIterator it = new Lexer("();; 1;; 1.1;; true;; \"bonjour\";; 'a';;").wrap();
        Expression e = ExpressionParser.parse(it, ctx);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(new UnitExpression(), e);
        Assertions.assertEquals(BuiltinType.unit(), e.getType());
        Assertions.assertEquals(e, e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        e = ExpressionParser.parse(it, ctx);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(new IntExpression(1), e);
        Assertions.assertEquals(BuiltinType.integer(), e.getType());
        Assertions.assertEquals(e, e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        e = ExpressionParser.parse(it, ctx);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(new FloatExpression(1.1), e);
        Assertions.assertEquals(BuiltinType.floating(), e.getType());
        Assertions.assertEquals(e, e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        e = ExpressionParser.parse(it, ctx);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(new BoolExpression(true), e);
        Assertions.assertEquals(BuiltinType.bool(), e.getType());
        Assertions.assertEquals(e, e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        e = ExpressionParser.parse(it, ctx);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(new StringExpression("bonjour"), e);
        Assertions.assertEquals(BuiltinType.str(), e.getType());
        Assertions.assertEquals(e, e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        e = ExpressionParser.parse(it, ctx);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(new CharExpression('a'), e);
        Assertions.assertEquals(BuiltinType.character(), e.getType());
        Assertions.assertEquals(e, e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        Assertions.assertFalse(it.hasNext());
    }

    @Test
    public void varExpressionTest() {
        ValueDef vd = new ValueDef("var", SymbolPosition.begin(), BuiltinType.integer());
        vd.setExpression(new IntExpression(10));
        ctx.addVariable(vd);
        TokenPeekIterator it = new Lexer("var;;").wrap();
        Expression e = ExpressionParser.parse(it, ctx);
        Expression exp = new VarExpression(vd);
        Assertions.assertNotNull(e);
        Assertions.assertEquals(exp, e);
        Assertions.assertEquals(new IntExpression(10), e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        Assertions.assertFalse(it.hasNext());
    }

    @Test
    public void nameExpressionTest() {
        TokenPeekIterator it = new Lexer("var;;").wrap();
        Assertions.assertFalse(ctx.hasVariable("var"));
        Expression e = ExpressionParser.parse(it, ctx);
        Expression exp = new NameExpression("var", new GenericType("a"));
        Assertions.assertEquals(exp, e);
        ValueDef vd = new ValueDef("var", SymbolPosition.begin(), new GenericType("int"));
        vd.setExpression(new IntExpression(2));
        ctx.addVariable(vd);
        Assertions.assertEquals(vd.getExpression(), e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        Assertions.assertFalse(it.hasNext());
    }

    @Test
    public void simpleConditionTest() {
        TokenPeekIterator it = new Lexer("if true then 1 else 2;;").wrap();
        Expression e = ExpressionParser.parse(it, ctx);
        Expression exp = new ConditionExpression(
                new BoolExpression(true),
                new IntExpression(1),
                new IntExpression(2)
        );
        Assertions.assertNotNull(e);
        Assertions.assertEquals(exp, e);
        Assertions.assertEquals(new IntExpression(1), e.evaluate(ctx));
        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
        Assertions.assertFalse(it.hasNext());
    }

    @Test
    public void badBooleanConditionTest() {
        TokenPeekIterator it = new Lexer("if 1 then 1 else 0;;").wrap();
        Assertions.assertThrows(ParsingException.class, () -> ExpressionParser.parse(it, ctx));
    }

    @Test
    public void badResultsConditionTest() {
        TokenPeekIterator it = new Lexer("if true then \"lol\" else 0;;").wrap();
        Assertions.assertThrows(ParsingException.class, () -> ExpressionParser.parse(it, ctx));
    }

}