Skip to content

Commit ceecbd4

Browse files
committed
Tweaking to handle empty lines a bit better for #18.
1 parent c43baf9 commit ceecbd4

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

api/src/main/java/io/github/applecommander/bastools/api/Parser.java

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.applecommander.bastools.api;
22

33
import java.util.Objects;
4+
import java.util.Optional;
45
import java.util.Queue;
56

67
import io.github.applecommander.bastools.api.model.Line;
@@ -24,26 +25,27 @@ public Parser(Queue<Token> tokens) {
2425
public Program parse() {
2526
Program program = new Program();
2627
while (!tokens.isEmpty()) {
27-
Line line = readLine(program);
28-
program.lines.add(line);
28+
readLine(program).ifPresent(program.lines::add);
2929
}
3030
return program;
3131
}
3232

33-
public Line readLine(Program program) {
34-
Line line = new Line(expectNumber(), program);
35-
while (!tokens.isEmpty() && tokens.peek().type != Type.EOL) {
36-
Statement statement = readStatement();
37-
if (statement != null) {
38-
line.statements.add(statement);
39-
} else {
40-
break;
41-
}
42-
}
43-
if (!tokens.isEmpty() && tokens.peek().type == Type.EOL) {
44-
tokens.remove(); // Skip that EOL
45-
}
46-
return line;
33+
public Optional<Line> readLine(Program program) {
34+
return expectNumber().map(lineNumber -> {
35+
Line line = new Line(lineNumber, program);
36+
while (!tokens.isEmpty() && tokens.peek().type != Type.EOL) {
37+
Statement statement = readStatement();
38+
if (statement != null) {
39+
line.statements.add(statement);
40+
} else {
41+
break;
42+
}
43+
}
44+
if (!tokens.isEmpty() && tokens.peek().type == Type.EOL) {
45+
tokens.remove(); // Skip that EOL
46+
}
47+
return line;
48+
});
4749
}
4850

4951
public Statement readStatement() {
@@ -57,15 +59,14 @@ public Statement readStatement() {
5759
return statement;
5860
}
5961

60-
public int expectNumber() {
62+
public Optional<Integer> expectNumber() {
6163
Token c = tokens.remove();
6264
while (c.type == Type.EOL) {
63-
// Allow blank lines...
64-
c = tokens.remove();
65+
return Optional.empty();
6566
}
6667
if (c.type != Type.NUMBER) {
6768
throw new RuntimeException("Expected a number in line #" + c.line);
6869
}
69-
return c.number.intValue();
70+
return Optional.of(c.number.intValue());
7071
}
7172
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.github.applecommander.bastools.api;
2+
3+
import java.util.Queue;
4+
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
import io.github.applecommander.bastools.api.model.Program;
9+
import io.github.applecommander.bastools.api.model.Token;
10+
import io.github.applecommander.bastools.api.utils.TokenBuilder;
11+
12+
public class ParserTest {
13+
@Test
14+
public void testBlankLines() {
15+
Queue<Token> tokens = TokenBuilder.builder()
16+
.eol() // Blank line before
17+
.number(10.0).ident("A").syntax('=').number(42.0).eol()
18+
.eol() // Blank line after
19+
.tokens();
20+
21+
Parser parser = new Parser(tokens);
22+
Program program = parser.parse();
23+
Assert.assertNotNull(program);
24+
}
25+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.github.applecommander.bastools.api.utils;
2+
3+
import java.util.LinkedList;
4+
import java.util.Queue;
5+
6+
import io.github.applecommander.bastools.api.model.ApplesoftKeyword;
7+
import io.github.applecommander.bastools.api.model.Token;
8+
9+
public class TokenBuilder {
10+
private int lineNumber;
11+
private Queue<Token> tokens = new LinkedList<Token>();
12+
13+
public static TokenBuilder builder() {
14+
return new TokenBuilder();
15+
}
16+
17+
public TokenBuilder eol() {
18+
add(Token.eol(lineNumber));
19+
lineNumber += 1;
20+
return this;
21+
}
22+
public TokenBuilder number(Double number) {
23+
return add(Token.number(lineNumber, number));
24+
}
25+
public TokenBuilder ident(String text) {
26+
return add(Token.ident(lineNumber, text));
27+
}
28+
public TokenBuilder comment(String text) {
29+
return add(Token.comment(lineNumber, text));
30+
}
31+
public TokenBuilder string(String text) {
32+
return add(Token.string(lineNumber, text));
33+
}
34+
public TokenBuilder keyword(ApplesoftKeyword keyword) {
35+
return add(Token.keyword(lineNumber, keyword));
36+
}
37+
public TokenBuilder syntax(int ch) {
38+
return add(Token.syntax(lineNumber, ch));
39+
}
40+
public TokenBuilder directive(String text) {
41+
return add(Token.directive(lineNumber, text));
42+
}
43+
private TokenBuilder add(Token token) {
44+
tokens.add(token);
45+
return this;
46+
}
47+
public Queue<Token> tokens() {
48+
return tokens;
49+
}
50+
}

0 commit comments

Comments
 (0)