mirror of
https://github.com/peterdell/wudsn-ide.git
synced 2024-06-03 06:29:35 +00:00
205 lines
6.1 KiB
Java
205 lines
6.1 KiB
Java
/**
|
|
* Copyright (C) 2009 - 2019 <a href="https://www.wudsn.com" target="_top">Peter Dell</a>
|
|
*
|
|
* This file is part of WUDSN IDE.
|
|
*
|
|
* WUDSN IDE is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* WUDSN IDE is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with WUDSN IDE. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package com.wudsn.ide.asm.compiler.syntax;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import com.wudsn.ide.asm.CPU;
|
|
import com.wudsn.ide.base.common.NumberFactory;
|
|
|
|
public abstract class Instruction implements Comparable<Instruction> {
|
|
|
|
public static final char CURSOR = '_';
|
|
public static final char NEWLINE = '\n';
|
|
|
|
private Set<CPU> cpus;
|
|
private int type;
|
|
private String name;
|
|
private String upperCaseName;
|
|
private String lowerCaseName;
|
|
private String title;
|
|
private String formattedTitle;
|
|
private String styledTitle;
|
|
private int[] styledTitleOffsets;
|
|
private String proposal;
|
|
|
|
protected Instruction(Set<CPU> cpus, int type, boolean caseSensitive,
|
|
String name, String title, String proposal) {
|
|
if (cpus == null) {
|
|
throw new IllegalArgumentException(
|
|
"Parameter 'cpus' must not be null.");
|
|
}
|
|
if (name == null) {
|
|
throw new IllegalArgumentException(
|
|
"Parameter 'name' must not be null.");
|
|
}
|
|
if (title == null) {
|
|
throw new IllegalArgumentException(
|
|
"Parameter 'title' must not be null for instruction '"
|
|
+ name + "'.");
|
|
}
|
|
if (proposal == null) {
|
|
throw new IllegalArgumentException(
|
|
"Parameter 'proposal' must not be null for instruction '"
|
|
+ name + "'.");
|
|
}
|
|
this.cpus = cpus;
|
|
this.type = type;
|
|
this.name = name;
|
|
if (caseSensitive) {
|
|
this.upperCaseName = name;
|
|
this.lowerCaseName = name;
|
|
} else {
|
|
this.upperCaseName = name.toUpperCase();
|
|
this.lowerCaseName = name.toLowerCase();
|
|
}
|
|
this.title = title;
|
|
|
|
int length = title.length();
|
|
StringBuilder mnemonicBuilder = new StringBuilder(3);
|
|
StringBuilder formattedTitleBuilder = new StringBuilder(length);
|
|
StringBuilder styledTitleBuilder = new StringBuilder(length);
|
|
List<Integer> styledTitleOffsetsList = new ArrayList<Integer>(10);
|
|
for (int i = 0; i < length; i++) {
|
|
char c = title.charAt(i);
|
|
char fc;
|
|
if (c == '_') {
|
|
i++;
|
|
if (i >= title.length()) {
|
|
throw new RuntimeException("Instruction '" + name
|
|
+ "' has invalid title '" + title + "'.");
|
|
}
|
|
c = title.charAt(i);
|
|
fc = Character.toUpperCase(c);
|
|
mnemonicBuilder.append(fc);
|
|
styledTitleOffsetsList.add(NumberFactory
|
|
.getInteger(styledTitleBuilder.length()));
|
|
} else {
|
|
fc = c;
|
|
}
|
|
formattedTitleBuilder.append(fc);
|
|
styledTitleBuilder.append(c);
|
|
}
|
|
this.formattedTitle = formattedTitleBuilder.toString();
|
|
this.styledTitle = styledTitleBuilder.toString();
|
|
int size = styledTitleOffsetsList.size();
|
|
this.styledTitleOffsets = new int[size];
|
|
for (int i = 0; i < size; i++) {
|
|
this.styledTitleOffsets[i] = styledTitleOffsetsList.get(i)
|
|
.intValue();
|
|
}
|
|
|
|
proposal = proposal.replace("\\n", "" + NEWLINE);
|
|
if (!proposal.startsWith(name)) {
|
|
throw new RuntimeException("Proposal '" + proposal
|
|
+ "' of instruction '" + name + "' does not start with '"
|
|
+ name + "'.");
|
|
}
|
|
if (proposal.indexOf(CURSOR) == -1) {
|
|
|
|
throw new RuntimeException("Proposal '" + proposal
|
|
+ "' of instruction '" + name
|
|
+ "' does not contain cursor positioning via '_'.");
|
|
}
|
|
|
|
this.proposal = proposal;
|
|
|
|
// Remove all special characters like
|
|
StringBuilder mnemonicNameBuilder = new StringBuilder(upperCaseName);
|
|
for (int i = 0; i < mnemonicNameBuilder.length(); i++) {
|
|
if (!Character.isLetter(mnemonicNameBuilder.charAt(i))
|
|
&& !Character.isDigit(mnemonicNameBuilder.charAt(i))) {
|
|
mnemonicNameBuilder.deleteCharAt(i);
|
|
}
|
|
}
|
|
|
|
String mnemonic = mnemonicBuilder.toString();
|
|
String mnemonicName = mnemonicNameBuilder.toString();
|
|
if (!mnemonicName.equalsIgnoreCase(mnemonic)) {
|
|
throw new RuntimeException("Menmonic '" + mnemonic
|
|
+ "' derived from title '" + title
|
|
+ "' with of instruction '" + name
|
|
+ "' does match mnemonic '" + mnemonicName
|
|
+ " derived from the name'.");
|
|
|
|
}
|
|
}
|
|
|
|
public Set<CPU> getCPUs() {
|
|
return cpus;
|
|
}
|
|
|
|
public int getType() {
|
|
return type;
|
|
}
|
|
|
|
public final String getName() {
|
|
return name;
|
|
}
|
|
|
|
public final String getUpperCaseName() {
|
|
return upperCaseName;
|
|
}
|
|
|
|
public final String getLowerCaseName() {
|
|
return lowerCaseName;
|
|
}
|
|
|
|
public final String getTitle() {
|
|
return title;
|
|
}
|
|
|
|
public final String getFormattedTitle() {
|
|
return formattedTitle;
|
|
}
|
|
|
|
public final String getStyledTitle() {
|
|
return styledTitle;
|
|
}
|
|
|
|
public final int[] getStyledTitleOffsets() {
|
|
return styledTitleOffsets;
|
|
}
|
|
|
|
/**
|
|
* Gets the upper case proposal text for the instruction. By default the
|
|
* proposal is the same as the {@link #getName()}. In case the instruction
|
|
* has a mandatory parameter, a space is added. In case the proposal span
|
|
* several line, they are separated via {@link #NEWLINE}. The position of
|
|
* the cursor is defined by the character {@link #CURSOR}.
|
|
*
|
|
* @return The proposal, not empty, not <code>null</code>.
|
|
*/
|
|
public final String getProposal() {
|
|
return proposal;
|
|
}
|
|
|
|
@Override
|
|
public final int compareTo(Instruction o) {
|
|
return name.compareToIgnoreCase(o.name);
|
|
}
|
|
|
|
@Override
|
|
public final String toString() {
|
|
return "type=" + type + ", name=" + name;
|
|
}
|
|
} |