【问题标题】:JavaCC: Matching an empty stringJavaCC:匹配一个空字符串
【发布时间】:2015-05-04 09:27:29
【问题描述】:

我在使用模棱两可的标记时遇到了问题。我的语法定义了两个产生式,一个形式为 2e3100e1 的数字常量,以及形式为 abcuvw123 的标识符强>。

问题在于 e1 是一个有效的标识符,但也构成了数字常量的一部分。例如,如果我的输入由 2e3 组成,它将被标记为一个数字后跟一个标识符 (2 + e3),这不是我想要的。

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

我试图通过使用分词器状态来解决这个问题。因为标识符不能以数字开头,所以数字必须表示数字常量的开头,所以我转换到 STATE_NUMBER。在这种状态下,我定义了一个 e 标记来引用数字常量的指数部分。然后我有一个“catch all else”标记,目的是转换回 DEFAULT 状态。在默认状态下,e 将与标识符正则表达式匹配。

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 代码,我会更喜欢它。

【问题讨论】:

  • 如果您将 digit_sequence 定义为数字加上(可选)e 和更多数字怎么办?像 (["0"-"9"]+(e["0"-"9"]+)?) 之类的东西,所以你得到的数字只有一个状态......它会工作吗?
  • 谢谢,但这不是我想要的,因为令牌值/图像需要解析以分隔整数和指数部分。
  • 我更改了标题,因为我认为这与歧义无关。

标签: java regex tokenize javacc


【解决方案1】:

问题是&lt; end_number: ~[] &gt; : 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,“e”。如果您希望它只是 number_without_exponent,请将最后一个 + 更改为 *

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    相关资源
    最近更新 更多