summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter01/README.md4
-rw-r--r--chapter01/src/main/java/com/seaofnodes/simple/Parser.java15
-rw-r--r--chapter01/src/main/java/com/seaofnodes/simple/node/ConstantNode.java13
-rw-r--r--chapter01/src/main/java/com/seaofnodes/simple/node/ReturnNode.java11
-rw-r--r--chapter01/src/main/java/com/seaofnodes/simple/node/StartNode.java4
-rw-r--r--chapter01/src/test/java/com/seaofnodes/simple/ParserTest.java18
6 files changed, 32 insertions, 33 deletions
diff --git a/chapter01/README.md b/chapter01/README.md
index 5a59ace8..f3231d8c 100644
--- a/chapter01/README.md
+++ b/chapter01/README.md
@@ -100,8 +100,8 @@ The Constant's value is the value stored in it.
The Return node has two inputs. The first input is a control node and the
second is the data node that supplies the return value.
-In this presentation, Return functions as a Stop node, since we are compiling a single unnamed function.
-A separate Stop is not necessary. Compiling multiple functions is covered in Chapter 9: Functions and Calls.
+In this presentation, Return functions as a Stop node, since multiple `return` statements are not possible.
+The Stop node will be introduced in Chapter 6 when we implement `if` statements.
The Return's output is the value from the data node.
diff --git a/chapter01/src/main/java/com/seaofnodes/simple/Parser.java b/chapter01/src/main/java/com/seaofnodes/simple/Parser.java
index a4c07217..8fb1ebaf 100644
--- a/chapter01/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter01/src/main/java/com/seaofnodes/simple/Parser.java
@@ -209,19 +209,16 @@ public class Parser {
return c;
}
- // First digit of a number.
- // Allows 0 on its own or
- // [-][1-9][0-9]*
- private boolean isFirstNumber(char ch) {
- char ch2 = peek();
- return (ch=='0' && (ch2 <'0' || ch2 > '9')) || // 0 followed by non-digit
- ('1'<=ch && ch<='9') || // starts with [1-9]
- (ch=='-' && ('1'<=ch2 && ch2<='9')); // starts with - and followed by [1-9]
+ private boolean isDigit(char ch) {
+ return ('0'<=ch && ch<='9');
}
+
private Token parseNumber() {
int start = _position-1;
while( Character.isDigit( nextChar() ) ) ;
String snum = new String(_input,start,--_position-start);
+ if (snum.length() > 1 && snum.charAt(0) == '0')
+ throw error("syntax error: integer values cannot start with '0'");
return Token.newNum(Integer.parseInt(snum),snum);
}
@@ -259,7 +256,7 @@ public class Parser {
char ch = skipWhiteSpace();
if (ch == Character.MAX_VALUE)
return Token.EOF;
- if (isFirstNumber(ch))
+ if (isDigit(ch))
return parseNumber();
if (isIdentifierStart(ch))
return parseIdentifier();
diff --git a/chapter01/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter01/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
index e7a3b3f2..7644daf2 100644
--- a/chapter01/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
+++ b/chapter01/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
@@ -1,13 +1,16 @@
package com.seaofnodes.simple.node;
/**
- * The Constant node represents a constant value. At present, the only constants that we allow are integer literals; therefore the Constant node contains
- * an integer value. As we add other types of constants, we will need to refactor how we represent Constant nodes.
+ * A Constant node represents a constant value. At present, the only constants
+ * that we allow are integer literals; therefore Constants contain an integer
+ * value. As we add other types of constants, we will refactor how we represent
+ * Constants.
* <p>
- * The Constant node has no inputs. However, we set the Start node as an input to the Constant node to enable forward graph walk. This edge carries no semantic meaning,
- * it is present _solely_ to allow visitation.
+ * Constants have no semantic inputs. However, we set Start as an input to
+ * Constants to enable a forward graph walk. This edge carries no semantic
+ * meaning, and it is present <em>solely</em> to allow visitation.
* <p>
- * The Constant node's output is the value stored in it.
+ * The Constant's value is the value stored in it.
*/
public class ConstantNode extends Node {
diff --git a/chapter01/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/chapter01/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
index eafcab94..12a5b464 100644
--- a/chapter01/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
+++ b/chapter01/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
@@ -1,16 +1,17 @@
package com.seaofnodes.simple.node;
/**
- * The Return node has two inputs. The first input is a control node. The second input is the data node that supplies the return value.
+ * The Return node has two inputs. The first input is a control node and the
+ * second is the data node that supplies the return value.
* <p>
- * In this presentation, the Return node functions as the Stop node, since we are compiling a single unnamed function.
- * A separate Stop node is not necessary. Compiling multiple functions is covered in Chapter 9: Functions and Calls.
+ * In this presentation, Return functions as a Stop node, since multiple <code>return</code> statements are not possible.
+ * The Stop node will be introduced in Chapter 6 when we implement <code>if</code> statements.
* <p>
- * The output of the Return node is the value it obtained from the data node.
+ * The Return's output is the value from the data node.
*/
public class ReturnNode extends Node implements Control {
public ReturnNode(Node ctrl, Node data) {
- super(ctrl,data);
+ super(ctrl, data);
}
}
diff --git a/chapter01/src/main/java/com/seaofnodes/simple/node/StartNode.java b/chapter01/src/main/java/com/seaofnodes/simple/node/StartNode.java
index 6944e8fc..c29ba53c 100644
--- a/chapter01/src/main/java/com/seaofnodes/simple/node/StartNode.java
+++ b/chapter01/src/main/java/com/seaofnodes/simple/node/StartNode.java
@@ -1,8 +1,8 @@
package com.seaofnodes.simple.node;
/**
- * The Start node represents the start of the function. For now, we do not have any values in the Start node, this is because our function does not
- * yet accept parameters. When we add parameters, the value of the Start node will be a tuple, and will require Projection nodes to extract the values.
+ * The Start node represents the start of the function. For now, we do not have any inputs to Start because our function does not
+ * yet accept parameters. When we add parameters the value of Start will be a tuple, and will require Projections to extract the values.
* We discuss this in detail in Chapter 9: Functions and Calls.
*/
public class StartNode extends Node implements Control {
diff --git a/chapter01/src/test/java/com/seaofnodes/simple/ParserTest.java b/chapter01/src/test/java/com/seaofnodes/simple/ParserTest.java
index 029f6121..887f63b8 100644
--- a/chapter01/src/test/java/com/seaofnodes/simple/ParserTest.java
+++ b/chapter01/src/test/java/com/seaofnodes/simple/ParserTest.java
@@ -31,15 +31,6 @@ public class ParserTest {
}
@Test
- public void testNegative() {
- Parser parser = new Parser();
- StartNode start = parser.parse("return -123;");
- for( Node use : start._outputs )
- if( use instanceof ConstantNode con )
- assertEquals(-123,con._value);
- }
-
- @Test
public void testZero() {
Parser parser = new Parser();
StartNode start = parser.parse("return 0;");
@@ -57,7 +48,7 @@ public class ParserTest {
@Test
public void testBad2() {
try { new Parser().parse("return 0123;"); }
- catch( RuntimeException e ) { assertEquals("syntax error: unexpected input '0'",e.getMessage()); }
+ catch( RuntimeException e ) { assertEquals("syntax error: integer values cannot start with '0'",e.getMessage()); }
}
@Test
@@ -71,4 +62,11 @@ public class ParserTest {
try { new Parser().parse("return 100"); }
catch( RuntimeException e ) { assertTrue(e.getMessage().contains("syntax error, expected ; got :")); }
}
+
+ // Negative numbers require unary operator support that is not in scope
+ @Test
+ public void testBad5() {
+ try { new Parser().parse("return -100;"); }
+ catch( RuntimeException e ) { assertEquals("syntax error, expected integer literal: -", e.getMessage()); }
+ }
}