下面是解析输入汇编文件的语法的简化版本。我的语法中的一切都很好,直到我使用具有 3 个字符的标签(即与我的语法中的操作码长度相同),所以我假设 Antlr 将其匹配为操作码而不是标签,但我怎么说“在这个位置,它应该是一个标签,而不是一个操作码”?
试用输入:
set a, label1
set b, abc
标准装备的输出给出:
line 2:5 missing EOF at ','
(OP_BAS set a (REF label1)) (OP_SPE set b)
当我通过 ANTLRWorks 进行单步调试时,我看到它从指令规则 2 开始,但在引用“abc”时跳转到规则 3,然后在“,”处失败。
我可以通过大量的左分解来解决这个问题,但这使得语法变得非常难以阅读。我试图在可读性和功能之间找到一个折衷方案(没有太多的输入,全局回溯会影响性能)。
grammar TestLabel;
options {
language = Java;
output = AST;
ASTLabelType = CommonTree;
backtrack = true;
}
tokens {
NEGATION;
OP_BAS;
OP_SPE;
OP_CMD;
REF;
DEF;
}
program
: instruction* EOF!
;
instruction
: LABELDEF -> ^(DEF LABELDEF)
| OPCODE dst_op ',' src_op -> ^(OP_BAS OPCODE dst_op src_op)
| OPCODE src_op -> ^(OP_SPE OPCODE src_op)
| OPCODE -> ^(OP_CMD OPCODE)
;
operand
: REG
| LABEL -> ^(REF LABEL)
| expr
;
dst_op
: PUSH
| operand
;
src_op
: POP
| operand
;
term
: '('! expr ')'!
| literal
;
unary
: ('+'! | negation^ )* term
;
negation
: '-' -> NEGATION
;
mult
: unary ( ( '*'^ | '/'^ ) unary )*
;
expr
: mult ( ( '+'^ | '-'^ ) mult )*
;
literal
: number
| CHAR
;
number
: HEX
| BIN
| DECIMAL
;
REG: ('A'..'C'|'I'..'J'|'X'..'Z'|'a'..'c'|'i'..'j'|'x'..'z') ;
OPCODE: LETTER LETTER LETTER;
HEX: '0x' ( 'a'..'f' | 'A'..'F' | DIGIT )+ ;
BIN: '0b' ('0'|'1')+;
DECIMAL: DIGIT+ ;
LABEL: ( '.' | LETTER | DIGIT | '_' )+ ;
LABELDEF: ':' ( '.' | LETTER | DIGIT | '_' )+ {setText(getText().substring(1));} ;
STRING: '\"' .* '\"' {setText(getText().substring(1, getText().length()-1));} ;
CHAR: '\'' . '\'' {setText(getText().substring(1, 2));} ;
WS: (' ' | '\n' | '\r' | '\t' | '\f')+ { $channel = HIDDEN; } ;
fragment LETTER: ('a'..'z'|'A'..'Z') ;
fragment DIGIT: '0'..'9' ;
fragment PUSH: ('P'|'p')('U'|'u')('S'|'s')('H'|'h');
fragment POP: ('P'|'p')('O'|'o')('P'|'p');
最佳答案
解析器对词法分析器生成的标记没有影响。所以,输入"abc"
将始终被标记为 OPCODE
,无论解析器尝试匹配什么。
你可以做的是创建一个 label
与 LABEL
匹配的解析器规则或OPCODE
然后使用这个label
统治你的operand
规则:
label
: LABEL
| OPCODE
;
operand
: REG
| label -> ^(REF label)
| expr
;
为您的示例输入生成以下 AST:
这只会匹配 OPCODE
,但不会改变 token 的类型。如果您也希望更改类型,请在规则中添加一些自定义代码,将其更改为类型 LABEL
:
label
: LABEL
| t=OPCODE {$t.setType(LABEL);}
;
关于parsing - Antlr解析匹配固定字符串长度而不是规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10570830/