diff --git a/src/main/java/net/simon987/mar/server/assembly/Assembler.java b/src/main/java/net/simon987/mar/server/assembly/Assembler.java index 9369fcb..f82fd80 100755 --- a/src/main/java/net/simon987/mar/server/assembly/Assembler.java +++ b/src/main/java/net/simon987/mar/server/assembly/Assembler.java @@ -304,6 +304,10 @@ public class Assembler { } } + private static final Pattern EQU_PATTERN = Pattern.compile("([\\w]+)[^\\S\\n]+EQU[^\\S\\n]+(.+)", + Pattern.CASE_INSENSITIVE + ); + /** * Check for and handle the EQU instruction * @@ -311,30 +315,25 @@ public class Assembler { * @param labels Map of labels. Constants will be added as labels * @param currentLine Current line number */ - private static void checkForEQUInstruction(String line, HashMap labels, int currentLine) + private static void checkForEQUInstruction(String line, HashMap labels, + int currentLine, RegisterSet registers) throws AssemblyException { /* the EQU pseudo instruction is equivalent to the #define compiler directive in C/C++ * usage: constant_name EQU * A constant treated the same way as a label. */ line = line.trim(); - String[] tokens = line.split("\\s+"); + Matcher matcher = EQU_PATTERN.matcher(line); - if (line.toUpperCase().matches(".*\\bEQU\\b.*")) { - if (tokens[1].toUpperCase().equals("EQU") && tokens.length == 3) { - try { - //Save value as a label - labels.put(tokens[0], (char) (int) Integer.decode(tokens[2])); - } catch (NumberFormatException e) { - throw new InvalidOperandException("Usage: constant_name EQU immediate_value", currentLine); - } - } else { - throw new InvalidOperandException("Usage: constant_name EQU immediate_value", currentLine); - } - + if (matcher.lookingAt()) { + //Save value as a label + TokenParser parser = new TokenParser(matcher.group(2), currentLine, labels); + char value = (char)parser.parseConstExpression(); + labels.put(matcher.group(1), value); throw new PseudoInstructionException(currentLine); } + } /** @@ -452,7 +451,7 @@ public class Assembler { //Check for pseudo instructions checkForSectionDeclaration(line, result, currentLine, currentOffset); - checkForEQUInstruction(line, result.labels, currentLine); + checkForEQUInstruction(line, result.labels, currentLine, registerSet); checkForORGInstruction(line, result, currentLine); for (String label : result.labels.keySet()) { diff --git a/src/main/java/net/simon987/mar/server/assembly/Operand.java b/src/main/java/net/simon987/mar/server/assembly/Operand.java index 7029e78..6be8aac 100755 --- a/src/main/java/net/simon987/mar/server/assembly/Operand.java +++ b/src/main/java/net/simon987/mar/server/assembly/Operand.java @@ -27,8 +27,8 @@ public class Operand { private OperandType type; /** - * Value of the the operand, this is the part that will - * written into the instruction. + * Value of the operand, this is the part that will + * be written into the instruction. */ private int value = 0; @@ -73,40 +73,59 @@ public class Operand { this.text = text.replace(",", ""); this.text = this.text.trim(); + if (parseReg(this.text, registerSet)) { + return; + } + if (parseConstExpression(line, labels)) { + type = OperandType.IMMEDIATE16; + value = IMMEDIATE_VALUE; + return; + } + if (this.text.startsWith("[") && this.text.endsWith("]")) { - if (!parseImmediate(this.text) && !parseReg(this.text, registerSet) && !parseLabel(this.text, labels)) { - if (this.text.startsWith("[") && this.text.endsWith("]")) { - - //Remove []s - this.text = this.text.substring(1, this.text.length() - 1); - - if (parseImmediate(this.text) || parseLabel(this.text, labels)) { - //Operand refers to memory - type = OperandType.MEMORY_IMM16; - value = Operand.IMMEDIATE_VALUE_MEM; - - } else if (!parseRegExpr(registerSet, labels)) { - - if (labels == null) { - type = OperandType.MEMORY_IMM16; - data = 0; - } else { - throw new InvalidOperandException("Invalid operand " + this.text, line); - } - - } - - } else { + //Remove []s + this.text = this.text.substring(1, this.text.length() - 1); + if (parseConstExpression(line, labels)) { + type = OperandType.MEMORY_IMM16; + value = Operand.IMMEDIATE_VALUE_MEM; + return; + } + if (!parseRegExpr(registerSet, labels)) { if (labels == null) { - type = OperandType.IMMEDIATE16; + type = OperandType.MEMORY_IMM16; data = 0; } else { throw new InvalidOperandException("Invalid operand " + this.text, line); } + + } + } else { + if (labels == null) { + type = OperandType.IMMEDIATE16; + data = 0; + } else { + throw new InvalidOperandException("Invalid operand " + this.text, line); } } } + /** + * Parses a constant expression made of operators, literals, and labels as a single immediate. + * Sets data to this value. + * @param line The current line of compilation + * @param labels The labels known to the compiler + * @return true on success, false otherwise. + */ + private boolean parseConstExpression(int line, HashMap labels) { + TokenParser parser = new TokenParser(text, line, labels); + if (labels == null) return false; + try { + data = parser.parseConstExpression(); + return true; + } catch (AssemblyException ex) { + return false; + } + } /** * Attempt to parse an integer diff --git a/src/main/java/net/simon987/mar/server/assembly/TokenParser.java b/src/main/java/net/simon987/mar/server/assembly/TokenParser.java index 2423542..66498cb 100644 --- a/src/main/java/net/simon987/mar/server/assembly/TokenParser.java +++ b/src/main/java/net/simon987/mar/server/assembly/TokenParser.java @@ -2,6 +2,7 @@ package net.simon987.mar.server.assembly; import java.util.HashMap; import java.util.Map; +import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -147,6 +148,64 @@ public class TokenParser { } } + /** + * Interface allowing parse states to be manipulated, evaluated, and stacked. + */ + private static class ParseOperator { + public int getPrecedence() { + return 0; + } + public int apply(int other) { + return other; + } + + public final int closeExpect; + + public ParseOperator(int closeExpect) { + this.closeExpect = closeExpect; + } + } + + private static class ParseOperatorUnary extends ParseOperator { + TokenParser.UnaryOperatorType op; + @Override + public int getPrecedence() { + return 0; + } + + @Override + public int apply(int other) { + return op.apply(other); + } + + public ParseOperatorUnary(int closeExpect, TokenParser.UnaryOperatorType op) { + super(closeExpect); + this.op = op; + } + } + + private static class ParseOperatorBinary extends ParseOperator { + private final TokenParser.BinaryOperatorType op; + private final int value; + @Override + public int getPrecedence() { + return op.precedence; + } + + @Override + public int apply(int other) { + return op.apply(value, other); + } + + public ParseOperatorBinary(int closeExpect, TokenParser.BinaryOperatorType op, int value) { + super(closeExpect); + this.op = op; + this.value = value; + } + } + + + public enum ParseContext { TackOn, Value } @@ -155,11 +214,11 @@ public class TokenParser { private static final Pattern UNARY_OPERATOR_PATTERN = Pattern.compile("([\\-~])"); private static final Pattern GROUP_OPERATOR_PATTERN = Pattern.compile("([()])"); private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("([\\w]+)"); - private static final Pattern NUMBER_PATTERN_16 = Pattern.compile("0[xX]([\\da-fA-F]+)(?![\\w\\d])"); - private static final Pattern NUMBER_PATTERN_8 = Pattern.compile("0[oO]([0-7]+)(?![\\w\\d])"); + private static final Pattern NUMBER_PATTERN_16 = Pattern.compile("(?:0[xX]|#)([\\da-fA-F]+)(?![\\w\\d])"); + private static final Pattern NUMBER_PATTERN_8 = Pattern.compile("0[oO]?([0-7]+)(?![\\w\\d])"); private static final Pattern NUMBER_PATTERN_2 = Pattern.compile("0[bB]([01]+)(?![\\w\\d])"); - private static final Pattern NUMBER_PATTERN_10 = Pattern.compile("(\\d+)(?![\\w\\d])"); - private static final Pattern NUMBER_PATTERN_START = Pattern.compile("(\\d)"); + private static final Pattern NUMBER_PATTERN_10 = Pattern.compile("([1-9][\\d]*|0)(?![\\w\\d])"); + private static final Pattern NUMBER_PATTERN_START = Pattern.compile("([+]?)[\\d#]"); private static final Pattern RESET_PATTERN = Pattern.compile("[^\\w\\d]"); private static final Pattern SPACE_PATTERN = Pattern.compile("[^\\S\\n]+"); @@ -181,11 +240,11 @@ public class TokenParser { this(sequence, line, labels,0, sequence.length()); } - private int line, start, end; + public int line, start, end; - private Map labels; + private final Map labels; - private Matcher matcher; + private final Matcher matcher; public int lastInt; @@ -238,19 +297,23 @@ public class TokenParser { } else { if (matcher.usePattern(NUMBER_PATTERN_START).lookingAt()) { - + start = matcher.end(1); + matcher.region(start, end); try { - if (matcher.usePattern(NUMBER_PATTERN_10).lookingAt()) + if (matcher.usePattern(NUMBER_PATTERN_10).lookingAt()) { lastInt = Integer.parseInt(matcher.group(1), 10); - else if (matcher.usePattern(NUMBER_PATTERN_16).lookingAt()) + } else if (matcher.usePattern(NUMBER_PATTERN_16).lookingAt()) { lastInt = Integer.parseInt(matcher.group(1), 16); - else if (matcher.usePattern(NUMBER_PATTERN_2).lookingAt()) + } else if (matcher.usePattern(NUMBER_PATTERN_2).lookingAt()) { lastInt = Integer.parseInt(matcher.group(1), 2); - else if (matcher.usePattern(NUMBER_PATTERN_8).lookingAt()) + } else if (matcher.usePattern(NUMBER_PATTERN_8).lookingAt()) { lastInt = Integer.parseInt(matcher.group(1), 8); - else { - if (matcher.usePattern(RESET_PATTERN).find()) start = matcher.start(); - else start = end; + } else { + if (matcher.usePattern(RESET_PATTERN).find()) { + start = matcher.start(); + } else { + start = end; + } throw new AssemblyException("Invalid number found.", line); } } catch (NumberFormatException ex) { @@ -266,7 +329,9 @@ public class TokenParser { String identifier = matcher.group(1); Character val = labels.get(identifier); - if (val == null) throw new AssemblyException("Unknown label found", line); + if (val == null) { + throw new AssemblyException("Unknown label found", line); + } lastInt = val; return TokenType.Constant; @@ -278,14 +343,110 @@ public class TokenParser { lastUnary = UnaryOperatorType.stringMap.get(symbol); // Should never happen unless the regex does not agree with UnaryOperatorType. - if (lastUnary == null) throw new AssemblyException("Unary operator not supported", line); + if (lastUnary == null) { + throw new AssemblyException("Unary operator not supported", line); + } return TokenType.UnaryOperator; } } - if (matcher.usePattern(RESET_PATTERN).find()) start = matcher.end(); - else start = end; + matcher.usePattern(RESET_PATTERN); + if (matcher.lookingAt()) { + start = matcher.end(); + } else if (matcher.find()) { + start = matcher.end(); + } else { + start = end; + } throw new AssemblyException("Invalid token found", line); } + public int parseConstExpression() + throws AssemblyException { + Stack parseOps = new Stack<>(); + int closeExpect = -1; // No closing parenthesis expected + TokenParser.ParseContext context = TokenParser.ParseContext.Value; + int lastValue = 0; + while (true) { + TokenParser.TokenType ty = getNextToken(true, context); + if (context == TokenParser.ParseContext.Value) { + // Parse value + if (ty == TokenParser.TokenType.UnaryOperator) { + parseOps.push(new ParseOperatorUnary(closeExpect, lastUnary)); + closeExpect = -1; + } else if (ty == TokenParser.TokenType.GroupOperator) { + if (lastGroup.end) { + throw new AssemblyException("Unexpected group close", line); + } + if (closeExpect != -1) { + parseOps.push(new ParseOperator(closeExpect)); + } + closeExpect = lastGroup.groupType; + } else if (ty == TokenParser.TokenType.Constant) { + lastValue = lastInt; + context = TokenParser.ParseContext.TackOn; + } else { + throw new AssemblyException("Value not found", line); + } + } else { + // Parse modifier + if (ty == TokenParser.TokenType.EOF || ty == TokenParser.TokenType.GroupOperator) { + if (ty == TokenParser.TokenType.GroupOperator && !lastGroup.end) { + throw new AssemblyException("Unexpected group open", line); + } + if (closeExpect != -1) { + if (ty == TokenParser.TokenType.EOF) { + throw new AssemblyException("Unclosed group", line); + } else if (closeExpect != lastGroup.groupType) { + throw new AssemblyException("Unmatched group ends", line); + } else { + closeExpect = -1; + continue; + } + } + + boolean completed = false; + + //Evaluation chain + while (!parseOps.isEmpty()) { + ParseOperator op = parseOps.pop(); + if (op.closeExpect != -1) { + if (ty == TokenParser.TokenType.EOF) { + throw new AssemblyException("Unclosed group", line); + } else if (op.closeExpect != lastGroup.groupType) { + throw new AssemblyException("Unmatched group ends", line); + } + lastValue = op.apply(lastValue); + completed = true; + break; + } + lastValue = op.apply(lastValue); + } + if (!completed) { + if (ty == TokenParser.TokenType.EOF) { + return lastValue; + } else if (lastGroup.groupType != -1) { + throw new AssemblyException("Unexpected group close", line); + } + } + } else if (ty == TokenParser.TokenType.BinaryOperator) { + TokenParser.BinaryOperatorType bop = lastBinary; + while (closeExpect == -1 && !parseOps.empty()) { + ParseOperator op = parseOps.peek(); + if (bop.precedence <= op.getPrecedence()) { + break; + } + lastValue = op.apply(lastValue); + closeExpect = op.closeExpect; + parseOps.pop(); + } + parseOps.push(new ParseOperatorBinary(closeExpect, bop, lastValue)); + closeExpect = -1; + context = TokenParser.ParseContext.Value; + } + else throw new AssemblyException("Modifier or end not found", line); + } + } + } + } diff --git a/src/main/java/net/simon987/mar/server/websocket/CodeRequestHandler.java b/src/main/java/net/simon987/mar/server/websocket/CodeRequestHandler.java index 4936298..7de7992 100644 --- a/src/main/java/net/simon987/mar/server/websocket/CodeRequestHandler.java +++ b/src/main/java/net/simon987/mar/server/websocket/CodeRequestHandler.java @@ -14,24 +14,16 @@ public class CodeRequestHandler implements MessageHandler { LogManager.LOGGER.fine("(WS) Code request from " + user.getUser().getUsername()); - if (user.getUser().isGuest()) { + JSONObject response = new JSONObject(); - JSONObject response = new JSONObject(); + response.put("t", "code"); - response.put("t", "code"); - response.put("code", GameServer.INSTANCE.getConfig().getString("guest_user_code")); + String code = user.getUser().isGuest() ? + GameServer.INSTANCE.getConfig().getString("guest_user_code") : + user.getUser().getUserCode(); - user.getWebSocket().getRemote().sendString(response.toJSONString()); - - } else { - - JSONObject response = new JSONObject(); - - response.put("t", "code"); - response.put("code", user.getUser().getUserCode()); - - user.getWebSocket().getRemote().sendString(response.toJSONString()); - } + response.put("code", code); + user.getWebSocket().getRemote().sendString(response.toJSONString()); } } } diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index a5b99c4..7a1e908 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -12,7 +12,7 @@ server_name=MAR dev # ALLOW | BLOCK guest_policy=ALLOW # DEBUG -autologin=simon987 +#autologin=simon987 #Database mongo_dbname=mar_beta3 diff --git a/src/main/typescript/GameClient.ts b/src/main/typescript/GameClient.ts index 88d570d..ecb4b94 100644 --- a/src/main/typescript/GameClient.ts +++ b/src/main/typescript/GameClient.ts @@ -538,6 +538,8 @@ class GameClient { console.log("[MAR] Connected. Sent auth request"); } + if (info.token == null) throw new Error("Auth token not found"); + //Send auth request self.socket.send(info.token); diff --git a/src/main/typescript/World.ts b/src/main/typescript/World.ts index 2089b6e..6fa9702 100644 --- a/src/main/typescript/World.ts +++ b/src/main/typescript/World.ts @@ -17,7 +17,8 @@ enum TileType { VAULT_FLOOR, VAULT_WALL, FLUID, - MAGNETIC + MAGNETIC, + VOID } class Tile extends Phaser.Plugin.Isometric.IsoSprite { @@ -70,7 +71,7 @@ class Tile extends Phaser.Plugin.Isometric.IsoSprite { return new VaultFloorTile(x, y); case TileType.VAULT_WALL: return new VaultWallTile(x, y); - case -1: + case TileType.VOID: return new VoidTile(x, y); case TileType.FLUID: return new FluidTile(x, y); diff --git a/src/main/typescript/phaser.d.ts b/src/main/typescript/phaser.d.ts index 1d5b402..629620d 100644 --- a/src/main/typescript/phaser.d.ts +++ b/src/main/typescript/phaser.d.ts @@ -3697,19 +3697,19 @@ declare module Phaser { button: number; capture: boolean; callbackContext: any; - event: MSPointerEvent; + event: PointerEvent; game: Phaser.Game; input: Phaser.Input; - onPointerDown: (event: MSPointerEvent) => void; - onPointerMove: (event: MSPointerEvent) => void; - onPointerUp: (event: MSPointerEvent) => void; - mouseDownCallback: (event: MSPointerEvent) => void; - mouseMoveCallback: (event: MSPointerEvent) => void; - mouseUpCallback: (event: MSPointerEvent) => void; - pointerDownCallback: (event: MSPointerEvent) => void; - pointerMoveCallback: (event: MSPointerEvent) => void; - pointerUpCallback: (event: MSPointerEvent) => void; + onPointerDown: (event: PointerEvent) => void; + onPointerMove: (event: PointerEvent) => void; + onPointerUp: (event: PointerEvent) => void; + mouseDownCallback: (event: PointerEvent) => void; + mouseMoveCallback: (event: PointerEvent) => void; + mouseUpCallback: (event: PointerEvent) => void; + pointerDownCallback: (event: PointerEvent) => void; + pointerMoveCallback: (event: PointerEvent) => void; + pointerUpCallback: (event: PointerEvent) => void; start(): void; diff --git a/src/test/java/net/simon987/mar/server/assembly/OperandTest.java b/src/test/java/net/simon987/mar/server/assembly/OperandTest.java index 3ee8439..f447714 100644 --- a/src/test/java/net/simon987/mar/server/assembly/OperandTest.java +++ b/src/test/java/net/simon987/mar/server/assembly/OperandTest.java @@ -165,6 +165,7 @@ public class OperandTest { fail(); } catch (InvalidOperandException ignored) { } + /* Tests disabled due to compile time constant folding. try { new Operand("[- 12]", labels, registerSet, 0); fail(); @@ -174,7 +175,7 @@ public class OperandTest { new Operand("[12+1]", labels, registerSet, 0); fail(); } catch (InvalidOperandException ignored) { - } + } */ try { new Operand("[+label1", labels, registerSet, 0); fail(); diff --git a/src/test/java/net/simon987/mar/server/assembly/TokenTest.java b/src/test/java/net/simon987/mar/server/assembly/TokenTest.java index c55ee34..729cd6a 100644 --- a/src/test/java/net/simon987/mar/server/assembly/TokenTest.java +++ b/src/test/java/net/simon987/mar/server/assembly/TokenTest.java @@ -17,7 +17,7 @@ public class TokenTest { labels.put("gamma", (char)-5); labels.put("epsilon", (char)0); TokenParser parser = new TokenParser( - " 27 0x27 0o27 0b11011 alpha beta gamma delta epsilon 0 1a 0xG 0o8 0b2", + " 27 0x27 #27 0o27 027 0b11011 alpha beta gamma delta epsilon 0 1a 0xG 0o8 0b2", 0, labels); assertEquals(TokenParser.TokenType.Space, parser.getNextToken(false, TokenParser.ParseContext.Value)); @@ -27,6 +27,10 @@ public class TokenTest { assertEquals(TokenParser.TokenType.Constant, parser.getNextToken(true, TokenParser.ParseContext.Value)); assertEquals((char)39, parser.lastInt); assertEquals(TokenParser.TokenType.Constant, parser.getNextToken(true, TokenParser.ParseContext.Value)); + assertEquals((char)39, parser.lastInt); + assertEquals(TokenParser.TokenType.Constant, parser.getNextToken(true, TokenParser.ParseContext.Value)); + assertEquals((char)23, parser.lastInt); + assertEquals(TokenParser.TokenType.Constant, parser.getNextToken(true, TokenParser.ParseContext.Value)); assertEquals((char)23, parser.lastInt); assertEquals(TokenParser.TokenType.Constant, parser.getNextToken(true, TokenParser.ParseContext.Value)); assertEquals((char)27, parser.lastInt); @@ -41,31 +45,38 @@ public class TokenTest { try { parser.getNextToken(true, TokenParser.ParseContext.Value); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } try { parser.getNextToken(true, TokenParser.ParseContext.TackOn); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } try { parser.getNextToken(true, TokenParser.ParseContext.TackOn); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } try { parser.getNextToken(true, TokenParser.ParseContext.Value); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } try { parser.getNextToken(true, TokenParser.ParseContext.Value); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } try { parser.getNextToken(true, TokenParser.ParseContext.Value); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } try { parser.getNextToken(true, TokenParser.ParseContext.Value); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) { + } } @Test public void operatorTokenParsing() throws Exception { @@ -77,7 +88,7 @@ public class TokenTest { try { parser.getNextToken(true, TokenParser.ParseContext.TackOn); fail(); - } catch (AssemblyException ignore) {} + } catch (AssemblyException expected) {} assertEquals(TokenParser.TokenType.BinaryOperator, parser.getNextToken(true, TokenParser.ParseContext.TackOn)); assertEquals(TokenParser.BinaryOperatorType.Sub, parser.lastBinary); @@ -87,8 +98,7 @@ public class TokenTest { try { parser.getNextToken(true, TokenParser.ParseContext.Value); fail(); - } catch (AssemblyException ignore) {} - + } catch (AssemblyException expected) {} assertEquals(TokenParser.TokenType.UnaryOperator, parser.getNextToken(true, TokenParser.ParseContext.Value)); assertEquals(TokenParser.UnaryOperatorType.Not, parser.lastUnary); @@ -104,85 +114,39 @@ public class TokenTest { assertEquals(TokenParser.GroupOperatorType.GroupEnd, parser.lastGroup); } - @Test - public void parseTest() throws AssemblyException { - assertEquals(1, Operand.parseConstExpression( - "1", - 0, new HashMap<>()) - ); - assertEquals(2, Operand.parseConstExpression( - "1 + 1", - 0, new HashMap<>()) - ); - assertEquals(82, Operand.parseConstExpression( - "10 + 9 * 8", - 0, new HashMap<>()) - ); - assertEquals(98, Operand.parseConstExpression( - "10 * 9 + 8", - 0, new HashMap<>()) - ); - assertEquals(2, Operand.parseConstExpression( - "(1 + 1)", - 0, new HashMap<>()) - ); - assertEquals(152, Operand.parseConstExpression( - "((10 + 9)) * 8", - 0, new HashMap<>()) - ); - assertEquals(170, Operand.parseConstExpression( - "(10 * ((9 + 8)))", - 0, new HashMap<>()) - ); - assertEquals((char)-170, Operand.parseConstExpression( - "(-10 * ((9 + 8)))", - 0, new HashMap<>()) - ); - assertEquals(2, Operand.parseConstExpression( - "(-3 + 5)", - 0, new HashMap<>()) - ); + private void assertParse(int expect, String in) throws AssemblyException { + assertEquals(expect, new TokenParser(in,0, new HashMap<>()).parseConstExpression()); + } + + private void failParse(String in) { try { - Operand.parseConstExpression( - "(1", - 0, new HashMap<>() - ); - fail(); - } catch (AssemblyException ignore) {} - try { - Operand.parseConstExpression( - "1)", - 0, new HashMap<>() - ); - fail(); - } catch (AssemblyException ignore) {} - try { - Operand.parseConstExpression( - "(1+1", - 0, new HashMap<>() - ); - fail(); - } catch (AssemblyException ignore) {} - try { - Operand.parseConstExpression( - "1+1)", - 0, new HashMap<>() - ); - fail(); - } catch (AssemblyException ignore) {} - try { - Operand.parseConstExpression( - "((1+1)", - 0, new HashMap<>() - ); - fail(); - } catch (AssemblyException ignore) {} - try { - Operand.parseConstExpression( - "(1+1))", - 0, new HashMap<>() - ); + new TokenParser(in,0, new HashMap<>()).parseConstExpression(); fail(); } catch (AssemblyException ignore) {} } + + @Test + public void parseTest() throws AssemblyException { + assertParse(10, "10"); + assertParse(16, "0x10"); + assertParse(8, "0o10"); + assertParse(2, "0b10"); + assertParse(2, "1 + (1)"); + assertParse(98, "(10) * 9 + 8"); + assertParse(82, "10 + (9) * 8"); + assertParse(2, "(1 + 1)"); + assertParse(152, "((10 + 9)) * 8"); + assertParse(170, "(10 * ((9 + 8)))"); + assertParse((char)-170, "(-10 * ((9 + 8)))"); + assertParse((char)-170, "(10 * -((9 + 8)))"); + assertParse(170, "(-10 * -((9 + 8)))"); + assertParse(2, "(-3 + 5)"); + + failParse("1)"); + failParse("(1"); + failParse("(1 + 1"); + failParse("1 + 1)"); + failParse("((1 + 1)"); + failParse("(1 + 1))"); + } }