Made AsmOperands private. Added support for generic assembler directives. Bugfixes. Added more Tests.

This commit is contained in:
2021-07-15 21:00:12 +02:00
parent f482948abe
commit aa14984a8e
47 changed files with 1142 additions and 1110 deletions
@@ -0,0 +1,46 @@
package de.platon42.intellij.plugins.m68k.asm
object AssemblerDirectives {
val dataDirectives: Set<String> = setOf(
"section", "pushsection", "popsection",
"bss", "bss_c", "bss_f",
"data", "data_c", "data_f",
"text", "cseg", "code", "code_c", "code_f",
"offset",
"abs",
"db", "dw", "dl",
"dr.b", "dr.w", "dr.l",
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
"blk.b", "blk.w", "blk.l",
"ds", "ds.b", "ds.w", "ds.l",
"align", "even", "odd", "cnop", "long", "dphrase", "phrase", "qphrase",
"cargs", "comm", "comment",
"rsset", "clrfo", "clrso", "setfo", "setso"
)
val otherDirective: Set<String> = setOf(
"if",
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
"ifd", "ifnd", "ifmacrod", "ifmacrond",
//"iif" // not supported
"else", "endif", "endc",
"macro", "exitm", "mexit",
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
"incdir", "include", "incbin", "output",
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
"org",
"assert", "fail", "print", "printt", "printv", "echo",
"inline", "einline",
"rem", "erem"
)
}
@@ -1,5 +1,6 @@
package de.platon42.intellij.plugins.m68k.lexer
import de.platon42.intellij.plugins.m68k.asm.AssemblerDirectives
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.mnemonics
object LexerUtil {
@@ -9,12 +10,23 @@ object LexerUtil {
@JvmStatic
fun isAsmMnemonic(text: CharSequence) = mnemonics.contains(text.toString().lowercase())
@JvmStatic
fun isAsmMnemonicWithSize(text: CharSequence) = text.contains('.')
&& text.dropLast(1).endsWith('.')
&& mnemonics.contains(text.dropLast(2).toString().lowercase())
@JvmStatic
fun isDataDirective(text: CharSequence) = AssemblerDirectives.dataDirectives.contains(text.toString().lowercase())
@JvmStatic
fun isOtherDirective(text: CharSequence) = AssemblerDirectives.otherDirective.contains(text.toString().lowercase())
@JvmStatic
fun pushbackAssignment(text: CharSequence): Int {
val spacePos = text.indexOfAny(ASSIGNMENT_SEPARATORS)
if (spacePos > -1) {
return text.length - spacePos
}
return text.length - 1 - text.indexOf('=')
return text.length - text.indexOf('=')
}
}
@@ -24,12 +24,8 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
%unicode
%ignorecase
EOL=\R
WHITE_SPACE=\s+
EOL=\R
WHITE_SPACE=\p{Blank}+
IF_TAG=(if[:letter:]*)
AREG=((a[0-7])|sp)
DREG=(d[0-7])
ASSIGNMENT=(([:letter:]|_)(([:letter:]|[:digit:])|_)*((\p{Blank}+equ\p{Blank}+)|(\p{Blank}+set\p{Blank}+)|\p{Blank}*=\p{Blank}*))
@@ -37,19 +33,21 @@ LOCAL_LABEL=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:?)|(([:letter:]|_)(([:l
LOCAL_LABEL_WC=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:)|(([:letter:]|_)(([:letter:]|[:digit:])|_)*\$:)
GLOBAL_LABEL=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?:?)
GLOBAL_LABEL_WC=(([:letter:]|_)(([:letter:]|[:digit:])|_)*::?)
MNEMONIC=(([:letter:])+)
//MNEMONIC=(([:letter:])+)
SYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:])|[_\$])*)
DIRECTIVE_KEYWORD=(([:letter:])(([:letter:]))*)(\..)?
OPSIZE_BS=(\.[bs])
OPSIZE_WL=(\.[wl])
BINARY=(%[01]+)
HEXADECIMAL=(\$[0-9a-f]+)
OCTAL=(@[0-7]+)
DECIMAL=([0-9]+)
STRINGLIT=(`([^`\\]|\\.)*`|'([^'\\]|\\.)*'|\"([^\"\\]|\\.)*\")|<([^`\\]|\\.)*>
STRINGLIT=(`([^`\\]|\\.)*`|'([^'\\]|\\.)*'|\"([^\"\\]|\\.)*\")
PLAINPARAM=(`([^`\\]|\\.)*`|'([^'\\]|\\.)*'|\"([^\"\\]|\\.)*\")|<([^>\\]|\\.)*>|([^,;\p{Blank}\r\n])+ // why does \R not work, I have no idea
COMMENT=([;].*+)
HASH_COMMENT=([#;*].*+)
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASSIGNMENT,WAITEOL
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASSIGNMENT,EXPR,MACROCALL,WAITEOL
%%
<YYINITIAL> {
@@ -67,9 +65,15 @@ HASH_COMMENT=([#;*].*+)
{EOL} { yybegin(YYINITIAL); return WHITE_SPACE; }
{LOCAL_LABEL_WC} { yybegin(INSTRPART); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL_WC} { yybegin(INSTRPART); return GLOBAL_LABEL_DEF; }
{MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
{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(INSTRPART); return SYMBOL;
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
{SYMBOL} { yybegin(INSTRPART); return SYMBOL; }
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
}
@@ -77,23 +81,14 @@ HASH_COMMENT=([#;*].*+)
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
"even" { return EVEN_TAG; }
"cnop" { return CNOP_TAG; }
"section" { return SECTION_TAG; }
"include" { return INCLUDE_TAG; }
"incbin" { return INCBIN_TAG; }
"else" { return ELSE_TAG; }
"endc" { return ENDC_TAG; }
"macro" { return MACRO_TAG; }
"endm" { return MACRO_END_TAG; }
"rept" { return REPT_TAG; }
"endr" { return REPT_END_TAG; }
"fail" { return FAIL_TAG; }
"end" { return END_TAG; }
{IF_TAG} { return IF_TAG; }
{MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
{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(INSTRPART); return SYMBOL;
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
{SYMBOL} { return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
@@ -109,7 +104,29 @@ HASH_COMMENT=([#;*].*+)
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<MACROCALL> {
{WHITE_SPACE} { return WHITE_SPACE; } // FIXME space optionally introduces comment
{EOL} { yybegin(YYINITIAL); return EOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
"," { return SEPARATOR; }
{PLAINPARAM} { return SYMBOL; }
}
<ASSIGNMENT> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
"equ"|"set" { yybegin(EXPR); return EQU; }
"=" { yybegin(EXPR); return OP_ASSIGN; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<EXPR> {
{WHITE_SPACE} { return WHITE_SPACE; } // FIXME space optionally introduces comment
{EOL} { yybegin(YYINITIAL); return EOL; }
@@ -119,9 +136,6 @@ HASH_COMMENT=([#;*].*+)
{DECIMAL} { return DECIMAL; }
{STRINGLIT} { return STRINGLIT; }
"equ" { return EQU; }
"set" { return EQU; }
"<<" { return OP_AR_SHIFT_L; }
">>" { return OP_AR_SHIFT_R; }
"&&" { return OP_LOGICAL_AND; }
@@ -140,6 +154,7 @@ HASH_COMMENT=([#;*].*+)
// ";" { return SEMICOLON; }
// "[" { return SQUARE_L; }
// "]" { return SQUARE_R; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { return ROUND_R; }
// "." { return DOT; }
@@ -144,21 +144,7 @@ DataWidth ::= OPSIZE_WL
AsmOp ::= MNEMONIC OperandSize?
PreprocessorDirective ::= SYMBOL?
(END_TAG
| EVEN_TAG
| CNOP_TAG
| SECTION_TAG
| INCLUDE_TAG
| INCBIN_TAG
| IF_TAG
| ELSE_TAG
| ENDC_TAG
| MACRO_TAG
| MACRO_END_TAG
| REPT_TAG
| REPT_END_TAG
| FAIL_TAG)
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
PreprocessorOperands?
MacroCall ::= SYMBOL PreprocessorOperands?
@@ -166,7 +152,7 @@ AsmInstruction ::= AsmOp AsmOperands?
private Instruction ::= AsmInstruction | MacroCall
//external Instruction ::= parseMacroCallOrAsmInstruction
AsmOperands ::= AddressingMode (SEPARATOR AddressingMode)*
private AsmOperands ::= AddressingMode (SEPARATOR AddressingMode)?
private PreprocessorOperands ::= PreprocessorOperand (SEPARATOR PreprocessorOperand)*