package me.tomassetti.turin.parser;
import com.google.common.collect.ImmutableList;
import me.tomassetti.parser.antlr.TurinParser;
import me.tomassetti.turin.parser.ast.typeusage.BasicTypeUsageNode;
import me.tomassetti.turin.parser.ast.*;
import me.tomassetti.turin.parser.ast.expressions.*;
import me.tomassetti.turin.parser.ast.expressions.literals.IntLiteral;
import me.tomassetti.turin.parser.ast.expressions.literals.StringLiteral;
import me.tomassetti.turin.parser.ast.properties.PropertyDefinition;
import me.tomassetti.turin.parser.ast.properties.PropertyReference;
import me.tomassetti.turin.parser.ast.statements.BlockStatement;
import me.tomassetti.turin.parser.ast.statements.ExpressionStatement;
import me.tomassetti.turin.parser.ast.statements.VariableDeclaration;
import me.tomassetti.turin.parser.ast.typeusage.ReferenceTypeUsageNode;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ParseTreeToAstTest {
private TurinFile basicMangaAst() {
TurinFile turinFile = new TurinFile();
NamespaceDefinition namespaceDefinition = new NamespaceDefinition("manga");
turinFile.setNameSpace(namespaceDefinition);
ReferenceTypeUsageNode stringType = new ReferenceTypeUsageNode("String");
BasicTypeUsageNode intType = new BasicTypeUsageNode("uint");
PropertyDefinition nameProperty = new PropertyDefinition("name", stringType, Optional.empty(), Optional.empty(), Collections.emptyList());
turinFile.add(nameProperty);
TurinTypeDefinition mangaCharacter = new TurinTypeDefinition("MangaCharacter");
PropertyDefinition ageProperty = new PropertyDefinition("age", intType, Optional.empty(), Optional.empty(), Collections.emptyList());
PropertyReference nameRef = new PropertyReference("name");
mangaCharacter.add(nameRef);
mangaCharacter.add(ageProperty);
turinFile.add(mangaCharacter);
return turinFile;
}
private TurinFile mangaAst() {
TurinFile turinFile = new TurinFile();
NamespaceDefinition namespaceDefinition = new NamespaceDefinition("manga");
turinFile.setNameSpace(namespaceDefinition);
ReferenceTypeUsageNode stringType = new ReferenceTypeUsageNode("String");
BasicTypeUsageNode intType = new BasicTypeUsageNode("uint");
PropertyDefinition nameProperty = new PropertyDefinition("name", stringType, Optional.empty(), Optional.empty(), Collections.emptyList());
turinFile.add(nameProperty);
TurinTypeDefinition mangaCharacter = new TurinTypeDefinition("MangaCharacter");
PropertyDefinition ageProperty = new PropertyDefinition("age", intType, Optional.empty(), Optional.empty(), Collections.emptyList());
PropertyReference nameRef = new PropertyReference("name");
mangaCharacter.add(nameRef);
mangaCharacter.add(ageProperty);
turinFile.add(mangaCharacter);
// val ranma = MangaCharacter("Ranma", 16)
Creation value = new Creation("MangaCharacter", ImmutableList.of(new ActualParam(new StringLiteral("Ranma")), new ActualParam(new IntLiteral(16))));
VariableDeclaration varDecl = new VariableDeclaration("ranma", value);
// print("The protagonist is #{ranma}")
StringInterpolation string = new StringInterpolation();
string.add(new StringLiteral("The protagonist is "));
string.add(new ValueReference("ranma"));
FunctionCall functionCall = new FunctionCall(new ValueReference("print"), ImmutableList.of(new ActualParam(string)));
Program program = new Program("MangaExample", new BlockStatement(ImmutableList.of(varDecl, new ExpressionStatement(functionCall))), "args");
turinFile.add(program);
return turinFile;
}
@Test
public void convertBasicMangaExample() throws IOException {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("basicManga.to");
TurinParser.TurinFileContext root = new InternalParser().produceParseTree(inputStream);
TurinFile expectedAst = basicMangaAst();
TurinFile actualAst = new ParseTreeToAst().toAst(root);
assertEquals(expectedAst.getTopLevelPropertyDefinitions().size(), actualAst.getTopLevelPropertyDefinitions().size());
PropertyDefinition expProp = expectedAst.getTopLevelPropertyDefinitions().get(0);
PropertyDefinition actProp = actualAst.getTopLevelPropertyDefinitions().get(0);
assertEquals(expProp, actProp);
assertEquals(expProp.getName(), actProp.getName());
assertEquals(expProp.getType(), actProp.getType());
assertEquals(expectedAst.getTopLevelPropertyDefinitions(), actualAst.getTopLevelPropertyDefinitions());
assertEquals(expectedAst, actualAst);
}
@Test
public void convertMangaExample() throws IOException {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("manga.to");
TurinParser.TurinFileContext root = new InternalParser().produceParseTree(inputStream);
assertEquals(mangaAst(), new ParseTreeToAst().toAst(root));
}
@Test
public void typeExtendingAndImplementin() throws IOException {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("parser_examples/type_extending_and_implementing.to");
TurinParser.TurinFileContext root = new InternalParser().produceParseTree(inputStream);
TurinFile turinFile = new ParseTreeToAst().toAst(root);
assertEquals(1, turinFile.getTopLevelTypeDefinitions().size());
TurinTypeDefinition typeDefinition = turinFile.getTopLevelTypeDefinitions().get(0);
assertTrue(typeDefinition.getBaseType().isPresent());
assertEquals(2, typeDefinition.getInterfaces().size());
}
}