| 1 | package com.rox.cpu.mos6502.assembler; | |
| 2 | ||
| 3 | import java.util.ArrayList; | |
| 4 | import java.util.List; | |
| 5 | import java.util.Locale; | |
| 6 | ||
| 7 | /** | |
| 8 | * Splits 6502 assembly source into comment-stripped, label/mnemonic/operand-separated {@link SourceLine}s. | |
| 9 | */ | |
| 10 | final class LineScanner { | |
| 11 | private static final String ROL_COMMENT_START = ";"; | |
| 12 | private static final String LABEL_END = ":"; | |
| 13 | ||
| 14 | private LineScanner() { | |
| 15 | } | |
| 16 | ||
| 17 | /** | |
| 18 | * @param source a textual MOS6502 program | |
| 19 | * @return A {@link List} of {@link SourceLine} representing the comment-stripped program | |
| 20 | */ | |
| 21 | static List<SourceLine> scan(final String source) { | |
| 22 | final List<SourceLine> scannedLines = new ArrayList<>(); | |
| 23 | final List<String> rawLines = source.lines().toList(); | |
| 24 | ||
| 25 |
2
1. scan : changed conditional boundary → KILLED 2. scan : negated conditional → KILLED |
for (int i = 0; i < rawLines.size(); i++) { |
| 26 | final String lineWithoutComment = rawLines.get(i).split(ROL_COMMENT_START, 2)[0].strip(); | |
| 27 | ||
| 28 |
1
1. scan : negated conditional → KILLED |
if (!lineWithoutComment.isEmpty()) { |
| 29 |
1
1. scan : Replaced integer addition with subtraction → KILLED |
scannedLines.add(parseLine(i + 1, lineWithoutComment)); |
| 30 | } | |
| 31 | } | |
| 32 | ||
| 33 |
1
1. scan : replaced return value with Collections.emptyList for com/rox/cpu/mos6502/assembler/LineScanner::scan → KILLED |
return scannedLines; |
| 34 | } | |
| 35 | ||
| 36 | /** | |
| 37 | * Parse out a {@link SourceLine} which can be a label or a label and content | |
| 38 | */ | |
| 39 | private static SourceLine parseLine(final int lineNumber, final String trimmed) { | |
| 40 | String lineWithoutLabel = trimmed; | |
| 41 | String labelForThisLine = null; | |
| 42 | ||
| 43 | final int endLabelIndex = lineWithoutLabel.indexOf(LABEL_END); | |
| 44 |
1
1. parseLine : negated conditional → KILLED |
if (endLabelIndex != -1) { |
| 45 | final String candidateLabel = lineWithoutLabel.substring(0, endLabelIndex).trim(); | |
| 46 |
1
1. parseLine : negated conditional → KILLED |
if (Identifiers.isValidLabelName(candidateLabel)) { |
| 47 | labelForThisLine = candidateLabel; | |
| 48 |
1
1. parseLine : Replaced integer addition with subtraction → KILLED |
lineWithoutLabel = lineWithoutLabel.substring(endLabelIndex + 1).trim(); |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 |
1
1. parseLine : negated conditional → KILLED |
if (lineWithoutLabel.isEmpty()) { |
| 53 | //Label only line | |
| 54 |
1
1. parseLine : replaced return value with null for com/rox/cpu/mos6502/assembler/LineScanner::parseLine → KILLED |
return new SourceLine(lineNumber, labelForThisLine, null, ""); |
| 55 | } | |
| 56 | ||
| 57 | final String[] parts = lineWithoutLabel.split("\\s+", 2); | |
| 58 | final String operationMnemonic = parts[0].toUpperCase(Locale.ROOT); | |
| 59 |
2
1. parseLine : negated conditional → KILLED 2. parseLine : changed conditional boundary → KILLED |
final String operandText = parts.length > 1 ? parts[1].trim() : ""; |
| 60 | ||
| 61 | //Content line, possibly with label | |
| 62 |
1
1. parseLine : replaced return value with null for com/rox/cpu/mos6502/assembler/LineScanner::parseLine → KILLED |
return new SourceLine(lineNumber, labelForThisLine, operationMnemonic, operandText); |
| 63 | } | |
| 64 | } | |
Mutations | ||
| 25 |
1.1 2.2 |
|
| 28 |
1.1 |
|
| 29 |
1.1 |
|
| 33 |
1.1 |
|
| 44 |
1.1 |
|
| 46 |
1.1 |
|
| 48 |
1.1 |
|
| 52 |
1.1 |
|
| 54 |
1.1 |
|
| 59 |
1.1 2.2 |
|
| 62 |
1.1 |