读取字符串时如何在ANTLR4中保留空格?

时间:2019-06-24 12:52:49

标签: antlr4

我正在创建一个语法,该语法将用于为C#创建词法分析器和解析器。这将采用以下输入并输出SQL。

(path.path.path="how to do something")

此刻,我通过以下方式忽略空格:

WS : [ \t\r\n]+ -> skip; // Skips whitespace

问题是,当我阅读引号中的内容时,我需要保留空格,因为它将在搜索中使用。 我该怎么做呢? 谢谢。

编辑1

这是我目前对字符串进行解析的尝试:

TEXT            :   [a-zA-Z_]+;

我刚刚遇到这个问题的机会不多,但是找不到我知道如何实现的解决方案。

我还添加了

@lexer::members{
    //Lexer members

    //Used to preserve whitespace when reading in statements
    boolean ignore=true;
}

我看到了类似的东西。 ignore的值将确定空白是否将跳过。我也将空白规则更改为:

WS              :   [ \t\r\n]+ {if(ignore) skip();};   

但是我不确定在扫描该语句之前如何将ignore设置为false,以及在完成后如何将其更改回true

编辑2

我已复制了整个语法文件:

// Grammar for Search Criteria
grammar SearchGen;

@members{
    //Lexer members

    //Used to preserve whitespace when reading in statements
    boolean ignore=true;
}

r               :   block_clause*
                |   block
                |   statement;

// block = ( statement CLAUSE statement )
block           :   OPEN_BRACKET start_segment+ end_segment CLOSE_BRACKET;

block_clause    :   block clause;

start_segment   :   statement clause;

end_segment     :   statement;

statement       :   OPEN_BRACKET path search_term CLOSE_BRACKET; //Change TEXT to allows for blah.blah="hiv"

path            :   TEXT '.' TEXT '.' TEXT;

clause          :   NOT | OR | AND | WITHIN;

search_term     :   OPERATOR SEARCH_TYPE;

OPEN_BRACKET    :   '(';

CLOSE_BRACKET   :   ')';

UNDERSCORE      :   '_';

SEARCH_TYPE     :   '"' (~["\\] | '\\' .)* '"';

OPERATOR        :   EQUALS | GREATER_THAN | LESS_THAN | AMP; //Maybe put the amp and quotes in TEXT/

GREATER_THAN    :   '>' | '>';

LESS_THAN       :   '<' | '&lt;';

QUOTE           :   '"' | '&amp;quot;';

EQUALS          :   '=';

AMP             :   '&' | '&amp;';

NOT             :   'NOT' | 'not';

OR              :   'OR' | 'or';

AND             :   'AND' | 'and';

WITHIN          :   'WITHIN' | 'within';



//Possible problem : If a keyword that the user is looking for matches one of the above tokens

TEXT            :   [a-zA-Z_]+; // Include Underscore

DIGIT           :   [0-9]+;

// yyyy-mm-dd

DATE            : YEAR'-'MONTH'-'DAY;

YEAR            :   [1-2][(0-9)][(0-9)][(0-9)];

MONTH           :   [0][1-9] | [1-9] | [1][(0-2)];

DAY             :   [0][1-9] | [1-2][0-9] | [3][0-1];

WS              :   [ \t\r\n]+ ->skip;               // Skips whitespace



1 个答案:

答案 0 :(得分:1)

因此,看起来您在SEARCH_TYPE的第一个替代方案中处理了字符串,即:

SEARCH_TYPE     :   '"'TEXT'"'

现在,该规则的问题不在于它忽略空格-就是因为TEXT与空格不匹配,根本不允许使用空格。因此,如果您输入类似" hello "的内容,则没有空格就不会得到字符串,您会收到语法错误,因为该输入与'"'TEXT'"'模式不匹配。根据该规则,只有“ hello”是有效的字符串。除字母或下划线外,也不允许使用其他字符,这与字符串通常的工作方式不同。

大概您想在双引号字符串中允许除双引号之外的任何内容(并且在大多数编程语言中,也有某种转义双引号的方法)。因此,我们可以只使用与双引号之外的任何字符匹配的反向字符类:

SEARCH_TYPE: '"' ~'"'* '"';

现在允许转义,我们还可以允许在反斜杠后加上任何字符(包括双引号):

SEARCH_TYPE: '"' (~["\\] | '\\' .)* '"';

请注意,这还允许使用空字符串,而您的原始规则则不允许。

所以现在我们的字符串实际上可以包含空格而不会产生语法错误。那么如何防止空格被忽略呢?我们不是因为我们不需要。 WS : [ \t\r\n]+ ->skip;只是意味着如果词法分析器要生成WS令牌,它只会跳到下一个令牌。这不会影响其他词法分析器规则内部发生的情况。换句话说:WS规则会跳过标记之间的空格 ,而不是 inside 标记。因此,忽略空格根本不是问题。

PS:您的语法还包含一个您从未使用过的QUOTE令牌,这看起来像是一个错误。此外,YEARMONTHDAY规则可能应该声明为片段,因为它们永远无法单独匹配。