ANTLR 重用令牌的子集
ANTLR reuse subsets of tokens
在我的 ANTLR 语法中我有一组操作(OP):
- OP: 'I1', 'I2'.....'I9', 'I10' (一组TOKENS);
每当我找到令牌时:
- CASE : 有效操作是 'I1','I2','I3' (move1);
- SWITCH : 有效操作是 'I2','I4','I5' (move2);
其余的操作被其他指令使用。
当然在我的 Lexer 中我不能将两个标记定义为:
OP_MOVE1 : 'I1' | 'I2' | 'I3';
OP_MOVE2 : 'I2' | 'I4' | 'I5';
因为我会得到::
OP_MOVE2 值无法访问。 I2 总是被 token OP_MOVE1
重叠
因此,假设事务不仅仅是从 I1 到 I10,而是从 I1 到 I5000。
一个可能的解决方案可能是:
LEXER.G4
lexer grammar LexerComment;
CASE : 'CASE' -> pushMode(CASE_MODE);
SWITCH : 'SWITCH' -> pushMode(CASE_SWITCH);
WS : [ \t] -> skip ;
EOL : [\r\n]+;
// ------------ Everything INSIDE a CASE ------------
mode CASE_MODE;
CASE_MODE_MOVE1 : 'I1' | 'I2' | 'I3';
CASE_MODE_WS : [ \t] -> channel(HIDDEN) ;
CASE_MODE_EOL : EOL -> type(EOL),popMode;
// ------------ Everything INSIDE a SWITCH ------------
mode CASE_SWITCH;
CASE_SWITCH_MOVE2: 'I2' | 'I4' | 'I5';
CASE_SWITCH_WS : [ \t] -> channel(HIDDEN) ;
CASE_SWITCHT_EOL : EOL -> type(EOL),popMode;
解析器.g4:
parser grammar ParserComment;
options {
tokenVocab = LexerComment;
}
prog : (line? EOL)+;
line : instruction;
instruction: CASE CASE_MODE_MOVE1
|SWITCH CASE_SWITCH_MOVE2;
输入文件:
CASE I1
CASE I2
CASE I3
SWITCH I2
SWITCH I4
SWITCH I5
虽然我对解决方案不满意,但语法似乎工作正常,因为它需要大量代码,每种情况 1 种模式,以及模式中常见标记的重复。
还因为如果我想识别,除了 CASE 和 SWITCH,以 MOVE1 OR MOVE2 开头的行为:
instruction: CASE CASE_MODE_MOVE1
|SWITCH CASE_SWITCH_MOVE2
| MOVE1 ;
我还没有找到解决问题的最佳方案:
- 我不能重复使用之前的MOVE1 (CASE_MODE_MOVE1);
- 我无法定义新模式。
有没有办法正确处理类似的情况?
给定一组令牌,我想要一个可以根据上下文使用的子集。
可能试图避免将每个操作都定义为基本令牌:
fragment I1: 'I1';
fragment I2: 'I2';
etc
编辑:
在我的语法中,相等的 TOKEN 可以有不同的含义。
例如,对于以下语法,TOKEN I1 具有不同的含义。
解析器:
parser grammar ParserComment;
options {
tokenVocab = LexerComment;
}
prog : (line? EOL)+;
line : instruction;
instruction: CONTEXT case_instruction;
case_instruction
: I1
| I2
| I3
;
词法分析器:
lexer grammar LexerComment;
// I1 IS A CONTEXT
CONTEXT: I1 | CASE;
CASE : 'CASE';
SWITCH : 'SWITCH';
//OPERATIONS
I1 : 'I1';
I2 : 'I2';
I3 : 'I3';
I4 : 'I4';
I5 : 'I5';
WS : [ \t] -> skip ;
EOL : [\r\n]+;
尽管名称相同,但 I1 具有两个完全不同的含义(CONTEXT 和 OP)。我想承认这两种情况并避免有一个共同的 I1:
prog : (line? EOL)+;
line : instruction;
instruction: context case_instruction;
context: I1 | CASE;
case_instruction
: I1
| I2
| I3
;
出于这个原因,我曾尝试在词法分析器中使用模式进行管理。
IMO,你不应该让词法分析器决定何时应该创建某些标记。让解析器决定令牌在特定位置何时正确。
像这样:
prog
: instruction* EOF
;
instruction
: CASE case_instruction EOL
| SWITCH switch_instruction EOL
| EOL
;
case_instruction
: I1
| I2
| I3
;
switch_instruction
: I2
| I4
| I5
;
CASE : 'CASE';
SWITCH : 'SWITCH';
I1 : 'I1';
I2 : 'I2';
I3 : 'I3';
I4 : 'I4';
I5 : 'I5';
EOL : '\r'? '\n' | '\r';
SPACES : [ \t]+ -> skip;
在我的 ANTLR 语法中我有一组操作(OP):
- OP: 'I1', 'I2'.....'I9', 'I10' (一组TOKENS);
每当我找到令牌时:
- CASE : 有效操作是 'I1','I2','I3' (move1);
- SWITCH : 有效操作是 'I2','I4','I5' (move2);
其余的操作被其他指令使用。
当然在我的 Lexer 中我不能将两个标记定义为:
OP_MOVE1 : 'I1' | 'I2' | 'I3';
OP_MOVE2 : 'I2' | 'I4' | 'I5';
因为我会得到::
OP_MOVE2 值无法访问。 I2 总是被 token OP_MOVE1
重叠因此,假设事务不仅仅是从 I1 到 I10,而是从 I1 到 I5000。
一个可能的解决方案可能是:
LEXER.G4
lexer grammar LexerComment;
CASE : 'CASE' -> pushMode(CASE_MODE);
SWITCH : 'SWITCH' -> pushMode(CASE_SWITCH);
WS : [ \t] -> skip ;
EOL : [\r\n]+;
// ------------ Everything INSIDE a CASE ------------
mode CASE_MODE;
CASE_MODE_MOVE1 : 'I1' | 'I2' | 'I3';
CASE_MODE_WS : [ \t] -> channel(HIDDEN) ;
CASE_MODE_EOL : EOL -> type(EOL),popMode;
// ------------ Everything INSIDE a SWITCH ------------
mode CASE_SWITCH;
CASE_SWITCH_MOVE2: 'I2' | 'I4' | 'I5';
CASE_SWITCH_WS : [ \t] -> channel(HIDDEN) ;
CASE_SWITCHT_EOL : EOL -> type(EOL),popMode;
解析器.g4:
parser grammar ParserComment;
options {
tokenVocab = LexerComment;
}
prog : (line? EOL)+;
line : instruction;
instruction: CASE CASE_MODE_MOVE1
|SWITCH CASE_SWITCH_MOVE2;
输入文件:
CASE I1
CASE I2
CASE I3
SWITCH I2
SWITCH I4
SWITCH I5
虽然我对解决方案不满意,但语法似乎工作正常,因为它需要大量代码,每种情况 1 种模式,以及模式中常见标记的重复。
还因为如果我想识别,除了 CASE 和 SWITCH,以 MOVE1 OR MOVE2 开头的行为:
instruction: CASE CASE_MODE_MOVE1
|SWITCH CASE_SWITCH_MOVE2
| MOVE1 ;
我还没有找到解决问题的最佳方案:
- 我不能重复使用之前的MOVE1 (CASE_MODE_MOVE1);
- 我无法定义新模式。
有没有办法正确处理类似的情况? 给定一组令牌,我想要一个可以根据上下文使用的子集。
可能试图避免将每个操作都定义为基本令牌:
fragment I1: 'I1';
fragment I2: 'I2';
etc
编辑: 在我的语法中,相等的 TOKEN 可以有不同的含义。
例如,对于以下语法,TOKEN I1 具有不同的含义。
解析器:
parser grammar ParserComment;
options {
tokenVocab = LexerComment;
}
prog : (line? EOL)+;
line : instruction;
instruction: CONTEXT case_instruction;
case_instruction
: I1
| I2
| I3
;
词法分析器:
lexer grammar LexerComment;
// I1 IS A CONTEXT
CONTEXT: I1 | CASE;
CASE : 'CASE';
SWITCH : 'SWITCH';
//OPERATIONS
I1 : 'I1';
I2 : 'I2';
I3 : 'I3';
I4 : 'I4';
I5 : 'I5';
WS : [ \t] -> skip ;
EOL : [\r\n]+;
尽管名称相同,但 I1 具有两个完全不同的含义(CONTEXT 和 OP)。我想承认这两种情况并避免有一个共同的 I1:
prog : (line? EOL)+;
line : instruction;
instruction: context case_instruction;
context: I1 | CASE;
case_instruction
: I1
| I2
| I3
;
出于这个原因,我曾尝试在词法分析器中使用模式进行管理。
IMO,你不应该让词法分析器决定何时应该创建某些标记。让解析器决定令牌在特定位置何时正确。
像这样:
prog
: instruction* EOF
;
instruction
: CASE case_instruction EOL
| SWITCH switch_instruction EOL
| EOL
;
case_instruction
: I1
| I2
| I3
;
switch_instruction
: I2
| I4
| I5
;
CASE : 'CASE';
SWITCH : 'SWITCH';
I1 : 'I1';
I2 : 'I2';
I3 : 'I3';
I4 : 'I4';
I5 : 'I5';
EOL : '\r'? '\n' | '\r';
SPACES : [ \t]+ -> skip;