From ceecbd49fac75ba36994423645d1acaa20b4fdf7 Mon Sep 17 00:00:00 2001 From: Rob Greene Date: Wed, 21 Nov 2018 14:34:03 -0600 Subject: [PATCH] Tweaking to handle empty lines a bit better for #18. --- .../applecommander/bastools/api/Parser.java | 41 +++++++-------- .../bastools/api/ParserTest.java | 25 ++++++++++ .../bastools/api/utils/TokenBuilder.java | 50 +++++++++++++++++++ 3 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 api/src/test/java/io/github/applecommander/bastools/api/ParserTest.java create mode 100644 api/src/test/java/io/github/applecommander/bastools/api/utils/TokenBuilder.java diff --git a/api/src/main/java/io/github/applecommander/bastools/api/Parser.java b/api/src/main/java/io/github/applecommander/bastools/api/Parser.java index 1b33b24..74e9690 100644 --- a/api/src/main/java/io/github/applecommander/bastools/api/Parser.java +++ b/api/src/main/java/io/github/applecommander/bastools/api/Parser.java @@ -1,6 +1,7 @@ package io.github.applecommander.bastools.api; import java.util.Objects; +import java.util.Optional; import java.util.Queue; import io.github.applecommander.bastools.api.model.Line; @@ -24,26 +25,27 @@ public class Parser { public Program parse() { Program program = new Program(); while (!tokens.isEmpty()) { - Line line = readLine(program); - program.lines.add(line); + readLine(program).ifPresent(program.lines::add); } return program; } - public Line readLine(Program program) { - Line line = new Line(expectNumber(), program); - while (!tokens.isEmpty() && tokens.peek().type != Type.EOL) { - Statement statement = readStatement(); - if (statement != null) { - line.statements.add(statement); - } else { - break; - } - } - if (!tokens.isEmpty() && tokens.peek().type == Type.EOL) { - tokens.remove(); // Skip that EOL - } - return line; + public Optional readLine(Program program) { + return expectNumber().map(lineNumber -> { + Line line = new Line(lineNumber, program); + while (!tokens.isEmpty() && tokens.peek().type != Type.EOL) { + Statement statement = readStatement(); + if (statement != null) { + line.statements.add(statement); + } else { + break; + } + } + if (!tokens.isEmpty() && tokens.peek().type == Type.EOL) { + tokens.remove(); // Skip that EOL + } + return line; + }); } public Statement readStatement() { @@ -57,15 +59,14 @@ public class Parser { return statement; } - public int expectNumber() { + public Optional expectNumber() { Token c = tokens.remove(); while (c.type == Type.EOL) { - // Allow blank lines... - c = tokens.remove(); + return Optional.empty(); } if (c.type != Type.NUMBER) { throw new RuntimeException("Expected a number in line #" + c.line); } - return c.number.intValue(); + return Optional.of(c.number.intValue()); } } diff --git a/api/src/test/java/io/github/applecommander/bastools/api/ParserTest.java b/api/src/test/java/io/github/applecommander/bastools/api/ParserTest.java new file mode 100644 index 0000000..2c65f3f --- /dev/null +++ b/api/src/test/java/io/github/applecommander/bastools/api/ParserTest.java @@ -0,0 +1,25 @@ +package io.github.applecommander.bastools.api; + +import java.util.Queue; + +import org.junit.Assert; +import org.junit.Test; + +import io.github.applecommander.bastools.api.model.Program; +import io.github.applecommander.bastools.api.model.Token; +import io.github.applecommander.bastools.api.utils.TokenBuilder; + +public class ParserTest { + @Test + public void testBlankLines() { + Queue tokens = TokenBuilder.builder() + .eol() // Blank line before + .number(10.0).ident("A").syntax('=').number(42.0).eol() + .eol() // Blank line after + .tokens(); + + Parser parser = new Parser(tokens); + Program program = parser.parse(); + Assert.assertNotNull(program); + } +} diff --git a/api/src/test/java/io/github/applecommander/bastools/api/utils/TokenBuilder.java b/api/src/test/java/io/github/applecommander/bastools/api/utils/TokenBuilder.java new file mode 100644 index 0000000..3f584ea --- /dev/null +++ b/api/src/test/java/io/github/applecommander/bastools/api/utils/TokenBuilder.java @@ -0,0 +1,50 @@ +package io.github.applecommander.bastools.api.utils; + +import java.util.LinkedList; +import java.util.Queue; + +import io.github.applecommander.bastools.api.model.ApplesoftKeyword; +import io.github.applecommander.bastools.api.model.Token; + +public class TokenBuilder { + private int lineNumber; + private Queue tokens = new LinkedList(); + + public static TokenBuilder builder() { + return new TokenBuilder(); + } + + public TokenBuilder eol() { + add(Token.eol(lineNumber)); + lineNumber += 1; + return this; + } + public TokenBuilder number(Double number) { + return add(Token.number(lineNumber, number)); + } + public TokenBuilder ident(String text) { + return add(Token.ident(lineNumber, text)); + } + public TokenBuilder comment(String text) { + return add(Token.comment(lineNumber, text)); + } + public TokenBuilder string(String text) { + return add(Token.string(lineNumber, text)); + } + public TokenBuilder keyword(ApplesoftKeyword keyword) { + return add(Token.keyword(lineNumber, keyword)); + } + public TokenBuilder syntax(int ch) { + return add(Token.syntax(lineNumber, ch)); + } + public TokenBuilder directive(String text) { + return add(Token.directive(lineNumber, text)); + } + private TokenBuilder add(Token token) { + tokens.add(token); + return this; + } + public Queue tokens() { + return tokens; + } +}