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

如何在读取字符串时保留ANTLR4中的空白?,antlr4,Antlr4,我正在创建一个语法,它将用于创建C#的词法分析器和解析器。这将接受下面的输入并输出SQL (path.path.path=“如何做某事”) 目前,我使用以下方法忽略空白: WS:[\t\r\n]+->skip;//跳过空白 问题是,当我阅读引号中的内容时,我需要保留空格,因为它将用于搜索。 我该怎么做呢? 多谢各位 编辑1 以下是我当前解析字符串的尝试: TEXT : [a-zA-Z_]+; 我刚刚遇到的问题并不多,但我找不到一个我理解如何实现的解决方案 我还补充说

我正在创建一个语法,它将用于创建C#的词法分析器和解析器。这将接受下面的输入并输出SQL

(path.path.path=“如何做某事”)

目前,我使用以下方法忽略空白:

WS:[\t\r\n]+->skip;//跳过空白

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

编辑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



//搜索条件的语法
语法搜索引擎;
@成员{
//Lexer成员
//用于在读取in语句时保留空白
布尔忽略=真;
}
r:block_子句*
|挡块
|声明;
//block=(语句子句语句)
块:开括号开始括号+结束括号结束括号;
block_子句:block子句;
start_段:语句子句;
结束部分:声明;
语句:打开_括号路径搜索_术语关闭_括号//将文本更改为允许blah.blah=“hiv”
路径:文本“.”文本“.”文本;
条款:不在|或|和|内;
搜索项:操作员搜索类型;
左括号:'(';
右括号:');
下划线:''";
搜索类型:“”(~[“\\]”“\\”)*“;
运算符:等于|大于|小于| AMP;//可以将AMP和引号放在文本中/
大于:'>'.'';

小于:“所以看起来您在第一种可选的
搜索类型中处理字符串,即:

SEARCH_TYPE     :   '"'TEXT'"'
现在,该规则的问题不是它忽略了空格,而是根本不允许使用空格,因为
TEXT
与空格不匹配。因此,如果您输入类似
“hello”
,您将无法获得没有空格的字符串,您将获得语法错误,因为该输入与
“'TEXT”不匹配“'
模式。根据该规则,只有“hello”才是有效字符串。也不允许使用字母或下划线以外的字符,这与字符串通常的工作方式不同

大概您希望在双引号字符串中允许除双引号以外的任何内容(在大多数编程语言中,也有一些方法可以转义双引号)。所以我们可以使用一个倒排字符类,它匹配除了双引号以外的任何东西:

SEARCH_TYPE: '"' ~'"'* '"';
现在为了允许转义,我们还可以允许反斜杠后跟任何字符(包括双引号):

请注意,这也允许空字符串,而您的原始规则不允许空字符串

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


PS:您的语法还包含一个您从未使用过的
引号
标记,这看起来像是一个错误。此外,
规则可能应声明为片段,因为它们本身永远无法匹配。

因此,看起来您在
搜索类型
的第一个备选方案中处理字符串,即:

SEARCH_TYPE     :   '"'TEXT'"'
现在,该规则的问题不是它忽略了空格,而是根本不允许使用空格,因为
TEXT
与空格不匹配。因此,如果您输入了类似于
“hello”
,您将无法得到没有空格的字符串,您将得到一个语法错误,因为该输入与
“'TEXT'”
模式不匹配。根据该规则,只有“hello”才是有效字符串。也不允许使用字母或下划线以外的字符,这与字符串通常的工作方式不同

大概您希望在双引号字符串中允许除双引号以外的任何内容(在大多数编程语言中,也有一些方法可以转义双引号)。所以我们可以使用一个倒排字符类,它匹配除了双引号以外的任何东西:

SEARCH_TYPE: '"' ~'"'* '"';
现在为了允许转义,我们还可以允许反斜杠后跟任何字符(包括双引号):

请注意,这也允许空字符串,而您的原始规则不允许空字符串

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

PS:您的语法还包含一个您从未使用过的
引号
标记,看起来像一团雾