简体   繁体   English

Antlr4/Java:如何根据调用它的解析器规则制作一个跳过标记(词法分析器)的语义谓词

[英]Antlr4/Java : how to make a semantic predicate that skips a token (lexer) according to the parser rule that calls it

I would like to use my lexer rule我想使用我的词法分析器规则

NEW_LINE : '\n' -> skip;

Like a normal rule.就像一个正常的规则。 Understanding by this: I want to ignore the new lines except when they are mandatory, to create a Python similar syntax.对此的理解:我想忽略新行,除非它们是强制性的,以创建 Python 类似的语法。 For example, here, new lines are ignored:例如,在这里,新行被忽略:

cook("banana",
     "potatoe)

but it is impossible to skip the new line for a new statement, like this:但不可能为新语句跳过新行,如下所示:

cook("banana", "potatoe") varA = 12.4

, there must be a new line between cook() and the assignment. cook()和赋值之间必须有一个新行。 This is why I sometimes have to skip the new lines, but still force them somewhere else.这就是为什么我有时不得不跳过新行,但仍将它们强制到其他地方。

This is why I got this idea:这就是为什么我有这个想法:

start
    : line*
    ;

line
    : line_expression (NEW_LINE | EOF)
    ;

line_expression
    : expression
    | assignment
    ;

expression
    : Decimal
    | Integer
    | Text
    | Boolean
    ;

And make a semantic predicate like "if the calling parser rule is not line , skip(); it."并制作一个语义谓词,例如“如果调用解析器规则不是line ,则skip(); it”。 Now I just need help to do that.现在我只需要帮助来做到这一点。

I hope I was clear !我希望我很清楚!

PS: I'm using Java as main language if that wasn't clear PS:如果不清楚,我正在使用 Java 作为主要语言

You could keep track of the number of ( you encounter (and decrease this numbers if you encounter a ) ).您可以跟踪您遇到的(并减少此数字,如果您遇到 a ) )。 Then you only create NL tokens if this number is equal to zero.然后,如果此数字等于 0,则仅创建NL令牌。

Here's a quick demo:这是一个快速演示:

grammar T;

@lexer::members {
  int parensLevel = 0;
}

parse
 : .*? EOF
 ;

OPAR    : '(' {parensLevel++;};
CPAR    : ')' {parensLevel--;};
NUMBER  : [0-9]+ ( '.' [0-9]+)?;
STRING  : '"' ~'"'* '"';
ASSIGN  : '=';
COMMA   : ',';
ID      : [a-zA-Z]+;
SPACES  : [ \t]+ -> skip;
NL      : {parensLevel == 0}? [\r\n]+;
NL_SKIP : [\r\n]+ -> skip;

If you feed the lexer the following input:如果您向词法分析器提供以下输入:

cook("banana",
     "potatoe")
  varA = 12.4

the following tokens will be created:将创建以下令牌:

ID                        `cook`
'('                       `(`
STRING                    `"banana"`
','                       `,`
STRING                    `"potatoe"`
')'                       `)`
NL                        `\n`
ID                        `varA`
'='                       `=`
NUMBER                    `12.4`

As you can see, the NL inside the parens is skipped, while the one after the ) is not.如您所见,括号内的NL被跳过,而)后面的则没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM