JAVACC 如何为 1 个或多个传递令牌
JAVACC How to pass token for 1 or more
最近开始学习javacc解析器。我被要求编写一个解析器,其中一个令牌采用从 1 到多个的数字,另一个令牌采用从 2 到多个的数字
因此我想到了这样的事情:
TOKEN : {
<NUM1: <NUM> (<NUM>)* > //for one or more
<NUM2: (<NUM>)+> //for two or more
<NUM :(["0"-"9"])+>
// and in the function
void calc():
{}
{
(
(<NUM1>)+
(<NUM2>)+
)* <EOF>
}
然而,即使我传递一个没有数字的文本值,它也会成功传递。我做错了什么?
词法标记的 JavaCC 语法允许您重复包含在范围 ()
中的元素,后跟以下之一:
? - zero or one time
* - zero or more times
+ - one or more times
在您的情况下,您需要两个令牌:
TOKEN:
{
<NUM2: ["0"-"9"] (["0"-"9"])+> // for two or more
<NUM1: (["0"-"9"])+> // for one or more
}
您读作:
- 名为
NUM1
的令牌匹配从一到无穷大的数字
- 名为
NUM2
的令牌匹配从两位到无穷大的数字
JavaCC 中的词法机制使用输入字符流中的一个字符并尝试识别标记。两个自动机如下:
lexer 在两个自动机中针对两个标记同时进行。在无法取得更多进展后,识别出 latest 找到的令牌。如果 一个 令牌类型是可能的,那么声明的 第一个 被识别。因此 NUM2
在 NUM1
之前声明。这意味着对于输入 1
,令牌 NUM2
是 而不是 将被识别,因为它需要不止一位数。在这种情况下,NUM1
将是唯一与此输入匹配的标记类型。对于输入 12
两种标记类型都会接受它,但是 NUM2
会被识别,因为它首先声明。这意味着如果您先订购它们 NUM1
,然后订购 NUM2
,您将永远不会收到 NUM2
令牌,因为 NUM1
将始终以最高优先级“获胜”。
要使用它们,您可以拥有如下两个解析器函数:
void match_one_to_many_numbers() : {} { <NUM1> (" " <NUM1>)* <EOF> }
void match_two_to_many_numbers() : {} { <NUM2> (" " <NUM2>)* <EOF> }
您读作:
- function
match_one_to_many_numbers
接受从 one 到 infinity 数量的令牌 NUM1
,由 [= 分隔77=],然后输入流必须以 EOF
系统标记 结束
- 功能
match_two_to_many_numbers
相同,只是来自token NUM2
因为这两个标记都接受无限数量的数字,所以如果没有非数字的分隔符,就不能拥有这些标记的序列。
最近开始学习javacc解析器。我被要求编写一个解析器,其中一个令牌采用从 1 到多个的数字,另一个令牌采用从 2 到多个的数字 因此我想到了这样的事情:
TOKEN : {
<NUM1: <NUM> (<NUM>)* > //for one or more
<NUM2: (<NUM>)+> //for two or more
<NUM :(["0"-"9"])+>
// and in the function
void calc():
{}
{
(
(<NUM1>)+
(<NUM2>)+
)* <EOF>
}
然而,即使我传递一个没有数字的文本值,它也会成功传递。我做错了什么?
词法标记的 JavaCC 语法允许您重复包含在范围 ()
中的元素,后跟以下之一:
? - zero or one time
* - zero or more times
+ - one or more times
在您的情况下,您需要两个令牌:
TOKEN:
{
<NUM2: ["0"-"9"] (["0"-"9"])+> // for two or more
<NUM1: (["0"-"9"])+> // for one or more
}
您读作:
- 名为
NUM1
的令牌匹配从一到无穷大的数字 - 名为
NUM2
的令牌匹配从两位到无穷大的数字
JavaCC 中的词法机制使用输入字符流中的一个字符并尝试识别标记。两个自动机如下:
lexer 在两个自动机中针对两个标记同时进行。在无法取得更多进展后,识别出 latest 找到的令牌。如果 一个 令牌类型是可能的,那么声明的 第一个 被识别。因此 NUM2
在 NUM1
之前声明。这意味着对于输入 1
,令牌 NUM2
是 而不是 将被识别,因为它需要不止一位数。在这种情况下,NUM1
将是唯一与此输入匹配的标记类型。对于输入 12
两种标记类型都会接受它,但是 NUM2
会被识别,因为它首先声明。这意味着如果您先订购它们 NUM1
,然后订购 NUM2
,您将永远不会收到 NUM2
令牌,因为 NUM1
将始终以最高优先级“获胜”。
要使用它们,您可以拥有如下两个解析器函数:
void match_one_to_many_numbers() : {} { <NUM1> (" " <NUM1>)* <EOF> }
void match_two_to_many_numbers() : {} { <NUM2> (" " <NUM2>)* <EOF> }
您读作:
- function
match_one_to_many_numbers
接受从 one 到 infinity 数量的令牌NUM1
,由 [= 分隔77=],然后输入流必须以EOF
系统标记 结束
- 功能
match_two_to_many_numbers
相同,只是来自tokenNUM2
因为这两个标记都接受无限数量的数字,所以如果没有非数字的分隔符,就不能拥有这些标记的序列。