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 { 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;

View File

@ -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);

View File

@ -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) {
} }