Antlr4 不匹配复合标记

标签 antlr4

我正在尝试使用 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 规则中的空格。这会产生很多问题。在我们的书写系统中,空格字符是单词之间的分隔符。有时您不能这样使用它,而在其他情况下则将其视为更大 token 的一部分。相反,我建议您像这样更改语法(这还将所有隐式标记转换为显式标记,避免其他麻烦):

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;

这给你一个很好的解析树:

enter image description here

在您的描述中,您将一个部分提到为[此处的任何内容都是一个 token ]。您可能想跳过所有这些,因为您对此不感兴趣。但是,我建议您仍然解析该部分(并且不要管它)。它需要实现空格的双重角色,并且您稍后可能会需要它。

关于Antlr4 不匹配复合标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59310157/

相关文章:

java - ANTLR4语法无法涵盖所有​​情况

maven - ANTLR4生成的代码未编译: “cannot override reset()”

antlr4 - Cobol - 解析 cobol 程序中的组项

antlr4 - 处理 Antlr 中的关键字冲突

java - 如何让antlr语法识别带空格的字符串?

java - antlr4 - 如何实现递归

c# - 访问 ANTLR 4 中的 channel 并分别解析它们

java - 具有基本算术和符号表达式的 Antlr4 语法

parsing - 如何判断 ANTLR4 解析器是否消耗了 TokenStream 的所有 token ?

词法分析器中的 ANTLR4 负前瞻