Parsing ANTLR4中单引号和双引号字符串的处理范围

Parsing ANTLR4中单引号和双引号字符串的处理范围,parsing,antlr,antlr4,Parsing,Antlr,Antlr4,我正在使用ANTLR4,并且正在编写语法来处理单引号和双引号字符串。我正在尝试使用Lexer模式来确定字符串的范围,但这对我来说不起作用,我的语法如下所示。这是正确的方法吗?或者如何正确地将它们解析为令牌,而不是使用上下文解析规则。有什么见解吗 例如: 'single quote that contain "a double quote 'that has another single quote'"' 词汇语法 lexer grammar StringLexer; fragment SQU

我正在使用ANTLR4,并且正在编写语法来处理单引号和双引号字符串。我正在尝试使用Lexer模式来确定字符串的范围,但这对我来说不起作用,我的语法如下所示。这是正确的方法吗?或者如何正确地将它们解析为令牌,而不是使用上下文解析规则。有什么见解吗

例如:

'single quote that contain "a double quote 'that has another single quote'"'
词汇语法

lexer grammar StringLexer;

fragment SQUOTE: '\'';

fragment QUOTE:  '"';

SQSTR_START: SQUOTE     -> pushMode(SQSTR_MODE);

DQSTR_START: QUOTE      -> pushMode(DQSTR_MODE);

CONTENTS: ~["\']+;

mode SQSTR_MODE;

SQSTR_END: (CONTENTS | DQSTR_START)+ SQUOTE -> popMode;

mode DQSTR_MODE;

DQSTR_END:(CONTENTS | SQSTR_START)+ QUOTE -> popMode;
分析器

parser grammar StringParser;
options { tokenVocab=StringLexer; }

start:
    dqstr | sqstr
;

dqstr:
 DQSTR_START DQSTR_END
 ;  

sqstr:
 SQSTR_START SQSTR_END
;
附录 感谢@Lucas Trzesniewski的回答

这是我为解析shell语言而编写的语法的一部分,我可以有多行脚本,其中包含
SQSTR
DQSTR
。根据答案中提供的lexer规则,它可以将多行脚本组合在一起

快乐案例示例(使用答案正确解析):

这将被识别为三个命令和三个字符串(单字符串和双字符串)

未分析示例:另一方面,请注意单引号字符串中的引号:

cmd 'single "quote string'
cmd2 "double quote"
cmd3 'another "single quote' 
在这种情况下,它会错误地将它们全部检测为SQSTR类型的单个字符串标记


有什么办法解决这个问题吗?

太复杂了,你想的是什么。您以前在哪里看到过这样的解决方案?(几乎)github上语法存储库中所有具有此类规则的语法都使用一种简单且工作良好的方法,其中您有一个介绍人、内容和终止符,所有这些都包含在一个规则中,例如:

SQSTRING: '\'' .*? '\'';
DQSTRING: '"' .*? '"';

类似地,对于具有这种结构的所有其他元素(单引号字符串、反勾引号字符串、多行注释等)。

您所想到的太复杂了。您以前在哪里看到过这样的解决方案?(几乎)github上语法存储库中所有具有此类规则的语法都使用一种简单且工作良好的方法,其中您有一个介绍人、内容和终止符,所有这些都包含在一个规则中,例如:

SQSTRING: '\'' .*? '\'';
DQSTRING: '"' .*? '"';

类似地,对于具有这种结构的所有其他元素(单引号字符串、回勾引号字符串、多行注释等)。

如果要将示例字符串解析为单个标记,不一定要使用lexer模式,可以使用相互递归的lexer规则:

SQSTR : '\'' (~['"] | DQSTR)* '\'';
DQSTR : '"'  (~['"] | SQSTR)* '"';
然后,在解析器中使用如下内容:

str : SQSTR | DQSTR;

如果要将示例字符串作为单个标记进行分析,则不必使用lexer模式,可以使用相互递归的lexer规则:

SQSTR : '\'' (~['"] | DQSTR)* '\'';
DQSTR : '"'  (~['"] | SQSTR)* '"';
然后,在解析器中使用如下内容:

str : SQSTR | DQSTR;

这将正确地处理字符串的单个实例,但是如果我在同一个代码段中有多个实例,我将尝试解析它,它将在单个标记中包含所有字符串。如果我添加“*?”使其变得不贪婪,它将无法正确处理字符串包含其他字符串的情况。有什么想法吗?@Jafarkoffahi我不明白你在说什么,你可能想问一个新问题,并附上一个例子。@Lucas Trzesniewski我更新了我的问题来解释这个语法的问题。我试图以各种形式解决它,但没有任何想法?@Jafarkoffahi只需将
~['”]
替换为
~['”\r\n]
,它应该在第一和第三命令中报告语法错误,这将解决此示例,但我正在分析的脚本中的字符串可能有新行。这就是为什么我开始考虑希望作用于strings的模式这将正确处理字符串的单个实例,但是如果我在同一个代码段中有多个实例,我尝试解析它,它将在单个标记中包含所有字符串。如果我添加“*?”使其变得不贪婪,它将无法正确处理字符串包含其他字符串的情况。有什么想法吗?@Jafarkoffahi我不明白你在说什么,你可能想问一个新问题,并附上一个例子。@Lucas Trzesniewski我更新了我的问题来解释这个语法的问题。我试图以各种形式解决它,但没有任何想法?@Jafarkoffahi只需将
~['”]
替换为
~['”\r\n]
,它应该在第一和第三命令中报告语法错误,这将解决此示例,但我正在分析的脚本中的字符串可能有新行。这就是为什么我开始考虑模式,希望能确定严格的范围。我的答案仍然有效,即使在你编辑之后。试试看。单引号字符串中嵌入的双引号和双引号字符串中的单引号与该字符串中的任何其他字符一样匹配。这里没有什么特别的事情要做。@MikeLischke嗨,Mike,是的,它会处理这种情况,但包含
“double-containing'single-containing”double-that-containing'single'”
的其他情况也会失败。我的答案仍然有效,即使在您编辑之后。试试看。单引号字符串中嵌入的双引号和双引号字符串中的单引号与该字符串中的任何其他字符一样匹配。这里没有什么特别的事情要做。@MikeLischke您好Mike,是的,它会处理这种情况,但是包含
“double containing”single containing“double that contains'single'”
的其他场景会因这种语法而失败。