diff options
| author | dibyendumajumdar <mobile@majumdar.org.uk> | 2023-09-19 21:30:41 +0100 |
|---|---|---|
| committer | dibyendumajumdar <mobile@majumdar.org.uk> | 2023-09-19 21:30:41 +0100 |
| commit | cecb62d847da7dc937b52857ae2fd4b41af98a7c (patch) | |
| tree | 0e628f6a331a0c7e3b56424021243535019f7784 /chapter01 | |
| parent | bf82e7a511cd1f2ab739f75b4dcf536478591f09 (diff) | |
| download | Simple-cecb62d847da7dc937b52857ae2fd4b41af98a7c.tar.gz Simple-cecb62d847da7dc937b52857ae2fd4b41af98a7c.zip | |
Do not parse negative integers, - will be treated as unary operator.
Update the comments for Return node.
Sync comments with README.
Diffstat (limited to 'chapter01')
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()); } + } } |
