mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-24 21:46:00 -04:00
cleanup of hgs parser, see #708
This commit is contained in:
parent
45edbdf7c6
commit
3b6dffc335
@ -9,6 +9,7 @@ import de.neemann.digital.core.Bits;
|
||||
import de.neemann.digital.hdl.hgs.function.FirstClassFunction;
|
||||
import de.neemann.digital.hdl.hgs.function.FirstClassFunctionCall;
|
||||
import de.neemann.digital.hdl.hgs.refs.*;
|
||||
import de.neemann.digital.testing.parser.OperatorPrecedence;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -337,14 +338,6 @@ public class Parser {
|
||||
return false;
|
||||
}
|
||||
|
||||
private Tokenizer.Token nextIsIn(Tokenizer.Token... ts) throws IOException {
|
||||
Tokenizer.Token next = tok.peek();
|
||||
for (Tokenizer.Token t : ts)
|
||||
if (next == t)
|
||||
return tok.next();
|
||||
return null;
|
||||
}
|
||||
|
||||
private void expect(Tokenizer.Token token) throws IOException, ParserException {
|
||||
Tokenizer.Token t = tok.next();
|
||||
if (t != token)
|
||||
@ -390,128 +383,26 @@ public class Parser {
|
||||
}
|
||||
|
||||
private Expression parseExpression() throws IOException, ParserException {
|
||||
Expression a = parseOR();
|
||||
Tokenizer.Token t = nextIsIn(LESS, LESSEQUAL, EQUAL, NOTEQUAL, GREATER, GREATEREQUAL);
|
||||
if (t != null) {
|
||||
Expression b = parseOR();
|
||||
switch (t) {
|
||||
case EQUAL:
|
||||
return c -> Value.equals(a.value(c), b.value(c));
|
||||
case NOTEQUAL:
|
||||
return c -> !Value.equals(a.value(c), b.value(c));
|
||||
case LESS:
|
||||
return c -> Value.less(a.value(c), b.value(c));
|
||||
case LESSEQUAL:
|
||||
return c -> Value.lessEqual(a.value(c), b.value(c));
|
||||
case GREATER:
|
||||
return c -> Value.less(b.value(c), a.value(c));
|
||||
case GREATEREQUAL:
|
||||
return c -> Value.lessEqual(b.value(c), a.value(c));
|
||||
default:
|
||||
throw newUnexpectedToken(t);
|
||||
}
|
||||
} else
|
||||
return a;
|
||||
return parseExpression(OperatorPrecedence.lowest());
|
||||
}
|
||||
|
||||
private Expression parseOR() throws IOException, ParserException {
|
||||
Expression ac = parseXOR();
|
||||
while (nextIs(OR)) {
|
||||
private Expression parseExpression(OperatorPrecedence op) throws IOException, ParserException {
|
||||
Next next = getNextParser(op.getNextHigherPrecedence());
|
||||
Expression ac = next.next();
|
||||
while (tok.peek().getPrecedence() == op) {
|
||||
Tokenizer.Binary function = tok.next().getBinary();
|
||||
Expression a = ac;
|
||||
Expression b = parseXOR();
|
||||
ac = c -> Value.or(a.value(c), b.value(c));
|
||||
Expression b = next.next();
|
||||
ac = (c) -> function.op(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseXOR() throws IOException, ParserException {
|
||||
Expression ac = parseAND();
|
||||
while (nextIs(XOR)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseAND();
|
||||
ac = c -> Value.xor(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseAND() throws IOException, ParserException {
|
||||
Expression ac = parseShiftRight();
|
||||
while (nextIs(AND)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseShiftRight();
|
||||
ac = c -> Value.and(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseShiftRight() throws IOException, ParserException {
|
||||
Expression ac = parseShiftLeft();
|
||||
while (nextIs(SHIFTRIGHT)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseShiftLeft();
|
||||
ac = c -> Value.toLong(a.value(c)) >>> Value.toLong(b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseShiftLeft() throws IOException, ParserException {
|
||||
Expression ac = parseAdd();
|
||||
while (nextIs(SHIFTLEFT)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseAdd();
|
||||
ac = c -> Value.toLong(a.value(c)) << Value.toLong(b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseAdd() throws IOException, ParserException {
|
||||
Expression ac = parseSub();
|
||||
while (nextIs(ADD)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseSub();
|
||||
ac = c -> Value.add(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseSub() throws IOException, ParserException {
|
||||
Expression ac = parseMul();
|
||||
while (nextIs(SUB)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseMul();
|
||||
ac = c -> Value.sub(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseMul() throws IOException, ParserException {
|
||||
Expression ac = parseDiv();
|
||||
while (nextIs(MUL)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseDiv();
|
||||
ac = c -> Value.mul(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseDiv() throws IOException, ParserException {
|
||||
Expression ac = parseMod();
|
||||
while (nextIs(DIV)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseMod();
|
||||
ac = c -> Value.div(a.value(c), b.value(c));
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
private Expression parseMod() throws IOException, ParserException {
|
||||
Expression ac = parseIdent();
|
||||
while (nextIs(MOD)) {
|
||||
Expression a = ac;
|
||||
Expression b = parseIdent();
|
||||
ac = c -> Value.toLong(a.value(c)) % Value.toLong(b.value(c));
|
||||
}
|
||||
return ac;
|
||||
private Next getNextParser(OperatorPrecedence pr) {
|
||||
if (pr == null)
|
||||
return this::parseIdent;
|
||||
else
|
||||
return () -> parseExpression(pr);
|
||||
}
|
||||
|
||||
private Expression parseIdent() throws IOException, ParserException {
|
||||
@ -602,6 +493,10 @@ public class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
private interface Next {
|
||||
Expression next() throws IOException, ParserException;
|
||||
}
|
||||
|
||||
private FirstClassFunction parseFunction() throws IOException, ParserException {
|
||||
expect(OPEN);
|
||||
ArrayList<String> args = new ArrayList<>();
|
||||
|
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package de.neemann.digital.hdl.hgs;
|
||||
|
||||
import de.neemann.digital.testing.parser.OperatorPrecedence;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.HashMap;
|
||||
@ -14,36 +16,76 @@ import java.util.HashMap;
|
||||
*/
|
||||
class Tokenizer {
|
||||
|
||||
enum Token {
|
||||
UNKNOWN, IDENT, AND, OR, XOR, NOT, OPEN, CLOSE, NUMBER, EOL, EOF, SHIFTLEFT, SHIFTRIGHT, COMMA, EQUAL,
|
||||
ADD, SUB, MUL, GREATER, LESS, DIV, MOD, END, IF, ELSE, FOR, WHILE, SEMICOLON, NOTEQUAL, STRING,
|
||||
OPENBRACE, CLOSEDBRACE, CODEEND, OPENSQUARE, CLOSEDSQUARE, DOT, FUNC, GREATEREQUAL, LESSEQUAL,
|
||||
REPEAT, RETURN, COLON, UNTIL, DOUBLE, EXPORT, TRUE, FALSE
|
||||
interface Binary {
|
||||
Object op(Object a, Object b) throws HGSEvalException;
|
||||
}
|
||||
|
||||
private static HashMap<String, Token> statementMap = new HashMap<>();
|
||||
enum Token {
|
||||
UNKNOWN, IDENT, OPEN, CLOSE, NUMBER, EOL, EOF, COMMA, NOT,
|
||||
OR(OperatorPrecedence.OR, Value::or),
|
||||
XOR(OperatorPrecedence.XOR, Value::xor),
|
||||
AND(OperatorPrecedence.AND, Value::and),
|
||||
EQUAL(OperatorPrecedence.EQUAL, Value::equals),
|
||||
NOTEQUAL(OperatorPrecedence.EQUAL, (a, b) -> !Value.equals(a, b)),
|
||||
ADD(OperatorPrecedence.ADD, Value::add),
|
||||
SUB(OperatorPrecedence.ADD, Value::sub),
|
||||
MUL(OperatorPrecedence.MUL, Value::mul),
|
||||
DIV(OperatorPrecedence.MUL, Value::div),
|
||||
MOD(OperatorPrecedence.MUL, (a, b) -> Value.toLong(a) % Value.toLong(b)),
|
||||
LESS(OperatorPrecedence.COMPARE, Value::less),
|
||||
LESSEQUAL(OperatorPrecedence.COMPARE, Value::lessEqual),
|
||||
GREATER(OperatorPrecedence.COMPARE, (a, b) -> Value.less(b, a)),
|
||||
GREATEREQUAL(OperatorPrecedence.COMPARE, (a, b) -> Value.lessEqual(b, a)),
|
||||
SHIFTLEFT(OperatorPrecedence.SHIFT, (a, b) -> Value.toLong(a) << Value.toLong(b)),
|
||||
SHIFTRIGHT(OperatorPrecedence.SHIFT, (a, b) -> Value.toLong(a) >>> Value.toLong(b)),
|
||||
END, IF, ELSE, FOR, WHILE, SEMICOLON, STRING,
|
||||
OPENBRACE, CLOSEDBRACE, CODEEND, OPENSQUARE, CLOSEDSQUARE, DOT, FUNC,
|
||||
REPEAT, RETURN, COLON, UNTIL, DOUBLE, EXPORT, TRUE, FALSE;
|
||||
|
||||
private final OperatorPrecedence precedence;
|
||||
private final Binary binary;
|
||||
|
||||
Token() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
Token(OperatorPrecedence precedence, Binary binary) {
|
||||
this.precedence = precedence;
|
||||
this.binary = binary;
|
||||
}
|
||||
|
||||
public OperatorPrecedence getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
public Binary getBinary() {
|
||||
return binary;
|
||||
}
|
||||
}
|
||||
|
||||
private static final HashMap<String, Token> STATEMENT_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
statementMap.put("if", Token.IF);
|
||||
statementMap.put("else", Token.ELSE);
|
||||
statementMap.put("for", Token.FOR);
|
||||
statementMap.put("while", Token.WHILE);
|
||||
statementMap.put("func", Token.FUNC);
|
||||
statementMap.put("repeat", Token.REPEAT);
|
||||
statementMap.put("until", Token.UNTIL);
|
||||
statementMap.put("return", Token.RETURN);
|
||||
statementMap.put("export", Token.EXPORT);
|
||||
statementMap.put("true", Token.TRUE);
|
||||
statementMap.put("false", Token.FALSE);
|
||||
STATEMENT_MAP.put("if", Token.IF);
|
||||
STATEMENT_MAP.put("else", Token.ELSE);
|
||||
STATEMENT_MAP.put("for", Token.FOR);
|
||||
STATEMENT_MAP.put("while", Token.WHILE);
|
||||
STATEMENT_MAP.put("func", Token.FUNC);
|
||||
STATEMENT_MAP.put("repeat", Token.REPEAT);
|
||||
STATEMENT_MAP.put("until", Token.UNTIL);
|
||||
STATEMENT_MAP.put("return", Token.RETURN);
|
||||
STATEMENT_MAP.put("export", Token.EXPORT);
|
||||
STATEMENT_MAP.put("true", Token.TRUE);
|
||||
STATEMENT_MAP.put("false", Token.FALSE);
|
||||
}
|
||||
|
||||
private final Reader in;
|
||||
private final StringBuilder builder;
|
||||
private final String srcFile;
|
||||
private Token token;
|
||||
private boolean isToken;
|
||||
private StringBuilder builder;
|
||||
private boolean isUnreadChar = false;
|
||||
private int unreadChar;
|
||||
private String srcFile;
|
||||
private int line = 1;
|
||||
|
||||
/**
|
||||
@ -301,7 +343,7 @@ class Tokenizer {
|
||||
wasChar = false;
|
||||
}
|
||||
} while (wasChar);
|
||||
token = statementMap.get(builder.toString());
|
||||
token = STATEMENT_MAP.get(builder.toString());
|
||||
if (token == null) token = Token.IDENT;
|
||||
}
|
||||
|
||||
@ -394,7 +436,7 @@ class Tokenizer {
|
||||
isToken = false;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
while ((c = readChar())>0) {
|
||||
while ((c = readChar()) > 0) {
|
||||
if (c == '<' || c == '{') {
|
||||
if (isNextChar('?')) {
|
||||
return sb.toString();
|
||||
|
Loading…
x
Reference in New Issue
Block a user