ANTLR4 中上下文相关的空白处理

Jim*_*ton 5 parsing antlr antlr4

我正在尝试在 ANTLR4 中实现表达式/公式语言,但在处理空格时遇到问题。在大多数情况下,我不关心空格,所以我有“标准”词法分析器规则将它发送到 HIDDEN 通道,即

// Whitespace
WS
    :   ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
    ;
Run Code Online (Sandbox Code Playgroud)

但是,我有一个运算符,它之前或之后都不允许出现空格,而且我不知道如何在不更改 WS 词法分析器规则的情况下处理这种情况,以将空格保留在默认通道中,并且WS?在我的所有其他内容中都有明确的术语解析器规则(有很多)。

作为简化示例,我为虚构的谓词语言创建了以下语法:

grammar Logik;

/*
 * Parser Rules
 */

ruleExpression
    :   orExpression
    ;

orExpression
    :   andExpression ( 'OR' andExpression)*
    ;

andExpression
    :   primaryExpression ( 'AND' primaryExpression)*
    ;

primaryExpression
    :   variableExpression
    |   '(' ruleExpression ')'
    ;

variableExpression
    :   IDENTIFIER ( '.' IDENTIFIER )*
    ;

/*
 * Lexer Rules
 */

IDENTIFIER
    :   LETTER LETTERORDIGIT*
    ;

fragment LETTER : [a-zA-Z_];
fragment LETTERORDIGIT : [a-zA-Z0-9_];

// Whitespace
WS
    :   ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
    ;
Run Code Online (Sandbox Code Playgroud)

既然这样,这个解析A OR B AND C.DA OR B AND C. D成功-我需要的是对.运营商不允许的空白,使第二个表达式是无效的。

Vin*_*ega 2

您可以使用词法分析器谓词来执行前视(和后视)并为“.”创建专用标记。。在您的示例中,它看起来像这样:

grammar Logik;

/*
 * Parser Rules
 */

ruleExpression
    :   orExpression
    ;

orExpression
    :   andExpression ( 'OR' andExpression)*
    ;

andExpression
    :   primaryExpression ( 'AND' primaryExpression)*
    ;

primaryExpression
    :   variableExpression
    |   '(' ruleExpression ')'
    ;

variableExpression
    :   IDENTIFIER ( POINT IDENTIFIER )*
    ;

/*
 * Lexer Rules
 */

POINT : {_input.LA(-1) != ' ' && _input.LA(2) != ' '}? '.';
IDENTIFIER
    :   LETTER LETTERORDIGIT*
    ;

fragment LETTER : [a-zA-Z_];
fragment LETTERORDIGIT : [a-zA-Z0-9_];

// Whitespace
WS
    :   ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
    ;
Run Code Online (Sandbox Code Playgroud)

这样,A OR B AND C.D就可以了,但A OR B AND C. D会给出一个错误(如A OR B AND C .D),如下所示:token recognition error at: '.' ...

笔记

HIDDEN_CHANEL可能有一种方法可以在语法规则部分中使用 和语义谓词。但是,如果多次有相同的约束,则必须在应启用约束的每个语法规则中编写谓词。