JavaCC:匹配一个空字符串

时间:2015-03-03 16:21:42

标签: java regex tokenize javacc

我遇到了含糊不清的令牌。我的语法定义了两个产品,一个是 2e3 100e1 形式的数字常量,以及 abc uvw123 形式的标识符强>

问题是 e1 是有效的标识符,但也构成数字常量的一部分。例如,如果我的输入包含 2e3 ,则会将其标记为数字后跟标识符( 2 + e3 ),不是我想要的。

我可以通过编写包含 e 的更一般的正则表达式来匹配数字常量,而不是将其留给语法生成,但是令牌值/图像将需要解析来分隔整数和指数部分,这不是我想要的。这不是我想要的。

我试图通过使用tokenizer状态来解决这个问题。由于标识符不能以数字开头,因此数字必须指示数字常量的开头,因此我转换为 STATE_NUMBER 。在这种状态下,我定义了一个 e 标记来引用数字常量的指数部分。然后我有一个"赶上其他一切"令牌,旨在转换回 DEFAULT 状态。在默认状态下, e 将与标识符regex匹配。

TOKEN : {
  < digit_sequence: (["0"-"9"])+ > : STATE_NUMBER
}

<STATE_NUMBER> TOKEN : {
  < exponent_prefix: "e" >
}

<STATE_NUMBER> MORE : {
  < end_number: ~[] > : DEFAULT
}

TOKEN : {
  < identifier: ["a"-"z"] (["0"-"9","a"-"z"])* >
}

这不能按预期工作。与 MORE 标记匹配的字符似乎被丢弃,而不是成为标识符的第一个字符。

我想知道如何为此写出正确的语法。如果我不必使用任何内联Java代码,我会更喜欢它。

1 个答案:

答案 0 :(得分:0)

问题是< end_number: ~[] > : DEFAULT匹配任何不是e的字符。你要匹配的是一个空字符串。尝试

< end_number: "" > : DEFAULT

我认为以下内容可行。

TOKEN : {
  < (["0"-"9"])+ > : STATE_NUMBER0
}

<STATE_NUMBER0> TOKEN : {
  < "e" > : STATE_NUMBER1
}

<STATE_NUMBER0> MORE : {
  < number_without_exponent: "" > : DEFAULT
}

<STATE_NUMBER1> MORE : {
   < number_with_exponent: (["0"-"9"])+ > : DEFAULT
}

这会导致123e错误,123edf也是如此。如果您不希望这些是错误,那么您可以减少一些状态。

TOKEN : {
  < (["0"-"9"])+ > : STATE_NUMBER
}

<STATE_NUMBER> TOKEN : {
  < number_with_exponent: "e" (["0"-"9"])+ > : DEFAULT
}

<STATE_NUMBER> MORE : {
  < number_without_exponent: "" > : DEFAULT
}

这使得123e成为number_without_exponent后跟identifier,&#34; e&#34;。如果您希望它只是number_without_exponent,请将上一个+更改为*