LineScanner.java

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
Location : scan
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:BlankAndCommentLines]/[method:blankLinesProduceNoSourceLines()]
changed conditional boundary → KILLED

2.2
Location : scan
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:InstructionLines]/[method:mnemonicIsNormalizedToUpperCase()]
negated conditional → KILLED

28

1.1
Location : scan
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:BlankAndCommentLines]/[method:blankLinesProduceNoSourceLines()]
negated conditional → KILLED

29

1.1
Location : scan
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:LineNumbers]/[method:lineNumbersTrackOriginalSourcePositionSkippingBlankAndCommentLines()]
Replaced integer addition with subtraction → KILLED

33

1.1
Location : scan
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:InstructionLines]/[method:mnemonicIsNormalizedToUpperCase()]
replaced return value with Collections.emptyList for com/rox/cpu/mos6502/assembler/LineScanner::scan → KILLED

44

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:InstructionLines]/[method:mnemonicIsNormalizedToUpperCase()]
negated conditional → KILLED

46

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:LabelLines]/[method:emptyTextBeforeAColonIsNotTreatedAsALabel()]
negated conditional → KILLED

48

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:LabelLines]/[method:labelOnlyLineHasNoMnemonic()]
Replaced integer addition with subtraction → KILLED

52

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:InstructionLines]/[method:mnemonicIsNormalizedToUpperCase()]
negated conditional → KILLED

54

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:LabelLines]/[method:labelOnlyLineHasNoMnemonic()]
replaced return value with null for com/rox/cpu/mos6502/assembler/LineScanner::parseLine → KILLED

59

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:BlankAndCommentLines]/[method:trailingCommentIsStrippedFromAnInstructionLine()]
negated conditional → KILLED

2.2
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:InstructionLines]/[method:instructionWithNoOperandHasEmptyOperandText()]
changed conditional boundary → KILLED

62

1.1
Location : parseLine
Killed by : com.rox.cpu.mos6502.assembler.LineScannerTest.[engine:junit-jupiter]/[class:com.rox.cpu.mos6502.assembler.LineScannerTest]/[nested-class:InstructionLines]/[method:mnemonicIsNormalizedToUpperCase()]
replaced return value with null for com/rox/cpu/mos6502/assembler/LineScanner::parseLine → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1