Reworked label handling: Colons are no longer part of the label definition itself. Added PsiNamedElement for Labels.
This commit is contained in:
@@ -25,4 +25,9 @@ object LexerUtil {
|
||||
fun pushbackAssignment(text: CharSequence): Int {
|
||||
return text.length - text.indexOfAny(ASSIGNMENT_SEPARATORS)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun pushbackLabelColons(text: CharSequence): Int {
|
||||
return text.count { it == ':' }
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,8 @@ HASH_COMMENT=([#;*].*+)
|
||||
{WHITE_SPACE} { yybegin(NOSOL); return WHITE_SPACE; }
|
||||
{EOL} { return WHITE_SPACE; }
|
||||
{ASSIGNMENT} { yybegin(ASSIGNMENT); yypushback(pushbackAssignment(yytext())); return SYMBOLDEF; }
|
||||
{LOCAL_LABEL} { yybegin(INSTRPART); return LOCAL_LABEL_DEF; }
|
||||
{GLOBAL_LABEL} { yybegin(INSTRPART); return GLOBAL_LABEL_DEF; }
|
||||
{LOCAL_LABEL} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
|
||||
{GLOBAL_LABEL} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
|
||||
|
||||
{HASH_COMMENT} { return COMMENT; }
|
||||
}
|
||||
@@ -66,8 +66,8 @@ HASH_COMMENT=([#;*].*+)
|
||||
<NOSOL> {
|
||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
||||
{EOL} { yybegin(YYINITIAL); return WHITE_SPACE; }
|
||||
{LOCAL_LABEL_WC} { yybegin(INSTRPART); return LOCAL_LABEL_DEF; }
|
||||
{GLOBAL_LABEL_WC} { yybegin(INSTRPART); return GLOBAL_LABEL_DEF; }
|
||||
{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; }
|
||||
@@ -84,6 +84,8 @@ HASH_COMMENT=([#;*].*+)
|
||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
||||
{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; }
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
parserUtilClass="de.platon42.intellij.plugins.m68k.parser.M68kParserUtilBase"
|
||||
|
||||
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
|
||||
|
||||
psiClassPrefix="M68k"
|
||||
psiImplClassSuffix="Impl"
|
||||
psiPackage="de.platon42.intellij.plugins.m68k.psi"
|
||||
psiImplPackage="de.platon42.intellij.plugins.m68k.psi.impl"
|
||||
psiImplUtilClass="de.platon42.intellij.plugins.m68k.psi.M68kPsiImplUtil"
|
||||
|
||||
// elementTypeFactory="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition.createType"
|
||||
// tokenTypeFactory="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition.createTokenType"
|
||||
@@ -134,13 +134,27 @@ private LabelOnly ::= Label
|
||||
private LabelWithInstruction ::= Label Instruction
|
||||
private InstructionOnly ::= Instruction
|
||||
|
||||
LocalLabel ::= LOCAL_LABEL_DEF {extends=Label}
|
||||
GlobalLabel ::= GLOBAL_LABEL_DEF {extends=Label}
|
||||
LocalLabel ::= LOCAL_LABEL_DEF COLON? {
|
||||
name = "local label"
|
||||
extends = Label
|
||||
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
|
||||
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kLocalLabelMixin"
|
||||
methods = [getName setName getNameIdentifier]
|
||||
}
|
||||
|
||||
GlobalLabel ::= GLOBAL_LABEL_DEF COLON* {
|
||||
name = "global label"
|
||||
extends = Label
|
||||
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
|
||||
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabelMixin"
|
||||
methods = [getName setName getNameIdentifier]
|
||||
}
|
||||
|
||||
Label ::= LocalLabel | GlobalLabel
|
||||
|
||||
OperandSize ::= (OPSIZE_BS|OPSIZE_W|OPSIZE_L)
|
||||
AddressSize ::= (OPSIZE_W|OPSIZE_L)
|
||||
DataWidth ::= (OPSIZE_W|OPSIZE_L)
|
||||
OperandSize ::= (OPSIZE_BS|OPSIZE_W|OPSIZE_L) { name = ".s|.b|.w|.l" }
|
||||
AddressSize ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
|
||||
DataWidth ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
|
||||
|
||||
AsmOp ::= MNEMONIC OperandSize?
|
||||
|
||||
@@ -159,13 +173,24 @@ private PreprocessorOperand ::= expr
|
||||
|
||||
private PlainOperands ::= STRINGLIT (SEPARATOR STRINGLIT)*
|
||||
|
||||
DataRegister ::= DREG {extends=Register}
|
||||
AddressRegister ::= AREG {extends=Register}
|
||||
SpecialRegister ::= REG_CCR | REG_SR | REG_USP | REG_VBR {extends=Register}
|
||||
DataRegister ::= DREG {
|
||||
name = "data register"
|
||||
extends = Register
|
||||
}
|
||||
|
||||
AddressRegister ::= AREG {
|
||||
name = "address register"
|
||||
extends = Register
|
||||
}
|
||||
|
||||
SpecialRegister ::= REG_CCR | REG_SR | REG_USP | REG_VBR {
|
||||
name = "special register"
|
||||
extends = Register
|
||||
}
|
||||
|
||||
Register ::= DataRegister | AddressRegister | SpecialRegister
|
||||
|
||||
private DataOrAddressRegister ::= DataRegister | AddressRegister
|
||||
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
|
||||
|
||||
AddressingMode ::= ImmediateData
|
||||
| AddressRegisterIndirectPreDecAddressingMode
|
||||
@@ -202,7 +227,10 @@ ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? P
|
||||
AbsoluteAddressAddressingMode ::= expr AddressSize? !ROUND_L
|
||||
private RegisterRange ::= (DataOrAddressRegister OP_MINUS DataOrAddressRegister)
|
||||
RegisterListAddressingMode ::= (DataOrAddressRegister|RegisterRange) ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
|
||||
ImmediateData ::= HASH expr {extends=AddressingMode}
|
||||
ImmediateData ::= HASH expr {
|
||||
name = "immediate data"
|
||||
extends = AddressingMode
|
||||
}
|
||||
|
||||
expr ::= binary_logical_or_expr
|
||||
| binary_logical_and_expr
|
||||
@@ -215,7 +243,7 @@ expr ::= binary_logical_or_expr
|
||||
| binary_bitwise_and_expr
|
||||
| binary_shift_group
|
||||
| unary_group
|
||||
| primary_group
|
||||
| primary_group { name = "expression" }
|
||||
// | macrobrace_expr
|
||||
|
||||
// private rules to define operators with the same priority
|
||||
@@ -247,11 +275,13 @@ binary_cmp_gt_expr ::= expr OP_CMP_GT expr
|
||||
binary_cmp_ge_expr ::= expr OP_CMP_GT_EQ expr
|
||||
binary_cmp_eq_expr ::= expr OP_CMP_EQ expr
|
||||
binary_cmp_ne_expr ::= expr OP_CMP_NOT_EQ expr
|
||||
//binary_cmp_ne_expr ::= expr (OP_CMP_NOT_EQ|OP_CMP_NOT_EQ2) expr
|
||||
binary_logical_and_expr ::= expr OP_LOGICAL_AND expr
|
||||
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
|
||||
literal_expr ::= BINARY|DECIMAL|HEXADECIMAL|OCTAL|STRINGLIT
|
||||
literal_expr ::= BINARY|DECIMAL|HEXADECIMAL|OCTAL|STRINGLIT {
|
||||
implements = "com.intellij.psi.PsiLiteralValue"
|
||||
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kLiteralExprMixin"
|
||||
}
|
||||
|
||||
@@ -1,22 +1,7 @@
|
||||
package de.platon42.intellij.plugins.m68k.parser;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.parser.GeneratedParserUtilBase;
|
||||
|
||||
import static de.platon42.intellij.plugins.m68k.psi.M68kTypes.SYMBOL;
|
||||
|
||||
public class M68kParserUtilBase extends GeneratedParserUtilBase {
|
||||
|
||||
public static boolean parseMacroCallOrAsmInstruction(PsiBuilder b, int level) {
|
||||
boolean r = false;
|
||||
if (!nextTokenIs(b, SYMBOL)) return M68kParser.MacroCall(b, level);
|
||||
|
||||
PsiBuilder.Marker m = enter_section_(b);
|
||||
|
||||
//M68kMnemonics.INSTANCE.getMnemonics().stream().findFirst() nextTokenIs(, )
|
||||
r = M68kParser.AsmInstruction(b, level);
|
||||
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import de.platon42.intellij.plugins.m68k.M68kFileType.Companion.INSTANCE
|
||||
|
||||
object M68kElementFactory {
|
||||
|
||||
fun createGlobalLabel(project: Project, label: String): M68kGlobalLabel {
|
||||
val file = createFile(project, label)
|
||||
return PsiTreeUtil.findChildOfType(file, M68kGlobalLabel::class.java)!!
|
||||
}
|
||||
|
||||
fun createLocalLabel(project: Project, label: String): M68kLocalLabel {
|
||||
val file = createFile(project, label)
|
||||
return PsiTreeUtil.findChildOfType(file, M68kLocalLabel::class.java)!!
|
||||
}
|
||||
|
||||
fun createFile(project: Project, content: String): M68kFile {
|
||||
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
abstract class M68kGlobalLabelMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kGlobalLabel {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
abstract class M68kLiteralExprMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kLiteralExpr {
|
||||
override fun getValue(): Any? {
|
||||
val childNode = firstChild.node
|
||||
when (childNode.elementType) {
|
||||
M68kTypes.STRINGLIT -> {
|
||||
return text.run {
|
||||
when {
|
||||
startsWith('"') -> removeSurrounding("\"")
|
||||
startsWith('\'') -> removeSurrounding("'")
|
||||
startsWith('<') -> removeSurrounding(">")
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
}
|
||||
M68kTypes.DECIMAL -> {
|
||||
try {
|
||||
return childNode.text.toInt()
|
||||
} catch (ex: NumberFormatException) {
|
||||
// ignore and fall through
|
||||
}
|
||||
}
|
||||
M68kTypes.HEXADECIMAL -> {
|
||||
try {
|
||||
return childNode.text.substring(1).toInt(16)
|
||||
} catch (ex: NumberFormatException) {
|
||||
// ignore and fall through
|
||||
}
|
||||
}
|
||||
M68kTypes.BINARY -> {
|
||||
try {
|
||||
return childNode.text.substring(1).toInt(2)
|
||||
} catch (ex: NumberFormatException) {
|
||||
// ignore and fall through
|
||||
}
|
||||
}
|
||||
M68kTypes.OCTAL -> {
|
||||
try {
|
||||
return childNode.text.substring(1).toInt(8)
|
||||
} catch (ex: NumberFormatException) {
|
||||
// ignore and fall through
|
||||
}
|
||||
}
|
||||
}
|
||||
return text
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
abstract class M68kLocalLabelMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kLocalLabel {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
|
||||
public interface M68kNamedElement extends PsiNameIdentifierOwner {
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
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
|
||||
|
||||
object M68kPsiImplUtil {
|
||||
|
||||
@JvmStatic
|
||||
fun getName(element: M68kGlobalLabel): String? = element.firstChild.text
|
||||
|
||||
@JvmStatic
|
||||
fun setName(element: M68kGlobalLabel, name: String): PsiElement {
|
||||
val nameNode = element.node.findChildByType(M68kTypes.GLOBAL_LABEL_DEF)
|
||||
if (nameNode != null) {
|
||||
val newGlobalLabel = createGlobalLabel(element.project, name)
|
||||
element.node.replaceChild(nameNode, newGlobalLabel.firstChild.node)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getNameIdentifier(element: M68kGlobalLabel): PsiElement = element.firstChild
|
||||
|
||||
@JvmStatic
|
||||
fun getName(element: M68kLocalLabel): String? = element.firstChild.text
|
||||
|
||||
@JvmStatic
|
||||
fun setName(element: M68kLocalLabel, name: String): PsiElement {
|
||||
if (!(name.startsWith(".") || name.endsWith("$"))) throw IncorrectOperationException("local label must start with '.' or end with '$'")
|
||||
val nameNode = element.node.findChildByType(M68kTypes.LOCAL_LABEL_DEF)
|
||||
if (nameNode != null) {
|
||||
val newLocalLabel = createLocalLabel(element.project, name)
|
||||
element.node.replaceChild(nameNode, newLocalLabel.firstChild.node)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getNameIdentifier(element: M68kLocalLabel): PsiElement = element.firstChild
|
||||
}
|
||||
Reference in New Issue
Block a user