mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-28 07:28:20 -04:00
better test data parser to allow multi row repeats
This commit is contained in:
parent
c7393a2619
commit
4b3e100730
@ -1465,73 +1465,25 @@ in der Speichermatrix gespeichert.</string>
|
|||||||
<testData>
|
<testData>
|
||||||
<dataString>C0 C1 R0 R1 WE D_In D_Out
|
<dataString>C0 C1 R0 R1 WE D_In D_Out
|
||||||
|
|
||||||
|
# write all cells to one
|
||||||
|
loop(n,16)
|
||||||
|
bits(4,n) 0 1 0
|
||||||
|
bits(4,n) 1 1 1
|
||||||
|
bits(4,n) 0 1 1
|
||||||
|
endloop
|
||||||
|
|
||||||
|
# check all cells are one
|
||||||
|
repeat(16) bits(4,n) 0 x 1
|
||||||
|
|
||||||
# write all cells to zero
|
# write all cells to zero
|
||||||
0 0 0 0 0 0 0
|
loop(n,16)
|
||||||
0 0 0 0 1 0 0
|
bits(4,n) 0 0 1
|
||||||
0 0 0 0 0 0 0
|
bits(4,n) 1 0 0
|
||||||
|
bits(4,n) 0 0 0
|
||||||
0 0 0 1 0 0 0
|
endloop
|
||||||
0 0 0 1 1 0 0
|
|
||||||
0 0 0 1 0 0 0
|
|
||||||
|
|
||||||
0 0 1 0 0 0 0
|
|
||||||
0 0 1 0 1 0 0
|
|
||||||
0 0 1 0 0 0 0
|
|
||||||
|
|
||||||
0 0 1 1 0 0 0
|
|
||||||
0 0 1 1 1 0 0
|
|
||||||
0 0 1 1 0 0 0
|
|
||||||
|
|
||||||
0 1 0 0 0 0 0
|
|
||||||
0 1 0 0 1 0 0
|
|
||||||
0 1 0 0 0 0 0
|
|
||||||
|
|
||||||
0 1 0 1 0 0 0
|
|
||||||
0 1 0 1 1 0 0
|
|
||||||
0 1 0 1 0 0 0
|
|
||||||
|
|
||||||
0 1 1 0 0 0 0
|
|
||||||
0 1 1 0 1 0 0
|
|
||||||
0 1 1 0 0 0 0
|
|
||||||
|
|
||||||
0 1 1 1 0 0 0
|
|
||||||
0 1 1 1 1 0 0
|
|
||||||
0 1 1 1 0 0 0
|
|
||||||
|
|
||||||
|
|
||||||
1 0 0 0 0 0 0
|
|
||||||
1 0 0 0 1 0 0
|
|
||||||
1 0 0 0 0 0 0
|
|
||||||
|
|
||||||
1 0 0 1 0 0 0
|
|
||||||
1 0 0 1 1 0 0
|
|
||||||
1 0 0 1 0 0 0
|
|
||||||
|
|
||||||
1 0 1 0 0 0 0
|
|
||||||
1 0 1 0 1 0 0
|
|
||||||
1 0 1 0 0 0 0
|
|
||||||
|
|
||||||
1 0 1 1 0 0 0
|
|
||||||
1 0 1 1 1 0 0
|
|
||||||
1 0 1 1 0 0 0
|
|
||||||
|
|
||||||
1 1 0 0 0 0 0
|
|
||||||
1 1 0 0 1 0 0
|
|
||||||
1 1 0 0 0 0 0
|
|
||||||
|
|
||||||
1 1 0 1 0 0 0
|
|
||||||
1 1 0 1 1 0 0
|
|
||||||
1 1 0 1 0 0 0
|
|
||||||
|
|
||||||
1 1 1 0 0 0 0
|
|
||||||
1 1 1 0 1 0 0
|
|
||||||
1 1 1 0 0 0 0
|
|
||||||
|
|
||||||
1 1 1 1 0 0 0
|
|
||||||
1 1 1 1 1 0 0
|
|
||||||
1 1 1 1 0 0 0
|
|
||||||
|
|
||||||
|
# check all cells are zero
|
||||||
|
repeat(16) bits(4,n) 0 x 0
|
||||||
|
|
||||||
#write cell 00 to 1
|
#write cell 00 to 1
|
||||||
|
|
||||||
@ -1547,8 +1499,6 @@ in der Speichermatrix gespeichert.</string>
|
|||||||
# cell 00 is still 1
|
# cell 00 is still 1
|
||||||
|
|
||||||
0 0 0 0 0 0 1
|
0 0 0 0 0 0 1
|
||||||
|
|
||||||
|
|
||||||
</dataString>
|
</dataString>
|
||||||
</testData>
|
</testData>
|
||||||
</entry>
|
</entry>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package de.neemann.digital.testing;
|
package de.neemann.digital.testing;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.parser.LineEmitter;
|
||||||
import de.neemann.digital.testing.parser.Parser;
|
import de.neemann.digital.testing.parser.Parser;
|
||||||
import de.neemann.digital.testing.parser.ParserException;
|
import de.neemann.digital.testing.parser.ParserException;
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ public class TestData {
|
|||||||
public static final TestData DEFAULT = new TestData("");
|
public static final TestData DEFAULT = new TestData("");
|
||||||
|
|
||||||
private String dataString;
|
private String dataString;
|
||||||
private transient ArrayList<Value[]> lines;
|
private transient LineEmitter lines;
|
||||||
private transient ArrayList<String> names;
|
private transient ArrayList<String> names;
|
||||||
|
|
||||||
TestData(String data) {
|
TestData(String data) {
|
||||||
@ -74,7 +75,7 @@ public class TestData {
|
|||||||
* @return the data lines
|
* @return the data lines
|
||||||
* @throws TestingDataException TestingDataException
|
* @throws TestingDataException TestingDataException
|
||||||
*/
|
*/
|
||||||
public ArrayList<Value[]> getLines() throws TestingDataException {
|
public LineEmitter getLines() throws TestingDataException {
|
||||||
check();
|
check();
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import de.neemann.digital.core.ObservableValue;
|
|||||||
import de.neemann.digital.core.Signal;
|
import de.neemann.digital.core.Signal;
|
||||||
import de.neemann.digital.core.wiring.Clock;
|
import de.neemann.digital.core.wiring.Clock;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
|
import de.neemann.digital.testing.parser.Context;
|
||||||
|
import de.neemann.digital.testing.parser.LineEmitter;
|
||||||
|
import de.neemann.digital.testing.parser.ParserException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -21,7 +24,7 @@ import java.util.NoSuchElementException;
|
|||||||
public class TestResult {
|
public class TestResult {
|
||||||
|
|
||||||
private final ArrayList<String> names;
|
private final ArrayList<String> names;
|
||||||
private final ArrayList<Value[]> lines;
|
private final LineEmitter lines;
|
||||||
private final ArrayList<Value[]> results;
|
private final ArrayList<Value[]> results;
|
||||||
private boolean allPassed;
|
private boolean allPassed;
|
||||||
private Exception exception;
|
private Exception exception;
|
||||||
@ -87,55 +90,63 @@ public class TestResult {
|
|||||||
|
|
||||||
model.init();
|
model.init();
|
||||||
|
|
||||||
for (Value[] rowWithDontCare : lines) {
|
try {
|
||||||
|
lines.emitLines(rowWithDontCare -> {
|
||||||
|
for (Value[] row : resolveDontCares(inputs, rowWithDontCare)) {
|
||||||
|
|
||||||
for (Value[] row : resolveDontCares(inputs, rowWithDontCare)) {
|
Value[] res = new Value[row.length];
|
||||||
|
|
||||||
Value[] res = new Value[row.length];
|
boolean clockIsUsed = false;
|
||||||
|
// set all values except the clocks
|
||||||
boolean clockIsUsed = false;
|
for (TestSignal in : inputs) {
|
||||||
// set all values except the clocks
|
if (row[in.index].getType() != Value.Type.CLOCK) {
|
||||||
for (TestSignal in : inputs) {
|
|
||||||
if (row[in.index].getType() != Value.Type.CLOCK) {
|
|
||||||
row[in.index].copyTo(in.value);
|
|
||||||
} else {
|
|
||||||
clockIsUsed = true;
|
|
||||||
}
|
|
||||||
res[in.index] = row[in.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clockIsUsed) { // a clock signal is used
|
|
||||||
model.doStep(); // propagate all except clock
|
|
||||||
|
|
||||||
// set clock
|
|
||||||
for (TestSignal in : inputs)
|
|
||||||
if (row[in.index].getType() == Value.Type.CLOCK)
|
|
||||||
row[in.index].copyTo(in.value);
|
row[in.index].copyTo(in.value);
|
||||||
|
} else {
|
||||||
|
clockIsUsed = true;
|
||||||
|
}
|
||||||
|
res[in.index] = row[in.index];
|
||||||
|
}
|
||||||
|
|
||||||
// propagate clock change
|
try {
|
||||||
model.doStep();
|
if (clockIsUsed) { // a clock signal is used
|
||||||
|
model.doStep(); // propagate all except clock
|
||||||
|
|
||||||
// restore clock
|
// set clock
|
||||||
for (TestSignal in : inputs) // invert the clock values
|
for (TestSignal in : inputs)
|
||||||
if (row[in.index].getType() == Value.Type.CLOCK)
|
if (row[in.index].getType() == Value.Type.CLOCK)
|
||||||
in.value.setBool(!in.value.getBool());
|
row[in.index].copyTo(in.value);
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
// propagate clock change
|
||||||
model.doStep();
|
model.doStep();
|
||||||
} catch (NodeException | RuntimeException e) {
|
|
||||||
exception = e;
|
|
||||||
allPassed = false;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TestSignal out : outputs) {
|
// restore clock
|
||||||
MatchedValue matchedValue = new MatchedValue(row[out.index], out.value);
|
for (TestSignal in : inputs) // invert the clock values
|
||||||
res[out.index] = matchedValue;
|
if (row[in.index].getType() == Value.Type.CLOCK)
|
||||||
if (!matchedValue.isPassed())
|
in.value.setBool(!in.value.getBool());
|
||||||
|
}
|
||||||
|
|
||||||
|
model.doStep();
|
||||||
|
} catch (NodeException | RuntimeException e) {
|
||||||
|
exception = e;
|
||||||
allPassed = false;
|
allPassed = false;
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TestSignal out : outputs) {
|
||||||
|
MatchedValue matchedValue = new MatchedValue(row[out.index], out.value);
|
||||||
|
res[out.index] = matchedValue;
|
||||||
|
if (!matchedValue.isPassed())
|
||||||
|
allPassed = false;
|
||||||
|
}
|
||||||
|
results.add(res);
|
||||||
}
|
}
|
||||||
results.add(res);
|
}, new Context());
|
||||||
|
} catch (ParserException e) {
|
||||||
|
throw new TestingDataException(e);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
if (allPassed) {
|
||||||
|
allPassed = false;
|
||||||
|
exception = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package de.neemann.digital.testing;
|
package de.neemann.digital.testing;
|
||||||
|
|
||||||
import de.neemann.digital.core.element.PinDescription;
|
import de.neemann.digital.core.element.PinDescription;
|
||||||
|
import de.neemann.digital.testing.parser.Context;
|
||||||
import de.neemann.digital.testing.parser.Parser;
|
import de.neemann.digital.testing.parser.Parser;
|
||||||
import de.neemann.digital.testing.parser.ParserException;
|
import de.neemann.digital.testing.parser.ParserException;
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Helper to create all possible transitions between states.
|
||||||
* Created by hneemann on 24.02.17.
|
* Created by hneemann on 24.02.17.
|
||||||
*/
|
*/
|
||||||
public class Transitions {
|
public class Transitions {
|
||||||
@ -44,7 +46,7 @@ public class Transitions {
|
|||||||
inVarNum.add(i);
|
inVarNum.add(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Value[] line : p.getLines()) {
|
p.getLines().emitLines(line -> {
|
||||||
if (isNormal(line)) {
|
if (isNormal(line)) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Value[] u : uniqueLines) {
|
for (Value[] u : uniqueLines) {
|
||||||
@ -56,7 +58,7 @@ public class Transitions {
|
|||||||
if (!found)
|
if (!found)
|
||||||
uniqueLines.add(line);
|
uniqueLines.add(line);
|
||||||
}
|
}
|
||||||
}
|
}, new Context());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInputEqual(Value[] l1, Value[] l2) {
|
private boolean isInputEqual(Value[] l1, Value[] l2) {
|
||||||
|
@ -1,93 +1,23 @@
|
|||||||
package de.neemann.digital.testing.parser;
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.digital.testing.Value;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The context of the calculations.
|
* The context of the calculations.
|
||||||
* Containf the variables to use and the test values list.
|
* <p>
|
||||||
* Created by hneemann on 02.12.16.
|
* Created by hneemann on 02.12.16.
|
||||||
*/
|
*/
|
||||||
public class Context {
|
public class Context {
|
||||||
private final HashMap<String, Long> vars;
|
|
||||||
private final ArrayList<Value> values;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Returnes the value of a variable
|
||||||
*/
|
|
||||||
public Context() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
*
|
*
|
||||||
* @param values the values array to fill
|
* @param name the name of the variable
|
||||||
*/
|
* @return the value
|
||||||
public Context(ArrayList<Value> values) {
|
* @throws ParserException if the variable does not exist
|
||||||
vars = new HashMap<>();
|
|
||||||
this.values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the actual loop value
|
|
||||||
* @throws ParserException Thrown if variable not present
|
|
||||||
*/
|
|
||||||
public long getN() throws ParserException {
|
|
||||||
return getVar("n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of a variable
|
|
||||||
*
|
|
||||||
* @param name the variables name
|
|
||||||
* @return the long value
|
|
||||||
* @throws ParserException Thrown if variable not present
|
|
||||||
*/
|
*/
|
||||||
public long getVar(String name) throws ParserException {
|
public long getVar(String name) throws ParserException {
|
||||||
Long l = vars.get(name);
|
throw new ParserException(Lang.get("err_variable_N0_notFound", name));
|
||||||
if (l == null)
|
|
||||||
throw new ParserException(Lang.get("err_variable_N0_notFound", name));
|
|
||||||
return l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a simple value to the value list
|
|
||||||
*
|
|
||||||
* @param v the value to add
|
|
||||||
*/
|
|
||||||
public void addValue(Value v) {
|
|
||||||
values.add(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds bitcount values to the values list.
|
|
||||||
* Bitcount bits from the given value are added to the values list
|
|
||||||
*
|
|
||||||
* @param bitCount the numbers of bits to add
|
|
||||||
* @param value the bit values
|
|
||||||
*/
|
|
||||||
public void addBits(int bitCount, long value) {
|
|
||||||
long mask = 1L << (bitCount - 1);
|
|
||||||
for (int i = 0; i < bitCount; i++) {
|
|
||||||
boolean v = (value & mask) != 0;
|
|
||||||
values.add(new Value(v ? 1 : 0));
|
|
||||||
mask >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a variable value to the context
|
|
||||||
*
|
|
||||||
* @param name name of the variable
|
|
||||||
* @param value value
|
|
||||||
* @return this for chained calls
|
|
||||||
*/
|
|
||||||
public Context setVar(String name, long value) {
|
|
||||||
vars.put(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A context with a variable
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class ContextWithVar extends Context {
|
||||||
|
|
||||||
|
private final Context parent;
|
||||||
|
private final String var;
|
||||||
|
private long value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param parent the parent
|
||||||
|
* @param var the variable
|
||||||
|
*/
|
||||||
|
public ContextWithVar(Context parent, String var) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param var the variable
|
||||||
|
*/
|
||||||
|
public ContextWithVar(String var) {
|
||||||
|
this.parent = new Context();
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a value to this variable
|
||||||
|
*
|
||||||
|
* @param value the value
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public ContextWithVar setValue(long value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getVar(String name) throws ParserException {
|
||||||
|
if (name.equals(var))
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
return parent.getVar(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to describe a line
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public interface LineEmitter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is called to imit the described line to the listener
|
||||||
|
*
|
||||||
|
* @param listener the listener to emit the lines
|
||||||
|
* @param conext the context
|
||||||
|
* @throws ParserException ParserException
|
||||||
|
*/
|
||||||
|
void emitLines(LineListener listener, Context conext) throws ParserException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class LineEmitterList implements LineEmitter {
|
||||||
|
|
||||||
|
private ArrayList<LineEmitter> lines;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance
|
||||||
|
*/
|
||||||
|
public LineEmitterList() {
|
||||||
|
lines = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a line to this list
|
||||||
|
*
|
||||||
|
* @param line the line to add
|
||||||
|
*/
|
||||||
|
public void add(LineEmitter line) {
|
||||||
|
lines.add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this list contains anly a single line this line is returned.
|
||||||
|
* Otherwise this is returned
|
||||||
|
*
|
||||||
|
* @return this of the only lists item
|
||||||
|
*/
|
||||||
|
public LineEmitter minimize() {
|
||||||
|
if (lines.size() == 1)
|
||||||
|
return lines.get(0);
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitLines(LineListener listener, Context conext) throws ParserException {
|
||||||
|
for (LineEmitter l : lines)
|
||||||
|
l.emitLines(listener, conext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repeats some inner table rows.
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class LineEmitterRepeat implements LineEmitter {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final int size;
|
||||||
|
private final LineEmitter inner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new loop
|
||||||
|
*
|
||||||
|
* @param name name of the loop variable
|
||||||
|
* @param size number of iterations
|
||||||
|
* @param inner the lines to repeat
|
||||||
|
*/
|
||||||
|
public LineEmitterRepeat(String name, int size, LineEmitter inner) {
|
||||||
|
this.name = name;
|
||||||
|
this.size = size;
|
||||||
|
this.inner = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitLines(LineListener listener, Context conext) throws ParserException {
|
||||||
|
ContextWithVar c = new ContextWithVar(conext, name);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
c.setValue(i);
|
||||||
|
inner.emitLines(listener, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
import de.neemann.digital.testing.Value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Line emitter to create a simple row of values.
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class LineEmitterSimple implements LineEmitter {
|
||||||
|
|
||||||
|
private final ArrayList<ValueAppender> appender;
|
||||||
|
private final int valuesCount;
|
||||||
|
private final int line;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Instance
|
||||||
|
*
|
||||||
|
* @param valuesCount number of expected columns
|
||||||
|
* @param line the source line
|
||||||
|
*/
|
||||||
|
public LineEmitterSimple(int valuesCount, int line) {
|
||||||
|
this.valuesCount = valuesCount;
|
||||||
|
this.line = line;
|
||||||
|
this.appender = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a value appender
|
||||||
|
*
|
||||||
|
* @param app the appender
|
||||||
|
*/
|
||||||
|
public void add(ValueAppender app) {
|
||||||
|
appender.add(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitLines(LineListener listener, Context conext) throws ParserException {
|
||||||
|
ArrayList<Value> vals = new ArrayList<>(valuesCount);
|
||||||
|
for (ValueAppender ve : appender)
|
||||||
|
ve.appendValues(vals, conext);
|
||||||
|
|
||||||
|
if (vals.size() != valuesCount)
|
||||||
|
throw new ParserException(Lang.get("err_testDataExpected_N0_found_N1_numbersInLine_N2", valuesCount, vals.size(), line));
|
||||||
|
|
||||||
|
listener.add(vals.toArray(new Value[vals.size()]));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for truth table lines
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public interface LineListener {
|
||||||
|
/**
|
||||||
|
* Adds a line to the table
|
||||||
|
*
|
||||||
|
* @param values the values in the line
|
||||||
|
*/
|
||||||
|
void add(Value[] values);
|
||||||
|
}
|
@ -21,9 +21,8 @@ import java.util.ArrayList;
|
|||||||
public class Parser {
|
public class Parser {
|
||||||
|
|
||||||
private final ArrayList<String> names;
|
private final ArrayList<String> names;
|
||||||
private final ArrayList<Value[]> lines;
|
|
||||||
private final ArrayList<Value> values;
|
|
||||||
private final Tokenizer tok;
|
private final Tokenizer tok;
|
||||||
|
private LineEmitter emitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
@ -32,8 +31,6 @@ public class Parser {
|
|||||||
*/
|
*/
|
||||||
public Parser(String data) {
|
public Parser(String data) {
|
||||||
names = new ArrayList<>();
|
names = new ArrayList<>();
|
||||||
lines = new ArrayList<>();
|
|
||||||
values = new ArrayList<>();
|
|
||||||
tok = new Tokenizer(new BufferedReader(new StringReader(data)));
|
tok = new Tokenizer(new BufferedReader(new StringReader(data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +43,8 @@ public class Parser {
|
|||||||
*/
|
*/
|
||||||
public Parser parse() throws IOException, ParserException {
|
public Parser parse() throws IOException, ParserException {
|
||||||
parseHeader();
|
parseHeader();
|
||||||
parseValues();
|
emitter = parseValues(false);
|
||||||
|
expect(Tokenizer.Token.EOF);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,28 +69,47 @@ public class Parser {
|
|||||||
return new ParserException(Lang.get("err_unexpectedToken_N0_inLine_N1", name, tok.getLine()));
|
return new ParserException(Lang.get("err_unexpectedToken_N0_inLine_N1", name, tok.getLine()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseValues() throws IOException, ParserException {
|
private LineEmitter parseValues(boolean loop) throws IOException, ParserException {
|
||||||
|
LineEmitterList list = new LineEmitterList();
|
||||||
while (true) {
|
while (true) {
|
||||||
Tokenizer.Token t = tok.peek();
|
Tokenizer.Token t = tok.peek();
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case EOL:
|
case EOL:
|
||||||
break;
|
break;
|
||||||
case EOF:
|
case EOF:
|
||||||
return;
|
if (loop)
|
||||||
|
throw newUnexpectedToken(t);
|
||||||
|
return list.minimize();
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
parseLine();
|
list.add(parseLine());
|
||||||
break;
|
break;
|
||||||
case IDENT:
|
case IDENT:
|
||||||
if (tok.getIdent().equals("repeat")) {
|
if (tok.getIdent().equals("endloop")) {
|
||||||
|
tok.consume();
|
||||||
|
if (!loop)
|
||||||
|
throw newUnexpectedToken(t);
|
||||||
|
return list.minimize();
|
||||||
|
} else if (tok.getIdent().equals("repeat")) {
|
||||||
tok.consume();
|
tok.consume();
|
||||||
expect(Tokenizer.Token.OPEN);
|
expect(Tokenizer.Token.OPEN);
|
||||||
int count = (int) parseInt();
|
int count = (int) parseInt();
|
||||||
if (count > 1 << 16)
|
if (count > 1 << 16)
|
||||||
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
||||||
expect(Tokenizer.Token.CLOSE);
|
expect(Tokenizer.Token.CLOSE);
|
||||||
parseForLine(count);
|
list.add(new LineEmitterRepeat("n", count, parseLine()));
|
||||||
|
} else if (tok.getIdent().equals("loop")) {
|
||||||
|
tok.consume();
|
||||||
|
expect(Tokenizer.Token.OPEN);
|
||||||
|
expect(Tokenizer.Token.IDENT);
|
||||||
|
String var = tok.getIdent();
|
||||||
|
expect(Tokenizer.Token.COMMA);
|
||||||
|
int count = (int) parseInt();
|
||||||
|
if (count > 1 << 16)
|
||||||
|
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
||||||
|
expect(Tokenizer.Token.CLOSE);
|
||||||
|
list.add(new LineEmitterRepeat(var, count, parseValues(true)));
|
||||||
} else {
|
} else {
|
||||||
parseLine();
|
list.add(parseLine());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -101,14 +118,16 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseForLine(int count) throws IOException, ParserException {
|
private LineEmitter parseLine() throws IOException, ParserException {
|
||||||
ArrayList<Entry> entries = new ArrayList<>();
|
LineEmitterSimple line = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
Tokenizer.Token token = tok.next();
|
Tokenizer.Token token = tok.next();
|
||||||
|
if (line == null)
|
||||||
|
line = new LineEmitterSimple(names.size(), tok.getLine());
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
Value num = new Value(tok.getIdent());
|
Value num = new Value(tok.getIdent());
|
||||||
entries.add(n -> n.addValue(num));
|
line.add((vals, conext) -> vals.add(num));
|
||||||
break;
|
break;
|
||||||
case IDENT:
|
case IDENT:
|
||||||
if (tok.getIdent().equals("bits")) {
|
if (tok.getIdent().equals("bits")) {
|
||||||
@ -116,25 +135,25 @@ public class Parser {
|
|||||||
int bitCount = (int) parseInt();
|
int bitCount = (int) parseInt();
|
||||||
expect(Tokenizer.Token.COMMA);
|
expect(Tokenizer.Token.COMMA);
|
||||||
Expression exp = parseExpression();
|
Expression exp = parseExpression();
|
||||||
entries.add(c -> c.addBits(bitCount, exp.value(c)));
|
line.add(new ValueAppenderBits(bitCount, exp));
|
||||||
expect(Tokenizer.Token.CLOSE);
|
expect(Tokenizer.Token.CLOSE);
|
||||||
} else {
|
} else {
|
||||||
Value v = new Value(tok.getIdent().toUpperCase());
|
try {
|
||||||
entries.add(n -> n.addValue(v));
|
final Value value = new Value(tok.getIdent().toUpperCase());
|
||||||
|
line.add((vals, context) -> vals.add(value));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new ParserException(Lang.get("err_notANumber_N0_inLine_N1", tok.getIdent(), tok.getLine()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPEN:
|
case OPEN:
|
||||||
Expression exp = parseExpression();
|
Expression exp = parseExpression();
|
||||||
entries.add(c -> c.addValue(new Value((int) exp.value(c))));
|
line.add((vals, context) -> vals.add(new Value((int) exp.value(context))));
|
||||||
expect(Tokenizer.Token.CLOSE);
|
expect(Tokenizer.Token.CLOSE);
|
||||||
break;
|
break;
|
||||||
case EOF:
|
case EOF:
|
||||||
case EOL:
|
case EOL:
|
||||||
for (int n = 0; n < count; n++) {
|
return line;
|
||||||
for (Entry entry : entries) entry.calculate(new Context(values).setVar("n", n));
|
|
||||||
addLine();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
default:
|
default:
|
||||||
throw newUnexpectedToken(token);
|
throw newUnexpectedToken(token);
|
||||||
}
|
}
|
||||||
@ -145,39 +164,6 @@ public class Parser {
|
|||||||
return parseExpression().value(new Context());
|
return parseExpression().value(new Context());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tokenizer.Token parseLine() throws IOException, ParserException {
|
|
||||||
while (true) {
|
|
||||||
Tokenizer.Token token = tok.next();
|
|
||||||
switch (token) {
|
|
||||||
case IDENT:
|
|
||||||
case NUMBER:
|
|
||||||
try {
|
|
||||||
values.add(new Value(tok.getIdent().toUpperCase()));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new ParserException(Lang.get("err_notANumber_N0_inLine_N1", tok.getIdent(), tok.getLine()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EOF:
|
|
||||||
case EOL:
|
|
||||||
addLine();
|
|
||||||
return token;
|
|
||||||
default:
|
|
||||||
throw newUnexpectedToken(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addLine() throws ParserException {
|
|
||||||
if (values.size() > 0) {
|
|
||||||
|
|
||||||
if (values.size() != names.size())
|
|
||||||
throw new ParserException(Lang.get("err_testDataExpected_N0_found_N1_numbersInLine_N2", names.size(), values.size(), tok.getLine()));
|
|
||||||
|
|
||||||
lines.add(values.toArray(new Value[names.size()]));
|
|
||||||
values.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expect(Tokenizer.Token token) throws IOException, ParserException {
|
private void expect(Tokenizer.Token token) throws IOException, ParserException {
|
||||||
Tokenizer.Token t = tok.next();
|
Tokenizer.Token t = tok.next();
|
||||||
if (t != token)
|
if (t != token)
|
||||||
@ -193,14 +179,10 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the test vectors
|
* @return the line emitter
|
||||||
*/
|
*/
|
||||||
public ArrayList<Value[]> getLines() {
|
public LineEmitter getLines() {
|
||||||
return lines;
|
return emitter;
|
||||||
}
|
|
||||||
|
|
||||||
private interface Entry {
|
|
||||||
void calculate(Context c) throws ParserException;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isToken(Tokenizer.Token t) throws IOException {
|
private boolean isToken(Tokenizer.Token t) throws IOException {
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.Value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to append some values to a table row
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public interface ValueAppender {
|
||||||
|
/**
|
||||||
|
* Appends some values to the given row
|
||||||
|
*
|
||||||
|
* @param values the row
|
||||||
|
* @param context the context to acess variables
|
||||||
|
* @throws ParserException ParserException
|
||||||
|
*/
|
||||||
|
void appendValues(ArrayList<Value> values, Context context) throws ParserException;
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.Value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the bits of an integer value to the given row.
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class ValueAppenderBits implements ValueAppender {
|
||||||
|
private final Expression expression;
|
||||||
|
private final int bitCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param bitCount the number of bits to append
|
||||||
|
* @param expression the expression to calculate the int value
|
||||||
|
*/
|
||||||
|
public ValueAppenderBits(int bitCount, Expression expression) {
|
||||||
|
this.bitCount = bitCount;
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendValues(ArrayList<Value> values, Context conext) throws ParserException {
|
||||||
|
long value = expression.value(conext);
|
||||||
|
long mask = 1L << (bitCount - 1);
|
||||||
|
for (int i = 0; i < bitCount; i++) {
|
||||||
|
boolean v = (value & mask) != 0;
|
||||||
|
values.add(new Value(v ? 1 : 0));
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package de.neemann.digital.testing;
|
package de.neemann.digital.testing;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.parser.LineCollector;
|
||||||
import de.neemann.digital.testing.parser.ParserException;
|
import de.neemann.digital.testing.parser.ParserException;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
@ -15,7 +16,10 @@ public class TestDataTest extends TestCase {
|
|||||||
|
|
||||||
public void testSetDataNonParseable() throws Exception {
|
public void testSetDataNonParseable() throws Exception {
|
||||||
TestData td = new TestData(DATA1);
|
TestData td = new TestData(DATA1);
|
||||||
assertEquals(4, td.getLines().size());
|
|
||||||
|
LineCollector cl = new LineCollector(td.getLines());
|
||||||
|
|
||||||
|
assertEquals(4, cl.getLines().size());
|
||||||
assertEquals(DATA1, td.getDataString());
|
assertEquals(DATA1, td.getDataString());
|
||||||
|
|
||||||
// try to set a non parsable string
|
// try to set a non parsable string
|
||||||
@ -31,7 +35,10 @@ public class TestDataTest extends TestCase {
|
|||||||
|
|
||||||
public void testSetDataParseable() throws Exception {
|
public void testSetDataParseable() throws Exception {
|
||||||
TestData td = new TestData(DATA1);
|
TestData td = new TestData(DATA1);
|
||||||
assertEquals(4, td.getLines().size());
|
|
||||||
|
LineCollector cl = new LineCollector(td.getLines());
|
||||||
|
|
||||||
|
assertEquals(4, cl.getLines().size());
|
||||||
assertEquals(DATA1, td.getDataString());
|
assertEquals(DATA1, td.getDataString());
|
||||||
|
|
||||||
// try to set a parsable string
|
// try to set a parsable string
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.Value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class LineCollector implements LineListener {
|
||||||
|
private final ArrayList<String> names;
|
||||||
|
private final ArrayList<Value[]> list;
|
||||||
|
|
||||||
|
public LineCollector(LineEmitter le) throws ParserException {
|
||||||
|
this.list = new ArrayList<>();
|
||||||
|
le.emitLines(this, new Context());
|
||||||
|
names = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineCollector(Parser parser) throws ParserException {
|
||||||
|
this.list = new ArrayList<>();
|
||||||
|
parser.getLines().emitLines(this, new Context());
|
||||||
|
names = parser.getNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(Value[] values) {
|
||||||
|
list.add(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Value[]> getLines() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getNames() {
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
}
|
@ -12,12 +12,12 @@ public class ParserExpressionTest extends TestCase {
|
|||||||
public void testParseExpression() throws Exception {
|
public void testParseExpression() throws Exception {
|
||||||
assertEquals(7, new Parser("2+5").getValue());
|
assertEquals(7, new Parser("2+5").getValue());
|
||||||
assertEquals(7, new Parser("9-2").getValue());
|
assertEquals(7, new Parser("9-2").getValue());
|
||||||
assertEquals(6, new Parser("2*n").getValue(new Context().setVar("n", 3)));
|
assertEquals(6, new Parser("2*n").getValue(new ContextWithVar("n").setValue(3)));
|
||||||
assertEquals(7, new Parser("2*n+1").getValue(new Context().setVar("n", 3)));
|
assertEquals(7, new Parser("2*n+1").getValue(new ContextWithVar("n").setValue(3)));
|
||||||
assertEquals(7, new Parser("1+2*n").getValue(new Context().setVar("n", 3)));
|
assertEquals(7, new Parser("1+2*n").getValue(new ContextWithVar("n").setValue(3)));
|
||||||
assertEquals(8, new Parser("2*(1+n)").getValue(new Context().setVar("n", 3)));
|
assertEquals(8, new Parser("2*(1+n)").getValue(new ContextWithVar("n").setValue(3)));
|
||||||
assertEquals(4, new Parser("2*(n-1)").getValue(new Context().setVar("n", 3)));
|
assertEquals(4, new Parser("2*(n-1)").getValue(new ContextWithVar("n").setValue(3)));
|
||||||
assertEquals(2, new Parser("(2*n)/3").getValue(new Context().setVar("n", 3)));
|
assertEquals(2, new Parser("(2*n)/3").getValue(new ContextWithVar("n").setValue(3)));
|
||||||
assertEquals(-1, new Parser("-1").getValue());
|
assertEquals(-1, new Parser("-1").getValue());
|
||||||
assertEquals(-2, new Parser("-1-1").getValue());
|
assertEquals(-2, new Parser("-1-1").getValue());
|
||||||
|
|
||||||
@ -37,10 +37,10 @@ public class ParserExpressionTest extends TestCase {
|
|||||||
|
|
||||||
assertEquals(-1, new Parser("~0").getValue());
|
assertEquals(-1, new Parser("~0").getValue());
|
||||||
|
|
||||||
assertEquals(1, new Parser("(n>>8)*(n&255)").getValue(new Context().setVar("n", 257)));
|
assertEquals(1, new Parser("(n>>8)*(n&255)").getValue(new ContextWithVar("n").setValue(257)));
|
||||||
|
|
||||||
assertEquals(0x11, new Parser("0x10+1").getValue());
|
assertEquals(0x11, new Parser("0x10+1").getValue());
|
||||||
assertEquals(6, new Parser("a*b").getValue(new Context().setVar("a", 2).setVar("b", 3)));
|
assertEquals(6, new Parser("a*b").getValue(new ContextWithVar(new ContextWithVar("a").setValue(2),"b").setValue(3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVarNotFound() throws IOException {
|
public void testVarNotFound() throws IOException {
|
||||||
@ -54,7 +54,7 @@ public class ParserExpressionTest extends TestCase {
|
|||||||
|
|
||||||
public void testInvalidExpressionClose() throws IOException {
|
public void testInvalidExpressionClose() throws IOException {
|
||||||
try {
|
try {
|
||||||
new Parser("n*3)").getValue(new Context().setVar("n", 2));
|
new Parser("n*3)").getValue(new ContextWithVar("n").setValue(2));
|
||||||
fail();
|
fail();
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
package de.neemann.digital.testing.parser;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.Value;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class ParserLoopTest extends TestCase {
|
||||||
|
|
||||||
|
public void testLoop() throws IOException, ParserException {
|
||||||
|
Parser parser = new Parser("A B\nloop(n,10)\n C (n*2)\nendloop").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
|
assertEquals(2, td.getNames().size());
|
||||||
|
assertEquals(10, td.getLines().size());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertEquals(Value.Type.CLOCK, td.getLines().get(i)[0].getType());
|
||||||
|
assertEquals(i * 2, td.getLines().get(i)[1].getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLoopVar() throws IOException, ParserException {
|
||||||
|
Parser parser = new Parser("A B\nloop(i,10)\n C (i*2)\nendloop").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
|
assertEquals(2, td.getNames().size());
|
||||||
|
assertEquals(10, td.getLines().size());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertEquals(Value.Type.CLOCK, td.getLines().get(i)[0].getType());
|
||||||
|
assertEquals(i * 2, td.getLines().get(i)[1].getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNested() throws IOException, ParserException {
|
||||||
|
Parser parser = new Parser("A B\nloop(i,10)\nloop(j,10)\n C ((i+j)*2)\nendloop\nendloop").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
|
assertEquals(2, td.getNames().size());
|
||||||
|
assertEquals(100, td.getLines().size());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
for (int j = 0; j < 10; j++) {
|
||||||
|
int ind = i * 10 + j;
|
||||||
|
assertEquals(Value.Type.CLOCK, td.getLines().get(ind)[0].getType());
|
||||||
|
assertEquals((i + j) * 2, td.getLines().get(ind)[1].getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLoopMultiLines() throws IOException, ParserException {
|
||||||
|
Parser parser = new Parser("A B\nloop(i,10)\n C (i*2)\n C (i*2+1)\nendloop").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
|
assertEquals(2, td.getNames().size());
|
||||||
|
assertEquals(20, td.getLines().size());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertEquals(Value.Type.CLOCK, td.getLines().get(i * 2)[0].getType());
|
||||||
|
assertEquals(i * 2, td.getLines().get(i * 2)[1].getValue());
|
||||||
|
assertEquals(Value.Type.CLOCK, td.getLines().get(i * 2 + 1)[0].getType());
|
||||||
|
assertEquals(i * 2 + 1, td.getLines().get(i * 2 + 1)[1].getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMissingEndloop() throws IOException, ParserException {
|
||||||
|
try {
|
||||||
|
new Parser("A B\nloop(i,10) C ((i+j)*2)").parse();
|
||||||
|
fail();
|
||||||
|
} catch (ParserException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnexpectedEndloop() throws IOException, ParserException {
|
||||||
|
try {
|
||||||
|
new Parser("A B\n C ((i+j)*2)\nendloop").parse();
|
||||||
|
fail();
|
||||||
|
} catch (ParserException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,9 @@ import java.io.IOException;
|
|||||||
public class ParserTest extends TestCase {
|
public class ParserTest extends TestCase {
|
||||||
|
|
||||||
public void testOk() throws TestingDataException, IOException, ParserException {
|
public void testOk() throws TestingDataException, IOException, ParserException {
|
||||||
Parser td = new Parser("A B\n0 1\n1 0\nX x").parse();
|
Parser parser = new Parser("A B\n0 1\n1 0\nX x").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
assertEquals(2, td.getNames().size());
|
assertEquals(2, td.getNames().size());
|
||||||
|
|
||||||
assertEquals(3, td.getLines().size());
|
assertEquals(3, td.getLines().size());
|
||||||
@ -36,7 +38,8 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testHex() throws TestingDataException, IOException, ParserException {
|
public void testHex() throws TestingDataException, IOException, ParserException {
|
||||||
Parser td = new Parser("A B\n0 0xff").parse();
|
Parser parser = new Parser("A B\n0 0xff").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
assertEquals(2, td.getNames().size());
|
assertEquals(2, td.getNames().size());
|
||||||
|
|
||||||
assertEquals(1, td.getLines().size());
|
assertEquals(1, td.getLines().size());
|
||||||
@ -50,7 +53,7 @@ public class ParserTest extends TestCase {
|
|||||||
|
|
||||||
public void testMissingValue() throws IOException, ParserException {
|
public void testMissingValue() throws IOException, ParserException {
|
||||||
try {
|
try {
|
||||||
new Parser("A B\n0 0\n1").parse();
|
new Parser("A B\n0 0\n1").parse().getLines().emitLines(values -> {}, new Context());
|
||||||
assertTrue(false);
|
assertTrue(false);
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
@ -67,7 +70,9 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testClock() throws Exception {
|
public void testClock() throws Exception {
|
||||||
Parser td = new Parser("A B\nC 1\nC 0").parse();
|
Parser parser = new Parser("A B\nC 1\nC 0").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
assertEquals(2, td.getNames().size());
|
assertEquals(2, td.getNames().size());
|
||||||
assertEquals(2, td.getLines().size());
|
assertEquals(2, td.getLines().size());
|
||||||
|
|
||||||
@ -78,7 +83,9 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testFor() throws IOException, ParserException {
|
public void testFor() throws IOException, ParserException {
|
||||||
Parser td = new Parser("A B\nrepeat(10) C (n*2)\n").parse();
|
Parser parser = new Parser("A B\nrepeat(10) C (n*2)\n").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
assertEquals(2, td.getNames().size());
|
assertEquals(2, td.getNames().size());
|
||||||
assertEquals(10, td.getLines().size());
|
assertEquals(10, td.getLines().size());
|
||||||
|
|
||||||
@ -89,7 +96,8 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testForBits() throws IOException, ParserException {
|
public void testForBits() throws IOException, ParserException {
|
||||||
Parser td = new Parser("A B C D \nrepeat(8) X bits(3,n)\n").parse();
|
Parser parser = new Parser("A B C D \nrepeat(8) X bits(3,n)\n").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
assertEquals(4, td.getNames().size());
|
assertEquals(4, td.getNames().size());
|
||||||
assertEquals(8, td.getLines().size());
|
assertEquals(8, td.getLines().size());
|
||||||
|
|
||||||
@ -102,19 +110,21 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testComment() throws TestingDataException, IOException, ParserException {
|
public void testComment() throws TestingDataException, IOException, ParserException {
|
||||||
Parser td = new Parser("#test\nA B\n1 1").parse();
|
Parser parser = new Parser("#test\nA B\n1 1").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
assertEquals(2, td.getNames().size());
|
assertEquals(2, td.getNames().size());
|
||||||
assertEquals(1, td.getLines().size());
|
assertEquals(1, td.getLines().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testHeader() throws TestingDataException, IOException, ParserException {
|
public void testHeader() throws TestingDataException, IOException, ParserException {
|
||||||
Parser td = new Parser("A B C D\n1 1 1 1").parse();
|
Parser parser = new Parser("A B C D\n1 1 1 1").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
assertEquals(4, td.getNames().size());
|
assertEquals(4, td.getNames().size());
|
||||||
assertEquals(1, td.getLines().size());
|
assertEquals(1, td.getLines().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEmptyLines() throws TestingDataException, IOException, ParserException {
|
public void testEmptyLines() throws TestingDataException, IOException, ParserException {
|
||||||
Parser td = new Parser("A_i B_i C_i-1 C_i S_i\n" +
|
Parser parser = new Parser("A_i B_i C_i-1 C_i S_i\n" +
|
||||||
" 0 0 0 0 0\n" +
|
" 0 0 0 0 0\n" +
|
||||||
" 0 0 1 0 1\n" +
|
" 0 0 1 0 1\n" +
|
||||||
" 0 1 0 0 1\n\n" +
|
" 0 1 0 0 1\n\n" +
|
||||||
@ -123,6 +133,8 @@ public class ParserTest extends TestCase {
|
|||||||
" 1 0 1 1 0\n" +
|
" 1 0 1 1 0\n" +
|
||||||
" 1 1 0 1 0\n" +
|
" 1 1 0 1 0\n" +
|
||||||
" 1 1 1 1 1\n").parse();
|
" 1 1 1 1 1\n").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
assertEquals(5, td.getNames().size());
|
assertEquals(5, td.getNames().size());
|
||||||
assertEquals(8, td.getLines().size());
|
assertEquals(8, td.getLines().size());
|
||||||
|
|
||||||
@ -132,11 +144,11 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testBUG1() throws IOException, ParserException {
|
public void testBUG1() throws IOException, ParserException {
|
||||||
Parser td = new Parser("C_i-1 A B C S\n" +
|
Parser parser = new Parser("C_i-1 A B C S\n" +
|
||||||
"repeat(1<<16) 0 (n>>8) (n&255) ((n>>8)*(n&255)) 0").parse();
|
"repeat(1<<16) 0 (n>>8) (n&255) ((n>>8)*(n&255)) 0").parse();
|
||||||
|
LineCollector td = new LineCollector(parser);
|
||||||
assertEquals(5, td.getNames().size());
|
assertEquals(5, td.getNames().size());
|
||||||
assertEquals(1<<16, td.getLines().size());
|
assertEquals(1<<16, td.getLines().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user