上节的实例用的了TOKEN和SKIP,本节写一个较为详细的用法。
token
先简单通过正则表达式来定义一个简单的TOKEN:
< ID: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","0"-"9"] )* >
创建一个名称为ID的正则表达式。在语法的其他任何地方,都可以简单地将其引用为<ID>,这个正则表达式的含义是:由小写或大写字母或者下划线开头,后面跟着0个或多个小写或大写字母、数字或下划线组成的字符串。
[…]定义了匹配模式,由…中指定的字符匹配。 其中可以是单个字符,也可以是字符的范围. "~" 在匹配之前代表‘非’的意思。 如下:
["a"-"z"] 匹配所有的小写字母
~[] 匹配任何字符串
~["\n","\r"] 匹配除换行符以外的任何字符
当我们通过正则表达是定义了一个token时, 它被生成到生成的解析器目录中,名为“Token.java”。 上面的例子, 我们定义了一个“Token”类型的变量,并将正则表达式的值赋给它
skip
下面的例子我们演示SKIP表达式的一个重要属性
SKIP中的正则表达式只会在*between tokens*中忽略,而不是*within tokens*.
PARSER_BEGIN(IdList)
package com.github.gambo.javacc.idlist;
/** ID lister. */
public class IdList {
/** Main entry point. */
public static void main(String args[]) throws ParseException {
IdList parser = new IdList(System.in);
parser.Input();
}
}
PARSER_END(IdList)
SKIP :
{
" "
| "\t"
| "\n"
| "\r"
}
TOKEN :
{
< Id: ["a"-"z","A"-"Z"] ( ["a"-"z","A"-"Z","0"-"9"] )* >
}
/** Top level production. */
void Input() :
{}
{
( <Id> )+ <EOF>
上面的例子引用了名为Id的token,可以解析若干个"Id",最后跟一个文件结束符,并且忽略换行符和空格。
编译运行示例如上一节所示:
以下输入是合法的:
ab ab123 ac_1234 _1234
aaaa
而以下输入则会解析失败!
xyz 123
这是两个token之间可允许使用任意数量的SKIP正则表达式,而“xyz”后面的空格字符属于SKIP类别,因此会导致一个token结束,另一个token开始,这就要求"123" 可以作为一个单独的token,然后“123”并不符合<id>的表达式。