summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter03/src/main/java/com/seaofnodes/simple/Parser.java18
-rw-r--r--chapter03/src/test/java/com/seaofnodes/simple/Chapter03Test.java7
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/Parser.java18
-rw-r--r--chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java7
-rw-r--r--chapter05/src/main/java/com/seaofnodes/simple/Parser.java18
-rw-r--r--chapter05/src/test/java/com/seaofnodes/simple/Chapter05Test.java10
6 files changed, 63 insertions, 15 deletions
diff --git a/chapter03/src/main/java/com/seaofnodes/simple/Parser.java b/chapter03/src/main/java/com/seaofnodes/simple/Parser.java
index 12e156ed..3d06a9c3 100644
--- a/chapter03/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter03/src/main/java/com/seaofnodes/simple/Parser.java
@@ -39,7 +39,7 @@ public class Parser {
}
public ReturnNode parse() {
- return (ReturnNode) parseBlock();
+ return (ReturnNode) parseBlock(false);
}
@@ -50,14 +50,22 @@ public class Parser {
* '{' statements '}'
* </pre>
*/
- private Node parseBlock() {
+ private Node parseBlock(boolean requireClosingBracket) {
// Enter a new scope
_scope.push();
Node n = null;
- while (!match("}") && !_lexer.isEOF()) {
+ do {
+ if (match("}")) {
+ if (requireClosingBracket) break;
+ else throw error("unexpected '}' token");
+ } else if (_lexer.isEOF()) {
+ if (requireClosingBracket) require("}");
+ else break;
+ }
+
Node n0 = parseStatement();
if (n0 != null) n = n0; // Allow null returns from eg showGraph
- }
+ } while (true);
// Exit scope
_scope.pop();
return n;
@@ -73,7 +81,7 @@ public class Parser {
private Node parseStatement() {
if (match("return")) return parseReturn();
else if (match("int")) return parseDecl();
- else if (match("{")) return parseBlock();
+ else if (match("{")) return parseBlock(true);
else if (match("#showGraph")) return showGraph();
else return parseExpressionStatement();
}
diff --git a/chapter03/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/chapter03/src/test/java/com/seaofnodes/simple/Chapter03Test.java
index 5af07ec3..21faacac 100644
--- a/chapter03/src/test/java/com/seaofnodes/simple/Chapter03Test.java
+++ b/chapter03/src/test/java/com/seaofnodes/simple/Chapter03Test.java
@@ -168,4 +168,11 @@ public class Chapter03Test {
// this test used to fail in chapter 1
assertEquals("return -100;", new Parser("return -100;").parse().print());
}
+
+ @Test
+ public void testBad6() {
+ exceptionRule.expect(RuntimeException.class);
+ exceptionRule.expectMessage("Syntax error, expected }:");
+ new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b;").parse();
+ }
}
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/Parser.java b/chapter04/src/main/java/com/seaofnodes/simple/Parser.java
index 147515f6..275a4ebd 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/Parser.java
@@ -52,7 +52,7 @@ public class Parser {
try {
_scope.define("$ctrl", new ProjNode(START, 0, "$ctrl").peephole());
_scope.define("arg" , new ProjNode(START, 1, "arg" ).peephole());
- return (ReturnNode) parseBlock();
+ return (ReturnNode) parseBlock(false);
}
finally {
_scope.pop();
@@ -66,14 +66,22 @@ public class Parser {
* '{' statements '}'
* </pre>
*/
- private Node parseBlock() {
+ private Node parseBlock(boolean requireClosingBracket) {
// Enter a new scope
_scope.push();
Node n = null;
- while (!match("}") && !_lexer.isEOF()) {
+ do {
+ if (match("}")) {
+ if (requireClosingBracket) break;
+ else throw error("unexpected '}' token");
+ } else if (_lexer.isEOF()) {
+ if (requireClosingBracket) require("}");
+ else break;
+ }
+
Node n0 = parseStatement();
if (n0 != null) n = n0; // Allow null returns from eg showGraph
- }
+ } while (true);
// Exit scope
_scope.pop();
return n;
@@ -89,7 +97,7 @@ public class Parser {
private Node parseStatement() {
if (match("return")) return parseReturn();
else if (match("int")) return parseDecl();
- else if (match("{")) return parseBlock();
+ else if (match("{")) return parseBlock(true);
else if (match("#showGraph")) return showGraph();
else return parseExpressionStatement();
}
diff --git a/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java b/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java
index 4782e568..ed999039 100644
--- a/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java
+++ b/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java
@@ -277,4 +277,11 @@ public class Chapter04Test {
// this test used to fail in chapter 1
assertEquals("return -100;", new Parser("return -100;").parse().print());
}
+
+ @Test
+ public void testBad6() {
+ exceptionRule.expect(RuntimeException.class);
+ exceptionRule.expectMessage("Syntax error, expected }:");
+ new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b;").parse();
+ }
}
diff --git a/chapter05/src/main/java/com/seaofnodes/simple/Parser.java b/chapter05/src/main/java/com/seaofnodes/simple/Parser.java
index 79b50672..a9bec582 100644
--- a/chapter05/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter05/src/main/java/com/seaofnodes/simple/Parser.java
@@ -93,7 +93,7 @@ public class Parser {
try {
_scope.define(CTRL , new ProjNode(START, 0, CTRL ).peephole());
_scope.define("arg", new ProjNode(START, 1, "arg").peephole());
- parseBlock();
+ parseBlock(false);
return STOP;
}
finally {
@@ -111,14 +111,22 @@ public class Parser {
* </pre>
* @return a {@link Node} or {@code null}
*/
- private Node parseBlock() {
+ private Node parseBlock(boolean requireClosingBracket) {
// Enter a new scope
_scope.push();
Node n = null;
- while (!match("}") && !_lexer.isEOF()) {
+ do {
+ if (match("}")) {
+ if (requireClosingBracket) break;
+ else throw error("unexpected '}' token");
+ } else if (_lexer.isEOF()) {
+ if (requireClosingBracket) require("}");
+ else break;
+ }
+
Node n0 = parseStatement();
if (n0 != null) n = n0; // Allow null returns from eg showGraph
- }
+ } while (true);
// Exit scope
_scope.pop();
return n;
@@ -135,7 +143,7 @@ public class Parser {
private Node parseStatement() {
if (matchx("return") ) return parseReturn();
else if (matchx("int")) return parseDecl();
- else if (match ("{" )) return parseBlock();
+ else if (match ("{" )) return parseBlock(true);
else if (matchx("if" )) return parseIf();
else if (matchx("#showGraph")) return require(showGraph(),";");
else return parseExpressionStatement();
diff --git a/chapter05/src/test/java/com/seaofnodes/simple/Chapter05Test.java b/chapter05/src/test/java/com/seaofnodes/simple/Chapter05Test.java
index 5ac309f3..0516fb73 100644
--- a/chapter05/src/test/java/com/seaofnodes/simple/Chapter05Test.java
+++ b/chapter05/src/test/java/com/seaofnodes/simple/Chapter05Test.java
@@ -430,4 +430,14 @@ return c;
// this test used to fail in chapter 1
assertEquals("return -100;", new Parser("return -100;").parse().print());
}
+
+ @Test
+ public void testBad6() {
+ try {
+ new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b;").parse();
+ fail();
+ } catch( RuntimeException e ) {
+ assertEquals("Syntax error, expected }: ",e.getMessage());
+ }
+ }
}