Antlr4 不匹配复合标记
Antlr4 Not matching composite tokens
我正在尝试使用 Antlr4 处理文件中的以下内容:
process example(test){
run $test say hi
}
我的语法如下所示:
grammar example;
main: process* EOF;
processCall: processName '(' processArg ')';
process: ('process' | 'Process' | 'PROCESS') processName '(' processArg ') {' IDENTIFIER?
processArgReplaces IDENTIFIER? '}';
processArgReplaces: IDENTIFIER? '$' processArg IDENTIFIER?;
processName: WORD;
processArg: (WORD ',')* WORD;
WORD: [a-zA-Z0-9?_]+;
IDENTIFIER: [a-zA-Z] [ a-zA-Z0-9?_]+;
BS: [\r\n\t\f]+ -> skip;
但我的输出给了我 no viable alternative at input 'process example name('
问题是我需要在某些区域支持空间。
process name(arg){
[anything here is one token]
OR
anotherprocess(arg) [comes out as {anotherprocess} and {arg}]
}
我已经尝试更改 IDENTIFIER,因为我认为它会在 process
有机会之前接管比赛,但是显式标记是否意味着该行不会只是通用词?
在这种情况下,打印词法分析器识别的标记列表总是非常有帮助的。在您的情况下,您将获得:
[@0,0:14='process example',<11>,1:0]
[@1,15:15='(',<1>,1:15]
[@2,16:19='test',<10>,1:16]
[@3,20:20=')',<2>,1:20]
[@4,27:30='run ',<11>,2:4]
[@5,31:31='$',<8>,2:8]
[@6,32:42='test say hi',<11>,2:9]
[@7,44:44='}',<7>,3:0]
[@8,46:45='<EOF>',<-1>,4:0]
如您所见,输入 process example
被识别为单个标记,而您希望 process
被识别为关键字。这种不当行为的原因是 IDENTIFIER
规则中的 space。这会产生很多问题。在我们的书写系统中,space 字符是单词之间的分隔符。有时您不能那样使用它,而在其他情况下将其视为更大令牌的一部分。相反,我建议您像这样更改语法(它还将所有隐式标记转换为显式标记,避免其他麻烦):
grammar Example;
start: process* EOF;
processCall: processName OPEN_PAR processArg CLOSE_PAR;
process:
PROCESS processName OPEN_PAR processArg CLOSE_PAR OPEN_CURLY IDENTIFIER? processArgReplaces IDENTIFIER? CLOSE_CURLY
;
processArgReplaces: IDENTIFIER? DOLLAR processArg IDENTIFIER?;
processName: IDENTIFIER;
processArg: (IDENTIFIER COMMA)* IDENTIFIER;
OPEN_PAR: '(';
CLOSE_PAR: ')';
OPEN_CURLY: '{';
CLOSE_CURLY: '}';
COMMA: ',';
DOLLAR: '$';
PROCESS: [pP] [rR] [oO] [cC] [eE] [sS] [sS];
IDENTIFIER: [a-zA-Z] [a-zA-Z0-9?_]+;
WS: [ \r\n\t\f]+ -> skip;
这给了你一个很好的解析树:
在您的描述中,您提到了一个部分 [anything here is one token]
。你可能想跳过所有这些,因为你对它不感兴趣。但是,我建议您仍然解析该部分(不要管它)。它需要实现白人的双重角色space,你以后可能仍然需要它。
我正在尝试使用 Antlr4 处理文件中的以下内容:
process example(test){
run $test say hi
}
我的语法如下所示:
grammar example;
main: process* EOF;
processCall: processName '(' processArg ')';
process: ('process' | 'Process' | 'PROCESS') processName '(' processArg ') {' IDENTIFIER?
processArgReplaces IDENTIFIER? '}';
processArgReplaces: IDENTIFIER? '$' processArg IDENTIFIER?;
processName: WORD;
processArg: (WORD ',')* WORD;
WORD: [a-zA-Z0-9?_]+;
IDENTIFIER: [a-zA-Z] [ a-zA-Z0-9?_]+;
BS: [\r\n\t\f]+ -> skip;
但我的输出给了我 no viable alternative at input 'process example name('
问题是我需要在某些区域支持空间。
process name(arg){
[anything here is one token]
OR
anotherprocess(arg) [comes out as {anotherprocess} and {arg}]
}
我已经尝试更改 IDENTIFIER,因为我认为它会在 process
有机会之前接管比赛,但是显式标记是否意味着该行不会只是通用词?
在这种情况下,打印词法分析器识别的标记列表总是非常有帮助的。在您的情况下,您将获得:
[@0,0:14='process example',<11>,1:0]
[@1,15:15='(',<1>,1:15]
[@2,16:19='test',<10>,1:16]
[@3,20:20=')',<2>,1:20]
[@4,27:30='run ',<11>,2:4]
[@5,31:31='$',<8>,2:8]
[@6,32:42='test say hi',<11>,2:9]
[@7,44:44='}',<7>,3:0]
[@8,46:45='<EOF>',<-1>,4:0]
如您所见,输入 process example
被识别为单个标记,而您希望 process
被识别为关键字。这种不当行为的原因是 IDENTIFIER
规则中的 space。这会产生很多问题。在我们的书写系统中,space 字符是单词之间的分隔符。有时您不能那样使用它,而在其他情况下将其视为更大令牌的一部分。相反,我建议您像这样更改语法(它还将所有隐式标记转换为显式标记,避免其他麻烦):
grammar Example;
start: process* EOF;
processCall: processName OPEN_PAR processArg CLOSE_PAR;
process:
PROCESS processName OPEN_PAR processArg CLOSE_PAR OPEN_CURLY IDENTIFIER? processArgReplaces IDENTIFIER? CLOSE_CURLY
;
processArgReplaces: IDENTIFIER? DOLLAR processArg IDENTIFIER?;
processName: IDENTIFIER;
processArg: (IDENTIFIER COMMA)* IDENTIFIER;
OPEN_PAR: '(';
CLOSE_PAR: ')';
OPEN_CURLY: '{';
CLOSE_CURLY: '}';
COMMA: ',';
DOLLAR: '$';
PROCESS: [pP] [rR] [oO] [cC] [eE] [sS] [sS];
IDENTIFIER: [a-zA-Z] [a-zA-Z0-9?_]+;
WS: [ \r\n\t\f]+ -> skip;
这给了你一个很好的解析树:
在您的描述中,您提到了一个部分 [anything here is one token]
。你可能想跳过所有这些,因为你对它不感兴趣。但是,我建议您仍然解析该部分(不要管它)。它需要实现白人的双重角色space,你以后可能仍然需要它。