1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00

Created ASM parser & representation

This commit is contained in:
jespergravgaard 2017-05-20 21:49:11 +02:00
parent 91b455e042
commit 8f9f042144
45 changed files with 2545 additions and 54 deletions

View File

@ -0,0 +1,47 @@
package dk.camelot64.kickc.asm;
/** 6502 Assembler Instruction Addressing Modes. */
public enum AsmAddressingMode {
NON("", "%i", 1),
IMM("#imm", "%i #%p", 2),
ZP("zp", "%i %p", 2),
ZPX("zp,x", "%i %p,x", 2),
ZPY("zp,y", "%i %p,y", 2),
ABS("abs", "%i %p", 3),
ABX("abs,x", "%i %p,x", 3),
ABY("abs,y", "%i %p,y", 4),
IZX("(zp,x)", "%i (%p,x)", 2),
IZY("(zp),y", "%i (%p),y", 2),
REL("rel", "%i %p", 2),
IND("(ind)", "%i (%p)", 3);
private String name;
private String template;
private int bytes;
AsmAddressingMode(String name, String template, int bytes) {
this.bytes = bytes;
this.template = template;
this.name = name;
}
public int getBytes() {
return bytes;
}
public String getName() {
return name;
}
public String getAsm(String mnemnonic, String parameter) {
String replaced = template.replace("%i", mnemnonic);
if(parameter!=null) {
replaced = replaced.replace("%p", parameter);
}
return replaced;
}
}

View File

@ -0,0 +1,35 @@
package dk.camelot64.kickc.asm;
/** An assember comment */
public class AsmComment implements AsmLine {
private String comment;
public AsmComment(String comment) {
this.comment = comment;
}
@Override
public int getLineBytes() {
return 0;
}
@Override
public double getLineCycles() {
return 0;
}
@Override
public int getInvocationCountEstimate() {
return 0;
}
@Override
public double getEstimatedTotalCycles() {
return 0;
}
@Override
public String getAsm() {
return "// "+comment;
}
}

View File

@ -1,9 +1,13 @@
package dk.camelot64.kickc.icl;
package dk.camelot64.kickc.asm;
import dk.camelot64.kickc.asm.parser.Asm6502BaseVisitor;
import dk.camelot64.kickc.asm.parser.Asm6502Lexer;
import dk.camelot64.kickc.asm.parser.Asm6502Parser;
import dk.camelot64.kickc.icl.*;
import org.antlr.v4.runtime.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
@ -26,7 +30,7 @@ public class AsmFragment {
private Map<String, Value> bindings;
/**
* The string signature/name of the asm fragment.
* The string signature/name of the fragment fragment.
*/
private String signature;
@ -106,8 +110,8 @@ public class AsmFragment {
case ">=":
case "=>":
return "_ge_";
default:
return op;
default:
return op;
}
}
@ -197,7 +201,7 @@ public class AsmFragment {
* @param name The name of the bound value in the fragment
* @return The bound value to use in the generated ASM code
*/
public String getValue(String name) {
public String getBoundValue(String name) {
Value boundValue = getBinding(name);
String bound;
if (boundValue instanceof Variable) {
@ -232,27 +236,30 @@ public class AsmFragment {
public void generateAsm(AsmSequence asm) {
String signature = this.getSignature();
ClassLoader classLoader = this.getClass().getClassLoader();
URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/icl/asm/" + signature + ".asm");
final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
if (fragmentResource == null) {
System.out.println("Fragment not found " + fragmentResource);
asm.addAsm(" // Fragment not found: " + signature);
return;
}
Pattern bindPattern = Pattern.compile(".*\\{([^}]*)}.*");
try {
InputStream fragmentStream = fragmentResource.openStream();
BufferedReader fragmentReader = new BufferedReader(new InputStreamReader(fragmentStream));
String line;
while ((line = fragmentReader.readLine()) != null) {
Matcher matcher = bindPattern.matcher(line);
if (matcher.matches()) {
String name = matcher.group(1);
String bound = this.getValue(name);
line = line.replaceFirst("\\{[^}]*}", bound);
Asm6502Lexer lexer = new Asm6502Lexer(new ANTLRInputStream(fragmentStream));
Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException("Error parsing fragment file "+fragmentResource+"\n - Line: "+line+"\n - Message: "+msg);
}
asm.addAsm(" " + line);
});
parser.setBuildParseTree(true);
Asm6502Parser.FileContext file = parser.file();
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(fragmentResource);
asmSequenceGenerator.generate(file);
for (AsmLine asmLine : asmSequenceGenerator.program.getLines()) {
asm.addAsm(" "+asmLine.getAsm());
}
fragmentReader.close();
fragmentStream.close();
} catch (IOException e) {
throw new RuntimeException("Error reading code fragment " + fragmentResource);
@ -260,5 +267,119 @@ public class AsmFragment {
}
private class AsmSequenceGenerator extends Asm6502BaseVisitor {
private URL fragmentResource;
private AsmProgram program;
public AsmSequenceGenerator(URL fragmentResource, AsmProgram program) {
this.fragmentResource = fragmentResource;
this.program = program;
}
public AsmSequenceGenerator(URL fragmentResource) {
this.fragmentResource = fragmentResource;
this.program = new AsmProgram();
}
public AsmProgram getProgram() {
return program;
}
public void generate(Asm6502Parser.FileContext context) {
this.visit(context);
}
@Override
public Object visitLabel(Asm6502Parser.LabelContext ctx) {
program.addLine(new AsmLabel(ctx.getChild(0).getText()));
return null;
}
@Override
public Object visitComment(Asm6502Parser.CommentContext ctx) {
program.addLine(new AsmComment(ctx.getChild(1).getText()));
return null;
}
@Override
public Object visitInstruction(Asm6502Parser.InstructionContext ctx) {
Asm6502Parser.ParamModeContext paramModeCtx = ctx.paramMode();
AsmInstruction instruction;
if(paramModeCtx==null) {
AsmInstructionType type = AsmInstuctionSet.getInstructionType(ctx.MNEMONIC().getText(), AsmAddressingMode.NON);
instruction = new AsmInstruction(type, null, 1);
} else {
instruction = (AsmInstruction) this.visit(paramModeCtx);
}
if(instruction!=null) {
program.addLine(instruction);
} else {
throw new RuntimeException("Error parsing ASM fragment line in "+fragmentResource.toString()+"\n - Line: "+ctx.getText());
}
return null;
}
@Override
public Object visitModeAbs(Asm6502Parser.ModeAbsContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABS);
}
@Override
public Object visitModeImm(Asm6502Parser.ModeImmContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IMM);
}
@Override
public Object visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABX);
}
@Override
public Object visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABY);
}
@Override
public Object visitModeIndY(Asm6502Parser.ModeIndYContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IZY);
}
@Override
public Object visitModeIndX(Asm6502Parser.ModeIndXContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IZX);
}
@Override
public Object visitModeInd(Asm6502Parser.ModeIndContext ctx) {
return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IND);
}
private AsmInstruction createAsmInstruction(Asm6502Parser.ParamModeContext ctx, Asm6502Parser.ParamContext paramCtx, AsmAddressingMode addressingMode) {
Asm6502Parser.InstructionContext instructionCtx = (Asm6502Parser.InstructionContext) ctx.getParent();
String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText();
String parameter = (String) this.visit(paramCtx);
AsmInstructionType type = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode);
return new AsmInstruction(type, parameter, 1);
}
@Override
public Object visitParamInt(Asm6502Parser.ParamIntContext ctx) {
return NumberParser.parseLiteral(ctx.NUMINT().getText()).toString();
}
@Override
public Object visitParamLabel(Asm6502Parser.ParamLabelContext ctx) {
return ctx.NAME().getSymbol().getText();
}
@Override
public Object visitParamReplace(Asm6502Parser.ParamReplaceContext ctx) {
String replaceName = ctx.NAME().getSymbol().getText();
return AsmFragment.this.getBoundValue(replaceName);
}
}
}

View File

@ -0,0 +1,45 @@
package dk.camelot64.kickc.asm;
/** An assembler instruction */
public class AsmInstruction implements AsmLine {
private AsmInstructionType type;
private String parameter;
private int invocationCountEstimate;
public AsmInstruction(AsmInstructionType type, String parameter, int invocationCountEstimate) {
this.type = type;
this.parameter = parameter;
this.invocationCountEstimate = invocationCountEstimate;
}
@Override
public int getLineBytes() {
return type.getBytes();
}
@Override
public double getLineCycles() {
return type.getCycles();
}
@Override
public int getInvocationCountEstimate() {
return invocationCountEstimate;
}
@Override
public double getEstimatedTotalCycles() {
return getInvocationCountEstimate()*getLineCycles();
}
@Override
public String getAsm() {
return type.getAsm(parameter);
}
}

View File

@ -0,0 +1,41 @@
package dk.camelot64.kickc.asm;
/** The instructions of the 6502 assembler instruction set */
public class AsmInstructionType {
private int opcode;
private String mnemnonic;
private AsmAddressingMode addressingMode;
private double cycles;
public AsmInstructionType(int opcode, String mnemnonic, AsmAddressingMode addressingMode, double cycles) {
this.opcode = opcode;
this.mnemnonic = mnemnonic;
this.addressingMode = addressingMode;
this.cycles = cycles;
}
public String getMnemnonic() {
return mnemnonic;
}
public AsmAddressingMode getAddressingMode() {
return addressingMode;
}
public double getCycles() {
return cycles;
}
public int getBytes() {
return addressingMode.getBytes();
}
public String getAsm(String parameter) {
return addressingMode.getAsm(mnemnonic, parameter);
}
}

View File

@ -0,0 +1,312 @@
package dk.camelot64.kickc.asm;
import java.util.ArrayList;
import java.util.List;
/**
* The set of all 6502 assembler instructions
*/
public class AsmInstuctionSet {
private static AsmInstuctionSet set = new AsmInstuctionSet();
public static AsmInstructionType getInstructionType(String mnemonic, AsmAddressingMode mode) {
AsmInstructionType type = set.getType(mnemonic, mode);
if(type==null && AsmAddressingMode.ABS.equals(mode)) {
type = set.getType(mnemonic, AsmAddressingMode.REL);
}
return type;
}
private List<AsmInstructionType> instructions;
private void add(int opcode, String mnemonic, AsmAddressingMode addressingmMode, double cycles) {
instructions.add(new AsmInstructionType(opcode, mnemonic.toLowerCase(), addressingmMode, cycles));
}
public AsmInstuctionSet() {
this.instructions = new ArrayList<>();
AsmAddressingMode non = AsmAddressingMode.NON;
AsmAddressingMode zp = AsmAddressingMode.ZP;
AsmAddressingMode zpx = AsmAddressingMode.ZPX;
AsmAddressingMode zpy = AsmAddressingMode.ZPY;
AsmAddressingMode imm = AsmAddressingMode.IMM;
AsmAddressingMode abs = AsmAddressingMode.ABS;
AsmAddressingMode abx = AsmAddressingMode.ABX;
AsmAddressingMode aby = AsmAddressingMode.ABY;
AsmAddressingMode izx = AsmAddressingMode.IZX;
AsmAddressingMode izy = AsmAddressingMode.IZY;
AsmAddressingMode rel = AsmAddressingMode.REL;
AsmAddressingMode ind = AsmAddressingMode.IND;
add(0x00, "BRK", non, 7.0);
add(0x01, "ORA", izx, 6.0);
add(0x01, "ORA", izx, 6.0);
add(0x02, "KIL", non, 0.0);
add(0x03, "SLO", izx, 8.0);
add(0x04, "NOP", zp, 3.0);
add(0x05, "ORA", zp, 3.0);
add(0x06, "ASL", zp, 5.0);
add(0x07, "SLO", zp, 5.0);
add(0x08, "PHP", non, 3.0);
add(0x09, "ORA", imm, 2.0);
add(0x0a, "ASL", non, 2.0);
add(0x0b, "ANC", imm, 2.0);
add(0x0c, "NOP", abs, 4.0);
add(0x0d, "ORA", abs, 4.0);
add(0x0e, "ASL", abs, 6.0);
add(0x0f, "SLO", abs, 6.0);
add(0x10, "BPL", rel, 2.5);
add(0x11, "ORA", izy, 5.5);
add(0x12, "KIL", non, 0.0);
add(0x13, "SLO", izy, 8.0);
add(0x14, "NOP", zpx, 4.0);
add(0x15, "ORA", zpx, 4.0);
add(0x16, "ASL", zpx, 6.0);
add(0x17, "SLO", zpx, 6.0);
add(0x18, "CLC", non, 2.0);
add(0x19, "ORA", aby, 4.5);
add(0x1a, "NOP", non, 2.0);
add(0x1b, "SLO", aby, 7.0);
add(0x1c, "NOP", abx, 4.5);
add(0x1d, "ORA", abx, 4.5);
add(0x1e, "ASL", abx, 7.0);
add(0x1f, "SLO", abx, 7.0);
add(0x20, "JSR", abs, 6.0);
add(0x21, "AND", izx, 6.0);
add(0x22, "KIL", non, 0.0);
add(0x23, "RLA", izx, 8.0);
add(0x24, "BIT", zp, 3.0);
add(0x25, "AND", zp, 3.0);
add(0x26, "ROL", zp, 5.0);
add(0x27, "RLA", zp, 5.0);
add(0x28, "PLP", non, 4.0);
add(0x29, "AND", imm, 2.0);
add(0x2a, "ROL", non, 2.0);
add(0x2b, "ANC", imm, 2.0);
add(0x2c, "BIT", abs, 4.0);
add(0x2d, "AND", abs, 4.0);
add(0x2e, "ROL", abs, 6.0);
add(0x2f, "RLA", abs, 6.0);
add(0x30, "BMI", rel, 2.5);
add(0x31, "AND", izy, 5.5);
add(0x32, "KIL", non, 0.0);
add(0x33, "RLA", izy, 8.0);
add(0x34, "NOP", zpx, 4.0);
add(0x35, "AND", zpx, 4.0);
add(0x36, "ROL", zpx, 6.0);
add(0x37, "RLA", zpx, 6.0);
add(0x38, "SEC", non, 2.0);
add(0x39, "AND", aby, 4.5);
add(0x3a, "NOP", non, 2.0);
add(0x3b, "RLA", aby, 7.0);
add(0x3c, "NOP", abx, 4.5);
add(0x3d, "AND", abx, 4.5);
add(0x3e, "ROL", abx, 7.0);
add(0x3f, "RLA", abx, 7.0);
add(0x40, "RTI", non, 6.0);
add(0x41, "EOR", izx, 6.0);
add(0x42, "KIL", non, 0.0);
add(0x43, "SRE", izx, 8.0);
add(0x44, "NOP", zp, 3.0);
add(0x45, "EOR", zp, 3.0);
add(0x46, "LSR", zp, 5.0);
add(0x47, "SRE", zp, 5.0);
add(0x48, "PHA", non, 3.0);
add(0x49, "EOR", imm, 2.0);
add(0x4a, "LSR", non, 2.0);
add(0x4b, "ALR", imm, 2.0);
add(0x4c, "JMP", abs, 3.0);
add(0x4d, "EOR", abs, 4.0);
add(0x4e, "LSR", abs, 6.0);
add(0x4f, "SRE", abs, 6.0);
add(0x50, "BVC", rel, 2.5);
add(0x51, "EOR", izy, 5.5);
add(0x52, "KIL", non, 0.0);
add(0x53, "SRE", izy, 8.0);
add(0x54, "NOP", zpx, 4.0);
add(0x55, "EOR", zpx, 4.0);
add(0x56, "LSR", zpx, 6.0);
add(0x57, "SRE", zpx, 6.0);
add(0x58, "CLI", non, 2.0);
add(0x59, "EOR", aby, 4.5);
add(0x5a, "NOP", non, 2.0);
add(0x5b, "SRE", aby, 7.0);
add(0x5c, "NOP", abx, 4.5);
add(0x5d, "EOR", abx, 4.5);
add(0x5e, "LSR", abx, 7.0);
add(0x5f, "SRE", abx, 7.0);
add(0x60, "RTS", non, 6.0);
add(0x61, "ADC", izx, 6.0);
add(0x62, "KIL", non, 0.0);
add(0x63, "RRA", izx, 8.0);
add(0x64, "NOP", zp, 3.0);
add(0x65, "ADC", zp, 3.0);
add(0x66, "ROR", zp, 5.0);
add(0x67, "RRA", zp, 5.0);
add(0x68, "PLA", non, 4.0);
add(0x69, "ADC", imm, 2.0);
add(0x6a, "ROR", non, 2.0);
add(0x6b, "ARR", imm, 2.0);
add(0x6c, "JMP", ind, 5.0);
add(0x6d, "ADC", abs, 4.0);
add(0x6e, "ROR", abs, 6.0);
add(0x6f, "RRA", abs, 6.0);
add(0x70, "BVS", rel, 2.5);
add(0x71, "ADC", izy, 5.5);
add(0x72, "KIL", non, 0.0);
add(0x73, "RRA", izy, 8.0);
add(0x74, "NOP", zpx, 4.0);
add(0x75, "ADC", zpx, 4.0);
add(0x76, "ROR", zpx, 6.0);
add(0x77, "RRA", zpx, 6.0);
add(0x78, "SEI", non, 2.0);
add(0x79, "ADC", aby, 4.5);
add(0x7a, "NOP", non, 2.0);
add(0x7b, "RRA", aby, 7.0);
add(0x7c, "NOP", abx, 4.5);
add(0x7d, "ADC", abx, 4.5);
add(0x7e, "ROR", abx, 7.0);
add(0x7f, "RRA", abx, 7.0);
add(0x80, "NOP", imm, 2.0);
add(0x81, "STA", izx, 6.0);
add(0x82, "NOP", imm, 2.0);
add(0x83, "SAX", izx, 6.0);
add(0x84, "STY", zp, 3.0);
add(0x85, "STA", zp, 3.0);
add(0x86, "STX", zp, 3.0);
add(0x87, "SAX", zp, 3.0);
add(0x88, "DEY", non, 2.0);
add(0x89, "NOP", imm, 2.0);
add(0x8a, "TXA", non, 2.0);
add(0x8b, "XAA", imm, 2.0);
add(0x8c, "STY", abs, 4.0);
add(0x8d, "STA", abs, 4.0);
add(0x8e, "STX", abs, 4.0);
add(0x8f, "SAX", abs, 4.0);
add(0x90, "BCC", rel, 2.5);
add(0x91, "STA", izy, 6.0);
add(0x92, "KIL", non, 0.0);
add(0x93, "AHX", izy, 6.0);
add(0x94, "STY", zpx, 4.0);
add(0x95, "STA", zpx, 4.0);
add(0x96, "STX", zpy, 4.0);
add(0x97, "SAX", zpy, 4.0);
add(0x98, "TYA", non, 2.0);
add(0x99, "STA", aby, 5.0);
add(0x9a, "TXS", non, 2.0);
add(0x9b, "TAS", aby, 5.0);
add(0x9c, "SHY", abx, 5.0);
add(0x9d, "STA", abx, 5.0);
add(0x9e, "SHX", aby, 5.0);
add(0x9f, "AHX", aby, 5.0);
add(0xa0, "LDY", imm, 2.0);
add(0xa1, "LDA", izx, 6.0);
add(0xa2, "LDX", imm, 2.0);
add(0xa3, "LAX", izx, 6.0);
add(0xa4, "LDY", zp, 3.0);
add(0xa5, "LDA", zp, 3.0);
add(0xa6, "LDX", zp, 3.0);
add(0xa7, "LAX", zp, 3.0);
add(0xa8, "TAY", non, 2.0);
add(0xa9, "LDA", imm, 2.0);
add(0xaa, "TAX", non, 2.0);
add(0xab, "LAX", imm, 2.0);
add(0xac, "LDY", abs, 4.0);
add(0xad, "LDA", abs, 4.0);
add(0xae, "LDX", abs, 4.0);
add(0xaf, "LAX", abs, 4.0);
add(0xb0, "BCS", rel, 2.5);
add(0xb1, "LDA", izy, 5.5);
add(0xb2, "KIL", non, 0.0);
add(0xb3, "LAX", izy, 5.5);
add(0xb4, "LDY", zpx, 4.0);
add(0xb5, "LDA", zpx, 4.0);
add(0xb6, "LDX", zpy, 4.0);
add(0xb7, "LAX", zpy, 4.0);
add(0xb8, "CLV", non, 2.0);
add(0xb9, "LDA", aby, 4.5);
add(0xba, "TSX", non, 2.0);
add(0xbb, "LAS", aby, 4.5);
add(0xbc, "LDY", abx, 4.5);
add(0xbd, "LDA", abx, 4.5);
add(0xbe, "LDX", aby, 4.5);
add(0xbf, "LAX", aby, 4.5);
add(0xc0, "CPY", imm, 2.0);
add(0xc1, "CMP", izx, 6.0);
add(0xc2, "NOP", imm, 2.0);
add(0xc3, "DCP", izx, 8.0);
add(0xc4, "CPY", zp, 3.0);
add(0xc5, "CMP", zp, 3.0);
add(0xc6, "DEC", zp, 5.0);
add(0xc7, "DCP", zp, 5.0);
add(0xc8, "INY", non, 2.0);
add(0xc9, "CMP", imm, 2.0);
add(0xca, "DEX", non, 2.0);
add(0xcb, "AXS", imm, 2.0);
add(0xcc, "CPY", abs, 4.0);
add(0xcd, "CMP", abs, 4.0);
add(0xce, "DEC", abs, 6.0);
add(0xcf, "DCP", abs, 6.0);
add(0xd0, "BNE", rel, 2.5);
add(0xd1, "CMP", izy, 5.5);
add(0xd2, "KIL", non, 0.0);
add(0xd3, "DCP", izy, 8.0);
add(0xd4, "NOP", zpx, 4.0);
add(0xd5, "CMP", zpx, 4.0);
add(0xd6, "DEC", zpx, 6.0);
add(0xd7, "DCP", zpx, 6.0);
add(0xd8, "CLD", non, 2.0);
add(0xd9, "CMP", aby, 4.5);
add(0xda, "NOP", non, 2.0);
add(0xdb, "DCP", aby, 7.0);
add(0xdc, "NOP", abx, 4.5);
add(0xdd, "CMP", abx, 4.5);
add(0xde, "DEC", abx, 7.0);
add(0xef, "CPX", imm, 2.0);
add(0xe0, "SBC", izx, 6.0);
add(0xe1, "NOP", imm, 2.0);
add(0xe2, "ISC", izx, 8.0);
add(0xe3, "CPX", zp, 3.0);
add(0xe4, "SBC", zp, 3.0);
add(0xe5, "INC", zp, 5.0);
add(0xe6, "ISC", zp, 5.0);
add(0xe7, "INX", non, 2.0);
add(0xe8, "SBC", imm, 2.0);
add(0xe9, "NOP", non, 2.0);
add(0xea, "SBC", imm, 2.0);
add(0xeb, "CPX", abs, 4.0);
add(0xec, "SBC", abs, 4.0);
add(0xed, "INC", abs, 6.0);
add(0xee, "ISC", abs, 6.0);
add(0xef, "DCP", abx, 7.0);
add(0xf0, "BEQ", rel, 2.5);
add(0xf1, "SBC", izy, 5.5);
add(0xf2, "KIL", non, 0.0);
add(0xf3, "ISC", izy, 8.0);
add(0xf4, "NOP", zpx, 4.0);
add(0xf5, "SBC", zpx, 4.0);
add(0xf6, "INC", zpx, 6.0);
add(0xf7, "ISC", zpx, 6.0);
add(0xf8, "SED", non, 2.0);
add(0xf9, "SBC", aby, 4.5);
add(0xfa, "NOP", non, 2.0);
add(0xfb, "ISC", aby, 7.0);
add(0xfc, "NOP", abx, 4.5);
add(0xfd, "SBC", abx, 4.5);
add(0xfe, "INC", abx, 7.0);
add(0xff, "ISC", abx, 7.0);
}
public AsmInstructionType getType(String mnemonic, AsmAddressingMode addressingMode) {
for (AsmInstructionType candidate : instructions) {
if(candidate.getMnemnonic().equals(mnemonic.toLowerCase()) && candidate.getAddressingMode().equals(addressingMode)) {
return candidate;
}
}
return null;
}
}

View File

@ -0,0 +1,36 @@
package dk.camelot64.kickc.asm;
/** A label / jump target */
public class AsmLabel implements AsmLine {
private String label;
public AsmLabel(String label) {
this.label = label;
}
@Override
public int getLineBytes() {
return 0;
}
@Override
public double getLineCycles() {
return 0;
}
@Override
public int getInvocationCountEstimate() {
return 0;
}
@Override
public double getEstimatedTotalCycles() {
return 0;
}
@Override
public String getAsm() {
return ":"+label;
}
}

View File

@ -0,0 +1,16 @@
package dk.camelot64.kickc.asm;
/** A line of 6502 assembler code */
public interface AsmLine {
public int getLineBytes();
public double getLineCycles();
public int getInvocationCountEstimate();
public double getEstimatedTotalCycles();
public String getAsm();
}

View File

@ -0,0 +1,22 @@
package dk.camelot64.kickc.asm;
import java.util.ArrayList;
import java.util.List;
/** A 6502 assembler program */
public class AsmProgram {
private List<AsmLine> lines;
public AsmProgram() {
this.lines = new ArrayList<>();
}
public List<AsmLine> getLines() {
return lines;
}
public void addLine(AsmLine line) {
lines.add(line);
}
}

View File

@ -1,4 +1,4 @@
package dk.camelot64.kickc.icl;
package dk.camelot64.kickc.asm;
import java.util.ArrayList;
import java.util.List;

View File

@ -0,0 +1 @@
ldx #{coby1}

View File

@ -0,0 +1 @@
dex

View File

@ -0,0 +1,2 @@
cpx #0
bne {la1}

View File

@ -0,0 +1,11 @@
LDA {zpby1}
CMP #{coby1}
BEQ !f+
BCS !t+
!f:
LDA #0
JMP !d+
!t:
LDA #$ff
!d:
STA {zpbo1}

View File

@ -5,4 +5,4 @@ beq !t+
!f: lda #0
jmp !d+
!t: lda #$ff
!d: sta {zpbo1}
!d: sta {zpbo1

View File

@ -4,4 +4,4 @@ bcc !t+
!f: lda #0
jmp !d+
!t: lda #$ff
!d: sta {zpbo1}
!d: sta {zpbo1}

View File

@ -0,0 +1,4 @@
lda {zpby2}
sec
sbc #1
sta {zpby1}

View File

@ -0,0 +1,4 @@
lda {zpby1}
clc
adc #1
sta {zpby2}

View File

@ -0,0 +1,3 @@
lda {zpby1}
cmp #{coby1}
bcc {la1}

View File

@ -0,0 +1,55 @@
// 6502 Assembler Grammar
grammar Asm6502;
file :
lineSeq EOF
;
lineSeq
: line+
;
line
: label? instruction? comment? '\n'
;
label
: NAME ':'
;
comment
: '//' .*?
;
instruction
: MNEMONIC (paramMode)?
;
paramMode
: param #modeAbs
| '#' param #modeImm
| param ',x' #modeAbsX
| param ',y' #modeAbsY
| '(' param ')' ',y' #modeIndY
| '(' param ',x' ')' #modeIndX
| '(' param ')' #modeInd
;
param
: NAME #paramLabel
| '{' NAME '}' #paramReplace
| NUMINT #paramInt
;
MNEMONIC: [A-Za-z][A-Za-z][A-Za-z];
NUMINT : DECINTEGER | HEXINTEGER | BININTEGER ;
BININTEGER : '0' [bB] BINDIGIT+ | '%' BINDIGIT+ ;
DECINTEGER : DECDIGIT+ ;
HEXINTEGER : ( '$' | '0x' | '0X' ) HEXDIGIT+ ;
fragment BINDIGIT : [0-1];
fragment DECDIGIT : [0-9];
fragment HEXDIGIT : [0-9a-fA-F];
NAME : NAME_START NAME_CHAR* [+-]* ;
fragment NAME_START : [!a-zA-Z_];
fragment NAME_CHAR : [a-zA-Z0-9_];
WS : [ \t\r]+ -> skip ; // skip spaces, tabs

View File

@ -0,0 +1,27 @@
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
T__5=6
T__6=7
T__7=8
T__8=9
T__9=10
MNEMONIC=11
NUMINT=12
BININTEGER=13
DECINTEGER=14
HEXINTEGER=15
NAME=16
WS=17
'\n'=1
':'=2
'//'=3
'#'=4
',x'=5
',y'=6
'('=7
')'=8
'{'=9
'}'=10

View File

@ -0,0 +1,231 @@
// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7
package dk.camelot64.kickc.asm.parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
/**
* This class provides an empty implementation of {@link Asm6502Listener},
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
public class Asm6502BaseListener implements Asm6502Listener {
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterFile(Asm6502Parser.FileContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitFile(Asm6502Parser.FileContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLineSeq(Asm6502Parser.LineSeqContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLineSeq(Asm6502Parser.LineSeqContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLine(Asm6502Parser.LineContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLine(Asm6502Parser.LineContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLabel(Asm6502Parser.LabelContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLabel(Asm6502Parser.LabelContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterComment(Asm6502Parser.CommentContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitComment(Asm6502Parser.CommentContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterInstruction(Asm6502Parser.InstructionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitInstruction(Asm6502Parser.InstructionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeAbs(Asm6502Parser.ModeAbsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeAbs(Asm6502Parser.ModeAbsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeImm(Asm6502Parser.ModeImmContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeImm(Asm6502Parser.ModeImmContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeIndY(Asm6502Parser.ModeIndYContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeIndY(Asm6502Parser.ModeIndYContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeIndX(Asm6502Parser.ModeIndXContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeIndX(Asm6502Parser.ModeIndXContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterModeInd(Asm6502Parser.ModeIndContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitModeInd(Asm6502Parser.ModeIndContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParamLabel(Asm6502Parser.ParamLabelContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParamLabel(Asm6502Parser.ParamLabelContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParamReplace(Asm6502Parser.ParamReplaceContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParamInt(Asm6502Parser.ParamIntContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParamInt(Asm6502Parser.ParamIntContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterEveryRule(ParserRuleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitEveryRule(ParserRuleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void visitTerminal(TerminalNode node) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void visitErrorNode(ErrorNode node) { }
}

View File

@ -0,0 +1,126 @@
// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7
package dk.camelot64.kickc.asm.parser;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link Asm6502Visitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class Asm6502BaseVisitor<T> extends AbstractParseTreeVisitor<T> implements Asm6502Visitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFile(Asm6502Parser.FileContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLineSeq(Asm6502Parser.LineSeqContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLine(Asm6502Parser.LineContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLabel(Asm6502Parser.LabelContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitComment(Asm6502Parser.CommentContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitInstruction(Asm6502Parser.InstructionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeAbs(Asm6502Parser.ModeAbsContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeImm(Asm6502Parser.ModeImmContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeIndY(Asm6502Parser.ModeIndYContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeIndX(Asm6502Parser.ModeIndXContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitModeInd(Asm6502Parser.ModeIndContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParamLabel(Asm6502Parser.ParamLabelContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParamInt(Asm6502Parser.ParamIntContext ctx) { return visitChildren(ctx); }
}

View File

@ -0,0 +1,152 @@
// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7
package dk.camelot64.kickc.asm.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class Asm6502Lexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9,
T__9=10, MNEMONIC=11, NUMINT=12, BININTEGER=13, DECINTEGER=14, HEXINTEGER=15,
NAME=16, WS=17;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static String[] modeNames = {
"DEFAULT_MODE"
};
public static final String[] ruleNames = {
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8",
"T__9", "MNEMONIC", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER",
"BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR",
"WS"
};
private static final String[] _LITERAL_NAMES = {
null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'{'",
"'}'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, "MNEMONIC",
"NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "WS"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
/**
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated
public static final String[] tokenNames;
static {
tokenNames = new String[_SYMBOLIC_NAMES.length];
for (int i = 0; i < tokenNames.length; i++) {
tokenNames[i] = VOCABULARY.getLiteralName(i);
if (tokenNames[i] == null) {
tokenNames[i] = VOCABULARY.getSymbolicName(i);
}
if (tokenNames[i] == null) {
tokenNames[i] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
public Asm6502Lexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "Asm6502.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public String[] getChannelNames() { return channelNames; }
@Override
public String[] getModeNames() { return modeNames; }
@Override
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\23\u008d\b\1\4\2"+
"\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
"\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
"\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\3\2\3\3\3"+
"\3\3\4\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n"+
"\3\13\3\13\3\f\3\f\3\f\3\f\3\r\3\r\3\r\5\rN\n\r\3\16\3\16\3\16\6\16S\n"+
"\16\r\16\16\16T\3\16\3\16\6\16Y\n\16\r\16\16\16Z\5\16]\n\16\3\17\6\17"+
"`\n\17\r\17\16\17a\3\20\3\20\3\20\3\20\3\20\5\20i\n\20\3\20\6\20l\n\20"+
"\r\20\16\20m\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\7\24x\n\24\f\24\16"+
"\24{\13\24\3\24\7\24~\n\24\f\24\16\24\u0081\13\24\3\25\3\25\3\26\3\26"+
"\3\27\6\27\u0088\n\27\r\27\16\27\u0089\3\27\3\27\2\2\30\3\3\5\4\7\5\t"+
"\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\2#\2%\2"+
"\'\22)\2+\2-\23\3\2\13\4\2C\\c|\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch"+
"\4\2--//\6\2##C\\aac|\6\2\62;C\\aac|\5\2\13\13\17\17\"\"\2\u0093\2\3\3"+
"\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2"+
"\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3"+
"\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2\'\3\2\2\2\2-\3\2\2\2\3"+
"/\3\2\2\2\5\61\3\2\2\2\7\63\3\2\2\2\t\66\3\2\2\2\138\3\2\2\2\r;\3\2\2"+
"\2\17>\3\2\2\2\21@\3\2\2\2\23B\3\2\2\2\25D\3\2\2\2\27F\3\2\2\2\31M\3\2"+
"\2\2\33\\\3\2\2\2\35_\3\2\2\2\37h\3\2\2\2!o\3\2\2\2#q\3\2\2\2%s\3\2\2"+
"\2\'u\3\2\2\2)\u0082\3\2\2\2+\u0084\3\2\2\2-\u0087\3\2\2\2/\60\7\f\2\2"+
"\60\4\3\2\2\2\61\62\7<\2\2\62\6\3\2\2\2\63\64\7\61\2\2\64\65\7\61\2\2"+
"\65\b\3\2\2\2\66\67\7%\2\2\67\n\3\2\2\289\7.\2\29:\7z\2\2:\f\3\2\2\2;"+
"<\7.\2\2<=\7{\2\2=\16\3\2\2\2>?\7*\2\2?\20\3\2\2\2@A\7+\2\2A\22\3\2\2"+
"\2BC\7}\2\2C\24\3\2\2\2DE\7\177\2\2E\26\3\2\2\2FG\t\2\2\2GH\t\2\2\2HI"+
"\t\2\2\2I\30\3\2\2\2JN\5\35\17\2KN\5\37\20\2LN\5\33\16\2MJ\3\2\2\2MK\3"+
"\2\2\2ML\3\2\2\2N\32\3\2\2\2OP\7\62\2\2PR\t\3\2\2QS\5!\21\2RQ\3\2\2\2"+
"ST\3\2\2\2TR\3\2\2\2TU\3\2\2\2U]\3\2\2\2VX\7\'\2\2WY\5!\21\2XW\3\2\2\2"+
"YZ\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[]\3\2\2\2\\O\3\2\2\2\\V\3\2\2\2]\34\3\2"+
"\2\2^`\5#\22\2_^\3\2\2\2`a\3\2\2\2a_\3\2\2\2ab\3\2\2\2b\36\3\2\2\2ci\7"+
"&\2\2de\7\62\2\2ei\7z\2\2fg\7\62\2\2gi\7Z\2\2hc\3\2\2\2hd\3\2\2\2hf\3"+
"\2\2\2ik\3\2\2\2jl\5%\23\2kj\3\2\2\2lm\3\2\2\2mk\3\2\2\2mn\3\2\2\2n \3"+
"\2\2\2op\t\4\2\2p\"\3\2\2\2qr\t\5\2\2r$\3\2\2\2st\t\6\2\2t&\3\2\2\2uy"+
"\5)\25\2vx\5+\26\2wv\3\2\2\2x{\3\2\2\2yw\3\2\2\2yz\3\2\2\2z\177\3\2\2"+
"\2{y\3\2\2\2|~\t\7\2\2}|\3\2\2\2~\u0081\3\2\2\2\177}\3\2\2\2\177\u0080"+
"\3\2\2\2\u0080(\3\2\2\2\u0081\177\3\2\2\2\u0082\u0083\t\b\2\2\u0083*\3"+
"\2\2\2\u0084\u0085\t\t\2\2\u0085,\3\2\2\2\u0086\u0088\t\n\2\2\u0087\u0086"+
"\3\2\2\2\u0088\u0089\3\2\2\2\u0089\u0087\3\2\2\2\u0089\u008a\3\2\2\2\u008a"+
"\u008b\3\2\2\2\u008b\u008c\b\27\2\2\u008c.\3\2\2\2\r\2MTZ\\ahmy\177\u0089"+
"\3\b\2\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

View File

@ -0,0 +1,27 @@
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
T__5=6
T__6=7
T__7=8
T__8=9
T__9=10
MNEMONIC=11
NUMINT=12
BININTEGER=13
DECINTEGER=14
HEXINTEGER=15
NAME=16
WS=17
'\n'=1
':'=2
'//'=3
'#'=4
',x'=5
',y'=6
'('=7
')'=8
'{'=9
'}'=10

View File

@ -0,0 +1,190 @@
// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7
package dk.camelot64.kickc.asm.parser;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link Asm6502Parser}.
*/
public interface Asm6502Listener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link Asm6502Parser#file}.
* @param ctx the parse tree
*/
void enterFile(Asm6502Parser.FileContext ctx);
/**
* Exit a parse tree produced by {@link Asm6502Parser#file}.
* @param ctx the parse tree
*/
void exitFile(Asm6502Parser.FileContext ctx);
/**
* Enter a parse tree produced by {@link Asm6502Parser#lineSeq}.
* @param ctx the parse tree
*/
void enterLineSeq(Asm6502Parser.LineSeqContext ctx);
/**
* Exit a parse tree produced by {@link Asm6502Parser#lineSeq}.
* @param ctx the parse tree
*/
void exitLineSeq(Asm6502Parser.LineSeqContext ctx);
/**
* Enter a parse tree produced by {@link Asm6502Parser#line}.
* @param ctx the parse tree
*/
void enterLine(Asm6502Parser.LineContext ctx);
/**
* Exit a parse tree produced by {@link Asm6502Parser#line}.
* @param ctx the parse tree
*/
void exitLine(Asm6502Parser.LineContext ctx);
/**
* Enter a parse tree produced by {@link Asm6502Parser#label}.
* @param ctx the parse tree
*/
void enterLabel(Asm6502Parser.LabelContext ctx);
/**
* Exit a parse tree produced by {@link Asm6502Parser#label}.
* @param ctx the parse tree
*/
void exitLabel(Asm6502Parser.LabelContext ctx);
/**
* Enter a parse tree produced by {@link Asm6502Parser#comment}.
* @param ctx the parse tree
*/
void enterComment(Asm6502Parser.CommentContext ctx);
/**
* Exit a parse tree produced by {@link Asm6502Parser#comment}.
* @param ctx the parse tree
*/
void exitComment(Asm6502Parser.CommentContext ctx);
/**
* Enter a parse tree produced by {@link Asm6502Parser#instruction}.
* @param ctx the parse tree
*/
void enterInstruction(Asm6502Parser.InstructionContext ctx);
/**
* Exit a parse tree produced by {@link Asm6502Parser#instruction}.
* @param ctx the parse tree
*/
void exitInstruction(Asm6502Parser.InstructionContext ctx);
/**
* Enter a parse tree produced by the {@code modeAbs}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeAbs(Asm6502Parser.ModeAbsContext ctx);
/**
* Exit a parse tree produced by the {@code modeAbs}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeAbs(Asm6502Parser.ModeAbsContext ctx);
/**
* Enter a parse tree produced by the {@code modeImm}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeImm(Asm6502Parser.ModeImmContext ctx);
/**
* Exit a parse tree produced by the {@code modeImm}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeImm(Asm6502Parser.ModeImmContext ctx);
/**
* Enter a parse tree produced by the {@code modeAbsX}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeAbsX(Asm6502Parser.ModeAbsXContext ctx);
/**
* Exit a parse tree produced by the {@code modeAbsX}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeAbsX(Asm6502Parser.ModeAbsXContext ctx);
/**
* Enter a parse tree produced by the {@code modeAbsY}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeAbsY(Asm6502Parser.ModeAbsYContext ctx);
/**
* Exit a parse tree produced by the {@code modeAbsY}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeAbsY(Asm6502Parser.ModeAbsYContext ctx);
/**
* Enter a parse tree produced by the {@code modeIndY}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeIndY(Asm6502Parser.ModeIndYContext ctx);
/**
* Exit a parse tree produced by the {@code modeIndY}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeIndY(Asm6502Parser.ModeIndYContext ctx);
/**
* Enter a parse tree produced by the {@code modeIndX}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeIndX(Asm6502Parser.ModeIndXContext ctx);
/**
* Exit a parse tree produced by the {@code modeIndX}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeIndX(Asm6502Parser.ModeIndXContext ctx);
/**
* Enter a parse tree produced by the {@code modeInd}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void enterModeInd(Asm6502Parser.ModeIndContext ctx);
/**
* Exit a parse tree produced by the {@code modeInd}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
*/
void exitModeInd(Asm6502Parser.ModeIndContext ctx);
/**
* Enter a parse tree produced by the {@code paramLabel}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
*/
void enterParamLabel(Asm6502Parser.ParamLabelContext ctx);
/**
* Exit a parse tree produced by the {@code paramLabel}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
*/
void exitParamLabel(Asm6502Parser.ParamLabelContext ctx);
/**
* Enter a parse tree produced by the {@code paramReplace}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
*/
void enterParamReplace(Asm6502Parser.ParamReplaceContext ctx);
/**
* Exit a parse tree produced by the {@code paramReplace}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
*/
void exitParamReplace(Asm6502Parser.ParamReplaceContext ctx);
/**
* Enter a parse tree produced by the {@code paramInt}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
*/
void enterParamInt(Asm6502Parser.ParamIntContext ctx);
/**
* Exit a parse tree produced by the {@code paramInt}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
*/
void exitParamInt(Asm6502Parser.ParamIntContext ctx);
}

View File

@ -0,0 +1,821 @@
// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7
package dk.camelot64.kickc.asm.parser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class Asm6502Parser extends Parser {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9,
T__9=10, MNEMONIC=11, NUMINT=12, BININTEGER=13, DECINTEGER=14, HEXINTEGER=15,
NAME=16, WS=17;
public static final int
RULE_file = 0, RULE_lineSeq = 1, RULE_line = 2, RULE_label = 3, RULE_comment = 4,
RULE_instruction = 5, RULE_paramMode = 6, RULE_param = 7;
public static final String[] ruleNames = {
"file", "lineSeq", "line", "label", "comment", "instruction", "paramMode",
"param"
};
private static final String[] _LITERAL_NAMES = {
null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'{'",
"'}'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, "MNEMONIC",
"NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "WS"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
/**
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated
public static final String[] tokenNames;
static {
tokenNames = new String[_SYMBOLIC_NAMES.length];
for (int i = 0; i < tokenNames.length; i++) {
tokenNames[i] = VOCABULARY.getLiteralName(i);
if (tokenNames[i] == null) {
tokenNames[i] = VOCABULARY.getSymbolicName(i);
}
if (tokenNames[i] == null) {
tokenNames[i] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
@Override
public String getGrammarFileName() { return "Asm6502.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public ATN getATN() { return _ATN; }
public Asm6502Parser(TokenStream input) {
super(input);
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
public static class FileContext extends ParserRuleContext {
public LineSeqContext lineSeq() {
return getRuleContext(LineSeqContext.class,0);
}
public TerminalNode EOF() { return getToken(Asm6502Parser.EOF, 0); }
public FileContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_file; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterFile(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitFile(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitFile(this);
else return visitor.visitChildren(this);
}
}
public final FileContext file() throws RecognitionException {
FileContext _localctx = new FileContext(_ctx, getState());
enterRule(_localctx, 0, RULE_file);
try {
enterOuterAlt(_localctx, 1);
{
setState(16);
lineSeq();
setState(17);
match(EOF);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class LineSeqContext extends ParserRuleContext {
public List<LineContext> line() {
return getRuleContexts(LineContext.class);
}
public LineContext line(int i) {
return getRuleContext(LineContext.class,i);
}
public LineSeqContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_lineSeq; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterLineSeq(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitLineSeq(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitLineSeq(this);
else return visitor.visitChildren(this);
}
}
public final LineSeqContext lineSeq() throws RecognitionException {
LineSeqContext _localctx = new LineSeqContext(_ctx, getState());
enterRule(_localctx, 2, RULE_lineSeq);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(20);
_errHandler.sync(this);
_la = _input.LA(1);
do {
{
{
setState(19);
line();
}
}
setState(22);
_errHandler.sync(this);
_la = _input.LA(1);
} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << MNEMONIC) | (1L << NAME))) != 0) );
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class LineContext extends ParserRuleContext {
public LabelContext label() {
return getRuleContext(LabelContext.class,0);
}
public InstructionContext instruction() {
return getRuleContext(InstructionContext.class,0);
}
public CommentContext comment() {
return getRuleContext(CommentContext.class,0);
}
public LineContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_line; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterLine(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitLine(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitLine(this);
else return visitor.visitChildren(this);
}
}
public final LineContext line() throws RecognitionException {
LineContext _localctx = new LineContext(_ctx, getState());
enterRule(_localctx, 4, RULE_line);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(25);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==NAME) {
{
setState(24);
label();
}
}
setState(28);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==MNEMONIC) {
{
setState(27);
instruction();
}
}
setState(31);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==T__2) {
{
setState(30);
comment();
}
}
setState(33);
match(T__0);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class LabelContext extends ParserRuleContext {
public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); }
public LabelContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_label; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterLabel(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitLabel(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitLabel(this);
else return visitor.visitChildren(this);
}
}
public final LabelContext label() throws RecognitionException {
LabelContext _localctx = new LabelContext(_ctx, getState());
enterRule(_localctx, 6, RULE_label);
try {
enterOuterAlt(_localctx, 1);
{
setState(35);
match(NAME);
setState(36);
match(T__1);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class CommentContext extends ParserRuleContext {
public CommentContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_comment; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterComment(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitComment(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitComment(this);
else return visitor.visitChildren(this);
}
}
public final CommentContext comment() throws RecognitionException {
CommentContext _localctx = new CommentContext(_ctx, getState());
enterRule(_localctx, 8, RULE_comment);
try {
int _alt;
enterOuterAlt(_localctx, 1);
{
setState(38);
match(T__2);
setState(42);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,4,_ctx);
while ( _alt!=1 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1+1 ) {
{
{
setState(39);
matchWildcard();
}
}
}
setState(44);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,4,_ctx);
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class InstructionContext extends ParserRuleContext {
public TerminalNode MNEMONIC() { return getToken(Asm6502Parser.MNEMONIC, 0); }
public ParamModeContext paramMode() {
return getRuleContext(ParamModeContext.class,0);
}
public InstructionContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_instruction; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterInstruction(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitInstruction(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitInstruction(this);
else return visitor.visitChildren(this);
}
}
public final InstructionContext instruction() throws RecognitionException {
InstructionContext _localctx = new InstructionContext(_ctx, getState());
enterRule(_localctx, 10, RULE_instruction);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(45);
match(MNEMONIC);
setState(47);
_errHandler.sync(this);
_la = _input.LA(1);
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__6) | (1L << T__8) | (1L << NUMINT) | (1L << NAME))) != 0)) {
{
setState(46);
paramMode();
}
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class ParamModeContext extends ParserRuleContext {
public ParamModeContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_paramMode; }
public ParamModeContext() { }
public void copyFrom(ParamModeContext ctx) {
super.copyFrom(ctx);
}
}
public static class ModeIndXContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeIndXContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeIndX(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeIndX(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeIndX(this);
else return visitor.visitChildren(this);
}
}
public static class ModeImmContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeImmContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeImm(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeImm(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeImm(this);
else return visitor.visitChildren(this);
}
}
public static class ModeIndYContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeIndYContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeIndY(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeIndY(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeIndY(this);
else return visitor.visitChildren(this);
}
}
public static class ModeAbsYContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeAbsYContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeAbsY(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeAbsY(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeAbsY(this);
else return visitor.visitChildren(this);
}
}
public static class ModeIndContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeIndContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeInd(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeInd(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeInd(this);
else return visitor.visitChildren(this);
}
}
public static class ModeAbsContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeAbsContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeAbs(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeAbs(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeAbs(this);
else return visitor.visitChildren(this);
}
}
public static class ModeAbsXContext extends ParamModeContext {
public ParamContext param() {
return getRuleContext(ParamContext.class,0);
}
public ModeAbsXContext(ParamModeContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeAbsX(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeAbsX(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitModeAbsX(this);
else return visitor.visitChildren(this);
}
}
public final ParamModeContext paramMode() throws RecognitionException {
ParamModeContext _localctx = new ParamModeContext(_ctx, getState());
enterRule(_localctx, 12, RULE_paramMode);
try {
setState(72);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
case 1:
_localctx = new ModeAbsContext(_localctx);
enterOuterAlt(_localctx, 1);
{
setState(49);
param();
}
break;
case 2:
_localctx = new ModeImmContext(_localctx);
enterOuterAlt(_localctx, 2);
{
setState(50);
match(T__3);
setState(51);
param();
}
break;
case 3:
_localctx = new ModeAbsXContext(_localctx);
enterOuterAlt(_localctx, 3);
{
setState(52);
param();
setState(53);
match(T__4);
}
break;
case 4:
_localctx = new ModeAbsYContext(_localctx);
enterOuterAlt(_localctx, 4);
{
setState(55);
param();
setState(56);
match(T__5);
}
break;
case 5:
_localctx = new ModeIndYContext(_localctx);
enterOuterAlt(_localctx, 5);
{
setState(58);
match(T__6);
setState(59);
param();
setState(60);
match(T__7);
setState(61);
match(T__5);
}
break;
case 6:
_localctx = new ModeIndXContext(_localctx);
enterOuterAlt(_localctx, 6);
{
setState(63);
match(T__6);
setState(64);
param();
setState(65);
match(T__4);
setState(66);
match(T__7);
}
break;
case 7:
_localctx = new ModeIndContext(_localctx);
enterOuterAlt(_localctx, 7);
{
setState(68);
match(T__6);
setState(69);
param();
setState(70);
match(T__7);
}
break;
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class ParamContext extends ParserRuleContext {
public ParamContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_param; }
public ParamContext() { }
public void copyFrom(ParamContext ctx) {
super.copyFrom(ctx);
}
}
public static class ParamReplaceContext extends ParamContext {
public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); }
public ParamReplaceContext(ParamContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamReplace(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamReplace(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitParamReplace(this);
else return visitor.visitChildren(this);
}
}
public static class ParamIntContext extends ParamContext {
public TerminalNode NUMINT() { return getToken(Asm6502Parser.NUMINT, 0); }
public ParamIntContext(ParamContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamInt(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamInt(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitParamInt(this);
else return visitor.visitChildren(this);
}
}
public static class ParamLabelContext extends ParamContext {
public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); }
public ParamLabelContext(ParamContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamLabel(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamLabel(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor<? extends T>)visitor).visitParamLabel(this);
else return visitor.visitChildren(this);
}
}
public final ParamContext param() throws RecognitionException {
ParamContext _localctx = new ParamContext(_ctx, getState());
enterRule(_localctx, 14, RULE_param);
try {
setState(79);
_errHandler.sync(this);
switch (_input.LA(1)) {
case NAME:
_localctx = new ParamLabelContext(_localctx);
enterOuterAlt(_localctx, 1);
{
setState(74);
match(NAME);
}
break;
case T__8:
_localctx = new ParamReplaceContext(_localctx);
enterOuterAlt(_localctx, 2);
{
setState(75);
match(T__8);
setState(76);
match(NAME);
setState(77);
match(T__9);
}
break;
case NUMINT:
_localctx = new ParamIntContext(_localctx);
enterOuterAlt(_localctx, 3);
{
setState(78);
match(NUMINT);
}
break;
default:
throw new NoViableAltException(this);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\23T\4\2\t\2\4\3\t"+
"\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\3\2\3\2\3\2\3\3\6\3"+
"\27\n\3\r\3\16\3\30\3\4\5\4\34\n\4\3\4\5\4\37\n\4\3\4\5\4\"\n\4\3\4\3"+
"\4\3\5\3\5\3\5\3\6\3\6\7\6+\n\6\f\6\16\6.\13\6\3\7\3\7\5\7\62\n\7\3\b"+
"\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+
"\b\3\b\3\b\3\b\3\b\5\bK\n\b\3\t\3\t\3\t\3\t\3\t\5\tR\n\t\3\t\3,\2\n\2"+
"\4\6\b\n\f\16\20\2\2\2Y\2\22\3\2\2\2\4\26\3\2\2\2\6\33\3\2\2\2\b%\3\2"+
"\2\2\n(\3\2\2\2\f/\3\2\2\2\16J\3\2\2\2\20Q\3\2\2\2\22\23\5\4\3\2\23\24"+
"\7\2\2\3\24\3\3\2\2\2\25\27\5\6\4\2\26\25\3\2\2\2\27\30\3\2\2\2\30\26"+
"\3\2\2\2\30\31\3\2\2\2\31\5\3\2\2\2\32\34\5\b\5\2\33\32\3\2\2\2\33\34"+
"\3\2\2\2\34\36\3\2\2\2\35\37\5\f\7\2\36\35\3\2\2\2\36\37\3\2\2\2\37!\3"+
"\2\2\2 \"\5\n\6\2! \3\2\2\2!\"\3\2\2\2\"#\3\2\2\2#$\7\3\2\2$\7\3\2\2\2"+
"%&\7\22\2\2&\'\7\4\2\2\'\t\3\2\2\2(,\7\5\2\2)+\13\2\2\2*)\3\2\2\2+.\3"+
"\2\2\2,-\3\2\2\2,*\3\2\2\2-\13\3\2\2\2.,\3\2\2\2/\61\7\r\2\2\60\62\5\16"+
"\b\2\61\60\3\2\2\2\61\62\3\2\2\2\62\r\3\2\2\2\63K\5\20\t\2\64\65\7\6\2"+
"\2\65K\5\20\t\2\66\67\5\20\t\2\678\7\7\2\28K\3\2\2\29:\5\20\t\2:;\7\b"+
"\2\2;K\3\2\2\2<=\7\t\2\2=>\5\20\t\2>?\7\n\2\2?@\7\b\2\2@K\3\2\2\2AB\7"+
"\t\2\2BC\5\20\t\2CD\7\7\2\2DE\7\n\2\2EK\3\2\2\2FG\7\t\2\2GH\5\20\t\2H"+
"I\7\n\2\2IK\3\2\2\2J\63\3\2\2\2J\64\3\2\2\2J\66\3\2\2\2J9\3\2\2\2J<\3"+
"\2\2\2JA\3\2\2\2JF\3\2\2\2K\17\3\2\2\2LR\7\22\2\2MN\7\13\2\2NO\7\22\2"+
"\2OR\7\f\2\2PR\7\16\2\2QL\3\2\2\2QM\3\2\2\2QP\3\2\2\2R\21\3\2\2\2\n\30"+
"\33\36!,\61JQ";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

View File

@ -0,0 +1,119 @@
// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7
package dk.camelot64.kickc.asm.parser;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
/**
* This interface defines a complete generic visitor for a parse tree produced
* by {@link Asm6502Parser}.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public interface Asm6502Visitor<T> extends ParseTreeVisitor<T> {
/**
* Visit a parse tree produced by {@link Asm6502Parser#file}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFile(Asm6502Parser.FileContext ctx);
/**
* Visit a parse tree produced by {@link Asm6502Parser#lineSeq}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLineSeq(Asm6502Parser.LineSeqContext ctx);
/**
* Visit a parse tree produced by {@link Asm6502Parser#line}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLine(Asm6502Parser.LineContext ctx);
/**
* Visit a parse tree produced by {@link Asm6502Parser#label}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLabel(Asm6502Parser.LabelContext ctx);
/**
* Visit a parse tree produced by {@link Asm6502Parser#comment}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitComment(Asm6502Parser.CommentContext ctx);
/**
* Visit a parse tree produced by {@link Asm6502Parser#instruction}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitInstruction(Asm6502Parser.InstructionContext ctx);
/**
* Visit a parse tree produced by the {@code modeAbs}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeAbs(Asm6502Parser.ModeAbsContext ctx);
/**
* Visit a parse tree produced by the {@code modeImm}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeImm(Asm6502Parser.ModeImmContext ctx);
/**
* Visit a parse tree produced by the {@code modeAbsX}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx);
/**
* Visit a parse tree produced by the {@code modeAbsY}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx);
/**
* Visit a parse tree produced by the {@code modeIndY}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeIndY(Asm6502Parser.ModeIndYContext ctx);
/**
* Visit a parse tree produced by the {@code modeIndX}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeIndX(Asm6502Parser.ModeIndXContext ctx);
/**
* Visit a parse tree produced by the {@code modeInd}
* labeled alternative in {@link Asm6502Parser#paramMode}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitModeInd(Asm6502Parser.ModeIndContext ctx);
/**
* Visit a parse tree produced by the {@code paramLabel}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParamLabel(Asm6502Parser.ParamLabelContext ctx);
/**
* Visit a parse tree produced by the {@code paramReplace}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParamReplace(Asm6502Parser.ParamReplaceContext ctx);
/**
* Visit a parse tree produced by the {@code paramInt}
* labeled alternative in {@link Asm6502Parser#param}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParamInt(Asm6502Parser.ParamIntContext ctx);
}

View File

@ -22,10 +22,10 @@ public class Pass3RegisterAllocation {
allocation.allocate(var, new RegisterAllocation.RegisterZpBool(currentZp++));
}
}
allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("n1#1"), new RegisterAllocation.RegisterZpByte(8));
allocation.allocate(symbols.getVariable("n1#2"), new RegisterAllocation.RegisterZpByte(8));
// allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX());
// allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX());
// allocation.allocate(symbols.getVariable("n1#1"), new RegisterAllocation.RegisterZpByte(8));
// allocation.allocate(symbols.getVariable("n1#2"), new RegisterAllocation.RegisterZpByte(8));
symbols.setAllocation(allocation);
}

View File

@ -1,5 +1,8 @@
package dk.camelot64.kickc.icl;
import dk.camelot64.kickc.asm.AsmFragment;
import dk.camelot64.kickc.asm.AsmSequence;
import java.util.List;
/**
@ -27,12 +30,10 @@ public class Pass4CodeGeneration {
// Generate exit
ControlFlowBlock defaultSuccessor = block.getDefaultSuccessor();
if (defaultSuccessor != null) {
if (defaultSuccessor.getPredecessors().size() > 1) {
String label = defaultSuccessor.getLabel().getName() + "_from_" + block.getLabel().getName();
genAsmJump(asm, label);
} else {
genAsmJump(asm, defaultSuccessor.getLabel().getName());
if(defaultSuccessor.getStatements().size()>0 && defaultSuccessor.getStatements().get(0) instanceof StatementPhi) {
genBlockPhiTransition(asm, block, defaultSuccessor);
}
genAsmJump(asm, defaultSuccessor.getLabel().getName());
}
}
return asm;
@ -64,30 +65,45 @@ public class Pass4CodeGeneration {
List<Statement> statements = block.getStatements();
if (statements.size() > 0 && (statements.get(0) instanceof StatementPhi)) {
for (ControlFlowBlock predecessor : block.getPredecessors()) {
genBlockEntryPoint(asm, block, predecessor);
if(block.equals(predecessor.getConditionalSuccessor())) {
genBlockPhiTransition(asm, predecessor, block);
genAsmJump(asm, block.getLabel().getName());
}
}
}
}
private void genBlockEntryPoint(AsmSequence asm, ControlFlowBlock block, ControlFlowBlock predecessor) {
genAsmLabel(asm, block.getLabel().getName() + "_from_" + predecessor.getLabel().getName());
for (Statement statement : block.getStatements()) {
private void genBlockPhiTransition(AsmSequence asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) {
genAsmLabel(asm, toBlock.getLabel().getName() + "_from_" + fromBlock.getLabel().getName());
for (Statement statement : toBlock.getStatements()) {
if (!(statement instanceof StatementPhi)) {
// No more phi statements to handle
break;
}
StatementPhi phi = (StatementPhi) statement;
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
if (previousSymbol.getBlock().equals(predecessor)) {
if (previousSymbol.getBlock().equals(fromBlock)) {
genAsmMove(asm, phi.getLValue(), previousSymbol.getRValue());
break;
}
}
}
genAsmJump(asm, block.getLabel().getName());
}
private RegisterAllocation.Register getRegister(RValue rValue) {
if(rValue instanceof Variable) {
return symbols.getRegister((Variable) rValue);
} else {
return null;
}
}
private void genAsmMove(AsmSequence asm, LValue lValue, RValue rValue) {
if(getRegister(lValue).equals(getRegister(rValue))) {
// Do not move from register to itself
asm.addAsm(" // " + lValue + " = " + rValue + " // register copy " );
return;
}
AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols);
asm.addAsm(" // " + lValue + " = " + rValue + " // " + asmFragment.getSignature());
asmFragment.generateAsm(asm);

View File

@ -61,6 +61,21 @@ public class RegisterAllocation {
public String toString() {
return "zp byte:"+zp;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RegisterZpByte that = (RegisterZpByte) o;
return zp == that.zp;
}
@Override
public int hashCode() {
return zp;
}
}
/** A zero page address used as a register for a boolean variable. */
@ -84,6 +99,21 @@ public class RegisterAllocation {
public String toString() {
return "zp bool:"+zp;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RegisterZpBool that = (RegisterZpBool) o;
return zp == that.zp;
}
@Override
public int hashCode() {
return zp;
}
}
/** The X register. */
@ -97,6 +127,13 @@ public class RegisterAllocation {
public String toString() {
return "reg byte x";
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
return true;
}
}
public static Register getRegisterX() {

View File

@ -1 +0,0 @@
ldx #{coby1}

View File

@ -1,2 +0,0 @@
cpx #0
bne {la1}

View File

@ -1,8 +0,0 @@
lda {zpby1}
cmp #{coby1}
beq !f+
bcs !t+
!f: lda #0
jmp !d+
!t: lda #$ff
!d: sta {zpbo1}

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.test;
import dk.camelot64.kickc.icl.*;
import dk.camelot64.kickc.asm.AsmSequence;
import dk.camelot64.kickc.parser.KickCLexer;
import dk.camelot64.kickc.parser.KickCParser;
import org.antlr.v4.runtime.CharStream;