避免词法分析规则互相打断?

时间:2014-12-24 14:17:14

标签: regex antlr4

所以,基本上我的MIPS汇编程序有一些前缀。我使用" 0x"和" $"对于十六进制数字,"#"对于十进制数和"%"对于二进制数。如何构建汇编程序的典型方法。

现在,前缀" 0x"有一点问题。使用匹配" TEXT"的词法分析器规则中断变量定义的规则。例:

[Var1] : 0x2554D

而Var1是TEXT。

我的规则:

mips32code  : instruction+
            ;

instruction : OPCODE_ITYPE rt COMMA rs COMMA prefix imm # ITypeInstruction
            | '[' TEXT ']' ':' prefix imm               # VariableDefinition
            ;

imm         : instruction   # immformat
            | INT           # immvalue
            ;

prefix      : instruction   # prefixinst
            | VALUE         # prefixval
            ;

rs          : instruction   # rsexpr
            | REG           # rsreg
            ;

rt          : instruction   # rtexpr
            | REG           # rtreg
            ;

/* Immediate-Value Lexer */

INT         : [0-9A-Fa-f]+
            ;

/* Text for variable definition and label definition names. */
TEXT        : [a-zA-Z0-9]+
            ;

/* Prefix */
VALUE       : ('$'|'0x'|'#'|'%') 
            ;

REG
    : [rR] '0'
    | [aA] [tT]
    | [vV] [01]
    | [aA] [0-3]
    | [tT] [0-9]
    | [sS] [0-8]
    | [kK] [01]
    | [gG] [pP]
    | [sS] [pP]
    | [fF] [pP]
    | [rR] [aA]
    ;

COMMA   : ','
        ;

OPCODE_ITYPE
      : [aA] [dD] [dD] [iI] // ADDI
      | [dD] [aA] [dD] [dD] [iI] // DADDI
      | [dD] [aA] [dD] [dD] [iI] [uU] // DADDIU
      | [aA] [dD] [dD] [iI] [uU] // ADDIU
      | [oO] [rR] [iI] // ORI
      | [xX] [oO] [rR] [iI] // XORI
      | [sS] [lL] [tT] [iI] // SLTI
      | [sS] [lL] [tT] [iI] [uU] // SLTIU
      | [aA] [nN] [dD] [iI] // ANDI
      ;

因此,上述方法无法正常工作。它成功地将上面的输入与Var1匹配,但是这些说明如下:

ADDIU T0, T1, 0x2544

不要工作,因为" 0x"前缀以某种方式中断TEXT词法分析器规则。我收到的错误是:

line 1:14 no viable alternative input 'ADDIU T0, T1, 0x2544'

我尝试过删除" +"来自TEXT。显然,这似乎有效,但随后变量定义不再正确匹配,只匹配一个字母。我尝试了解决方法,这些都以错误和混乱结束。所以,我认为我可以在这里得到一些帮助。

2 个答案:

答案 0 :(得分:1)

每当2个(或更多)词法分析器规则匹配相同的文本时,首先定义的词法优先级将获得优先权。这意味着0x将被匹配为TEXT令牌,因为该令牌在VALUE令牌之前定义。

因此,您还需要在OPCODE_ITYPE之前移动定义关键字(TEXT s)的规则,甚至是INT规则。

答案 1 :(得分:1)

要处理文本和值之间的重叠,请使用模式提供隔离。这里很容易做到,因为括号作为明确的警卫操作。

LBRAKCET : '[' -> pushMode(text) ;

mode text;
TEXT     : [a-zA-Z0-9]+ ;
RBRACKET : ']' -> popMode ;
BAD_TEXT : . ;

添加BAD_TEXT作为捕获 - 为您提供了在解析器中处理一些明显错误('var_1')的选项。注意,模式仅在split lexer / parser语法中可用。此外,请勿在解析器规则中使用字符文字,特别是在拆分语法中。