diff options
| author | Thalia Archibald <thalia@archibald.dev> | 2024-06-21 12:58:51 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-21 20:58:51 +0100 |
| commit | fd8442075faa603b3956d51d81486424624c5355 (patch) | |
| tree | 029c1afb736ff0e350c2b032318e5fc376c7e1e4 /chapter01/src/main/java/com/seaofnodes | |
| parent | e5f4f7b85fbb91a293a7d89d7b85adfbaeeb51f4 (diff) | |
| download | Simple-fd8442075faa603b3956d51d81486424624c5355.tar.gz Simple-fd8442075faa603b3956d51d81486424624c5355.zip | |
Backport tests (#87)
* Fix unexpected number parse errors
* Add chapter titles
* Split test files by chapter
* Backport rename Fuzzer08Test to FuzzerWrap
* Replace graph build scripts with Makefile
* Backport Chapter05Test.testRegress1
* Backport require space after 'return'
* Backport check EOF after return statement
Diffstat (limited to 'chapter01/src/main/java/com/seaofnodes')
| -rw-r--r-- | chapter01/src/main/java/com/seaofnodes/simple/Parser.java | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/chapter01/src/main/java/com/seaofnodes/simple/Parser.java b/chapter01/src/main/java/com/seaofnodes/simple/Parser.java index d79d23ff..8975a165 100644 --- a/chapter01/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter01/src/main/java/com/seaofnodes/simple/Parser.java @@ -31,8 +31,22 @@ public class Parser { } public ReturnNode parse() { - require("return"); - return parseReturn(); + var ret = (ReturnNode) parseStatement(); + if (!_lexer.isEOF()) throw error("Syntax error, unexpected " + _lexer.getAnyNextToken()); + return ret; + } + + /** + * Parses a statement + * + * <pre> + * returnStatement + * </pre> + * @return a {@link Node} or {@code null} + */ + private Node parseStatement() { + if (matchx("return")) return parseReturn(); + throw errorSyntax("a statement"); } /** @@ -89,7 +103,9 @@ public class Parser { // Utilities for lexical analysis // Return true and skip if "syntax" is next in the stream. - private boolean match(String syntax) { return _lexer.match(syntax); } + private boolean match (String syntax) { return _lexer.match (syntax); } + // Match must be "exact", not be followed by more id letters + private boolean matchx(String syntax) { return _lexer.matchx(syntax); } // Require an exact match private void require(String syntax) { require(null, syntax); } @@ -174,10 +190,18 @@ public class Parser { return true; } + boolean matchx(String syntax) { + if( !match(syntax) ) return false; + if( !isIdLetter(peek()) ) return true; + _position -= syntax.length(); + return false; + } + // Used for errors String getAnyNextToken() { if (isEOF()) return ""; if (isIdStart(peek())) return parseId(); + if (isNumber(peek())) return parseNumberString(); if (isPunctuation(peek())) return parsePunctuation(); return String.valueOf(peek()); } @@ -186,13 +210,16 @@ public class Parser { boolean isNumber(char ch) {return Character.isDigit(ch);} private long parseNumber() { - int start = _position; - while (isNumber(nextChar())) ; - String snum = new String(_input, start, --_position - start); + String snum = parseNumberString(); if (snum.length() > 1 && snum.charAt(0) == '0') throw error("Syntax error: integer values cannot start with '0'"); return Long.parseLong(snum); } + private String parseNumberString() { + int start = _position; + while (isNumber(nextChar())) ; + return new String(_input, start, --_position - start); + } // First letter of an identifier private boolean isIdStart(char ch) { |
