Adding merge-lines. Still need to work out max line length. #2.

This commit is contained in:
Rob Greene 2018-05-19 13:31:35 -05:00
parent e208fa453c
commit e5193a024f
3 changed files with 91 additions and 1 deletions

View File

@ -5,9 +5,11 @@ import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.Stack;
import java.util.TreeSet;
@ -62,6 +64,11 @@ public class Visitors {
return new ReassignmentVisitor(reassignments);
}
/** Collect all line numbers that are a target of GOTO, GOSUB, etc. */
public static LineNumberTargetCollector lineNumberTargetCollector() {
return new LineNumberTargetCollector();
}
public static Visitor variableReportVisitor() {
return new VariableReportVisitor();
}
@ -345,6 +352,44 @@ public class Visitors {
}
}
public static class LineNumberTargetCollector implements Visitor {
private Set<Integer> targets = new HashSet<>();
public Set<Integer> getTargets() {
return targets;
}
/**
* We saw a trigger, collect any numbers that follow.
*
* Trigger cases:
* - GOSUB n
* - GOTO n
* - IF ... THEN n
* - LIST n [ ,m ]
* - ON x GOTO n, m, ...
* - ON x GOSUB n, m, ...
* - ONERR GOTO n
* - RUN n
*/
@Override
public Statement visit(Statement statement) {
boolean next = false;
for (Token t : statement.tokens) {
if (next) {
if (t.type == Type.NUMBER) {
targets.add(t.number.intValue());
}
} else {
next = t.keyword == ApplesoftKeyword.GOSUB || t.keyword == ApplesoftKeyword.GOTO
|| t.keyword == ApplesoftKeyword.THEN || t.keyword == ApplesoftKeyword.RUN
|| t.keyword == ApplesoftKeyword.LIST;
}
}
return statement;
}
}
private static class VariableReportVisitor implements Visitor {
private Map<String,SortedSet<Integer>> refs = new HashMap<>();
private int currentLineNumber = -1;

View File

@ -62,11 +62,12 @@ public class Main implements Callable<Void> {
"Enable specific optimizations.",
"* @|green remove-empty-statements|@ - Strip out all '::'-like statements.",
"* @|green remove-rem-statements|@ - Remove all REM statements.",
"* @|green merge-lines|@ - Merge lines.",
"* @|green renumber|@ - Renumber program."
})
private List<Optimization> optimizations = new ArrayList<>();
@Option(names = "-O", description = "Apply all optimizations.")
@Option(names = { "-O", "--optimize" }, description = "Apply all optimizations.")
private boolean allOptimizations;
@Parameters(index = "0", description = "AppleSoft BASIC program to process.")

View File

@ -2,7 +2,9 @@ package io.github.applecommander.bastokenizer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.webcodepro.applecommander.util.applesoft.ApplesoftKeyword;
import com.webcodepro.applecommander.util.applesoft.Line;
import com.webcodepro.applecommander.util.applesoft.Program;
import com.webcodepro.applecommander.util.applesoft.Statement;
@ -10,6 +12,7 @@ import com.webcodepro.applecommander.util.applesoft.Token;
import com.webcodepro.applecommander.util.applesoft.Token.Type;
import com.webcodepro.applecommander.util.applesoft.Visitor;
import com.webcodepro.applecommander.util.applesoft.Visitors;
import com.webcodepro.applecommander.util.applesoft.Visitors.LineNumberTargetCollector;
import picocli.CommandLine.ITypeConverter;
@ -26,6 +29,47 @@ public enum Optimization {
return statement.tokens.get(0).type == Type.COMMENT ? null : statement;
}
}),
MERGE_LINES(new BaseVisitor() {
private Set<Integer> targets;
private Line mergeLine;
@Override
public Program visit(Program program) {
LineNumberTargetCollector c = Visitors.lineNumberTargetCollector();
program.accept(c);
targets = c.getTargets();
return super.visit(program);
}
@Override
public Line visit(Line line) {
if (mergeLine == null || targets.contains(line.lineNumber)) {
// merge may null out mergeLine if the this line has a "terminal".
// Preserve it with newLine so it get added to the program.
Line newLine = new Line(line.lineNumber);
mergeLine = newLine;
merge(line);
return newLine;
}
merge(line);
// Do not preserve old line!
return null;
}
private void merge(Line line) {
mergeLine.statements.addAll(line.statements);
// Terminals are: IF, REM, GOTO, END, ON .. GOTO (GOTO is trigger), RESUME, RETURN, STOP
boolean terminal = false;
for (Statement s : line.statements) {
for (Token t : s.tokens) {
terminal |= t.keyword == ApplesoftKeyword.IF || t.type == Type.COMMENT /* REM */
|| t.keyword == ApplesoftKeyword.GOTO || t.keyword == ApplesoftKeyword.END
|| t.keyword == ApplesoftKeyword.RESUME || t.keyword == ApplesoftKeyword.RETURN
|| t.keyword == ApplesoftKeyword.STOP;
}
}
if (terminal) {
mergeLine = null;
}
}
}),
RENUMBER(new BaseVisitor() {
protected int lineNumber = 0;
@Override