Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62f7f13323 | ||
|
|
c4051a0377 | ||
|
|
a03de6c394 | ||
|
|
1bff1a12c2 | ||
|
|
665947827b | ||
|
|
3bb6165a58 | ||
|
|
89bd964fe7 |
@@ -10,8 +10,8 @@ This plugin delivers support for MC68000 assembly language files ([VAsm](http://
|
|||||||
|
|
||||||
It adds a language parser with syntax highlighting, referencing and refactoring support, and a few more features.
|
It adds a language parser with syntax highlighting, referencing and refactoring support, and a few more features.
|
||||||
|
|
||||||
I'm an Amiga retro democoder, and the lack of a plugin for M68k was the motivation to write one. Also, diving deep into custom language plugins has a steep
|
I'm an Amiga retro democoder (among other things), and the lack of a plugin for M68k was the motivation to write one. Also, diving deep into custom language
|
||||||
learning curve.
|
plugins has a steep learning curve.
|
||||||
|
|
||||||
When I started the plugin in July 2021, I was not aware of the [M68k plugin efforts by Jetbrains employee Yann Cébron](https://github.com/YannCebron/m68kplugin)
|
When I started the plugin in July 2021, I was not aware of the [M68k plugin efforts by Jetbrains employee Yann Cébron](https://github.com/YannCebron/m68kplugin)
|
||||||
who has been working on the same topic for quite some time. At the time of writing, his plugin however, has not been release yet. Nevertheless, it has a lot of
|
who has been working on the same topic for quite some time. At the time of writing, his plugin however, has not been release yet. Nevertheless, it has a lot of
|
||||||
@@ -19,17 +19,17 @@ awesome features and is pretty advanced. Check it out. You can install both plug
|
|||||||
|
|
||||||
Big kudos to Yann -- a few features were _inspired_ by his code.
|
Big kudos to Yann -- a few features were _inspired_ by his code.
|
||||||
|
|
||||||
My plugin, on the other hand, is still pretty basic and is the result of a few weeks of work. I released a really early first version it because I think it's "
|
My plugin, on the other hand, is still pretty basic and is the result of a few weeks of work. I released the first versions because I think it's "good enough"
|
||||||
good enough" to get started, and I can return to demo coding with its current state.
|
to get started, and I can return to demo coding with its current state.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
|
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
|
||||||
- Inspection for validating the syntax of the 68000 ISA.
|
- Validates the assembly syntax against the 68000 ISA.
|
||||||
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
|
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
|
||||||
- Mnemonics code completion
|
- Mnemonics code completion
|
||||||
- Symbols / Labels / Macros code completion
|
- Symbols / labels / macros code completion
|
||||||
- References / Refactoring support for local and global labels, symbol assignments, and macros.
|
- References / refactoring support for local and global labels, symbol assignments, and macros.
|
||||||
- Simple register usage flow (hover over register or press F1 for full flow)
|
- Simple register usage flow (hover over register or press F1 for full flow)
|
||||||
- Brace matching
|
- Brace matching
|
||||||
- Quote handler
|
- Quote handler
|
||||||
@@ -85,11 +85,15 @@ weak warnings as missing macro evaluation will not resolve symbols defined via `
|
|||||||
|
|
||||||
### Documentation provider
|
### Documentation provider
|
||||||
|
|
||||||
#### M68kSymbolDefinitionDocumentationProvider
|
#### M68kSymbolDefinition
|
||||||
|
|
||||||
Provides the assigned value of a `=`, `set` or `equ` symbol definition when hovering over a symbol.
|
Provides the assigned value of a `=`, `set` or `equ` symbol definition when hovering over a symbol.
|
||||||
|
|
||||||
#### M68kRegisterFlowDocumentationProvider
|
#### M68kGlobalLabel
|
||||||
|
|
||||||
|
Shows the comments above the label and if the first statement after the label is a directive like `include` or `dc.b`, shows it, too.
|
||||||
|
|
||||||
|
#### M68kRegisterFlow
|
||||||
|
|
||||||
When hovering over or placing the cursor at a data or address register, the documentation will scan through the instructions backwards and forwards and will
|
When hovering over or placing the cursor at a data or address register, the documentation will scan through the instructions backwards and forwards and will
|
||||||
show all read, changes of the register contents. It does this until an instruction is found that defines (sets) the contents of the register
|
show all read, changes of the register contents. It does this until an instruction is found that defines (sets) the contents of the register
|
||||||
@@ -100,7 +104,7 @@ The analysis ignores all code flow instructions and might be inaccurate for bran
|
|||||||
The documentation will search up to 100 instructions in each direction, but only four when hovering over the register
|
The documentation will search up to 100 instructions in each direction, but only four when hovering over the register
|
||||||
(so if you need the whole analysis, use the documentation window).
|
(so if you need the whole analysis, use the documentation window).
|
||||||
|
|
||||||
#### M68kInstructionDocumentationProvider
|
#### M68kInstruction
|
||||||
|
|
||||||
When hovering over a mnemonic, it will show a short description of the assembly instruction.
|
When hovering over a mnemonic, it will show a short description of the assembly instruction.
|
||||||
|
|
||||||
@@ -112,13 +116,13 @@ If the current statement has no valid syntax, the instruction details of all mat
|
|||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
|
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
|
||||||
|
- `END` detection was breaking parsing, so this is disabled for now until I find a working solution.
|
||||||
- Macro invocations are not yet evaluated, thus no referencing to symbols defined via macros (e.g. `STRUCT`).
|
- 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.
|
- Scoping 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)
|
- 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 (default is off).
|
- 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 support for other processor instructions, FPU or 68020+ address modes.
|
||||||
- Unit Test coverage is not as good as it could be (ahem).
|
- Unit Test coverage is not as good as it could be (ahem).
|
||||||
- `opt` keyword needs special treatment and will currently show a parsing error.
|
|
||||||
- Missing but planned features:
|
- Missing but planned features:
|
||||||
- Macro evaluation on invocation
|
- Macro evaluation on invocation
|
||||||
- Folding
|
- Folding
|
||||||
@@ -141,12 +145,26 @@ It is probably the only plugin (besides [Cajon](https://github.com/chrisly42/caj
|
|||||||
far (or at least the only one I'm aware of ;) ). The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing, and it took me quite a while to
|
far (or at least the only one I'm aware of ;) ). The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing, and it took me quite a while to
|
||||||
make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for your projects (with attribution).
|
make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for your projects (with attribution).
|
||||||
|
|
||||||
## Private TODO list
|
## Feedback
|
||||||
|
|
||||||
- code completion suggestion for unresolved global labels and symbols
|
I guess there are currently over 500 users of this plugin and while I wrote this mainly for myself, I'm only doing this in my spare time.
|
||||||
|
|
||||||
|
Feedback and [rating](https://plugins.jetbrains.com/plugin/17268-mc68000-assembly-language-support/reviews)
|
||||||
|
are appreciated. It really is keeping me motivated to continue development.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### V0.7 (26-Sep-21)
|
||||||
|
|
||||||
|
- Bugfix: `btst` with pc-relative and weird immediate mode was missing (courtesy of Yann).
|
||||||
|
- Bugfix: `movem` with pc-relative mode was missing for weird immediate mode (courtesy of Yann).
|
||||||
|
- Bugfix: Special registers for address mode matching only worked with lower case register names (courtesy of Yann).
|
||||||
|
- Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors (courtesy of Yann).
|
||||||
|
- Enhancement: Documentation for instruction with special register shows specific register expected.
|
||||||
|
- New: Added documentation provider info for global labels. Shows directives and comments above.
|
||||||
|
- Bugfix: Fixed BNF for labels with preprocessor statements.
|
||||||
|
- Disabled: `END` detection was breaking parsing, causing havoc.
|
||||||
|
|
||||||
### V0.6 (09-Aug-21)
|
### V0.6 (09-Aug-21)
|
||||||
|
|
||||||
- Enhancement: `opt` and several other directives (`printt`, `fail` etc.) no longer causes a syntax error when unquoted.
|
- Enhancement: `opt` and several other directives (`printt`, `fail` etc.) no longer causes a syntax error when unquoted.
|
||||||
@@ -188,7 +206,7 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
|
|||||||
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
|
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
|
||||||
- New: Macro definition refactoring and find usages support.
|
- New: Macro definition refactoring and find usages support.
|
||||||
- Enhancement: Structural View also shows macro definitions.
|
- Enhancement: Structural View also shows macro definitions.
|
||||||
- Bugfix: Missing REPT and ENDR assembler directives added.
|
- Bugfix: Missing `REPT` and `ENDR` assembler directives added.
|
||||||
- Cosmetics: Changed or added some icons at various places.
|
- Cosmetics: Changed or added some icons at various places.
|
||||||
- Performance: Reference search for global labels and symbols now uses stub index.
|
- Performance: Reference search for global labels and symbols now uses stub index.
|
||||||
- Compatibility: Restored compatibility with IDE versions < 2021.1.
|
- Compatibility: Restored compatibility with IDE versions < 2021.1.
|
||||||
|
|||||||
+20
-43
@@ -1,13 +1,13 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.jetbrains.intellij' version '1.1.3'
|
id 'org.jetbrains.intellij' version '1.1.6'
|
||||||
id 'org.jetbrains.kotlin.jvm' version '1.5.21'
|
id 'org.jetbrains.kotlin.jvm' version '1.5.21'
|
||||||
id 'jacoco'
|
id 'jacoco'
|
||||||
id 'com.github.kt3k.coveralls' version '2.11.0'
|
id 'com.github.kt3k.coveralls' version '2.12.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'de.platon42'
|
group = 'de.platon42'
|
||||||
version = '0.6'
|
version = '0.7'
|
||||||
sourceCompatibility = "1.8"
|
sourceCompatibility = "1.8"
|
||||||
targetCompatibility = "1.8"
|
targetCompatibility = "1.8"
|
||||||
|
|
||||||
@@ -22,9 +22,9 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||||
testImplementation "org.assertj:assertj-core:3.20.2"
|
testImplementation "org.assertj:assertj-core:3.21.0"
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0-M1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test"
|
testImplementation "org.jetbrains.kotlin:kotlin-test"
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
|
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
|
||||||
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
|
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
|
||||||
@@ -42,55 +42,32 @@ compileTestKotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
intellij {
|
intellij {
|
||||||
setVersion("2021.2") // LATEST-EAP-SNAPSHOT
|
setVersion("2021.2.2") // LATEST-EAP-SNAPSHOT
|
||||||
setUpdateSinceUntilBuild(false)
|
setUpdateSinceUntilBuild(false)
|
||||||
// setPlugins(["com.intellij.java"])
|
// setPlugins(["com.intellij.java"])
|
||||||
}
|
}
|
||||||
|
|
||||||
runPluginVerifier {
|
runPluginVerifier {
|
||||||
ideVersions = ["IC-203.6682.168", "IC-212.4746.92", // 2020.3 - 2021.2
|
ideVersions = ["IC-203.6682.168", "IC-212.5284.40", // 2020.3 - 2021.2.2
|
||||||
"CL-203.5981.166", "CL-203.8084.11", // 2020.3
|
"CL-203.5981.166", "CL-203.8084.11", // 2020.3
|
||||||
"CL-211.6693.114", "CL-211.7628.27", // 2021.1
|
"CL-211.6693.114", "CL-211.7628.27", // 2021.1
|
||||||
"CL-212.4746.93"] // 2021.2
|
"CL-212.4746.93", "CL-212.5284.51"] // 2021.2 - 2021.2.2
|
||||||
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea"
|
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/verifier"
|
||||||
}
|
}
|
||||||
|
|
||||||
patchPluginXml {
|
patchPluginXml {
|
||||||
setChangeNotes("""
|
setChangeNotes("""
|
||||||
<h4>V0.6 (09-Aug-21)</h4>
|
<p>I still got zero feedback and zero <a href="https://plugins.jetbrains.com/plugin/17268-mc68000-assembly-language-support/reviews">ratings</a> :-(</p>
|
||||||
|
<h4>V0.7 (26-Sep-21)</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Enhancement: 'opt' and several other directives ('printt', 'fail' etc.) no longer causes a syntax error when unquoted.
|
<li>Bugfix: 'btst' with pc-relative and weird immediate mode was missing (courtesy of Yann).
|
||||||
<li>Enhancement: 'include', 'incdir' and 'incbin' and 'output' with '<pathname>' quotes no longer cause syntax error.
|
<li>Bugfix: 'movem' with pc-relative mode was missing for weird immediate mode (courtesy of Yann).
|
||||||
<li>New: Files in 'include' directives can be referenced and renamed/refactored.
|
<li>Bugfix: Special registers for address mode matching only worked with lower case register names (courtesy of Yann).
|
||||||
<li>New: Code completion for local label definitions, suggesting undefined labels already referenced.
|
<li>Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors (courtesy of Yann).
|
||||||
<li>New: Added inspection suppression possibility and quickfix.
|
<li>Enhancement: Documentation for instruction with special register shows specific register expected.
|
||||||
<li>New: Added inspection for unresolved symbols, macros and labels.
|
<li>New: Added documentation provider info for global labels. Shows directives and comments above.
|
||||||
<li>Enhancement: 'END' directive stops parsing.
|
<li>Bugfix: Fixed BNF for labels with preprocessor statements.
|
||||||
</ul>
|
<li>Disabled: 'END' detection was breaking parsing, causing havoc.
|
||||||
<h4>V0.5 (06-Aug-21)</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Bugfix: movem ISA was wrong regarding movem.w <ea>,<registerlist> (sign extends registers).
|
|
||||||
<li>Cosmetics: Changed Register Flow Documentation wording from 'reads' to 'uses' and from 'modifies' to 'changes'.
|
|
||||||
<li>Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
|
||||||
<li>Bugfix: Added alternate condition code tests HS (=CC) and LO (=CS).
|
|
||||||
<li>Performance: Optimized mnemonic lookup.
|
|
||||||
<li>Enhancement: Reworked Instruction Documentation provider, now shows condition codes.
|
|
||||||
<li>Bugfix: In ISA exg is no longer treated as setting a definitive value.
|
|
||||||
<li>New: Added inspection to find dead writes to registers!
|
|
||||||
<li>New: Added inspection to warn about unexpected condition code unaffecting instructions before conditional instructions.
|
|
||||||
</ul>
|
|
||||||
<h4>V0.4 (03-Aug-21)</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Notice: Due to major new API use, this plugin no longer works on IDEs >=2019.3.1, but rather requires >=2020.3.
|
|
||||||
<li>Enhancement: Added Structure View filters.
|
|
||||||
<li>New: Added inspection to validate the correctness of a MC68000 instruction regarding operation size and address modes.
|
|
||||||
<li>Bugfix: Added several missing assembler directives (opt, machine, etc.).
|
|
||||||
<li>Bugfix: Uppercase hexadecimal literals were not parsed (JFlex bug?).
|
|
||||||
<li>Bugfix: Interpretation of register lists was wrong in BNF.
|
|
||||||
<li>New: Added Documentation Provider for symbol definitions (shows assigned declaration).
|
|
||||||
<li>New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
|
|
||||||
<li>Bugfix: Macro definitions with colons and without space supported (as found in P61a source).
|
|
||||||
<li>New: When asking for documentation on registers, a code flow analysis is done. Cool stuff!
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
||||||
""")
|
""")
|
||||||
|
|||||||
@@ -871,11 +871,7 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
yybegin(ASMINSTR);
|
yybegin(ASMINSTR);
|
||||||
return MNEMONIC;
|
return MNEMONIC;
|
||||||
}
|
}
|
||||||
if (isEndDirective(yytext())) {
|
//if(isEndDirective(yytext())) { yybegin(YYINITIAL); zzAtEOF = true; return null; }
|
||||||
yybegin(YYINITIAL);
|
|
||||||
zzAtEOF = true;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (isDataDirective(yytext())) {
|
if (isDataDirective(yytext())) {
|
||||||
startExpr(EXPR, EXPR_OP);
|
startExpr(EXPR, EXPR_OP);
|
||||||
return DATA_DIRECTIVE;
|
return DATA_DIRECTIVE;
|
||||||
|
|||||||
@@ -562,9 +562,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Instruction
|
// Instruction|PreprocessorDirective
|
||||||
static boolean InstructionOnly(PsiBuilder b, int l) {
|
static boolean InstructionOnly(PsiBuilder b, int l) {
|
||||||
return Instruction(b, l + 1);
|
if (!recursion_guard_(b, l, "InstructionOnly")) return false;
|
||||||
|
boolean r;
|
||||||
|
r = Instruction(b, l + 1);
|
||||||
|
if (!r) r = PreprocessorDirective(b, l + 1);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
@@ -596,18 +600,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Label Instruction
|
// Label (Instruction|PreprocessorDirective)
|
||||||
static boolean LabelWithInstruction(PsiBuilder b, int l) {
|
static boolean LabelWithInstruction(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "LabelWithInstruction")) return false;
|
if (!recursion_guard_(b, l, "LabelWithInstruction")) return false;
|
||||||
if (!nextTokenIs(b, "", GLOBAL_LABEL_DEF, LOCAL_LABEL_DEF)) return false;
|
if (!nextTokenIs(b, "", GLOBAL_LABEL_DEF, LOCAL_LABEL_DEF)) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
Marker m = enter_section_(b);
|
||||||
r = Label(b, l + 1);
|
r = Label(b, l + 1);
|
||||||
r = r && Instruction(b, l + 1);
|
r = r && LabelWithInstruction_1(b, l + 1);
|
||||||
exit_section_(b, m, null, r);
|
exit_section_(b, m, null, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instruction|PreprocessorDirective
|
||||||
|
private static boolean LabelWithInstruction_1(PsiBuilder b, int l) {
|
||||||
|
if (!recursion_guard_(b, l, "LabelWithInstruction_1")) return false;
|
||||||
|
boolean r;
|
||||||
|
r = Instruction(b, l + 1);
|
||||||
|
if (!r) r = PreprocessorDirective(b, l + 1);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// LOCAL_LABEL_DEF COLON?
|
// LOCAL_LABEL_DEF COLON?
|
||||||
public static boolean LocalLabel(PsiBuilder b, int l) {
|
public static boolean LocalLabel(PsiBuilder b, int l) {
|
||||||
@@ -817,28 +830,21 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Label? PreprocessorKeyword PreprocessorOperands?
|
// PreprocessorKeyword PreprocessorOperands?
|
||||||
public static boolean PreprocessorDirective(PsiBuilder b, int l) {
|
public static boolean PreprocessorDirective(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective")) return false;
|
if (!recursion_guard_(b, l, "PreprocessorDirective")) return false;
|
||||||
|
if (!nextTokenIs(b, "<preprocessor directive>", DATA_DIRECTIVE, OTHER_DIRECTIVE)) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b, l, _NONE_, PREPROCESSOR_DIRECTIVE, "<preprocessor directive>");
|
Marker m = enter_section_(b, l, _NONE_, PREPROCESSOR_DIRECTIVE, "<preprocessor directive>");
|
||||||
r = PreprocessorDirective_0(b, l + 1);
|
r = PreprocessorKeyword(b, l + 1);
|
||||||
r = r && PreprocessorKeyword(b, l + 1);
|
r = r && PreprocessorDirective_1(b, l + 1);
|
||||||
r = r && PreprocessorDirective_2(b, l + 1);
|
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label?
|
|
||||||
private static boolean PreprocessorDirective_0(PsiBuilder b, int l) {
|
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective_0")) return false;
|
|
||||||
Label(b, l + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreprocessorOperands?
|
// PreprocessorOperands?
|
||||||
private static boolean PreprocessorDirective_2(PsiBuilder b, int l) {
|
private static boolean PreprocessorDirective_1(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective_2")) return false;
|
if (!recursion_guard_(b, l, "PreprocessorDirective_1")) return false;
|
||||||
PreprocessorOperands(b, l + 1);
|
PreprocessorOperands(b, l + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1220,14 +1226,12 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Assignment
|
// Assignment
|
||||||
// | PreprocessorDirective
|
|
||||||
// | LabelInsts
|
// | LabelInsts
|
||||||
public static boolean statement(PsiBuilder b, int l) {
|
public static boolean statement(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "statement")) return false;
|
if (!recursion_guard_(b, l, "statement")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b, l, _NONE_, STATEMENT, "<statement>");
|
Marker m = enter_section_(b, l, _NONE_, STATEMENT, "<statement>");
|
||||||
r = Assignment(b, l + 1);
|
r = Assignment(b, l + 1);
|
||||||
if (!r) r = PreprocessorDirective(b, l + 1);
|
|
||||||
if (!r) r = LabelInsts(b, l + 1);
|
if (!r) r = LabelInsts(b, l + 1);
|
||||||
exit_section_(b, l, m, r, false, M68kParser::statement_recover);
|
exit_section_(b, l, m, r, false, M68kParser::statement_recover);
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -2,18 +2,11 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.psi;
|
package de.platon42.intellij.plugins.m68k.psi;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface M68kPreprocessorDirective extends M68kPsiElement {
|
public interface M68kPreprocessorDirective extends M68kPsiElement {
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kGlobalLabel getGlobalLabel();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kLocalLabel getLocalLabel();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kPreprocessorKeyword getPreprocessorKeyword();
|
M68kPreprocessorKeyword getPreprocessorKeyword();
|
||||||
|
|
||||||
|
|||||||
-13
@@ -6,7 +6,6 @@ import com.intellij.psi.PsiElementVisitor;
|
|||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -26,18 +25,6 @@ public class M68kPreprocessorDirectiveImpl extends M68kPreprocessorDirectiveMixi
|
|||||||
else super.accept(visitor);
|
else super.accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kGlobalLabel getGlobalLabel() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kGlobalLabel.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kLocalLabel getLocalLabel() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kLocalLabel.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kPreprocessorKeyword getPreprocessorKeyword() {
|
public M68kPreprocessorKeyword getPreprocessorKeyword() {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ enum class AddressMode(val description: String, val syntax: String) {
|
|||||||
PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT("program counter indirect with displacement", "(d16,PC)"),
|
PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT("program counter indirect with displacement", "(d16,PC)"),
|
||||||
ADDRESS_REGISTER_INDIRECT_WITH_INDEX("address register indirect with index", "(d8,An,Xn)"),
|
ADDRESS_REGISTER_INDIRECT_WITH_INDEX("address register indirect with index", "(d8,An,Xn)"),
|
||||||
PROGRAM_COUNTER_INDIRECT_WITH_INDEX("program counter indirect with index", "(d8,PC,Xn)"),
|
PROGRAM_COUNTER_INDIRECT_WITH_INDEX("program counter indirect with index", "(d8,PC,Xn)"),
|
||||||
SPECIAL_REGISTER_DIRECT("special register", "ccr|usp|vbr"),
|
SPECIAL_REGISTER_DIRECT("special register", "sr|ccr|usp|vbr"),
|
||||||
REGISTER_LIST("register list", "list"),
|
REGISTER_LIST("register list", "list"),
|
||||||
IMMEDIATE_DATA("immediate", "#<xxx>"),
|
IMMEDIATE_DATA("immediate", "#<xxx>"),
|
||||||
ABSOLUTE_ADDRESS("absolute short/long", "(xxx).w|l")
|
ABSOLUTE_ADDRESS("absolute short/long", "(xxx).w|l")
|
||||||
@@ -202,6 +202,18 @@ object M68kIsa {
|
|||||||
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val ALL_EXCEPT_AREG_AND_DREG = setOf(
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
|
||||||
|
AddressMode.ABSOLUTE_ADDRESS,
|
||||||
|
AddressMode.IMMEDIATE_DATA,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
|
||||||
|
)
|
||||||
|
|
||||||
private val INDIRECT_MODES = setOf(
|
private val INDIRECT_MODES = setOf(
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT,
|
AddressMode.ADDRESS_REGISTER_INDIRECT,
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
||||||
@@ -256,33 +268,39 @@ object M68kIsa {
|
|||||||
private val ASD_LSD_MODES = listOf(
|
private val ASD_LSD_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
||||||
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")),
|
AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")),
|
||||||
|
// not an official address mode, but supported by assembler (implicit #1)
|
||||||
|
AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****"))
|
||||||
)
|
)
|
||||||
|
|
||||||
private val ROD_MODES = listOf(
|
private val ROD_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")),
|
AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
|
// not an official address mode, but supported by assembler (implicit #1)
|
||||||
|
AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val ROXD_MODES = listOf(
|
private val ROXD_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
|
// not an official address mode, but supported by assembler (implicit #1)
|
||||||
|
AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val BCHG_BCLR_BSET_MODES = listOf(
|
private val BCHG_BCLR_BSET_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val BTST_MODES = listOf(
|
private val BTST_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val conditionCodes =
|
private val conditionCodes =
|
||||||
@@ -354,7 +372,9 @@ object M68kIsa {
|
|||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
|
||||||
AddressMode.ABSOLUTE_ADDRESS
|
AddressMode.ABSOLUTE_ADDRESS,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
|
||||||
),
|
),
|
||||||
setOf(AddressMode.IMMEDIATE_DATA),
|
setOf(AddressMode.IMMEDIATE_DATA),
|
||||||
OP_SIZE_WL,
|
OP_SIZE_WL,
|
||||||
@@ -944,5 +964,5 @@ object M68kIsa {
|
|||||||
private fun isAddressModeMatching(am: AllowedAdrMode, op1: AddressMode?, op2: AddressMode?, specialReg: String?) =
|
private fun isAddressModeMatching(am: AllowedAdrMode, op1: AddressMode?, op2: AddressMode?, specialReg: String?) =
|
||||||
((((op1 == null) && (am.op1 == null)) || am.op1?.contains(op1) ?: false)
|
((((op1 == null) && (am.op1 == null)) || am.op1?.contains(op1) ?: false)
|
||||||
&& (((op2 == null) && (am.op2 == null)) || am.op2?.contains(op2) ?: false)
|
&& (((op2 == null) && (am.op2 == null)) || am.op2?.contains(op2) ?: false)
|
||||||
&& ((specialReg == null) || (specialReg == am.specialReg)))
|
&& ((specialReg == null) || (specialReg.equals(am.specialReg, true))))
|
||||||
}
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.documentation
|
||||||
|
|
||||||
|
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
||||||
|
import com.intellij.lang.documentation.DocumentationMarkup
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.util.SmartList
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kStatement
|
||||||
|
|
||||||
|
class M68kGlobalLabelDocumentationProvider : AbstractDocumentationProvider() {
|
||||||
|
|
||||||
|
override fun getQuickNavigateInfo(element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
|
return generateDoc(element, originalElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
|
return if (element is M68kGlobalLabel) {
|
||||||
|
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
|
||||||
|
val statement = element.parent as M68kStatement
|
||||||
|
var preprocessorDirective = statement.preprocessorDirective
|
||||||
|
if ((preprocessorDirective == null) && (statement.asmInstruction == null) && (statement.macroCall == null)) {
|
||||||
|
val nextLineStatement = PsiTreeUtil.skipWhitespacesAndCommentsForward(PsiTreeUtil.skipWhitespacesAndCommentsForward(statement))
|
||||||
|
as? M68kStatement
|
||||||
|
preprocessorDirective = nextLineStatement?.preprocessorDirective
|
||||||
|
}
|
||||||
|
val content = if (preprocessorDirective != null)
|
||||||
|
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(preprocessorDirective.text) + DocumentationMarkup.CONTENT_END
|
||||||
|
else ""
|
||||||
|
val comments = SmartList<String>()
|
||||||
|
var prevToken: PsiElement? = statement
|
||||||
|
do {
|
||||||
|
prevToken = PsiTreeUtil.skipWhitespacesBackward(prevToken)
|
||||||
|
if (prevToken !is PsiComment) break
|
||||||
|
comments.add(prevToken.text)
|
||||||
|
} while (true)
|
||||||
|
val commentpart =
|
||||||
|
if (comments.isNotEmpty()) comments.asReversed().joinToString("<br>", DocumentationMarkup.GRAYED_START, DocumentationMarkup.GRAYED_END) else ""
|
||||||
|
|
||||||
|
commentpart +
|
||||||
|
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
|
||||||
|
content
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-4
@@ -92,8 +92,8 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
val cellsPerRow = ArrayList<HtmlChunk>(3)
|
val cellsPerRow = ArrayList<HtmlChunk>(3)
|
||||||
cellsPerRow.add(contentBuilder.toFragment())
|
cellsPerRow.add(contentBuilder.toFragment())
|
||||||
|
|
||||||
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op1))
|
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op1, allowedAdrMode.specialReg))
|
||||||
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op2))
|
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op2, allowedAdrMode.specialReg))
|
||||||
|
|
||||||
addressModeInfoRows.append(HtmlChunk.tag("tr").children(cellsPerRow.map { it.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL) }))
|
addressModeInfoRows.append(HtmlChunk.tag("tr").children(cellsPerRow.map { it.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL) }))
|
||||||
addressModeInfoRows.toFragment()
|
addressModeInfoRows.toFragment()
|
||||||
@@ -126,11 +126,12 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
return defBuilder
|
return defBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectAddressModes(addressModes: Set<AddressMode>?): HtmlChunk {
|
private fun collectAddressModes(addressModes: Set<AddressMode>?, specialReg: String?): HtmlChunk {
|
||||||
if (addressModes == null) return HtmlChunk.text("")
|
if (addressModes == null) return HtmlChunk.text("")
|
||||||
val modes = HtmlBuilder()
|
val modes = HtmlBuilder()
|
||||||
addressModes.sortedBy(AddressMode::ordinal)
|
addressModes.sortedBy(AddressMode::ordinal)
|
||||||
.forEach { modes.append(HtmlChunk.text(it.syntax).wrapWith(HtmlChunk.div())) }
|
.map { if (it == AddressMode.SPECIAL_REGISTER_DIRECT) specialReg!! else it.syntax }
|
||||||
|
.forEach { modes.append(HtmlChunk.text(it).wrapWith(HtmlChunk.div())) }
|
||||||
return modes.toFragment()
|
return modes.toFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ class M68kSymbolDefinitionDocumentationProvider : AbstractDocumentationProvider(
|
|||||||
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
return if (element is M68kSymbolDefinition) {
|
return if (element is M68kSymbolDefinition) {
|
||||||
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
|
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
|
||||||
val value = (element.getParent() as M68kAssignment).expr.text
|
val value = (element.parent as M68kAssignment).expr.text
|
||||||
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
|
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
|
||||||
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(value) + DocumentationMarkup.CONTENT_END
|
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(value) + DocumentationMarkup.CONTENT_END
|
||||||
} else null
|
} else null
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
|||||||
{DIRECTIVE_KEYWORD} {
|
{DIRECTIVE_KEYWORD} {
|
||||||
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
|
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
|
||||||
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
|
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
|
||||||
if(isEndDirective(yytext())) { yybegin(YYINITIAL); zzAtEOF = true; return null; }
|
//if(isEndDirective(yytext())) { yybegin(YYINITIAL); zzAtEOF = true; return null; }
|
||||||
if(isDataDirective(yytext())) { startExpr(EXPR, EXPR_OP); return DATA_DIRECTIVE; }
|
if(isDataDirective(yytext())) { startExpr(EXPR, EXPR_OP); return DATA_DIRECTIVE; }
|
||||||
if(isPlainDirective(yytext())) { yybegin(PLAINPARAMS); return OTHER_DIRECTIVE; }
|
if(isPlainDirective(yytext())) { yybegin(PLAINPARAMS); return OTHER_DIRECTIVE; }
|
||||||
if(isOtherDirective(yytext())) { startExpr(EXPR, EXPR_OP); return OTHER_DIRECTIVE; }
|
if(isOtherDirective(yytext())) { startExpr(EXPR, EXPR_OP); return OTHER_DIRECTIVE; }
|
||||||
|
|||||||
@@ -121,7 +121,6 @@ M68kFile ::= line*
|
|||||||
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
|
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
|
||||||
|
|
||||||
statement ::= (Assignment
|
statement ::= (Assignment
|
||||||
| PreprocessorDirective
|
|
||||||
| LabelInsts)
|
| LabelInsts)
|
||||||
{pin = 1 recoverWhile = statement_recover}
|
{pin = 1 recoverWhile = statement_recover}
|
||||||
|
|
||||||
@@ -140,8 +139,8 @@ Assignment ::= SymbolDefinition COLON? (OP_ASSIGN|EQU) expr
|
|||||||
private LabelInsts ::= LabelWithInstruction | LabelOnly | InstructionOnly
|
private LabelInsts ::= LabelWithInstruction | LabelOnly | InstructionOnly
|
||||||
|
|
||||||
private LabelOnly ::= Label
|
private LabelOnly ::= Label
|
||||||
private LabelWithInstruction ::= Label Instruction
|
private LabelWithInstruction ::= Label (Instruction|PreprocessorDirective)
|
||||||
private InstructionOnly ::= Instruction
|
private InstructionOnly ::= (Instruction|PreprocessorDirective)
|
||||||
|
|
||||||
LocalLabel ::= LOCAL_LABEL_DEF COLON? {
|
LocalLabel ::= LOCAL_LABEL_DEF COLON? {
|
||||||
name = "local label"
|
name = "local label"
|
||||||
@@ -175,7 +174,7 @@ AsmOp ::= MNEMONIC OperandSize? {
|
|||||||
|
|
||||||
PreprocessorKeyword ::= (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
PreprocessorKeyword ::= (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
||||||
|
|
||||||
PreprocessorDirective ::= Label? PreprocessorKeyword PreprocessorOperands? {
|
PreprocessorDirective ::= PreprocessorKeyword PreprocessorOperands? {
|
||||||
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirectiveMixin"
|
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirectiveMixin"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ object M68kPsiImplUtil {
|
|||||||
|
|
||||||
// Local Label
|
// Local Label
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getName(element: M68kLocalLabel): String = element.firstChild?.text ?: ""
|
fun getName(element: M68kLocalLabel): String? = element.firstChild?.text
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setName(element: M68kLocalLabel, name: String): PsiElement {
|
fun setName(element: M68kLocalLabel, name: String): PsiElement {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<fileType name="MC68000 Assembler" implementationClass="de.platon42.intellij.plugins.m68k.M68kFileType"
|
<fileType name="MC68000 Assembler" implementationClass="de.platon42.intellij.plugins.m68k.M68kFileType"
|
||||||
fieldName="INSTANCE" language="MC68000" extensions="asm;ASM;s;S;i"/>
|
fieldName="INSTANCE" language="MC68000" extensions="asm;s;i"/>
|
||||||
<lang.parserDefinition language="MC68000"
|
<lang.parserDefinition language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/>
|
||||||
<lang.syntaxHighlighterFactory language="MC68000"
|
<lang.syntaxHighlighterFactory language="MC68000"
|
||||||
@@ -39,6 +39,8 @@
|
|||||||
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kPreprocessorDirectiveElementManipulator"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kPreprocessorDirectiveElementManipulator"/>
|
||||||
<lang.documentationProvider language="MC68000"
|
<lang.documentationProvider language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kSymbolDefinitionDocumentationProvider"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kSymbolDefinitionDocumentationProvider"/>
|
||||||
|
<lang.documentationProvider language="MC68000"
|
||||||
|
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kGlobalLabelDocumentationProvider"/>
|
||||||
<lang.documentationProvider language="MC68000"
|
<lang.documentationProvider language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kRegisterFlowDocumentationProvider"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kRegisterFlowDocumentationProvider"/>
|
||||||
<lang.documentationProvider language="MC68000"
|
<lang.documentationProvider language="MC68000"
|
||||||
@@ -47,7 +49,7 @@
|
|||||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/>
|
<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.M68kSymbolDefinitionStubIndex"/>
|
||||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
|
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
|
||||||
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
|
<psi.referenceContributor language="MC68000" implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
|
||||||
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
||||||
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
|
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
|
||||||
<include.provider implementation="de.platon42.intellij.plugins.m68k.scanner.M68kIncludeFileProvider"/>
|
<include.provider implementation="de.platon42.intellij.plugins.m68k.scanner.M68kIncludeFileProvider"/>
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.documentation
|
||||||
|
|
||||||
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
|
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||||
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
|
||||||
|
@ExtendWith(LightCodeInsightExtension::class)
|
||||||
|
internal class M68kGlobalLabelDocumentationProviderTest : AbstractDocumentationProviderTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_a_label_definition(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"documentme.asm", """
|
||||||
|
rts
|
||||||
|
; inputs: d0 = number
|
||||||
|
|
||||||
|
; output: d0 = square
|
||||||
|
squareme: include "fancysquarecode.asm"
|
||||||
|
rts
|
||||||
|
bsr square<caret>me
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assertThat(generateDocumentation(myFixture))
|
||||||
|
.isEqualTo("<span class='grayed'>; inputs: d0 = number<br>; output: d0 = square</span><div class='definition'><pre>squareme</pre></div><div class='content'>include "fancysquarecode.asm"</div>")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_a_label_definition_next_line(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"documentme.asm", """
|
||||||
|
; output: d0 = square
|
||||||
|
square<caret>me:
|
||||||
|
; oh man
|
||||||
|
include "fancysquarecode.asm"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assertThat(generateDocumentation(myFixture))
|
||||||
|
.isEqualTo("<span class='grayed'>; output: d0 = square</span><div class='definition'><pre>squareme</pre></div><div class='content'>include "fancysquarecode.asm"</div>")
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -108,6 +108,16 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
|||||||
assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
|
assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_instruction_with_special_register(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"documentme.asm", """
|
||||||
|
<caret>move.l usp,a0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assertThat(generateDocumentation(myFixture)).contains("<div>usp</div>")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun check_documentation_if_there_is_no_concrete_match(@MyFixture myFixture: CodeInsightTestFixture) {
|
internal fun check_documentation_if_there_is_no_concrete_match(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
myFixture.configureByText(
|
myFixture.configureByText(
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
|||||||
testGoodSyntax(testCase, " move.l 4.w,a6\n")
|
testGoodSyntax(testCase, " move.l 4.w,a6\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun btst_quirk(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
|
testGoodSyntax(testCase, " btst #5,#42\n btst d0,#42")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n")
|
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n")
|
||||||
@@ -118,7 +123,7 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
|||||||
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(
|
testGoodSyntax(
|
||||||
testCase, " move.l usp,a0\n"
|
testCase, " move.l usp,a0\n"
|
||||||
+ " move.l a5,usp\n"
|
+ " move.l a5,USP\n"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ package de.platon42.intellij.plugins.m68k.parser
|
|||||||
import de.platon42.intellij.jupiter.MyTestCase
|
import de.platon42.intellij.jupiter.MyTestCase
|
||||||
import de.platon42.intellij.jupiter.ParsingTestExtension
|
import de.platon42.intellij.jupiter.ParsingTestExtension
|
||||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||||
|
import org.junit.jupiter.api.Disabled
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
@TestDataSubPath("directives")
|
@TestDataSubPath("directives")
|
||||||
internal class EndDirectiveTest : AbstractParsingTest() {
|
internal class EndDirectiveTest : AbstractParsingTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("END directive detection breaks stuff, need to find a different solution")
|
||||||
internal fun end_directive(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun end_directive(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(
|
testGoodSyntax(
|
||||||
testCase, """
|
testCase, """
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
Assembly File: a.asm
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||||
|
M68kAsmOpImpl(ASM_OP)
|
||||||
|
PsiElement(M68kTokenType.MNEMONIC)('btst')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('5')
|
||||||
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('42')
|
||||||
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||||
|
M68kAsmOpImpl(ASM_OP)
|
||||||
|
PsiElement(M68kTokenType.MNEMONIC)('btst')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
|
||||||
|
M68kDataRegisterImpl(DATA_REGISTER)
|
||||||
|
PsiElement(M68kTokenType.DREG)('d0')
|
||||||
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('42')
|
||||||
@@ -29,5 +29,5 @@ Assembly File: a.asm
|
|||||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
M68kSpecialRegisterDirectAddressingModeImpl(SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE)
|
M68kSpecialRegisterDirectAddressingModeImpl(SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE)
|
||||||
M68kSpecialRegisterImpl(SPECIAL_REGISTER)
|
M68kSpecialRegisterImpl(SPECIAL_REGISTER)
|
||||||
PsiElement(M68kTokenType.REG_USP)('usp')
|
PsiElement(M68kTokenType.REG_USP)('USP')
|
||||||
PsiElement(M68kTokenType.EOL)('\n')
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
Assembly File: a.asm
|
Assembly File: a.asm
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
||||||
|
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('foo')
|
||||||
|
PsiElement(M68kTokenType.COLON)(':')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
|
||||||
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('foo')
|
|
||||||
PsiElement(M68kTokenType.COLON)(':')
|
|
||||||
PsiWhiteSpace(' ')
|
|
||||||
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.b')
|
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.b')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Assembly File: a.asm
|
Assembly File: a.asm
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
||||||
|
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('howto')
|
||||||
|
PsiElement(M68kTokenType.COLON)(':')
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
|
||||||
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('howto')
|
|
||||||
PsiElement(M68kTokenType.COLON)(':')
|
|
||||||
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('incbin')
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('incbin')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
Reference in New Issue
Block a user