simplified test data parser

This commit is contained in:
hneemann 2017-04-19 16:41:41 +02:00
parent a6759f0073
commit ba776b8ba4
3 changed files with 69 additions and 57 deletions

View File

@ -43,7 +43,7 @@ public class Parser {
*/
public Parser parse() throws IOException, ParserException {
parseHeader();
emitter = parseValues(false);
emitter = parseRows(false);
expect(Tokenizer.Token.EOF);
return this;
}
@ -69,7 +69,7 @@ public class Parser {
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();
while (true) {
Tokenizer.Token t = tok.peek();
@ -80,40 +80,38 @@ public class Parser {
if (loop)
throw newUnexpectedToken(t);
return list.minimize();
case NUMBER:
list.add(parseLine());
break;
case BITS:
case OPEN:
case IDENT:
if (tok.getIdent().equals("end")) {
tok.consume();
expect(Tokenizer.Token.IDENT);
if (!tok.getIdent().equals("loop"))
throw newUnexpectedToken(t);
if (!loop)
throw newUnexpectedToken(t);
return list.minimize();
} else if (tok.getIdent().equals("repeat")) {
tok.consume();
expect(Tokenizer.Token.OPEN);
int count = (int) parseInt();
if (count > 1 << 16)
throw new ParserException(Lang.get("err_toManyTestEntries"));
expect(Tokenizer.Token.CLOSE);
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 {
list.add(parseLine());
}
case NUMBER:
list.add(parseSingleRow());
break;
case END:
tok.consume();
expect(Tokenizer.Token.LOOP);
if (!loop)
throw newUnexpectedToken(t);
return list.minimize();
case REPEAT:
tok.consume();
expect(Tokenizer.Token.OPEN);
int count = (int) parseInt();
if (count > 1 << 16)
throw new ParserException(Lang.get("err_toManyTestEntries"));
expect(Tokenizer.Token.CLOSE);
list.add(new LineEmitterRepeat("n", count, parseSingleRow()));
break;
case LOOP:
tok.consume();
expect(Tokenizer.Token.OPEN);
expect(Tokenizer.Token.IDENT);
String var = tok.getIdent();
expect(Tokenizer.Token.COMMA);
count = (int) parseInt();
if (count > 1 << 16)
throw new ParserException(Lang.get("err_toManyTestEntries"));
expect(Tokenizer.Token.CLOSE);
list.add(new LineEmitterRepeat(var, count, parseRows(true)));
break;
default:
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;
while (true) {
Tokenizer.Token token = tok.next();
@ -132,25 +130,24 @@ public class Parser {
Value num = new Value(tok.getIdent());
line.add((vals, conext) -> vals.add(num));
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:
if (tok.getIdent().equals("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);
} 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()));
}
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;
case OPEN:
Expression exp = parseExpression();
exp = parseExpression();
line.add((vals, context) -> vals.add(new Value((int) exp.value(context))));
expect(Tokenizer.Token.CLOSE);
break;

View File

@ -2,6 +2,7 @@ package de.neemann.digital.testing.parser;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
/**
* Simple tokenizer to tokenize boolean expressions.
@ -10,7 +11,19 @@ import java.io.Reader;
*/
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 Token token;
@ -136,6 +149,8 @@ public class Tokenizer {
wasChar = false;
}
} while (wasChar);
token = statementMap.get(builder.toString());
if (token == null) token = Token.IDENT;
} else if (isNumberChar(c)) {
token = Token.NUMBER;
builder.setLength(0);

View File

@ -37,7 +37,7 @@ public class ParserLoopTest extends TestCase {
}
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);
assertEquals(2, td.getNames().size());
@ -47,7 +47,7 @@ public class ParserLoopTest extends TestCase {
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());
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 {
try {
new Parser("A B\nloop(i,10) C ((i+j)*2)").parse();
new Parser("A B\nloop(i,10) C (i)").parse();
fail();
} catch (ParserException e) {
}
@ -77,7 +77,7 @@ public class ParserLoopTest extends TestCase {
public void testUnexpectedEndLoop() throws IOException, ParserException {
try {
new Parser("A B\n C ((i+j)*2)\nend loop").parse();
new Parser("A B\n C 1\nend loop").parse();
fail();
} catch (ParserException e) {
}
@ -85,7 +85,7 @@ public class ParserLoopTest extends TestCase {
public void testIncompleteEndLoop() throws IOException, ParserException {
try {
new Parser("A B\n C ((i+j)*2)\nend").parse();
new Parser("A B\n C 1\nend").parse();
fail();
} catch (ParserException e) {
}