JFlex:如何在匹配期间让yytext继续

时间:2014-11-26 18:15:59

标签: intellij-idea jflex

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

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

JFlex可以实现吗?如果不是,那么为什么在匹配跨越多个操作的令牌后将内容从StringBuffer传递到IntelliJ API的原因是什么。

1 个答案:

答案 0 :(得分:0)

您可以编写一个与整个String字面值匹配的正则表达式,以便在一次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()