mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-28 23:45:17 -04:00
simplified test data parser
This commit is contained in:
parent
a6759f0073
commit
ba776b8ba4
@ -43,7 +43,7 @@ public class Parser {
|
|||||||
*/
|
*/
|
||||||
public Parser parse() throws IOException, ParserException {
|
public Parser parse() throws IOException, ParserException {
|
||||||
parseHeader();
|
parseHeader();
|
||||||
emitter = parseValues(false);
|
emitter = parseRows(false);
|
||||||
expect(Tokenizer.Token.EOF);
|
expect(Tokenizer.Token.EOF);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ 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 LineEmitter parseValues(boolean loop) throws IOException, ParserException {
|
private LineEmitter parseRows(boolean loop) throws IOException, ParserException {
|
||||||
LineEmitterList list = new LineEmitterList();
|
LineEmitterList list = new LineEmitterList();
|
||||||
while (true) {
|
while (true) {
|
||||||
Tokenizer.Token t = tok.peek();
|
Tokenizer.Token t = tok.peek();
|
||||||
@ -80,40 +80,38 @@ public class Parser {
|
|||||||
if (loop)
|
if (loop)
|
||||||
throw newUnexpectedToken(t);
|
throw newUnexpectedToken(t);
|
||||||
return list.minimize();
|
return list.minimize();
|
||||||
case NUMBER:
|
case BITS:
|
||||||
list.add(parseLine());
|
case OPEN:
|
||||||
break;
|
|
||||||
case IDENT:
|
case IDENT:
|
||||||
if (tok.getIdent().equals("end")) {
|
case NUMBER:
|
||||||
tok.consume();
|
list.add(parseSingleRow());
|
||||||
expect(Tokenizer.Token.IDENT);
|
break;
|
||||||
if (!tok.getIdent().equals("loop"))
|
case END:
|
||||||
throw newUnexpectedToken(t);
|
tok.consume();
|
||||||
if (!loop)
|
expect(Tokenizer.Token.LOOP);
|
||||||
throw newUnexpectedToken(t);
|
if (!loop)
|
||||||
return list.minimize();
|
throw newUnexpectedToken(t);
|
||||||
} else if (tok.getIdent().equals("repeat")) {
|
return list.minimize();
|
||||||
tok.consume();
|
case REPEAT:
|
||||||
expect(Tokenizer.Token.OPEN);
|
tok.consume();
|
||||||
int count = (int) parseInt();
|
expect(Tokenizer.Token.OPEN);
|
||||||
if (count > 1 << 16)
|
int count = (int) parseInt();
|
||||||
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
if (count > 1 << 16)
|
||||||
expect(Tokenizer.Token.CLOSE);
|
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
||||||
list.add(new LineEmitterRepeat("n", count, parseLine()));
|
expect(Tokenizer.Token.CLOSE);
|
||||||
} else if (tok.getIdent().equals("loop")) {
|
list.add(new LineEmitterRepeat("n", count, parseSingleRow()));
|
||||||
tok.consume();
|
break;
|
||||||
expect(Tokenizer.Token.OPEN);
|
case LOOP:
|
||||||
expect(Tokenizer.Token.IDENT);
|
tok.consume();
|
||||||
String var = tok.getIdent();
|
expect(Tokenizer.Token.OPEN);
|
||||||
expect(Tokenizer.Token.COMMA);
|
expect(Tokenizer.Token.IDENT);
|
||||||
int count = (int) parseInt();
|
String var = tok.getIdent();
|
||||||
if (count > 1 << 16)
|
expect(Tokenizer.Token.COMMA);
|
||||||
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
count = (int) parseInt();
|
||||||
expect(Tokenizer.Token.CLOSE);
|
if (count > 1 << 16)
|
||||||
list.add(new LineEmitterRepeat(var, count, parseValues(true)));
|
throw new ParserException(Lang.get("err_toManyTestEntries"));
|
||||||
} else {
|
expect(Tokenizer.Token.CLOSE);
|
||||||
list.add(parseLine());
|
list.add(new LineEmitterRepeat(var, count, parseRows(true)));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw newUnexpectedToken(t);
|
throw newUnexpectedToken(t);
|
||||||
@ -121,7 +119,7 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LineEmitter parseLine() throws IOException, ParserException {
|
private LineEmitter parseSingleRow() throws IOException, ParserException {
|
||||||
LineEmitterSimple line = null;
|
LineEmitterSimple line = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
Tokenizer.Token token = tok.next();
|
Tokenizer.Token token = tok.next();
|
||||||
@ -132,25 +130,24 @@ public class Parser {
|
|||||||
Value num = new Value(tok.getIdent());
|
Value num = new Value(tok.getIdent());
|
||||||
line.add((vals, conext) -> vals.add(num));
|
line.add((vals, conext) -> vals.add(num));
|
||||||
break;
|
break;
|
||||||
|
case BITS:
|
||||||
|
expect(Tokenizer.Token.OPEN);
|
||||||
|
int bitCount = (int) parseInt();
|
||||||
|
expect(Tokenizer.Token.COMMA);
|
||||||
|
Expression exp = parseExpression();
|
||||||
|
line.add(new ValueAppenderBits(bitCount, exp));
|
||||||
|
expect(Tokenizer.Token.CLOSE);
|
||||||
|
break;
|
||||||
case IDENT:
|
case IDENT:
|
||||||
if (tok.getIdent().equals("bits")) {
|
try {
|
||||||
expect(Tokenizer.Token.OPEN);
|
final Value value = new Value(tok.getIdent().toUpperCase());
|
||||||
int bitCount = (int) parseInt();
|
line.add((vals, context) -> vals.add(value));
|
||||||
expect(Tokenizer.Token.COMMA);
|
} catch (NumberFormatException e) {
|
||||||
Expression exp = parseExpression();
|
throw new ParserException(Lang.get("err_notANumber_N0_inLine_N1", tok.getIdent(), tok.getLine()));
|
||||||
line.add(new ValueAppenderBits(bitCount, exp));
|
|
||||||
expect(Tokenizer.Token.CLOSE);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
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();
|
exp = parseExpression();
|
||||||
line.add((vals, context) -> vals.add(new Value((int) exp.value(context))));
|
line.add((vals, context) -> vals.add(new Value((int) exp.value(context))));
|
||||||
expect(Tokenizer.Token.CLOSE);
|
expect(Tokenizer.Token.CLOSE);
|
||||||
break;
|
break;
|
||||||
|
@ -2,6 +2,7 @@ package de.neemann.digital.testing.parser;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple tokenizer to tokenize boolean expressions.
|
* Simple tokenizer to tokenize boolean expressions.
|
||||||
@ -10,7 +11,19 @@ import java.io.Reader;
|
|||||||
*/
|
*/
|
||||||
public class Tokenizer {
|
public class Tokenizer {
|
||||||
|
|
||||||
enum Token {UNKNOWN, IDENT, AND, OR, NOT, OPEN, CLOSE, NUMBER, EOL, EOF, SHIFTLEFT, SHIFTRIGHT, COMMA, EQUAL, ADD, SUB, MUL, GREATER, SMALER, DIV}
|
enum Token {
|
||||||
|
UNKNOWN, IDENT, AND, OR, NOT, OPEN, CLOSE, NUMBER, EOL, EOF, SHIFTLEFT, SHIFTRIGHT, COMMA, EQUAL,
|
||||||
|
ADD, SUB, MUL, GREATER, SMALER, DIV, END, LOOP, REPEAT, BITS
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashMap<String, Token> statementMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
statementMap.put("end", Token.END);
|
||||||
|
statementMap.put("loop", Token.LOOP);
|
||||||
|
statementMap.put("repeat", Token.REPEAT);
|
||||||
|
statementMap.put("bits", Token.BITS);
|
||||||
|
}
|
||||||
|
|
||||||
private final Reader in;
|
private final Reader in;
|
||||||
private Token token;
|
private Token token;
|
||||||
@ -136,6 +149,8 @@ public class Tokenizer {
|
|||||||
wasChar = false;
|
wasChar = false;
|
||||||
}
|
}
|
||||||
} while (wasChar);
|
} while (wasChar);
|
||||||
|
token = statementMap.get(builder.toString());
|
||||||
|
if (token == null) token = Token.IDENT;
|
||||||
} else if (isNumberChar(c)) {
|
} else if (isNumberChar(c)) {
|
||||||
token = Token.NUMBER;
|
token = Token.NUMBER;
|
||||||
builder.setLength(0);
|
builder.setLength(0);
|
||||||
|
@ -37,7 +37,7 @@ public class ParserLoopTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testNested() throws IOException, ParserException {
|
public void testNested() throws IOException, ParserException {
|
||||||
Parser parser = new Parser("A B\nloop(i,10)\nloop(j,10)\n C ((i+j)*2)\nend loop\nend loop").parse();
|
Parser parser = new Parser("A B\nloop(i,10)\nloop(j,10)\n C (i+j*2)\nend loop\nend loop").parse();
|
||||||
LineCollector td = new LineCollector(parser);
|
LineCollector td = new LineCollector(parser);
|
||||||
|
|
||||||
assertEquals(2, td.getNames().size());
|
assertEquals(2, td.getNames().size());
|
||||||
@ -47,7 +47,7 @@ public class ParserLoopTest extends TestCase {
|
|||||||
for (int j = 0; j < 10; j++) {
|
for (int j = 0; j < 10; j++) {
|
||||||
int ind = i * 10 + j;
|
int ind = i * 10 + j;
|
||||||
assertEquals(Value.Type.CLOCK, td.getLines().get(ind)[0].getType());
|
assertEquals(Value.Type.CLOCK, td.getLines().get(ind)[0].getType());
|
||||||
assertEquals((i + j) * 2, td.getLines().get(ind)[1].getValue());
|
assertEquals(i + j * 2, td.getLines().get(ind)[1].getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ public class ParserLoopTest extends TestCase {
|
|||||||
|
|
||||||
public void testMissingEndLoop() throws IOException, ParserException {
|
public void testMissingEndLoop() throws IOException, ParserException {
|
||||||
try {
|
try {
|
||||||
new Parser("A B\nloop(i,10) C ((i+j)*2)").parse();
|
new Parser("A B\nloop(i,10) C (i)").parse();
|
||||||
fail();
|
fail();
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ public class ParserLoopTest extends TestCase {
|
|||||||
|
|
||||||
public void testUnexpectedEndLoop() throws IOException, ParserException {
|
public void testUnexpectedEndLoop() throws IOException, ParserException {
|
||||||
try {
|
try {
|
||||||
new Parser("A B\n C ((i+j)*2)\nend loop").parse();
|
new Parser("A B\n C 1\nend loop").parse();
|
||||||
fail();
|
fail();
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ public class ParserLoopTest extends TestCase {
|
|||||||
|
|
||||||
public void testIncompleteEndLoop() throws IOException, ParserException {
|
public void testIncompleteEndLoop() throws IOException, ParserException {
|
||||||
try {
|
try {
|
||||||
new Parser("A B\n C ((i+j)*2)\nend").parse();
|
new Parser("A B\n C 1\nend").parse();
|
||||||
fail();
|
fail();
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user