JFlex:如何让 yytext 在匹配过程中继续



我正在尝试为IntelliJ语言插件编写一个词法分析器。在 JFLex 手册中,有一个示例可以对字符串文字进行词法化。但是,在此示例中,他们使用 StringBuffer 插入词法字符的每个部分,并不断构建单个字符串。我对这种方法的问题是它创建了正在读取的字符的副本,我不知道如何将该示例与 IntelliJ 集成。在IntelliJ中,总是返回一个IElementType,然后使用函数getTokenStart()getTokenEnd()从yytext()中获取关联的文本,使得整个令牌的开始和结束直接映射到输入字符串。

因此,我希望能够返回一个令牌,并且关联的yytext()应该跨越自上次返回另一个令牌以来的整个文本。例如,在字符串文本示例中,我将读取标记文本开始的",然后更改为状态STRING,当我再次读取"时,我变回另一个状态并返回字符串文本标记。在这一点上,我希望yytext()包含整个字符串文字。

这在JFlex中可能吗?如果不是,建议为什么要在匹配跨多个操作的令牌后将内容从 StringBuffer 传递到 IntelliJ API。

您可以编写一个与整个字符串文本匹配的正则表达式,以便在一次 yytext() 调用中获取它,但此匹配将包含未处理的转义序列。

从 JFlex java 示例:

<STRING> {
  "                             { yybegin(YYINITIAL); return symbol(STRING_LITERAL, string.toString()); }
  {StringCharacter}+             { string.append( yytext() ); }
  /* escape sequences */
  "\b"                          { string.append( 'b' ); }
  "\t"                          { string.append( 't' ); }
  "\n"                          { string.append( 'n' ); }
  "\f"                          { string.append( 'f' ); }
  "\r"                          { string.append( 'r' ); }
  "\""                         { string.append( '"' ); }
  "\'"                          { string.append( ''' ); }
  "\\"                         { string.append( '\' ); }
  \[0-3]?{OctDigit}?{OctDigit}  { char val = (char) Integer.parseInt(yytext().substring(1),8);
                                           string.append( val ); }
  /* error cases */
  \.                            { throw new RuntimeException("Illegal escape sequence ""+yytext()+"""); }
  {LineTerminator}               { throw new RuntimeException("Unterminated string at end of line"); }
}

此代码不仅匹配像 "\t" 这样的转义序列,而且将它们转换为单个字符't'。您可以在这样的表达式中的一个表达式中匹配整个字符串

" ({StringCharacter} | \[0-3]?{OctDigit}?{OctDigit} | "\b" | "\t" | .. | "\\") * "

但是 yytext 随后将包含未处理的序列\t而不是字符't'

如果这是可以接受的,那么这就是简单的解决方案。如果令牌应该是输入的实际子字符串,那么听起来这就是您想要的。

如果不是,您将需要更复杂的东西,例如一个中间接口函数,它不是yytext(),但当最后一个匹配是字符串匹配时返回StringBuffer内容(您可以在字符串操作中设置的标志),否则返回yytext()

相关内容

最新更新