Reworked BNF for symbol references and program counter. Enhanced syntax highlighting. Continued work on referencing (not yet working). Fixed renaming of Labels and Symbols. Added M68kRenameInputValidator for correct renaming of symbols and labels (allow local labels with dot or dollar). Added UsagesProvider (not sure if working). Added PairedBraceMatcher.
This commit is contained in:
@@ -126,7 +126,13 @@ statement ::= (Assignment
|
||||
|
||||
private statement_recover ::= !(EOL)
|
||||
|
||||
Assignment ::= SYMBOLDEF COLON? (OP_ASSIGN|EQU) expr
|
||||
SymbolDefinition ::= SYMBOLDEF {
|
||||
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
|
||||
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinitionMixin"
|
||||
methods = [getName setName getNameIdentifier]
|
||||
}
|
||||
|
||||
Assignment ::= SymbolDefinition COLON? (OP_ASSIGN|EQU) expr
|
||||
|
||||
private LabelInsts ::= LabelWithInstruction | LabelOnly | InstructionOnly
|
||||
|
||||
@@ -173,6 +179,9 @@ private PreprocessorOperand ::= expr
|
||||
|
||||
private PlainOperands ::= STRINGLIT (SEPARATOR STRINGLIT)*
|
||||
|
||||
SymbolReference ::= SYMBOL // TODO This should probably be a ILazyParseableElementType, no idea how to implement that yet
|
||||
ProgramCounterReference ::= CURRENT_PC_SYMBOL
|
||||
|
||||
DataRegister ::= DREG {
|
||||
name = "data register"
|
||||
extends = Register
|
||||
@@ -280,7 +289,7 @@ binary_logical_or_expr ::= expr OP_LOGICAL_OR expr
|
||||
|
||||
//macrobrace_expr ::= OP_CMP_LT expr OP_CMP_GT
|
||||
paren_expr ::= ROUND_L expr ROUND_R //{pin=1 recoverWhile=statement_recover}
|
||||
ref_expr ::= SYMBOL|CURRENT_PC_SYMBOL
|
||||
ref_expr ::= SymbolReference|ProgramCounterReference
|
||||
literal_expr ::= BINARY|DECIMAL|HEXADECIMAL|OCTAL|STRINGLIT {
|
||||
implements = "com.intellij.psi.PsiLiteralValue"
|
||||
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kLiteralExprMixin"
|
||||
|
||||
@@ -8,15 +8,20 @@ import de.platon42.intellij.plugins.m68k.M68kFileType.Companion.INSTANCE
|
||||
object M68kElementFactory {
|
||||
|
||||
fun createGlobalLabel(project: Project, label: String): M68kGlobalLabel {
|
||||
val file = createFile(project, label)
|
||||
val file = createFile(project, "$label\n")
|
||||
return PsiTreeUtil.findChildOfType(file, M68kGlobalLabel::class.java)!!
|
||||
}
|
||||
|
||||
fun createLocalLabel(project: Project, label: String): M68kLocalLabel {
|
||||
val file = createFile(project, label)
|
||||
val file = createFile(project, "$label\n")
|
||||
return PsiTreeUtil.findChildOfType(file, M68kLocalLabel::class.java)!!
|
||||
}
|
||||
|
||||
fun createSymbolDefinition(project: Project, label: String): M68kSymbolDefinition {
|
||||
val file = createFile(project, "$label=0\n")
|
||||
return PsiTreeUtil.findChildOfType(file, M68kSymbolDefinition::class.java)!!
|
||||
}
|
||||
|
||||
fun createFile(project: Project, content: String): M68kFile {
|
||||
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ 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.createSymbolDefinition
|
||||
|
||||
object M68kPsiImplUtil {
|
||||
|
||||
// Global Label
|
||||
@JvmStatic
|
||||
fun getName(element: M68kGlobalLabel): String? = element.firstChild.text
|
||||
|
||||
@@ -23,6 +25,7 @@ object M68kPsiImplUtil {
|
||||
@JvmStatic
|
||||
fun getNameIdentifier(element: M68kGlobalLabel): PsiElement = element.firstChild
|
||||
|
||||
// Local Label
|
||||
@JvmStatic
|
||||
fun getName(element: M68kLocalLabel): String? = element.firstChild.text
|
||||
|
||||
@@ -39,4 +42,24 @@ object M68kPsiImplUtil {
|
||||
|
||||
@JvmStatic
|
||||
fun getNameIdentifier(element: M68kLocalLabel): PsiElement = element.firstChild
|
||||
|
||||
|
||||
// Symbol Definition
|
||||
|
||||
@JvmStatic
|
||||
fun getName(element: M68kSymbolDefinition): String? = element.firstChild.text
|
||||
|
||||
@JvmStatic
|
||||
fun setName(element: M68kSymbolDefinition, name: String): PsiElement {
|
||||
val nameNode = element.node.findChildByType(M68kTypes.SYMBOLDEF)
|
||||
if (nameNode != null) {
|
||||
val newSymbolDefinition = createSymbolDefinition(element.project, name)
|
||||
element.node.replaceChild(nameNode, newSymbolDefinition.firstChild.node)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getNameIdentifier(element: M68kSymbolDefinition): PsiElement = element.firstChild
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.patterns.ElementPattern
|
||||
import com.intellij.patterns.PlatformPatterns
|
||||
import com.intellij.patterns.StandardPatterns
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.refactoring.rename.RenameInputValidator
|
||||
import com.intellij.util.ProcessingContext
|
||||
import java.util.regex.Pattern
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
override fun isInputValid(newName: String, element: PsiElement, context: ProcessingContext): Boolean {
|
||||
return when (element) {
|
||||
is M68kGlobalLabel, is M68kSymbolDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
|
||||
is M68kLocalLabel -> LOCAL_LABEL_PATTERN.matcher(newName).matches()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SYMBOL_PATTERN = Pattern.compile("(\\p{Alpha}|_)(\\p{Alnum}|_)*")
|
||||
private val LOCAL_LABEL_PATTERN = Pattern.compile("(\\.(\\p{Alpha}|_)(\\p{Alnum}|_)*)|((\\p{Alpha}|_)(\\p{Alnum}|_)*\\$)")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
abstract class M68kSymbolDefinitionMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kSymbolDefinition {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
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.M68kGlobalLabel
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kRefExpr
|
||||
|
||||
class M68kReferenceContributor : PsiReferenceContributor() {
|
||||
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kRefExpr::class.java), object : PsiReferenceProvider() {
|
||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
|
||||
return emptyArray()
|
||||
}
|
||||
})
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kGlobalLabel::class.java), object : PsiReferenceProvider() {
|
||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
|
||||
return emptyArray()
|
||||
}
|
||||
})
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kLocalLabel::class.java), object : PsiReferenceProvider() {
|
||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
|
||||
return emptyArray()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package de.platon42.intellij.plugins.m68k.scanner;
|
||||
|
||||
import com.intellij.lang.cacheBuilder.DefaultWordsScanner;
|
||||
import com.intellij.lang.cacheBuilder.WordsScanner;
|
||||
import com.intellij.lang.findUsages.FindUsagesProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import de.platon42.intellij.plugins.m68k.lexer.M68kLexer;
|
||||
import de.platon42.intellij.plugins.m68k.lexer.M68kLexerPrefs;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kTypes;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class M68kFindUsagesProvider implements FindUsagesProvider {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WordsScanner getWordsScanner() {
|
||||
return new DefaultWordsScanner(new M68kLexer(new M68kLexerPrefs()), // FIXME Oh no! More Prefs!
|
||||
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.SYMBOL),
|
||||
TokenSet.create(M68kTypes.COMMENT),
|
||||
TokenSet.create(M68kTypes.STRINGLIT),
|
||||
TokenSet.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFindUsagesFor(@NotNull PsiElement psiElement) {
|
||||
return psiElement instanceof PsiNamedElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable @NonNls String getHelpId(@NotNull PsiElement psiElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nls @NotNull String getType(@NotNull PsiElement element) {
|
||||
if (element instanceof M68kGlobalLabel) {
|
||||
return "global label";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nls @NotNull String getDescriptiveName(@NotNull PsiElement element) {
|
||||
if (element instanceof M68kGlobalLabel) {
|
||||
return ((M68kGlobalLabel) element).getName();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nls @NotNull String getNodeText(@NotNull PsiElement element, boolean useFullName) {
|
||||
return getDescriptiveName(element);
|
||||
}
|
||||
}
|
||||
@@ -22,11 +22,12 @@ import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.
|
||||
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
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.PROGRAM_COUNTER
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SEPARATOR
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SPECIAL_REG
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.STRING
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLDEF
|
||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLREF
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import javax.swing.Icon
|
||||
|
||||
@@ -55,6 +56,7 @@ demo_init ; global label
|
||||
tst.w d1
|
||||
beq.s .skip
|
||||
PUSHM d0-d7/a0-a6 ; this is a macro call
|
||||
lea hello(pc),a1
|
||||
lea pd_ModViewTable(a4,d1.w),a0
|
||||
moveq.l #0,d0
|
||||
move.w #PIC_HEIGHT-1,d7
|
||||
@@ -65,6 +67,7 @@ demo_init ; global label
|
||||
|
||||
hello: dc.b 'Hello World!',10,0
|
||||
even
|
||||
dc.w *-hello ; length of string
|
||||
"""
|
||||
}
|
||||
|
||||
@@ -91,7 +94,7 @@ hello: dc.b 'Hello World!',10,0
|
||||
AttributesDescriptor("Comma (separator)", SEPARATOR),
|
||||
AttributesDescriptor("Colon", COLON),
|
||||
AttributesDescriptor("Symbol definition", SYMBOLDEF),
|
||||
AttributesDescriptor("Symbol reference", SYMBOL),
|
||||
AttributesDescriptor("Symbol reference", SYMBOLREF),
|
||||
AttributesDescriptor("Assembly mnemonic", MNEMONIC),
|
||||
AttributesDescriptor("Macro invocation", MACRO_CALL),
|
||||
AttributesDescriptor("Byte/short data width", DATA_WIDTH_BS),
|
||||
@@ -103,6 +106,7 @@ hello: dc.b 'Hello World!',10,0
|
||||
AttributesDescriptor("Numbers", NUMBER),
|
||||
AttributesDescriptor("Address registers", AREG),
|
||||
AttributesDescriptor("Data registers", DREG),
|
||||
AttributesDescriptor("Program counter", PROGRAM_COUNTER),
|
||||
AttributesDescriptor("Special registers", SPECIAL_REG),
|
||||
AttributesDescriptor("Comments", COMMENT),
|
||||
AttributesDescriptor("Bad characters", BAD_CHARACTER)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.platon42.intellij.plugins.m68k.syntax
|
||||
|
||||
import com.intellij.lang.BracePair
|
||||
import com.intellij.lang.PairedBraceMatcher
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
||||
|
||||
class M68kPairedBraceMatcher : PairedBraceMatcher {
|
||||
|
||||
companion object {
|
||||
val bracePairs = arrayOf(
|
||||
BracePair(M68kTypes.ROUND_L, M68kTypes.ROUND_R, false)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getPairs(): Array<BracePair> = bracePairs
|
||||
|
||||
override fun isPairedBracesAllowedBeforeType(lbraceType: IElementType, contextType: IElementType?) = true
|
||||
|
||||
override fun getCodeConstructStart(file: PsiFile, openingBraceOffset: Int) = openingBraceOffset
|
||||
}
|
||||
@@ -26,10 +26,11 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
|
||||
return when (tokenType) {
|
||||
M68kTypes.SEPARATOR -> arrayOf(SEPARATOR)
|
||||
M68kTypes.COLON -> arrayOf(COLON)
|
||||
M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.GLOBAL_LABEL -> arrayOf(GLOBAL_LABEL)
|
||||
M68kTypes.LOCAL_LABEL_DEF, M68kTypes.LOCAL_LABEL -> arrayOf(LOCAL_LABEL)
|
||||
M68kTypes.GLOBAL_LABEL_DEF -> arrayOf(GLOBAL_LABEL)
|
||||
M68kTypes.LOCAL_LABEL_DEF -> arrayOf(LOCAL_LABEL)
|
||||
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOLDEF)
|
||||
M68kTypes.SYMBOL -> arrayOf(SYMBOL)
|
||||
M68kTypes.SYMBOL -> arrayOf(SYMBOLREF)
|
||||
M68kTypes.CURRENT_PC_SYMBOL, M68kTypes.PC -> arrayOf(PROGRAM_COUNTER)
|
||||
M68kTypes.MNEMONIC -> arrayOf(MNEMONIC)
|
||||
M68kTypes.MACRO_INVOKATION -> arrayOf(MACRO_CALL)
|
||||
M68kTypes.DATA_DIRECTIVE -> arrayOf(DATA_PREPROCESSOR)
|
||||
@@ -37,9 +38,9 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
|
||||
M68kTypes.OPSIZE_BS -> arrayOf(DATA_WIDTH_BS)
|
||||
M68kTypes.OPSIZE_W -> arrayOf(DATA_WIDTH_W)
|
||||
M68kTypes.OPSIZE_L -> arrayOf(DATA_WIDTH_L)
|
||||
M68kTypes.ADDRESS_REGISTER, M68kTypes.AREG -> arrayOf(AREG)
|
||||
M68kTypes.DATA_REGISTER, M68kTypes.DREG -> arrayOf(DREG)
|
||||
M68kTypes.SPECIAL_REGISTER, M68kTypes.REG_USP, M68kTypes.REG_SR, M68kTypes.REG_CCR -> arrayOf(SPECIAL_REG)
|
||||
M68kTypes.AREG -> arrayOf(AREG)
|
||||
M68kTypes.DREG -> arrayOf(DREG)
|
||||
M68kTypes.REG_USP, M68kTypes.REG_SR, M68kTypes.REG_CCR, M68kTypes.REG_VBR -> arrayOf(SPECIAL_REG)
|
||||
M68kTypes.COMMENT -> arrayOf(COMMENT)
|
||||
M68kTypes.DECIMAL, M68kTypes.HEXADECIMAL, M68kTypes.OCTAL -> arrayOf(NUMBER)
|
||||
M68kTypes.STRINGLIT -> arrayOf(STRING)
|
||||
@@ -54,7 +55,8 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
|
||||
val SEPARATOR = TextAttributesKey.createTextAttributesKey("M68K_SEPARATOR", DefaultLanguageHighlighterColors.COMMA)
|
||||
val COLON = TextAttributesKey.createTextAttributesKey("M68K_COLON", DefaultLanguageHighlighterColors.DOT)
|
||||
val SYMBOLDEF = TextAttributesKey.createTextAttributesKey("M68K_SYMBOLDEF", DefaultLanguageHighlighterColors.STATIC_FIELD)
|
||||
val SYMBOL = TextAttributesKey.createTextAttributesKey("M68K_SYMBOL", DefaultLanguageHighlighterColors.IDENTIFIER)
|
||||
val SYMBOLREF = TextAttributesKey.createTextAttributesKey("M68K_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
|
||||
val PROGRAM_COUNTER = TextAttributesKey.createTextAttributesKey("M68K_PROGRAM_COUNTER", DefaultLanguageHighlighterColors.IDENTIFIER)
|
||||
val MNEMONIC = TextAttributesKey.createTextAttributesKey("M68K_MNEMONIC", DefaultLanguageHighlighterColors.FUNCTION_CALL)
|
||||
val MACRO_CALL = TextAttributesKey.createTextAttributesKey("M68K_MACRO_CALL", DefaultLanguageHighlighterColors.STATIC_METHOD)
|
||||
val DATA_WIDTH_BS = TextAttributesKey.createTextAttributesKey("M68K_DATA_WIDTH_BS", DefaultLanguageHighlighterColors.DOT)
|
||||
|
||||
Reference in New Issue
Block a user