如何根据ANTLR4中的关键字跳过输入

如何根据ANTLR4中的关键字跳过输入,antlr4,grammar,keyword,skip,Antlr4,Grammar,Keyword,Skip,我是antlr4的新手,不知道它是否能满足我的需求。以下是一个输入示例: There is a lot of text in this file that i do not care about Lithium 20 g/ml Bor that should be skipped Potassium 300g/ml ... 和代码: SempredParser.g4 parser grammar SempredParser; options { tokenVocab=SempredLex

我是antlr4的新手,不知道它是否能满足我的需求。以下是一个输入示例:

There is a lot of text 
in this file that i do not care 
about
Lithium 20 g/ml
Bor that should be skipped
Potassium  300g/ml
...
和代码:

SempredParser.g4

parser grammar SempredParser;
options { tokenVocab=SempredLexer ;}

file        : line+ EOF;
line        : KEYWORD (NUM UNIT)+ '\n'+;
SempredLexer.g4:

lexer grammar SempredLexer;

//lexer rules

KEYWORD     : ('Lithium' | 'Potassium' ) ;
NL          : '\n';
NUM         : [0-9]+ ('.'[0-9]+)? ;
UNIT        : 'g/ml';
UNKNOWN     : . -> skip ;
我想跳过所有不包含关键字的行(我有大约100个关键字)。请注意,我在这里仅使用“\n”作为分隔符,理想情况下不会将其解析为输出


我在《权威指南》中读到了有关岛屿语法的内容,也尝试过使用lexer模式,但无法做到这一点。非常感谢您的任何提示和帮助。

您已经非常接近了,请避免定义两次换行标记。此语法适合我(我将其放入一个组合语法文件):

您的输入为我提供了以下解析树:


另外请注意:您无法避免输出中的NL标记,因为您决定基于
解析规则行,这需要换行标记。

我将首先将输入拆分为行,并过滤掉包含任何关键字的行,甚至不使用ANTLR。之后,您可以将找到的行提供给解析器以获取详细信息。我想这应该会限制解析所需的输入,甚至可以在不匿名跳过任何内容的情况下工作。实际上,我以前就是这样做的,使用正则表达式而不是ANTLR。我很好奇,难道岛屿语法不完全满足我的要求吗?“…岛屿语言,其句子中有许多有趣的部分,这些部分被我们不关心的东西包围着。”是的,这是一个解决方案,但它能更快地去除不必要的赘肉,而不是通过lexer+解析器免费提供。当然取决于有用/全部输入的比率。但是,除非无用的东西非常小,否则我总是只通过解析管道发送带有有趣输入的行。减少CPU周期的浪费,我明白你的意思。对我来说,这更多的是关于ANTLR的学习经验,而不是现在的效率。谢谢你告诉我我走在了正确的轨道上。现在,这个示例工作了,我开始使用真实输入。我一直在努力解决的一件事是,显然所有找到的标记都需要被解析器使用。我最初认为我可以挑选我感兴趣的。顺便说一句,你是怎么做这个很棒的解析树的?是的,lexer必须使用所有的输入,如果它看到一些不存在规则的东西,它会给你一个错误。这就是为什么我不喜欢使用lexer跳过不需要的输入的原因之一。解析树可视化是由我的Visual Studio代码扩展为ANTL4:生成的。
grammar IslandTest;

start: NL+ line+ EOF;
line:  KEYWORD (NUM UNIT)+ NL+;

KEYWORD: ('Lithium' | 'Potassium');
NUM:     [0-9]+ ('.' [0-9]+)?;
UNIT:    'g/ml';

NL:      '\n';
UNKNOWN: . -> skip;