JavaCC:匹配一个空字符串
JavaCC: Matching an empty string
我在使用不明确的标记时遇到了问题。我的语法定义了两个产生式,一个 2e3 或 100e1 形式的数字常量,以及 abc[=37] 形式的标识符=] 或 uvw123.
问题是 e1 是一个有效的标识符,但也构成了数字常量的一部分。因此,例如,如果我的输入由 2e3 组成,它将被标记为一个数字后跟一个标识符 (2 + e3), 这不是我想要的
我可以通过编写包含 e 的更通用的正则表达式来匹配数字常量,而不是将其留给语法产生式,但随后标记 value/image 将要求解析以分隔整数和指数部分,这不是我想要的。这不是我想要的。
我试图通过使用分词器状态来解决这个问题。因为标识符不能以数字开头,数字必须表示数字常量的开头,所以我过渡到STATE_NUMBER。在这种状态下,我定义了一个 e 标记来引用数字常量的指数部分。然后我有一个 "catch everything 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 代码,我会更喜欢它。
问题是 < 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
、"e"。如果您希望它只是一个 number_without_exponent
,请将最后一个 +
更改为 *
。
我在使用不明确的标记时遇到了问题。我的语法定义了两个产生式,一个 2e3 或 100e1 形式的数字常量,以及 abc[=37] 形式的标识符=] 或 uvw123.
问题是 e1 是一个有效的标识符,但也构成了数字常量的一部分。因此,例如,如果我的输入由 2e3 组成,它将被标记为一个数字后跟一个标识符 (2 + e3), 这不是我想要的
我可以通过编写包含 e 的更通用的正则表达式来匹配数字常量,而不是将其留给语法产生式,但随后标记 value/image 将要求解析以分隔整数和指数部分,这不是我想要的。这不是我想要的。
我试图通过使用分词器状态来解决这个问题。因为标识符不能以数字开头,数字必须表示数字常量的开头,所以我过渡到STATE_NUMBER。在这种状态下,我定义了一个 e 标记来引用数字常量的指数部分。然后我有一个 "catch everything 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 代码,我会更喜欢它。
问题是 < 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
、"e"。如果您希望它只是一个 number_without_exponent
,请将最后一个 +
更改为 *
。