2
下面是解析輸入程序集文件的語法的簡化版本。我的語法中的一切都很好,直到我使用具有3個字符(即與我的語法中的OPCODE相同的長度)的標籤時,所以我假設Antlr將其作爲OPCODE而不是LABEL匹配,但我怎麼說「in這個位置,它應該是一個LABEL,而不是一個操作碼「?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');
優秀再次巴特,謝謝。我確實想知道什麼時候打到與引用不同的寄存器,所以我沒有使用它的片段。在我寫這個問題的時候,我想過要創建一個像你所建議的規則,但它感覺就像是解決了解析器已經決定3個字母字符串必須始終是'OPCODE'的解決方案。我喜歡你添加到自定義代碼,我以前沒有見過,非常有用。再次感謝。 –
沒問題@MarkFisher。 –