5 Commits
Author SHA1 Message Date
chrisly42 8ea70f0dfa Docs update. Prepared next release. 2021-07-28 08:00:09 +02:00
chrisly42 fa1ef0b3d5 Reduced lexer code by combining state rules. Removed one rule, that seemed to be wrong. 2021-07-27 20:27:58 +02:00
chrisly42 3de9e9eba2 Restored compatibility with IDEs versions < 2021.1. Added PluginVerifier to build.gradle. 2021-07-27 17:46:11 +02:00
chrisly42 25450a9bf8 Macro definitions are now word and indexed, macro calls reference to definition.
Macro definition refactoring and find usages support.
Structural View also shows macro definitions.
Missing REPT and ENDR assembler directives added.
Changed or added some icons at various places.
Reference search for global labels and symbols now uses stub index.
2021-07-27 16:34:49 +02:00
chrisly42 6e683eb6a0 Started working on macro support. Macro-Definition are now plain, unparsed lines. Added Syntax-Highlighter options. 2021-07-27 12:42:26 +02:00
66 changed files with 1900 additions and 994 deletions
+20 -9
View File
@@ -27,8 +27,8 @@ it's "good enough" to get started, and I can return to demo coding with its curr
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
- Mnemonics code completion
- Symbols / Labels code completion
- References / Refactoring support for local and global labels, and symbol assignments.
- Symbols / Labels / Macros code completion
- References / Refactoring support for local and global labels, symbol assignments, and macros.
- Brace matching
- Quote handler
- Goto Symbol support
@@ -36,23 +36,22 @@ it's "good enough" to get started, and I can return to demo coding with its curr
## Known issues
- No referencing of macro invocations and macro definitions.
- `Find Usages` always shows _"Unclassified"_ though it shouldn't.
- Macro definitions may cause syntax errors when using backslash arguments.
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
- Macro invocations are not yet evaluated, thus no referencing to symbols defined via macros (e.g. `STRUCT`).
- No support for includes. Scoping is for global symbols and labels is currently the whole project.
- No support for register replacement (e.g. registers replaced by `EQUR` or `EQURL` will cause syntax errors)
- While the Lexer supports the -spaces option (where a space introduces a comment), this cannot be configured yet.
- While the Lexer supports the -spaces option (where a space introduces a comment), this cannot be configured yet (default is off).
- No support for other processor instructions, FPU or 68020+ address modes.
- No semantic checking for allowed address modes or data widths yet.
- Unit Test coverage is not as good as it could be (ahem).
- Missing but planned features:
- Macro definition and evaluation on invocation
- Macro evaluation on invocation
- Folding
- Semantic inspections
- Quick fixes
- Formatter + Code Style Settings
- Register use analysis (but this only makes sense after macro evaluation)
- Cycle counting
## Recommendations
@@ -69,11 +68,23 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
## Changelog
### V0.3 (28-Jul-21)
- Enhancement: Macro contents are no longer parsed, added syntax highlighting options for macros.
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
- Enhancement: Macro definition refactoring and find usages support.
- Enhancement: Structural View also shows macro definitions.
- Bugfix: Missing REPT and ENDR assembler directives added.
- Cosmetics: Changed or added some icons at various places.
- Performance: Reference search for global labels and symbols now uses stub index.
- Compatibility: Restored compatibility with IDE versions < 2021.1.
- Performance: Optimized lexer.
### V0.2 (27-Jul-21)
- Cosmetics: Added (same) icon for plugin as for file type.
- Performance improvement: Use Word-Index for global labels and symbols instead of iterating over the file.
- Performance improvement: Use Stub-Index for global labels and symbols.
- Performance: Use Word-Index for global labels and symbols instead of iterating over the file.
- Performance: Use Stub-Index for global labels and symbols.
- Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
- Enhancement: Registers are now offered for code completion, making editing less annoying.
+25 -7
View File
@@ -7,7 +7,7 @@ plugins {
}
group = 'de.platon42'
version = '0.2'
version = '0.3'
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
@@ -44,20 +44,38 @@ intellij {
// setPlugins(["com.intellij.java"])
}
runPluginVerifier {
ideVersions = ["IC-193.5662.53", "IC-211.7628.21", // 2019.3.1 - 2021.1.3
"CL-193.5233.103", "CL-193.7288.25", // 2019.3
"CL-201.6668.126", "CL-201.8743.17", // 2020.1
"CL-202.6397.106", "CL-202.8194.17", // 2020.2
"CL-203.5981.166", "CL-203.8084.11", // 2020.3
"CL-211.6693.114", "CL-211.7628.27"] // 2021.1
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea"
}
patchPluginXml {
setChangeNotes("""
<h4>V0.3 (28-Jul-21)</h4>
<ul>
<li>Enhancement: Macro contents are no longer parsed, added syntax highlighting options for macros.
<li>Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
<li>Enhancement: Macro definition refactoring and find usages support.
<li>Enhancement: Structural View also shows macro definitions.
<li>Bugfix: Missing REPT and ENDR assembler directives added.
<li>Cosmetics: Changed or added some icons at various places.
<li>Performance: Reference search for global labels and symbols now uses stub index.
<li>Compatibility: Restored compatibility with IDE versions < 2021.1.
<li>Performance: Optimized lexer.
</ul>
<h4>V0.2 (27-Jul-21)</h4>
<ul>
<li>Cosmetics: Added (same) icon for plugin as for file type.
<li>Performance improvement: Use Word-Index for global labels and symbols instead of iterating over the file.
<li>Performance improvement: Use Stub-Index for global labels and symbols.
<li>Performance: Use Word-Index for global labels and symbols instead of iterating over the file.
<li>Performance: Use Stub-Index for global labels and symbols.
<li>Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
<li>Enhancement: Registers are now offered for code completion, making editing less annoying.
</ul>
<h4>V0.1 (20-Jul-21)</h4>
<ul>
<li>Initial public release.
</ul>
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
""")
}
File diff suppressed because it is too large Load Diff
@@ -551,7 +551,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
// AsmInstruction | MacroCall
static boolean Instruction(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "Instruction")) return false;
if (!nextTokenIs(b, "", MACRO_INVOKATION, MNEMONIC)) return false;
if (!nextTokenIs(b, "", MACRO_INVOCATION, MNEMONIC)) return false;
boolean r;
r = AsmInstruction(b, l + 1);
if (!r) r = MacroCall(b, l + 1);
@@ -638,13 +638,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// MACRO_INVOKATION PlainOperands?
// MACRO_INVOCATION PlainOperands?
public static boolean MacroCall(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroCall")) return false;
if (!nextTokenIs(b, MACRO_INVOKATION)) return false;
if (!nextTokenIs(b, MACRO_INVOCATION)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_INVOKATION);
r = consumeToken(b, MACRO_INVOCATION);
r = r && MacroCall_1(b, l + 1);
exit_section_(b, m, MACRO_CALL, r);
return r;
@@ -657,6 +657,89 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
/* ********************************************************** */
// ((MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG
public static boolean MacroDefinition(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition")) return false;
if (!nextTokenIs(b, "<macro definition>", MACRO_NAME, MACRO_TAG)) return false;
boolean r, p;
Marker m = enter_section_(b, l, _NONE_, MACRO_DEFINITION, "<macro definition>");
r = MacroDefinition_0(b, l + 1);
p = r; // pin = 1
r = r && report_error_(b, MacroDefinition_1(b, l + 1));
r = p && consumeToken(b, MACRO_END_TAG) && r;
exit_section_(b, l, m, r, p, null);
return r || p;
}
// (MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)
private static boolean MacroDefinition_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = MacroDefinition_0_0(b, l + 1);
if (!r) r = MacroDefinition_0_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// MacroNameDefinition MACRO_TAG
private static boolean MacroDefinition_0_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = MacroNameDefinition(b, l + 1);
r = r && consumeToken(b, MACRO_TAG);
exit_section_(b, m, null, r);
return r;
}
// MACRO_TAG MacroNameDefinition
private static boolean MacroDefinition_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0_1")) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_TAG);
r = r && MacroNameDefinition(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// MacroPlainLine*
private static boolean MacroDefinition_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_1")) return false;
while (true) {
int c = current_position_(b);
if (!MacroPlainLine(b, l + 1)) break;
if (!empty_element_parsed_guard_(b, "MacroDefinition_1", c)) break;
}
return true;
}
/* ********************************************************** */
// MACRO_NAME
public static boolean MacroNameDefinition(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroNameDefinition")) return false;
if (!nextTokenIs(b, MACRO_NAME)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_NAME);
exit_section_(b, m, MACRO_NAME_DEFINITION, r);
return r;
}
/* ********************************************************** */
// MACRO_LINE
public static boolean MacroPlainLine(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroPlainLine")) return false;
if (!nextTokenIs(b, MACRO_LINE)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_LINE);
exit_section_(b, m, MACRO_PLAIN_LINE, r);
return r;
}
/* ********************************************************** */
// OPSIZE_BS|OPSIZE_W|OPSIZE_L
public static boolean OperandSize(PsiBuilder b, int l) {
@@ -671,19 +754,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// STRINGLIT (SEPARATOR STRINGLIT)*
// (expr|AddressingMode) (SEPARATOR (expr|AddressingMode))*
static boolean PlainOperands(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands")) return false;
if (!nextTokenIs(b, STRINGLIT)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, STRINGLIT);
r = PlainOperands_0(b, l + 1);
r = r && PlainOperands_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// (SEPARATOR STRINGLIT)*
// expr|AddressingMode
private static boolean PlainOperands_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_0")) return false;
boolean r;
r = expr(b, l + 1, -1);
if (!r) r = AddressingMode(b, l + 1);
return r;
}
// (SEPARATOR (expr|AddressingMode))*
private static boolean PlainOperands_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1")) return false;
while (true) {
@@ -694,16 +785,26 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// SEPARATOR STRINGLIT
// SEPARATOR (expr|AddressingMode)
private static boolean PlainOperands_1_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeTokens(b, 0, SEPARATOR, STRINGLIT);
r = consumeToken(b, SEPARATOR);
r = r && PlainOperands_1_0_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// expr|AddressingMode
private static boolean PlainOperands_1_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1_0_1")) return false;
boolean r;
r = expr(b, l + 1, -1);
if (!r) r = AddressingMode(b, l + 1);
return r;
}
/* ********************************************************** */
// Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
// PreprocessorOperands?
@@ -1048,13 +1149,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// !<<eof>> statement (<<eof>>|EOL)
// !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
static boolean line(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "line")) return false;
boolean r;
Marker m = enter_section_(b);
r = line_0(b, l + 1);
r = r && statement(b, l + 1);
r = r && line_1(b, l + 1);
r = r && line_2(b, l + 1);
exit_section_(b, m, null, r);
return r;
@@ -1070,6 +1171,17 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r;
}
// MacroDefinition | statement
private static boolean line_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "line_1")) return false;
boolean r;
Marker m = enter_section_(b);
r = MacroDefinition(b, l + 1);
if (!r) r = statement(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// <<eof>>|EOL
private static boolean line_2(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "line_2")) return false;
@@ -1,6 +1,19 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface M68kMacroCall extends M68kPsiElement {
@NotNull
List<M68kAddressingMode> getAddressingModeList();
@NotNull
List<M68kExpr> getExprList();
@NotNull
String getMacroName();
}
@@ -0,0 +1,29 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface M68kMacroDefinition extends M68kNamedElement, StubBasedPsiElement<M68kMacroDefinitionStub> {
@NotNull
M68kMacroNameDefinition getMacroNameDefinition();
@NotNull
List<M68kMacroPlainLine> getMacroPlainLineList();
@Nullable
String getName();
@NotNull
PsiElement setName(@NotNull String name);
@NotNull
PsiElement getNameIdentifier();
}
@@ -0,0 +1,6 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
public interface M68kMacroNameDefinition extends M68kPsiElement {
}
@@ -0,0 +1,6 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
public interface M68kMacroPlainLine extends M68kPsiElement {
}
@@ -51,6 +51,9 @@ public interface M68kTypes {
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
IElementType MACRO_DEFINITION = M68kStubElementTypeFactory.stubFactory("MACRO_DEFINITION");
IElementType MACRO_NAME_DEFINITION = new M68kElementType("MACRO_NAME_DEFINITION");
IElementType MACRO_PLAIN_LINE = new M68kElementType("MACRO_PLAIN_LINE");
IElementType OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
IElementType PREPROCESSOR_DIRECTIVE = new M68kElementType("PREPROCESSOR_DIRECTIVE");
@@ -86,7 +89,11 @@ public interface M68kTypes {
IElementType HASH = new M68kTokenType("HASH");
IElementType HEXADECIMAL = new M68kTokenType("HEXADECIMAL");
IElementType LOCAL_LABEL_DEF = new M68kTokenType("LOCAL_LABEL_DEF");
IElementType MACRO_INVOKATION = new M68kTokenType("MACRO_INVOKATION");
IElementType MACRO_END_TAG = new M68kTokenType("MACRO_END_TAG");
IElementType MACRO_INVOCATION = new M68kTokenType("MACRO_INVOCATION");
IElementType MACRO_LINE = new M68kTokenType("MACRO_LINE");
IElementType MACRO_NAME = new M68kTokenType("MACRO_NAME");
IElementType MACRO_TAG = new M68kTokenType("MACRO_TAG");
IElementType MNEMONIC = new M68kTokenType("MNEMONIC");
IElementType OCTAL = new M68kTokenType("OCTAL");
IElementType OPSIZE_BS = new M68kTokenType("OPSIZE_BS");
@@ -210,6 +217,12 @@ public interface M68kTypes {
return new M68kLocalLabelImpl(node);
} else if (type == MACRO_CALL) {
return new M68kMacroCallImpl(node);
} else if (type == MACRO_DEFINITION) {
return new M68kMacroDefinitionImpl(node);
} else if (type == MACRO_NAME_DEFINITION) {
return new M68kMacroNameDefinitionImpl(node);
} else if (type == MACRO_PLAIN_LINE) {
return new M68kMacroPlainLineImpl(node);
} else if (type == OPERAND_SIZE) {
return new M68kOperandSizeImpl(node);
} else if (type == PAREN_EXPR) {
@@ -94,6 +94,18 @@ public class M68kVisitor extends PsiElementVisitor {
visitPsiElement(o);
}
public void visitMacroDefinition(@NotNull M68kMacroDefinition o) {
visitNamedElement(o);
}
public void visitMacroNameDefinition(@NotNull M68kMacroNameDefinition o) {
visitPsiElement(o);
}
public void visitMacroPlainLine(@NotNull M68kMacroPlainLine o) {
visitPsiElement(o);
}
public void visitOperandSize(@NotNull M68kOperandSize o) {
visitPsiElement(o);
}
@@ -1,14 +1,15 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import org.jetbrains.annotations.NotNull;
public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacroCall {
import java.util.List;
public class M68kMacroCallImpl extends M68kMacroCallMixin implements M68kMacroCall {
public M68kMacroCallImpl(@NotNull ASTNode node) {
super(node);
@@ -24,4 +25,22 @@ public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacro
else super.accept(visitor);
}
@Override
@NotNull
public List<M68kAddressingMode> getAddressingModeList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kAddressingMode.class);
}
@Override
@NotNull
public List<M68kExpr> getExprList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kExpr.class);
}
@Override
@NotNull
public String getMacroName() {
return M68kPsiImplUtil.getMacroName(this);
}
}
@@ -0,0 +1,66 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class M68kMacroDefinitionImpl extends M68kMacroDefinitionMixin implements M68kMacroDefinition {
public M68kMacroDefinitionImpl(@NotNull ASTNode node) {
super(node);
}
public M68kMacroDefinitionImpl(@NotNull M68kMacroDefinitionStub stub, @NotNull IStubElementType<?, ?> nodeType) {
super(stub, nodeType);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroDefinition(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
@Override
@NotNull
public M68kMacroNameDefinition getMacroNameDefinition() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kMacroNameDefinition.class));
}
@Override
@NotNull
public List<M68kMacroPlainLine> getMacroPlainLineList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kMacroPlainLine.class);
}
@Override
@Nullable
public String getName() {
return M68kPsiImplUtil.getName(this);
}
@Override
@NotNull
public PsiElement setName(@NotNull String name) {
return M68kPsiImplUtil.setName(this, name);
}
@Override
@NotNull
public PsiElement getNameIdentifier() {
return M68kPsiImplUtil.getNameIdentifier(this);
}
}
@@ -0,0 +1,27 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroNameDefinition;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
public class M68kMacroNameDefinitionImpl extends ASTWrapperPsiElement implements M68kMacroNameDefinition {
public M68kMacroNameDefinitionImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroNameDefinition(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
}
@@ -0,0 +1,27 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroPlainLine;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
public class M68kMacroPlainLineImpl extends ASTWrapperPsiElement implements M68kMacroPlainLine {
public M68kMacroPlainLineImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroPlainLine(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
}
@@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
@JvmField
val INSTANCE = M68kFileElementType()
const val STUB_VERSION = 3
const val STUB_VERSION = 4
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
}
@@ -7,5 +7,8 @@ object M68kIcons {
val FILE = IconLoader.getIcon("/icons/FileType_m68k.svg", javaClass)
val LOCAL_LABEL = AllIcons.Nodes.AbstractMethod
val GLOBAL_LABEL = AllIcons.Nodes.Method
val SYMBOL_DEF = AllIcons.Nodes.Constant
val SYMBOL_DEF = AllIcons.Nodes.ClassInitializer
val MACRO_DEF = AllIcons.Nodes.MultipleTypeDefinitions
val REGISTER = AllIcons.Nodes.DataTables // AllIcons.Nodes.Record only available starting from 2020.1
val MNEMONIC = AllIcons.Nodes.C_protected
}
@@ -29,6 +29,8 @@ object AssemblerDirectives {
//"iif" // not supported
"else", "endif", "endc",
"rept", "endr",
"macro", "exitm", "mexit", "endm",
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
@@ -4,13 +4,20 @@ import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
class M68kMnemonicCompletionContributor : CompletionContributor() {
companion object {
val MNEMONICS = M68kIsa.mnemonics
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.MNEMONIC), 10.0) }
}
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOKATION), object : CompletionProvider<CompletionParameters>() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOCATION), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(M68kIsa.mnemonics.map(LookupElementBuilder::create))
resultSet.addAllElements(MNEMONICS)
}
})
}
@@ -4,10 +4,12 @@ import com.intellij.psi.TokenType
import com.intellij.psi.tree.IElementType
import de.platon42.intellij.plugins.m68k.asm.AssemblerDirectives
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.mnemonics
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
object LexerUtil {
private val ASSIGNMENT_SEPARATORS = charArrayOf(' ', '\t', '=', ':')
private val TOKEN_SEPARATORS = charArrayOf(' ', '\t')
@JvmStatic
fun isAsmMnemonic(text: CharSequence) = mnemonics.contains(text.toString().lowercase())
@@ -28,6 +30,11 @@ object LexerUtil {
return text.length - text.indexOfAny(ASSIGNMENT_SEPARATORS)
}
@JvmStatic
fun pushbackAfterFirstToken(text: CharSequence): Int {
return text.length - text.indexOfAny(TOKEN_SEPARATORS)
}
@JvmStatic
fun pushbackLabelColons(text: CharSequence): Int {
return text.count { it == ':' }
@@ -38,7 +45,28 @@ object LexerUtil {
if (!lexer.eatOneWhitespace && lexer.lexerPrefs.spaceIntroducesComment) {
lexer.yybegin(_M68kLexer.WAITEOL)
}
lexer.eatOneWhitespace = false;
lexer.eatOneWhitespace = false
return TokenType.WHITE_SPACE
}
@JvmStatic
fun handleMacroMode(lexer: _M68kLexer): IElementType {
if (lexer.lexerPrefs.macroParametersUnparsed) {
lexer.yybegin(_M68kLexer.MACROCALL)
} else {
lexer.yybegin(_M68kLexer.ASMOPS)
}
lexer.eatOneWhitespace = true
return M68kTypes.MACRO_INVOCATION
}
@JvmStatic
fun handleMacroLineEol(lexer: _M68kLexer): IElementType {
if (++lexer.macroLines > lexer.lexerPrefs.maxLinesPerMacro) {
lexer.yybegin(_M68kLexer.YYINITIAL)
return TokenType.BAD_CHARACTER
}
lexer.yybegin(_M68kLexer.MACROLINE)
return TokenType.WHITE_SPACE
}
}
@@ -13,6 +13,9 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
%{
private M68kLexerPrefs lexerPrefs;
boolean eatOneWhitespace = false;
int macroLines = 0;
int exprState = 0;
int exprOpState = 0;
public M68kLexerPrefs getLexerPrefs()
{
@@ -23,6 +26,12 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
this((java.io.Reader)null);
this.lexerPrefs = lexerPrefs;
}
private void startExpr(int newExprState, int newExprOpState) {
exprState = newExprState;
exprOpState = newExprOpState;
yybegin(exprState);
}
%}
%public
@@ -38,10 +47,12 @@ WHITE_SPACE=\p{Blank}+
AREG=(a[0-6])
DREG=(d[0-7])
ASSIGNMENT=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?((\p{Blank}+equ\p{Blank}+)|(\p{Blank}+set\p{Blank}+)|\p{Blank}*=\p{Blank}*))
LOCAL_LABEL=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:?)|(([:letter:]|_)(([:letter:]|[:digit:])|_)*\$:?)
LOCAL_LABEL_WC=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:)|(([:letter:]|_)(([:letter:]|[:digit:])|_)*\$:)
GLOBAL_LABEL=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?:?)
GLOBAL_LABEL_WC=(([:letter:]|_)(([:letter:]|[:digit:])|_)*::?)
LOCAL_LABEL=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:?)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:?)
LOCAL_LABEL_WC=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:)
GLOBAL_LABEL=(([:letter:]|_)([:letter:]|[:digit:]|_)*:?:?)
GLOBAL_LABEL_WC=(([:letter:]|_)([:letter:]|[:digit:]|_)*::?)
MACRO_DEF_LEFT=(([:letter:]|_)(([:letter:]|[:digit:]|_))*)\p{Blank}+macro\p{Blank}*
MACRO_END_TAG=\p{Blank}+endm\p{Blank}*[^;\r\n]*
//MNEMONIC=(([:letter:])+)
SYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$]))*)
BONUSSYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$\.\\]))*)
@@ -59,227 +70,159 @@ PLAINPARAM=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")|<([^
COMMENT=([;].*+)
HASH_COMMENT=([#;*].*+)
SKIP_TO_EOL=[^\r\n]+
PLAIN_MACRO_LINE=[^;\r\n]+
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASMOPS_OP,ASSIGNMENT,EXPR,EXPR_OP,MACROCALL,WAITEOL
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASMOPS_OP,ASSIGNMENT,EXPR,EXPR_OP,MACROCALL,WAITEOL,MACRODEF,MACROLINE,MACROTERMINATION,MACROWAITEOL
%%
<YYINITIAL> {
{WHITE_SPACE} { yybegin(NOSOL); eatOneWhitespace = false; return WHITE_SPACE; }
{EOL} { return WHITE_SPACE; }
{ASSIGNMENT} { yybegin(ASSIGNMENT); eatOneWhitespace = true; yypushback(pushbackAssignment(yytext())); return SYMBOLDEF; }
{LOCAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
{HASH_COMMENT} { return COMMENT; }
}
<NOSOL> {
{WHITE_SPACE} { return WHITE_SPACE; }
<YYINITIAL, NOSOL>
{
{EOL} { yybegin(YYINITIAL); return WHITE_SPACE; }
{LOCAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
{DIRECTIVE_KEYWORD} {
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { yybegin(EXPR); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { yybegin(EXPR); return OTHER_DIRECTIVE; }
yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION;
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
{MACRONAME} { yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION; }
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
}
<INSTRPART> {
{WHITE_SPACE} { return WHITE_SPACE; }
<INSTRPART,ASMINSTR,MACROCALL,ASSIGNMENT,EXPR,EXPR_OP,ASMOPS,ASMOPS_OP>
{
{EOL} { yybegin(YYINITIAL); return EOL; }
":" { return COLON; }
{DIRECTIVE_KEYWORD} {
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { yybegin(EXPR); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { yybegin(EXPR); return OTHER_DIRECTIVE; }
yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION;
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
{MACRONAME} { yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<NOSOL, INSTRPART, ASSIGNMENT>
{
{WHITE_SPACE} { return WHITE_SPACE; }
}
<MACROCALL, EXPR, EXPR_OP, ASMOPS, ASMOPS_OP> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
}
<YYINITIAL> {
{WHITE_SPACE} { yybegin(NOSOL); eatOneWhitespace = false; return WHITE_SPACE; }
{ASSIGNMENT} { yybegin(ASSIGNMENT); eatOneWhitespace = true; yypushback(pushbackAssignment(yytext())); return SYMBOLDEF; }
{MACRO_DEF_LEFT} { yybegin(MACRODEF); yypushback(pushbackAfterFirstToken(yytext())); return MACRO_NAME; }
{LOCAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
}
<NOSOL> {
"macro" { yybegin(MACRODEF); return MACRO_TAG; }
{LOCAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
}
<NOSOL, INSTRPART>
{
{DIRECTIVE_KEYWORD} {
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { startExpr(EXPR, EXPR_OP); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { startExpr(EXPR, EXPR_OP); return OTHER_DIRECTIVE; }
return handleMacroMode(this);
}
{MACRONAME} { return handleMacroMode(this); }
}
<INSTRPART> {
":" { return COLON; }
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
}
<ASMINSTR> {
{WHITE_SPACE} { yybegin(ASMOPS); return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
{WHITE_SPACE} { startExpr(ASMOPS, ASMOPS_OP); return WHITE_SPACE; }
{OPSIZE_BS} { return OPSIZE_BS; }
{OPSIZE_W} { return OPSIZE_W; }
{OPSIZE_L} { return OPSIZE_L; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<MACROCALL> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
"," { return SEPARATOR; }
{PLAINPARAM} { return STRINGLIT; }
}
<ASSIGNMENT> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
"equ"|"set" { yybegin(EXPR); return EQU; }
"equ"|"set" { startExpr(EXPR, EXPR_OP); return EQU; }
":" { return COLON; }
"=" { yybegin(EXPR); return OP_ASSIGN; }
"=" { startExpr(EXPR, EXPR_OP); return OP_ASSIGN; }
}
<EXPR, ASMOPS> {
{BINARY} { yybegin(exprOpState); return BINARY; }
{HEXADECIMAL} { yybegin(exprOpState); return HEXADECIMAL; }
{OCTAL} { yybegin(exprOpState); return OCTAL; }
{DECIMAL} { yybegin(exprOpState); return DECIMAL; }
{STRINGLIT} { yybegin(exprOpState); return STRINGLIT; }
"^" { return OP_BITWISE_XOR; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { yybegin(exprOpState); return ROUND_R; }
"!" { return OP_UNARY_NOT; }
"~" { return OP_UNARY_COMPL; }
"+" { return OP_PLUS; }
"-" { return OP_MINUS; }
"*" { yybegin(exprOpState); return CURRENT_PC_SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<EXPR> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{BINARY} { yybegin(EXPR_OP); return BINARY; }
{HEXADECIMAL} { yybegin(EXPR_OP); return HEXADECIMAL; }
{OCTAL} { yybegin(EXPR_OP); return OCTAL; }
{DECIMAL} { yybegin(EXPR_OP); return DECIMAL; }
{STRINGLIT} { yybegin(EXPR_OP); return STRINGLIT; }
"^" { return OP_BITWISE_XOR; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { yybegin(EXPR_OP); return ROUND_R; }
"!" { return OP_UNARY_NOT; }
"~" { return OP_UNARY_COMPL; }
"+" { return OP_PLUS; }
"-" { return OP_MINUS; }
"*" { yybegin(EXPR_OP); return CURRENT_PC_SYMBOL; }
{BONUSSYMBOL} { yybegin(EXPR_OP); return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
{BONUSSYMBOL} { yybegin(exprOpState); return SYMBOL; }
}
<EXPR_OP> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
<EXPR_OP, ASMOPS_OP> {
"<<" { yybegin(exprState); return OP_AR_SHIFT_L; }
">>" { yybegin(exprState); return OP_AR_SHIFT_R; }
"&&" { yybegin(exprState); return OP_LOGICAL_AND; }
"||" { yybegin(exprState); return OP_LOGICAL_OR; }
"=="|"=" { yybegin(exprState); return OP_CMP_EQ; }
"<>"|"!=" { yybegin(exprState); return OP_CMP_NOT_EQ; }
">=" { yybegin(exprState); return OP_CMP_GT_EQ; }
"<=" { yybegin(exprState); return OP_CMP_LT_EQ; }
"<" { yybegin(exprState); return OP_CMP_LT; }
">" { yybegin(exprState); return OP_CMP_GT; }
"&" { yybegin(exprState); return OP_BITWISE_AND; }
"|"|"!" { yybegin(exprState); return OP_BITWISE_OR; }
"^" { yybegin(exprState); return OP_BITWISE_XOR; }
"<<" { yybegin(EXPR); return OP_AR_SHIFT_L; }
">>" { yybegin(EXPR); return OP_AR_SHIFT_R; }
"&&" { yybegin(EXPR); return OP_LOGICAL_AND; }
"||" { yybegin(EXPR); return OP_LOGICAL_OR; }
"=="|"=" { yybegin(EXPR); return OP_CMP_EQ; }
"<>"|"!=" { yybegin(EXPR); return OP_CMP_NOT_EQ; }
">=" { yybegin(EXPR); return OP_CMP_GT_EQ; }
"<=" { yybegin(EXPR); return OP_CMP_LT_EQ; }
"<" { yybegin(EXPR); return OP_CMP_LT; }
">" { yybegin(EXPR); return OP_CMP_GT; }
"&" { yybegin(EXPR); return OP_BITWISE_AND; }
"|"|"!" { yybegin(EXPR); return OP_BITWISE_OR; }
"^" { yybegin(EXPR); return OP_BITWISE_XOR; }
// ":" { return COLON; }
// ";" { return SEMICOLON; }
// "[" { return SQUARE_L; }
// "]" { return SQUARE_R; }
"," { yybegin(EXPR); return SEPARATOR; }
"(" { yybegin(EXPR); return ROUND_L; }
"," { yybegin(exprState); return SEPARATOR; }
"(" { yybegin(exprState); return ROUND_L; }
")" { return ROUND_R; }
// "." { return DOT; }
// "$" { return DOLLAR; }
"~" { yybegin(EXPR); return OP_UNARY_COMPL; }
"+" { yybegin(EXPR); return OP_PLUS; }
"-" { yybegin(EXPR); return OP_MINUS; }
"*" { yybegin(EXPR); return OP_AR_MUL; }
"%"|"//" { yybegin(EXPR); return OP_AR_MOD; }
"/" { yybegin(EXPR); return OP_AR_DIV; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
"~" { yybegin(exprState); return OP_UNARY_COMPL; }
"+" { yybegin(exprState); return OP_PLUS; }
"-" { yybegin(exprState); return OP_MINUS; }
"*" { yybegin(exprState); return OP_AR_MUL; }
"%"|"//" { yybegin(exprState); return OP_AR_MOD; }
"/" { yybegin(exprState); return OP_AR_DIV; }
}
<ASMOPS> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{BINARY} { yybegin(ASMOPS_OP); return BINARY; }
{HEXADECIMAL} { yybegin(ASMOPS_OP); return HEXADECIMAL; }
{OCTAL} { yybegin(ASMOPS_OP); return OCTAL; }
{DECIMAL} { yybegin(ASMOPS_OP); return DECIMAL; }
{STRINGLIT} { yybegin(ASMOPS_OP); return STRINGLIT; }
{AREG} { yybegin(ASMOPS_OP); return AREG; }
{DREG} { yybegin(ASMOPS_OP); return DREG; }
"sp"|"a7" { yybegin(ASMOPS_OP); return REG_SP; }
"pc" { yybegin(ASMOPS_OP); return PC; }
"ccr" { yybegin(ASMOPS_OP); return REG_CCR; }
"sr" { yybegin(ASMOPS_OP); return REG_SR; }
"usp" { yybegin(ASMOPS_OP); return REG_USP; }
"vbr" { yybegin(ASMOPS_OP); return REG_VBR; }
"^" { return OP_BITWISE_XOR; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { yybegin(ASMOPS_OP); return ROUND_R; }
"!" { return OP_UNARY_NOT; }
"~" { return OP_UNARY_COMPL; }
"+" { return OP_PLUS; }
"-" { return OP_MINUS; }
"*" { yybegin(ASMOPS_OP); return CURRENT_PC_SYMBOL; }
{AREG} { yybegin(exprOpState); return AREG; }
{DREG} { yybegin(exprOpState); return DREG; }
"sp"|"a7" { yybegin(exprOpState); return REG_SP; }
"pc" { yybegin(exprOpState); return PC; }
"ccr" { yybegin(exprOpState); return REG_CCR; }
"sr" { yybegin(exprOpState); return REG_SR; }
"usp" { yybegin(exprOpState); return REG_USP; }
"vbr" { yybegin(exprOpState); return REG_VBR; }
"#" { return HASH; }
{SYMBOL} { yybegin(ASMOPS_OP); return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
{SYMBOL} { yybegin(exprOpState); return SYMBOL; }
}
<ASMOPS_OP> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{OPSIZE_BS} { return OPSIZE_BS; }
{OPSIZE_W} { return OPSIZE_W; }
{OPSIZE_L} { return OPSIZE_L; }
"<<" { yybegin(ASMOPS); return OP_AR_SHIFT_L; }
">>" { yybegin(ASMOPS); return OP_AR_SHIFT_R; }
"&&" { yybegin(ASMOPS); return OP_LOGICAL_AND; }
"||" { yybegin(ASMOPS); return OP_LOGICAL_OR; }
"=="|"=" { yybegin(ASMOPS); return OP_CMP_EQ; }
"<>"|"!=" { yybegin(ASMOPS); return OP_CMP_NOT_EQ; }
">=" { yybegin(ASMOPS); return OP_CMP_GT_EQ; }
"<=" { yybegin(ASMOPS); return OP_CMP_LT_EQ; }
"<" { yybegin(ASMOPS); return OP_CMP_LT; }
">" { yybegin(ASMOPS); return OP_CMP_GT; }
"&" { yybegin(ASMOPS); return OP_BITWISE_AND; }
"|"|"!" { yybegin(ASMOPS); return OP_BITWISE_OR; }
"^" { yybegin(ASMOPS); return OP_BITWISE_XOR; }
// ":" { return COLON; }
// ";" { return SEMICOLON; }
// "[" { return SQUARE_L; }
// "]" { return SQUARE_R; }
"," { yybegin(ASMOPS); return SEPARATOR; }
"(" { yybegin(ASMOPS); return ROUND_L; }
")" { return ROUND_R; }
// "." { return DOT; }
// "$" { return DOLLAR; }
"~" { yybegin(ASMOPS); return OP_UNARY_COMPL; }
"+" { yybegin(ASMOPS); return OP_PLUS; }
"-" { yybegin(ASMOPS); return OP_MINUS; }
"*" { yybegin(ASMOPS); return OP_AR_MUL; }
"%"|"//" { yybegin(ASMOPS); return OP_AR_MOD; }
"/" { yybegin(ASMOPS); return OP_AR_DIV; }
{SYMBOL} { return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<WAITEOL>
@@ -288,4 +231,35 @@ SKIP_TO_EOL=[^\r\n]+
{SKIP_TO_EOL} { return COMMENT; }
}
// The macro mess starts here
<MACRODEF> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(MACROLINE); macroLines = 0; return WHITE_SPACE; }
"macro" { return MACRO_TAG; }
{MACRONAME} { return MACRO_NAME; }
{COMMENT} { yybegin(MACROWAITEOL); return COMMENT; }
}
<MACROLINE> {
{EOL} { return handleMacroLineEol(this); }
{MACRO_END_TAG} { yybegin(MACROTERMINATION); return MACRO_END_TAG; }
{PLAIN_MACRO_LINE} { return MACRO_LINE; }
{COMMENT} { yybegin(MACROWAITEOL); return COMMENT; }
}
<MACROTERMINATION> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<MACROWAITEOL>
{
{EOL} { return handleMacroLineEol(this); }
{SKIP_TO_EOL} { return COMMENT; }
}
[^] { return BAD_CHARACTER; }
@@ -118,7 +118,7 @@
M68kFile ::= line*
private line ::= !<<eof>> statement (<<eof>>|EOL)
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
statement ::= (Assignment
| PreprocessorDirective
@@ -170,7 +170,25 @@ AsmOp ::= MNEMONIC OperandSize?
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
PreprocessorOperands?
MacroCall ::= MACRO_INVOKATION PlainOperands?
MacroPlainLine ::= MACRO_LINE
MacroNameDefinition ::= MACRO_NAME
MacroDefinition ::= ((MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG {
pin=1
name = "macro definition"
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinitionMixin"
elementTypeFactory = "de.platon42.intellij.plugins.m68k.stubs.M68kStubElementTypeFactory.stubFactory"
stubClass = "de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub"
methods = [getName setName getNameIdentifier]
}
MacroCall ::= MACRO_INVOCATION PlainOperands? {
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kMacroCallMixin"
methods = [getMacroName]
}
AsmInstruction ::= AsmOp AsmOperands?
private Instruction ::= AsmInstruction | MacroCall
//external Instruction ::= parseMacroCallOrAsmInstruction
@@ -180,7 +198,7 @@ private AsmOperands ::= AddressingMode (SEPARATOR AddressingMode)?
private PreprocessorOperands ::= PreprocessorOperand (SEPARATOR PreprocessorOperand)*
private PreprocessorOperand ::= expr
private PlainOperands ::= STRINGLIT (SEPARATOR STRINGLIT)*
private PlainOperands ::= (expr|AddressingMode) (SEPARATOR (expr|AddressingMode))*
// TODO This should probably be a ILazyParseableElementType, no idea how to implement that yet
SymbolReference ::= SYMBOL {
@@ -27,6 +27,16 @@ object M68kElementFactory {
return PsiTreeUtil.findChildOfType(file, M68kSymbolReference::class.java)!!
}
fun createMacroDefinition(project: Project, name: String): M68kMacroDefinition {
val file = createFile(project, "$name macro\nendm\n")
return PsiTreeUtil.findChildOfType(file, M68kMacroDefinition::class.java)!!
}
fun createMacroCall(project: Project, name: String): M68kMacroCall {
val file = createFile(project, " $name\n")
return PsiTreeUtil.findChildOfType(file, M68kMacroCall::class.java)!!
}
fun createFile(project: Project, content: String): M68kFile {
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
}
@@ -5,6 +5,7 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
object M68kLookupUtil {
@@ -93,4 +94,47 @@ object M68kLookupUtil {
}
fun findAllSymbolDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
fun findAllMacroDefinitions(project: Project): List<M68kMacroDefinition> {
val results: MutableList<M68kMacroDefinition> = ArrayList()
StubIndex.getInstance().processAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
{
results.addAll(
StubIndex.getElements(
M68kMacroDefinitionStubIndex.KEY,
it,
project,
GlobalSearchScope.allScope(project),
M68kMacroDefinition::class.java
)
)
true
}
return results
}
fun findAllMacroDefinitions(file: M68kFile): List<M68kMacroDefinition> {
val results: MutableList<M68kMacroDefinition> = ArrayList()
StubIndex.getInstance().processAllKeys(
M68kMacroDefinitionStubIndex.KEY,
{
results.addAll(
StubIndex.getElements(
M68kMacroDefinitionStubIndex.KEY,
it,
file.project,
GlobalSearchScope.fileScope(file),
M68kMacroDefinition::class.java
)
)
true
}, GlobalSearchScope.fileScope(file), null
)
return results
}
fun findAllMacroDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
}
@@ -0,0 +1,13 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiReference
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
abstract class M68kMacroCallMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kMacroCall {
override fun getReferences(): Array<PsiReference> {
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
}
}
@@ -0,0 +1,29 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.StubBasedPsiElementBase
import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.stubs.IStubElementType
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub
import javax.swing.Icon
abstract class M68kMacroDefinitionMixin : StubBasedPsiElementBase<M68kMacroDefinitionStub>, M68kMacroDefinition {
constructor(node: ASTNode) : super(node)
constructor(stub: M68kMacroDefinitionStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
override fun getPresentation(): ItemPresentation? {
return PresentationData(name, containingFile.name, getIcon(0), null)
}
override fun getIcon(flags: Int): Icon? {
return M68kIcons.MACRO_DEF
}
override fun toString(): String {
return javaClass.simpleName + "(MACRO_DEFINITION)"
}
}
@@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement
import com.intellij.util.IncorrectOperationException
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createSymbolDefinition
object M68kPsiImplUtil {
@@ -71,4 +72,26 @@ object M68kPsiImplUtil {
val text = element.firstChild.text
return text.startsWith('.') || text.endsWith('$')
}
// Macro Definition
@JvmStatic
fun getName(element: M68kMacroDefinition): String? = element.macroNameDefinition.firstChild.text
@JvmStatic
fun setName(element: M68kMacroDefinition, name: String): PsiElement {
val nameNode = element.macroNameDefinition
val newMacroDefinition = createMacroDefinition(element.project, name)
nameNode.replace(newMacroDefinition.firstChild)
return element
}
@JvmStatic
fun getNameIdentifier(element: M68kMacroDefinition): PsiElement = element.firstChild
// Macro Call
@JvmStatic
fun getMacroName(element: M68kMacroCall): String = element.firstChild.text
}
@@ -13,12 +13,13 @@ class M68kRenameInputValidator : RenameInputValidator {
override fun getPattern(): ElementPattern<out PsiElement?> = StandardPatterns.or(
PlatformPatterns.psiElement(M68kGlobalLabel::class.java),
PlatformPatterns.psiElement(M68kLocalLabel::class.java),
PlatformPatterns.psiElement(M68kSymbolDefinition::class.java)
PlatformPatterns.psiElement(M68kSymbolDefinition::class.java),
PlatformPatterns.psiElement(M68kMacroDefinition::class.java)
)
override fun isInputValid(newName: String, element: PsiElement, context: ProcessingContext): Boolean {
return when (element) {
is M68kGlobalLabel, is M68kSymbolDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
is M68kGlobalLabel, is M68kSymbolDefinition, is M68kMacroDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
is M68kLocalLabel -> LOCAL_LABEL_PATTERN.matcher(newName).matches()
else -> false
}
@@ -1,8 +1,7 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.navigation.ChooseByNameContributorEx2
import com.intellij.navigation.ChooseByNameContributorEx
import com.intellij.navigation.NavigationItem
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.Processor
@@ -13,17 +12,17 @@ import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
class M68kChooseByNameContributor : ChooseByNameContributorEx2 {
class M68kChooseByNameContributor : ChooseByNameContributorEx {
override fun processNames(processor: Processor<in String>, parameters: FindSymbolParameters) {
processNames(processor, parameters.searchScope, parameters.idFilter)
}
// override fun processNames(processor: Processor<in String>, parameters: FindSymbolParameters) {
// processNames(processor, parameters.searchScope, parameters.idFilter)
// }
override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
val result: MutableList<NavigationItem> = ArrayList()
processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
return result.toTypedArray()
}
// override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
// val result: MutableList<NavigationItem> = ArrayList()
// processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
// return result.toTypedArray()
// }
override fun processNames(processor: Processor<in String>, scope: GlobalSearchScope, filter: IdFilter?) {
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, processor, scope, filter)
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.icons.AllIcons
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
@@ -18,7 +18,7 @@ class M68kGlobalLabelSymbolCompletionContributor : CompletionContributor() {
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"pc"
)
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(AllIcons.Nodes.Record).withBoldness(true), 2.0) }
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
}
init {
@@ -7,12 +7,14 @@ import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchHelper
import com.intellij.psi.search.UsageSearchContext
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kNamedElement
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
@@ -24,18 +26,23 @@ class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
class Resolver : ResolveCache.PolyVariantResolver<M68kGlobalLabelSymbolReference> {
override fun resolve(ref: M68kGlobalLabelSymbolReference, incompleteCode: Boolean): Array<ResolveResult> {
val refName = ref.element.symbolName
val project = ref.element.project
val targets: MutableList<PsiElement> = SmartList()
PsiSearchHelper.getInstance(project).processElementsWithWord(
{ elem, _ ->
when (elem) {
is M68kGlobalLabel, is M68kSymbolDefinition -> targets.add(elem)
}
val targets: MutableList<M68kNamedElement> = SmartList()
StubIndex.getInstance()
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
{
targets.add(it)
true
}, GlobalSearchScope.allScope(project),
refName, UsageSearchContext.IN_CODE, true
)
}
StubIndex.getInstance()
.processElements(M68kSymbolDefinitionStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kSymbolDefinition::class.java)
{
targets.add(it)
true
}
return targets
.map(::PsiElementResolveResult)
.toTypedArray()
@@ -0,0 +1,19 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
class M68kMacroCallCompletionContributor : CompletionContributor() {
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOCATION), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(M68kLookupUtil.findAllMacroDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
}
})
}
}
@@ -0,0 +1,17 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.openapi.util.TextRange
import com.intellij.psi.AbstractElementManipulator
import com.intellij.util.IncorrectOperationException
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
class M68kMacroCallElementManipulator : AbstractElementManipulator<M68kMacroCall>() {
@Throws(IncorrectOperationException::class)
override fun handleContentChange(element: M68kMacroCall, range: TextRange, newContent: String): M68kMacroCall {
val newMacroCall = M68kElementFactory.createMacroCall(element.project, newContent)
element.firstChild.replace(newMacroCall.firstChild)
return element
}
}
@@ -0,0 +1,49 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
class M68kMacroReference(element: M68kMacroCall) :
PsiPolyVariantReferenceBase<M68kMacroCall>(element, TextRange(0, element.macroName.length)) {
companion object {
val INSTANCE = Resolver()
}
class Resolver : ResolveCache.PolyVariantResolver<M68kMacroReference> {
override fun resolve(ref: M68kMacroReference, incompleteCode: Boolean): Array<ResolveResult> {
val macroName = ref.element.macroName
val project = ref.element.project
val targets: MutableList<M68kMacroDefinition> = SmartList()
StubIndex.getInstance()
.processElements(M68kMacroDefinitionStubIndex.KEY, macroName, project, GlobalSearchScope.allScope(project), M68kMacroDefinition::class.java)
{
targets.add(it)
true
}
return targets
.map(::PsiElementResolveResult)
.toTypedArray()
}
}
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> =
ResolveCache.getInstance(element.project)
.resolveWithCaching(this, INSTANCE, false, incompleteCode)
override fun resolve(): PsiElement? = multiResolve(false).singleOrNull()?.element
override fun getVariants(): Array<Any> = emptyArray()
}
@@ -3,6 +3,7 @@ package de.platon42.intellij.plugins.m68k.refs
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.*
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
class M68kReferenceContributor : PsiReferenceContributor() {
@@ -10,11 +11,13 @@ class M68kReferenceContributor : PsiReferenceContributor() {
companion object {
val localLabelReferenceProvider = LocalLabelReferenceProvider()
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
val macroReferenceProvider = MacroReferenceProvider()
}
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kMacroCall::class.java), macroReferenceProvider)
}
class LocalLabelReferenceProvider : PsiReferenceProvider() {
@@ -32,4 +35,9 @@ class M68kReferenceContributor : PsiReferenceContributor() {
return arrayOf(M68kGlobalLabelSymbolReference(symbolReference))
}
}
class MacroReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> =
arrayOf(M68kMacroReference(element as M68kMacroCall))
}
}
@@ -16,7 +16,7 @@ class M68kFindUsagesProvider : FindUsagesProvider {
override fun getWordsScanner(): WordsScanner =
DefaultWordsScanner(
M68kLexer(M68kLexerPrefs()), // FIXME Oh no! More Prefs!
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.SYMBOL),
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.MACRO_NAME),
TokenSet.create(M68kTypes.COMMENT),
TokenSet.create(M68kTypes.STRINGLIT, M68kTypes.DECIMAL, M68kTypes.HEXADECIMAL, M68kTypes.OCTAL, M68kTypes.BINARY),
TokenSet.EMPTY
@@ -32,6 +32,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kLocalLabel -> "local label"
is M68kSymbolDefinition -> "symbol definition"
is M68kSymbolReference -> "symbol reference"
is M68kMacroDefinition -> "macro definition"
is M68kMacroCall -> "macro call"
is M68kRegister -> "register"
is M68kRefExpr -> "reference expression"
else -> ""
@@ -44,6 +46,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kLocalLabel -> element.name!!
is M68kSymbolDefinition -> element.parent.text
is M68kSymbolReference -> element.symbolName
is M68kMacroDefinition -> element.macroNameDefinition.text
is M68kMacroCall -> element.macroName
is M68kRefExpr -> element.symbolReference?.symbolName ?: ""
is M68kRegister -> element.text
else -> ""
@@ -4,7 +4,6 @@ import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.ide.util.treeView.smartTree.TreeElement
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.NavigatablePsiElement
import com.intellij.refactoring.suggested.startOffset
import de.platon42.intellij.plugins.m68k.psi.M68kFile
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
@@ -19,8 +18,9 @@ class M68kStructureViewElement(private val myElement: NavigatablePsiElement) : S
return when (myElement) {
is M68kFile -> {
listOf(
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.startOffset },
M68kLookupUtil.findAllGlobalLabels(myElement).sortedBy { it.startOffset },
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.textRange.startOffset },
M68kLookupUtil.findAllMacroDefinitions(myElement).sortedBy { it.textRange.startOffset },
M68kLookupUtil.findAllGlobalLabels(myElement).sortedBy { it.textRange.startOffset },
// M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! }),
// M68kLookupUtil.findAllGlobalLabels(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! })
)
@@ -7,6 +7,7 @@ import com.intellij.ide.util.treeView.smartTree.Sorter
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiFile
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider {
@@ -16,7 +17,7 @@ class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
}
override fun isAlwaysLeaf(element: StructureViewTreeElement): Boolean {
return element.value is M68kLocalLabel
return element.value is M68kLocalLabel || element.value is M68kMacroDefinition
}
override fun getSorters(): Array<Sorter> {
@@ -8,11 +8,14 @@ import com.intellij.psi.stubs.*
import com.intellij.psi.tree.ILightStubFileElementType
import de.platon42.intellij.plugins.m68k.MC68000Language.Companion.INSTANCE
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
import de.platon42.intellij.plugins.m68k.psi.impl.M68kGlobalLabelImpl
import de.platon42.intellij.plugins.m68k.psi.impl.M68kMacroDefinitionImpl
import de.platon42.intellij.plugins.m68k.psi.impl.M68kSymbolDefinitionImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kGlobalLabelStubImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kMacroDefinitionStubImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kSymbolDefinitionStubImpl
import java.io.IOException
@@ -67,5 +70,28 @@ interface M68kElementTypes {
override fun indexStub(stub: M68kSymbolDefinitionStub, sink: IndexSink) = sink.occurrence(M68kSymbolDefinitionStubIndex.KEY, stub.name!!)
}
@JvmField
val MACRO_DEFINITION: IStubElementType<M68kMacroDefinitionStub, M68kMacroDefinition> =
object : M68kStubElementType<M68kMacroDefinitionStub, M68kMacroDefinition>("MACRO_DEFINITION") {
override fun createPsi(stub: M68kMacroDefinitionStub): M68kMacroDefinition = M68kMacroDefinitionImpl(stub, this)
override fun createStub(psi: M68kMacroDefinition, parentStub: StubElement<out PsiElement>): M68kMacroDefinitionStub =
M68kMacroDefinitionStubImpl(parentStub, this, psi.name!!)
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): M68kMacroDefinitionStub {
val idNode = LightTreeUtil.requiredChildOfType(tree, node, M68kTypes.MACRO_NAME_DEFINITION)
return M68kMacroDefinitionStubImpl(parentStub, this, LightTreeUtil.toFilteredString(tree, idNode, null))
}
@Throws(IOException::class)
override fun serialize(stub: M68kMacroDefinitionStub, dataStream: StubOutputStream) = dataStream.writeName(stub.name)
@Throws(IOException::class)
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): M68kMacroDefinitionStub =
M68kMacroDefinitionStubImpl(parentStub, this, dataStream.readName()!!)
override fun indexStub(stub: M68kMacroDefinitionStub, sink: IndexSink) = sink.occurrence(M68kMacroDefinitionStubIndex.KEY, stub.name!!)
}
}
}
@@ -0,0 +1,6 @@
package de.platon42.intellij.plugins.m68k.stubs
import com.intellij.psi.stubs.NamedStub
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
interface M68kMacroDefinitionStub : NamedStub<M68kMacroDefinition>
@@ -0,0 +1,16 @@
package de.platon42.intellij.plugins.m68k.stubs
import com.intellij.psi.stubs.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndexKey
import de.platon42.intellij.plugins.m68k.M68kFileElementType
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
class M68kMacroDefinitionStubIndex : StringStubIndexExtension<M68kMacroDefinition>() {
override fun getKey(): StubIndexKey<String, M68kMacroDefinition> = KEY
override fun getVersion(): Int = M68kFileElementType.STUB_VERSION
companion object {
val KEY = StubIndexKey.createIndexKey<String, M68kMacroDefinition>("mc68000.macrodef.index")
}
}
@@ -10,6 +10,7 @@ object M68kStubElementTypeFactory {
return when (name) {
"GLOBAL_LABEL" -> M68kElementTypes.GLOBAL_LABEL
"SYMBOL_DEFINITION" -> M68kElementTypes.SYMBOL_DEFINITION
"MACRO_DEFINITION" -> M68kElementTypes.MACRO_DEFINITION
else -> throw RuntimeException("Unknown element type '$name'")
}
}
@@ -0,0 +1,13 @@
package de.platon42.intellij.plugins.m68k.stubs.impl
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.NamedStubBase
import com.intellij.psi.stubs.StubElement
import com.intellij.util.io.StringRef
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub
class M68kMacroDefinitionStubImpl : NamedStubBase<M68kMacroDefinition>, M68kMacroDefinitionStub {
constructor(parent: StubElement<*>, elementType: IStubElementType<*, *>, name: StringRef) : super(parent, elementType, name)
constructor(parent: StubElement<*>, elementType: IStubElementType<*, *>, name: String) : super(parent, elementType, name)
}
@@ -18,6 +18,9 @@ import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.GLOBAL_LABEL
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.LOCAL_LABEL
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_CALL
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_LINE
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_NAME_DEF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_PREPROCESSOR
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MNEMONIC
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.NUMBER
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.OTHER_PREPROCESSOR
@@ -26,8 +29,8 @@ import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SPECIAL_REG
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.STACK_POINTER
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.STRING
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLDEF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLREF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL_DEF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL_REF
import org.jetbrains.annotations.NonNls
import javax.swing.Icon
@@ -49,7 +52,7 @@ PIC_HEIGHT = 256
include "../includes/hardware/custom.i"
BLTHOGON MACRO ; macro definition
move.w #DMAF_SETCLR|DMAF_BLITHOG,dmacon(a5)
move.w #DMAF_SETCLR|DMAF_BLITHOG,dmacon(a5) ; hog!
ENDM
demo_init ; global label
@@ -99,9 +102,12 @@ hello: dc.b 'Hello World!',10,0
AttributesDescriptor("Local labels", LOCAL_LABEL),
AttributesDescriptor("Comma (separator)", SEPARATOR),
AttributesDescriptor("Colon", COLON),
AttributesDescriptor("Symbol definition", SYMBOLDEF),
AttributesDescriptor("Symbol reference", SYMBOLREF),
AttributesDescriptor("Symbol definition", SYMBOL_DEF),
AttributesDescriptor("Symbol reference", SYMBOL_REF),
AttributesDescriptor("Assembly mnemonic", MNEMONIC),
AttributesDescriptor("Macro name definition", MACRO_NAME_DEF),
AttributesDescriptor("Macro preprocessor directives", MACRO_PREPROCESSOR),
AttributesDescriptor("Macro line", MACRO_LINE),
AttributesDescriptor("Macro invocation", MACRO_CALL),
AttributesDescriptor("Data width: Byte/short", DATA_WIDTH_BS),
AttributesDescriptor("Data width: Word", DATA_WIDTH_W),
@@ -28,11 +28,14 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
M68kTypes.COLON -> arrayOf(COLON)
M68kTypes.GLOBAL_LABEL_DEF -> arrayOf(GLOBAL_LABEL)
M68kTypes.LOCAL_LABEL_DEF -> arrayOf(LOCAL_LABEL)
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOLDEF)
M68kTypes.SYMBOL -> arrayOf(SYMBOLREF)
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOL_DEF)
M68kTypes.SYMBOL -> arrayOf(SYMBOL_REF)
M68kTypes.CURRENT_PC_SYMBOL, M68kTypes.PC -> arrayOf(PROGRAM_COUNTER)
M68kTypes.MNEMONIC -> arrayOf(MNEMONIC)
M68kTypes.MACRO_INVOKATION -> arrayOf(MACRO_CALL)
M68kTypes.MACRO_TAG, M68kTypes.MACRO_END_TAG -> arrayOf(MACRO_PREPROCESSOR)
M68kTypes.MACRO_LINE -> arrayOf(MACRO_LINE)
M68kTypes.MACRO_INVOCATION -> arrayOf(MACRO_CALL)
M68kTypes.MACRO_NAME -> arrayOf(MACRO_NAME_DEF)
M68kTypes.DATA_DIRECTIVE -> arrayOf(DATA_PREPROCESSOR)
M68kTypes.OTHER_DIRECTIVE, M68kTypes.EQU -> arrayOf(OTHER_PREPROCESSOR)
M68kTypes.OPSIZE_BS -> arrayOf(DATA_WIDTH_BS)
@@ -55,9 +58,12 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
val LOCAL_LABEL = TextAttributesKey.createTextAttributesKey("MC68000_GLOBAL_LABEL", DefaultLanguageHighlighterColors.FUNCTION_DECLARATION)
val SEPARATOR = TextAttributesKey.createTextAttributesKey("MC68000_SEPARATOR", DefaultLanguageHighlighterColors.COMMA)
val COLON = TextAttributesKey.createTextAttributesKey("MC68000_COLON", DefaultLanguageHighlighterColors.DOT)
val SYMBOLDEF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLDEF", DefaultLanguageHighlighterColors.CONSTANT)
val SYMBOLREF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
val SYMBOL_DEF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLDEF", DefaultLanguageHighlighterColors.CONSTANT)
val SYMBOL_REF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
val MNEMONIC = TextAttributesKey.createTextAttributesKey("MC68000_MNEMONIC", DefaultLanguageHighlighterColors.FUNCTION_CALL)
val MACRO_PREPROCESSOR = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_PREPROCESSOR", DefaultLanguageHighlighterColors.INSTANCE_METHOD)
val MACRO_NAME_DEF = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_NAME_DEF", DefaultLanguageHighlighterColors.METADATA)
val MACRO_LINE = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_LINE", DefaultLanguageHighlighterColors.METADATA)
val MACRO_CALL = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_CALL", DefaultLanguageHighlighterColors.STATIC_METHOD)
val DATA_WIDTH_BS = TextAttributesKey.createTextAttributesKey("MC68000_DATA_WIDTH_BS", DefaultLanguageHighlighterColors.DOT)
val DATA_WIDTH_L = TextAttributesKey.createTextAttributesKey("MC68000_DATA_WIDTH_W", DefaultLanguageHighlighterColors.DOT)
+5 -1
View File
@@ -10,7 +10,7 @@
<p>
<a href="https://github.com/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
]]></description>
<idea-version since-build="193.7288.0"/>
<idea-version since-build="193.5233.103"/>
<depends>com.intellij.modules.lang</depends>
@@ -24,15 +24,19 @@
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.asm.M68kMnemonicCompletionContributor"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kGlobalLabelSymbolCompletionContributor"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallCompletionContributor"/>
<lang.braceMatcher language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kPairedBraceMatcher"/>
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
<lang.findUsagesProvider language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.scanner.M68kFindUsagesProvider"/>
<lang.psiStructureViewFactory language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.structureview.M68kStructureViewFactory"/>
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kMacroCall"
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallElementManipulator"/>
<stubElementTypeHolder class="de.platon42.intellij.plugins.m68k.stubs.M68kElementTypes"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
@@ -23,6 +23,11 @@ internal class MacroCallTest : AbstractParsingTest() {
testGoodSyntax(testCase, " PUSHM d0/d3/d5-d7/a0-a2/a4-a6 ; save a couple of registers\n")
}
@Test
internal fun call_with_label(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, "label FOOBAR narf ; wut?\n")
}
@Test
internal fun putmsg_call_with_specially_bracketed_parameters(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
// FIXME this doesn't work as intended...
@@ -0,0 +1,66 @@
package de.platon42.intellij.plugins.m68k.parser
import de.platon42.intellij.jupiter.MyTestCase
import de.platon42.intellij.jupiter.ParsingTestExtension
import de.platon42.intellij.jupiter.TestDataSubPath
import org.junit.jupiter.api.Test
@TestDataSubPath("macros")
internal class MacroDefinitionTest : AbstractParsingTest() {
@Test
internal fun macro_with_name_left(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
FOOBAR MACRO ; start of macro
.loop\@ move.l \1,(\2)+ ; just copy all the stuff
dbra \3,.loop\@
ENDM ; end of macro
move.w d0,d1
"""
)
}
@Test
internal fun macro_with_name_right(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
MACRO FOOBAR ; start of macro
.loop\@ move.l \1,(\2)+ ; just copy all the stuff
dbra \3,.loop\@
ENDM ; end of macro
label: move.w d0,d1
"""
)
}
@Test
internal fun empty_macro(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
MACRO FOOBAR
ENDM
NARF = 100
"""
)
}
@Test
internal fun two_macro_definitions_in_succession(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
MACRO FOOBAR1
.loop\@ move.l \1,(\2)+
dbra \3,.loop\@
ENDM
MACRO FOOBAR2
.loop\@ move.w \1,(\2)+
dbra \3,.loop\@
ENDM
label: move.w d0,d1
"""
)
}
}
@@ -0,0 +1,32 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@TestDataPath("src/test/resources/references")
@TestDataSubPath("completion")
@ExtendWith(LightCodeInsightExtension::class)
internal class M68kMacroCallCompletionContributorTest : AbstractM68kTest() {
@Test
internal fun completion_shows_mnemonics_and_macros(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"completeme.asm", """
noppy MACRO
ENDM
no<caret>
"""
)
myFixture.completeBasic()
assertThat(myFixture.lookupElementStrings).containsExactlyInAnyOrder("nop", "not", "noppy")
}
}
@@ -8,10 +8,7 @@ import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
import de.platon42.intellij.plugins.m68k.psi.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@@ -71,4 +68,22 @@ internal class M68kReferenceContributorTest : AbstractM68kTest() {
myFixture.checkResultByFile("symbol_assignment_after_rename.asm")
}
@Test
@TestDataSubPath("macros")
internal fun reference_to_macro_can_be_renamed(@MyFixture myFixture: CodeInsightTestFixture) {
val file = myFixture.configureByFile("macros.asm")
val elementAtCaret = myFixture.elementAtCaret
assertThat(elementAtCaret).isInstanceOf(M68kMacroDefinition::class.java)
val macroDef = elementAtCaret as M68kMacroDefinition
assertThat(macroDef.macroNameDefinition.text).isEqualTo("PUTMSG")
myFixture.renameElementAtCaret("PRINTF")
val reference = file.findReferenceAt(myFixture.editor.caretModel.offset)!!
assertThat(reference).isInstanceOf(M68kMacroReference::class.java)
assertThat(reference.variants).isEmpty()
myFixture.checkResultByFile("macros_after_rename.asm")
}
}
@@ -24,6 +24,8 @@ internal class M68kStructureViewTest : AbstractM68kTest() {
PIC_WIDTH
PIC_HEIGHT
DEBUG_LEVEL
BLTHOGON
BLTHOGOFF
entry
-init
.looph
@@ -2,10 +2,12 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUSHM')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUSHM')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('hey comment')
@@ -2,11 +2,13 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUSHM')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUSHM')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; hey comment')
@@ -2,5 +2,5 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
PsiErrorElement:'.' unexpected
PsiElement(BAD_CHARACTER)('.')
PsiElement(M68kTokenType.MACRO_INVOKATION)('local_label')
PsiElement(M68kTokenType.MACRO_INVOCATION)('local_label')
PsiElement(M68kTokenType.EOL)('\n')
@@ -2,6 +2,7 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('local_label')
PsiElement(M68kTokenType.MACRO_INVOCATION)('local_label')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('$')
PsiElement(M68kTokenType.EOL)('\n')
@@ -2,9 +2,11 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('COPIMOVE')
PsiElement(M68kTokenType.MACRO_INVOCATION)('COPIMOVE')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('(3<<0)|(3<<3)|(1<<6)')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('bplcon2')
PsiElement(M68kTokenType.EOL)('\n')
@@ -0,0 +1,13 @@
Assembly File: a.asm
M68kStatementImpl(STATEMENT)
M68kGlobalLabelImpl(GLOBAL_LABEL)
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('label')
PsiWhiteSpace(' ')
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOCATION)('FOOBAR')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('narf')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; wut?')
PsiElement(M68kTokenType.EOL)('\n')
@@ -0,0 +1,21 @@
Assembly File: a.asm
PsiWhiteSpace('\n')
PsiWhiteSpace(' ')
M68kMacroDefinitionImpl(MACRO_DEFINITION)
PsiElement(M68kTokenType.MACRO_TAG)('MACRO')
PsiWhiteSpace(' ')
M68kMacroNameDefinitionImpl(MACRO_NAME_DEFINITION)
PsiElement(M68kTokenType.MACRO_NAME)('FOOBAR')
PsiWhiteSpace('\n')
PsiElement(M68kTokenType.MACRO_END_TAG)(' ENDM')
PsiElement(M68kTokenType.EOL)('\n')
M68kStatementImpl(STATEMENT)
M68kAssignmentImpl(ASSIGNMENT)
M68kSymbolDefinitionImpl(SYMBOL_DEFINITION)
PsiElement(M68kTokenType.SYMBOLDEF)('NARF')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.OP_ASSIGN)('=')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.DECIMAL)('100')
PsiElement(M68kTokenType.EOL)('\n')
@@ -0,0 +1,37 @@
Assembly File: a.asm
PsiWhiteSpace('\n')
M68kMacroDefinitionImpl(MACRO_DEFINITION)
M68kMacroNameDefinitionImpl(MACRO_NAME_DEFINITION)
PsiElement(M68kTokenType.MACRO_NAME)('FOOBAR')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.MACRO_TAG)('MACRO')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; start of macro')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)('.loop\@ move.l \1,(\2)+ ')
PsiComment(M68kTokenType.COMMENT)('; just copy all the stuff')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)(' dbra \3,.loop\@')
PsiWhiteSpace('\n')
PsiElement(M68kTokenType.MACRO_END_TAG)(' ENDM ')
PsiComment(M68kTokenType.COMMENT)('; end of macro')
PsiElement(M68kTokenType.EOL)('\n')
PsiWhiteSpace('\n')
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kAsmInstructionImpl(ASM_INSTRUCTION)
M68kAsmOpImpl(ASM_OP)
PsiElement(M68kTokenType.MNEMONIC)('move')
M68kOperandSizeImpl(OPERAND_SIZE)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiWhiteSpace(' ')
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
M68kDataRegisterImpl(DATA_REGISTER)
PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
M68kDataRegisterImpl(DATA_REGISTER)
PsiElement(M68kTokenType.DREG)('d1')
PsiElement(M68kTokenType.EOL)('\n')
@@ -0,0 +1,40 @@
Assembly File: a.asm
PsiWhiteSpace('\n')
PsiWhiteSpace(' ')
M68kMacroDefinitionImpl(MACRO_DEFINITION)
PsiElement(M68kTokenType.MACRO_TAG)('MACRO')
PsiWhiteSpace(' ')
M68kMacroNameDefinitionImpl(MACRO_NAME_DEFINITION)
PsiElement(M68kTokenType.MACRO_NAME)('FOOBAR')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; start of macro')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)('.loop\@ move.l \1,(\2)+ ')
PsiComment(M68kTokenType.COMMENT)('; just copy all the stuff')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)(' dbra \3,.loop\@')
PsiWhiteSpace('\n')
PsiElement(M68kTokenType.MACRO_END_TAG)(' ENDM ')
PsiComment(M68kTokenType.COMMENT)('; end of macro')
PsiElement(M68kTokenType.EOL)('\n')
M68kStatementImpl(STATEMENT)
M68kGlobalLabelImpl(GLOBAL_LABEL)
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('label')
PsiElement(M68kTokenType.COLON)(':')
PsiWhiteSpace(' ')
M68kAsmInstructionImpl(ASM_INSTRUCTION)
M68kAsmOpImpl(ASM_OP)
PsiElement(M68kTokenType.MNEMONIC)('move')
M68kOperandSizeImpl(OPERAND_SIZE)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiWhiteSpace(' ')
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
M68kDataRegisterImpl(DATA_REGISTER)
PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
M68kDataRegisterImpl(DATA_REGISTER)
PsiElement(M68kTokenType.DREG)('d1')
PsiElement(M68kTokenType.EOL)('\n')
@@ -2,8 +2,9 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUSHM')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUSHM')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0/d3/d5-d7/a0-a2/a4-a6')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; save a couple of registers')
@@ -2,17 +2,23 @@ Assembly File: a.asm
PsiWhiteSpace('\t')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUTMSG')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUTMSG')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('10')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('<"%s has left the building at %d:%d",10,'Yup!'>')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('a0')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('$42(a1')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0.w)')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('#42')
PsiElement(M68kTokenType.EOL)('\n')
@@ -2,5 +2,5 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('BLT_HOG_ON')
PsiElement(M68kTokenType.MACRO_INVOCATION)('BLT_HOG_ON')
PsiElement(M68kTokenType.EOL)('\n')
@@ -0,0 +1,51 @@
Assembly File: a.asm
PsiWhiteSpace('\n')
PsiWhiteSpace(' ')
M68kMacroDefinitionImpl(MACRO_DEFINITION)
PsiElement(M68kTokenType.MACRO_TAG)('MACRO')
PsiWhiteSpace(' ')
M68kMacroNameDefinitionImpl(MACRO_NAME_DEFINITION)
PsiElement(M68kTokenType.MACRO_NAME)('FOOBAR1')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)('.loop\@ move.l \1,(\2)+')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)(' dbra \3,.loop\@')
PsiWhiteSpace('\n')
PsiElement(M68kTokenType.MACRO_END_TAG)(' ENDM')
PsiElement(M68kTokenType.EOL)('\n')
PsiWhiteSpace(' ')
M68kMacroDefinitionImpl(MACRO_DEFINITION)
PsiElement(M68kTokenType.MACRO_TAG)('MACRO')
PsiWhiteSpace(' ')
M68kMacroNameDefinitionImpl(MACRO_NAME_DEFINITION)
PsiElement(M68kTokenType.MACRO_NAME)('FOOBAR2')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)('.loop\@ move.w \1,(\2)+')
PsiWhiteSpace('\n')
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
PsiElement(M68kTokenType.MACRO_LINE)(' dbra \3,.loop\@')
PsiWhiteSpace('\n')
PsiElement(M68kTokenType.MACRO_END_TAG)(' ENDM')
PsiElement(M68kTokenType.EOL)('\n')
M68kStatementImpl(STATEMENT)
M68kGlobalLabelImpl(GLOBAL_LABEL)
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('label')
PsiElement(M68kTokenType.COLON)(':')
PsiWhiteSpace(' ')
M68kAsmInstructionImpl(ASM_INSTRUCTION)
M68kAsmOpImpl(ASM_OP)
PsiElement(M68kTokenType.MNEMONIC)('move')
M68kOperandSizeImpl(OPERAND_SIZE)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiWhiteSpace(' ')
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
M68kDataRegisterImpl(DATA_REGISTER)
PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
M68kDataRegisterImpl(DATA_REGISTER)
PsiElement(M68kTokenType.DREG)('d1')
PsiElement(M68kTokenType.EOL)('\n')
@@ -0,0 +1,13 @@
PUTMSG MACRO
printf
ENDM
UAEExitWarp MACRO
ENDM
main PUTM<caret>SG 10,<"Enter MAIN!">,d0
rts
exit PUTMSG 10,<"Exit!">,d0
illegal
rts
@@ -0,0 +1,13 @@
PRINTF MACRO
printf
ENDM
UAEExitWarp MACRO
ENDM
main PRINTF 10,<"Enter MAIN!">,d0
rts
exit PRINTF 10,<"Exit!">,d0
illegal
rts
@@ -2,6 +2,14 @@ PIC_WIDTH = 320
PIC_HEIGHT equ 256
DEBUG_LEVEL set 10
BLTHOGON MACRO
foo
ENDM
BLTHOGOFF MACRO
bar
ENDM
entry:
bsr init
bsr main