Commit 9c3d88b6 authored by Jean-Marc Ronck's avatar Jean-Marc Ronck
Browse files

Parenthesis Issue and better Tests.

parent 6aa36adc
......@@ -6,7 +6,7 @@
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>math-pretty-printer</artifactId>
<version>0.3.1</version>
<version>0.3.2-SNAPSHOT</version>
<properties>
......@@ -20,6 +20,7 @@
<commons.cli.version>1.4</commons.cli.version>
<jlatexmath.version>1.0.7</jlatexmath.version>
<batik.version>1.10</batik.version>
<commons.io.version>2.6</commons.io.version>
<!-- .. Plugins ....................................................... -->
......@@ -125,6 +126,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- == DISTRIBUTION ==================================================== -->
......
package de.monticore.lang.monticar.mpp.montimath;
import de.monticore.ast.ASTNode;
import de.monticore.commonexpressions._ast.*;
import de.monticore.lang.math._ast.*;
import de.monticore.lang.matrix._ast.ASTMathMatrixAccessExpression;
......@@ -12,13 +13,17 @@ import de.monticore.lang.matrixexpressions._ast.*;
import de.monticore.numberunit._ast.ASTTimeDiv;
import de.monticore.numberunit._ast.ASTUnitBaseDimWithPrefix;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
public class TeXMathPrettyPrinter extends MathPrettyPrinter implements TeXMathStructuredVisitor {
protected boolean needsParenthesis;
protected int parenthesis;
protected Stack<Boolean> nextParentheses;
protected Set<ASTNode> printedParentheses;
public TeXMathPrettyPrinter() {
this.needsParenthesis = true;
this.parenthesis = 0;
this.printedParentheses = new HashSet<>();
this.nextParentheses = new Stack<>();
}
@Override
......@@ -49,8 +54,8 @@ public class TeXMathPrettyPrinter extends MathPrettyPrinter implements TeXMathSt
@Override
public void visit(ASTDivideExpression node) {
this.needsParenthesis = false;
this.printer.print("\\dfrac{");
this.nextParentheses.push(false);
}
@Override
......@@ -61,12 +66,7 @@ public class TeXMathPrettyPrinter extends MathPrettyPrinter implements TeXMathSt
@Override
public void endVisit(ASTDivideExpression node) {
this.printer.print("}");
this.needsParenthesis = true;
}
@Override
public void visit(ASTMathAssignmentDeclarationStatement node){
this.nextParentheses.pop();
}
@Override
......@@ -185,19 +185,19 @@ public class TeXMathPrettyPrinter extends MathPrettyPrinter implements TeXMathSt
@Override
public void visit(ASTBracketExpression node) {
if (this.needsParenthesis) {
boolean nextParenthesis = this.nextParentheses.empty() || this.nextParentheses.peek();
if (nextParenthesis) {
this.printer.print("\\left(");
this.parenthesis++;
} else {
this.needsParenthesis = true;
this.printedParentheses.add(node);
}
}
@Override
public void endVisit(ASTBracketExpression node) {
if (this.parenthesis > 0) {
if (this.printedParentheses.contains(node)) {
this.printer.print("\\right)");
this.parenthesis--;
this.printedParentheses.remove(node);
}
}
......
var radios = document.querySelectorAll("input[name='View']");
var card = document.querySelector(".card");
var front = document.querySelectorAll(".card-face-front tr");
var back = document.querySelectorAll(".card-face-back tr");
function clickButton(index) {
radios[index].click();
}
function selectRange(start, end) {
var length = front.length;
for(var i = 0; i < length; i++) {
if(i >= start - 1 && i < (end || start)) {
front[i].classList.add("marked");
back[i].classList.add("marked");
} else {
front[i].classList.remove("marked");
back[i].classList.remove("marked");
}
}
}
function scroll(index, start) {
start = start - 1;
window.scrollTo(0, index === 0 ? front[start].offsetTop : back[start].offsetTop);
}
function onChange(event) {
card.classList.toggle("flipped");
}
function onHashChange() {
window.setTimeout(function() {
var hash = window.location.hash;
var parts = hash.substring(1).split(':');
var index = parts[0];
var start = parts[1];
var end = parts[2];
if(index) {
clickButton(index);
if(start) {
scroll(index, start);
selectRange(start, end);
}
}
}, 0);
}
function onWindowResize() {
}
radios.forEach(function(element) { element.addEventListener("change", onChange) });
onHashChange();
window.addEventListener("hashchange", onHashChange);
window.addEventListener("resize", onWindowResize);
\ No newline at end of file
......@@ -188,54 +188,6 @@
</div>
</body>
<script>
var radios = document.querySelectorAll("input[name='View']");
var card = document.querySelector(".card");
var front = document.querySelectorAll(".card-face-front tr");
var back = document.querySelectorAll(".card-face-back tr");
function clickButton(index) {
radios[index].click();
}
function selectRange(start, end) {
for(var i = start - 1; i < (end || start); i++) {
front[i].classList.add("marked");
back[i].classList.add("marked");
}
}
function scroll(index, start) {
start = start - 1;
window.scrollTo(0, index === 0 ? front[start].offsetTop : back[start].offsetTop);
}
function onChange(event) {
card.classList.toggle("flipped");
}
function onHashChange() {
window.setTimeout(function() {
var hash = window.location.hash;
var parts = hash.substring(1).split(':');
var index = parts[0];
var start = parts[1];
var end = parts[2];
if(index) {
clickButton(index);
if(start) {
scroll(index, start);
selectRange(start, end);
}
}
}, 0);
}
radios.forEach(function(element) { element.addEventListener("change", onChange) });
onHashChange();
window.addEventListener("hashchange", onHashChange);
${include("templates/js.ftl")}
</script>
</html>
\ No newline at end of file
package de.monticore.lang.monticar.mpp.models;
import de.monticore.lang.math._ast.ASTMathCompilationUnit;
import de.monticore.lang.math._parser.MathParser;
import de.monticore.lang.monticar.mpp.montimath.MathPrettyPrinter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import static junit.framework.TestCase.*;
public abstract class AbstractModelTest {
protected MathPrettyPrinter printer;
public AbstractModelTest()
{
this(new MathPrettyPrinter());
}
public AbstractModelTest(MathPrettyPrinter printer)
{
this.printer = printer;
}
public String printVanillaModel(String name) throws IOException
{
Path model = Paths.get("src/test/resources/models/montimath/vanilla/" + name).toAbsolutePath();
MathParser parser = new MathParser();
Optional<ASTMathCompilationUnit> astOptional = parser.parse(model.toString());
assertTrue(astOptional.isPresent());
return printer.prettyPrint(astOptional.get());
}
}
package de.monticore.lang.monticar.mpp.models;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
public class ArithmeticTest extends AbstractModelTest {
@Test
@Ignore
public void printTest() throws IOException
{
System.out.println(printVanillaModel("Arithmetic.m"));
}
@Test
public void testModel() throws IOException
{
String actual = printVanillaModel("Arithmetic.m");
String expected =
"package montimath.vanilla;\n" +
"\n" +
"script Arithmetic\n" +
" //Variable Declaration\n" +
" Q rational;\n" +
" rational = 1 + 2 * 3;\n" +
"end";
assertEquals(expected, actual);
}
}
package de.monticore.lang.monticar.mpp.models;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
public class CommentsTest extends AbstractModelTest {
@Test
@Ignore
public void printTest() throws IOException
{
System.out.println(printVanillaModel("Comments.m"));
}
@Test
@Ignore
//TODO somehow this test does not work even though the results are identical
public void testModel() throws IOException
{
String actual = printVanillaModel("Comments.m");
String expected = "/*\n" +
" * (C) SE RWTH 2018\n" +
" */\n" +
"package montimath.vanilla;\n" +
"\n" +
"/*\n" +
" * A Dummy Script to show that comments can be shown.\n" +
" */\n" +
"script Comments\n" +
" /* Vector of the form [1,3,5,7,9] */\n" +
" Q(0 : 10)^{1, 5} c = 1:2:10;\n" +
" Q x = 0;\n" +
" Q y = 0;\n" +
" // Iterate over all i in c\n" +
" for i = c\n" +
" // Iterate over all j in c\n" +
" for j = c\n" +
" // y might become very small when the\n" +
" // entries in c are very large.\n" +
" y += 1 / (c(x) * j^i);\n" +
" end\n" +
" x += 1;\n" +
" end\n" +
"end";
assertEquals(expected, actual);
}
}
package de.monticore.lang.monticar.mpp.models;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
public class ForLoopTest extends AbstractModelTest {
@Test
@Ignore
public void printTest1() throws IOException
{
System.out.println(printVanillaModel("ForLoop.m"));
}
@Test
public void testModel1() throws IOException
{
String actual = printVanillaModel("ForLoop.m");
String expected =
"package montimath.vanilla;\n" +
"\n" +
"script ForLoop\n" +
" Q sum = 1;\n" +
" for i = 1:2:9\n" +
" sum += sum * i;\n" +
" end\n" +
"end";
assertEquals(expected, actual);
}
@Test
@Ignore
public void printTest2() throws IOException
{
System.out.println(printVanillaModel("ForLoop2.m"));
}
@Test
public void testModel2() throws IOException
{
String actual = printVanillaModel("ForLoop2.m");
String expected =
"package montimath.vanilla;\n" +
"\n" +
"script ForLoop2\n" +
" Q(0 m : 1000 m)^{5} c = [1 m, 3 m, 5 m, 7 m, 9 m];\n" +
" Q x = 0;\n" +
" Q(0 m^2 : 1000 m^2) y = 0 m * m;\n" +
" Q(0 m : 1000 m) z = 0 m;\n" +
" //TODO fix this to work with variable vectors, and not only vectors that are equivalent to range vectors\n" +
" for i = c\n" +
" for j = c\n" +
" y += j * i;\n" +
" z += c(x + 0);\n" +
" end\n" +
" x += 1;\n" +
" end\n" +
"end";
assertEquals(expected, actual);
}
@Test
@Ignore
public void printTest3() throws IOException
{
System.out.println(printVanillaModel("ForLoop3.m"));
}
@Test
public void testModel3() throws IOException
{
String actual = printVanillaModel("ForLoop3.m");
String expected =
"package montimath.vanilla;\n" +
"\n" +
"script ForLoop3\n" +
" Q^{3, 3} A = [1, 2, 3; 4, 5, 6; 7, 8, 9];\n" +
" Q Cmat = 0;\n" +
" for i = 0:2\n" +
" for j = 0:2\n" +
" Cmat += A(i, j);\n" +
" end\n" +
" end\n" +
"end";
assertEquals(expected, actual);
}
}
package de.monticore.lang.monticar.mpp.models;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
public class NestedTest extends AbstractModelTest {
@Test
@Ignore
public void printTest() throws IOException
{
System.out.println(printVanillaModel("Nested.m"));
}
@Test
public void testModel() throws IOException
{
String actual = printVanillaModel("Nested.m");
String expected = "package montimath.vanilla;\n" +
"\n" +
"script Nested\n" +
" Q sum = 1;\n" +
" for i = 1:2:9\n" +
" if i < 2\n" +
" sum -= sum * i;\n" +
" elseif i < 4\n" +
" sum += sum * i;\n" +
" else\n" +
" for j = 1:2:6\n" +
" sum += sum * (i - j);\n" +
" end\n" +
" end\n" +
" end\n" +
"end";
assertEquals(expected, actual);
}
}
package de.monticore.lang.monticar.mpp.models;
import de.monticore.lang.monticar.mpp.montimath.MathPrettyPrinter;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
public class StatementsOnlyTest extends AbstractModelTest {
@Test
@Ignore
public void printTest3() throws IOException
{
this.printer = new MathPrettyPrinter(4, true);
System.out.println(printVanillaModel("Nested.m"));
}
@Test
public void testModel3() throws IOException
{
this.printer = new MathPrettyPrinter(4, true);
String actual = printVanillaModel("Nested.m");
String expected =
"Q sum = 1;\n" +
"for i = 1:2:9\n" +
" if i < 2\n" +
" sum -= sum * i;\n" +
" elseif i < 4\n" +
" sum += sum * i;\n" +
" else\n" +
" for j = 1:2:6\n" +
" sum += sum * (i - j);\n" +
" end\n" +
" end\n" +
"end\n";
assertEquals(expected, actual);
}
}
package de.monticore.lang.monticar.mpp.montimath;
import de.monticore.lang.math._ast.ASTMathCompilationUnit;
import de.monticore.lang.math._parser.MathParser;
import de.se_rwth.commons.logging.Log;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
public class HTMLMathPrettyPrinterTest {
protected static File[] sourceModels;
protected static File[] targetModels;
@BeforeClass
public static void prepare() {
Path sourcePath = Paths.get("src/test/resources/models/montimath/vanilla").toAbsolutePath();
Path targetPath = Paths.get("src/test/resources/models/montimath/html").toAbsolutePath();
File sourceFile = sourcePath.toFile();
File targetFile = targetPath.toFile();
sourceModels = sourceFile.listFiles();
targetModels = targetFile.listFiles();
}
@Test
public void testPrinter() throws IOException {
int length = sourceModels.length;
MathParser parser = new MathParser();
HTMLMathPrettyPrinter printer = new HTMLMathPrettyPrinter();
for (int i = 0; i < length; i++) {
File sourceModel = sourceModels[i];
File targetModel = targetModels[i];
String modelName = sourceModel.getName();
String message = String.format("Checking Equality of %s.", modelName);
if (modelName.equals("Comments.m")) continue;
Log.info(message, "HTMLMathPrettyPrinterTest");
Optional<ASTMathCompilationUnit> astOptional = parser.parse(sourceModel.toString());