我们要预先设立记录每个标识符的含义,这时候就需要用到javacc中的TOKEN
TOKEN 关键字用于定义词法分析器中的 token。
它指定了一种模式,当词法分析器匹配到满足该模式的文本时,将生成对应的 token。
对于< DOUBLE : "double" >这段代码,我们便是设置记录了double这个token,那么当编译器扫描到它时,就能弄清楚这个标识符的意义是什么:
TOKEN : /* LITERALS */
{
< INTEGER_LITERAL :
< DECIMAL_LITERAL > ([ "l", "L" ])? //整数 ,l和L出现0次或一次,表示为longlong类型
| < HEX_LITERAL > ([ "l", "L" ])? //16进制
| < OCTAL_LITERAL > ([ "l", "L" ])? //8进制
>
| < FLOAT_LITERAL :
(< INTEGER_LITERAL >)+
(
"." (< INTEGER_LITERAL >)+
)? > //浮点数的"."前面有一个或多个整数token。后面也有一个或多个整数token
| < #DECIMAL_LITERAL : [ "1"-"9" ] ([ "0"-"9" ])* >
| < #HEX_LITERAL : "0" [ "x", "X" ] ([ "0"-"9", "a"-"f", "A"-"F" ])+ >//十六进制整数是一个"0x"或"0X"加上若干个"0"-"9"或"a"-"f"或"A"-"F"
|< #OCTAL_LITERAL : "0" ([ "0"-"7" ])* >//八进制整数是一个"0"加上若干个"0"-"7"的数
}
TOKEN : /* KEYS 需要放在标识符的定义前面*/
{
//补充:int标识符
< DOUBLE : "double" >
| < FLOAT : "float" >
| < STRING : "string" >
| < CHAR : "char" >
| < VOID : "void" >
| < MAIN : "main" >
}
TOKEN : /* OPERATORS */
{
< ASSIGN : "=" >
}
TOKEN : /*界符*/
{
< LC : "(" >
| < RC : ")" >
| < LM : "[" >
| < RM : "]" >
| < LB : "{" >
//补充:右大括号
| < COMMA : "," >
| < SEMICOLON : ";" >
| < COLON : ":" >
}
TOKEN : /* IDENTIFIERS */
{
< IDENTIFIER :
< LETTER >
(
< LETTER >
| < DIGIT >
)* >
| < #LETTER : [ "_", "a"-"z", "A"-"Z" ] >
| < #DIGIT : [ "0"-"9" ] >
}//id:id由若干个letter和digit组成,但首位字符必须是letter
#
用于定义私有的(隐式)token,这些 token 本身不会被解析器直接使用或者返回,但它们可以在其他规则中被引用。也就是说,带有#
的 token 不会作为独立的词法单元暴露给语法规则,而是作为内部的辅助工具。~[ "*" ]
表示匹配非*
的任何字符.
题解
跳过//后面的内容,直到有回车或换行符为止:
跳过//后面的内容,直到有回车或换行符为止
<"//"(~["\n","\r"])*>