4.1 javacc正则表达式
e.g:
- 固定字符串:"int"
- 连接:"ABC" "XYC"
- 字符组: ["A", "B"]
- 排除: ~["X", "Y"]
- 任意字符: ~[]
- ("o")+
- ("o")?
- ("o")*
- ("o"){5}
- ("o"){3,5}
- "int"|"Int"
4.2 扫描没有结构的单词
// reserved words
// #@@range/lex_reswords{
TOKEN: {
<VOID : "void">
| <CHAR : "char">
| <SHORT : "short">
| <INT : "int">
| <LONG : "long">
| <STRUCT : "struct">
| <UNION : "union">
| <ENUM : "enum">
| <STATIC : "static">
| <EXTERN : "extern">
| <CONST : "const">
| <SIGNED : "signed">
| <UNSIGNED : "unsigned">
| <IF : "if">
| <ELSE : "else">
| <SWITCH : "switch">
| <CASE : "case">
| <DEFAULT_ : "default">
| <WHILE : "while">
| <DO : "do">
| <FOR : "for">
| <RETURN : "return">
| <BREAK : "break">
| <CONTINUE : "continue">
| <GOTO : "goto">
| <TYPEDEF : "typedef">
| <IMPORT : "import">
| <SIZEOF : "sizeof">
}
// #@@}
// identifier
// #@@range/lex_ident{
TOKEN: {
<IDENTIFIER: ["a"-"z", "A"-"Z", "_"] (["a"-"z", "A"-"Z", "_", "0"-"9"])*>
}
// #@@}
// integer literals
// #@@range/lex_integer{
TOKEN: {
<INTEGER: ["1"-"9"] (["0"-"9"])* ("U")? ("L")?
| "0" ["x", "X"] (["0"-"9", "a"-"f", "A"-"F"])+ ("U")? ("L")?
| "0" (["0"-"7"])* ("U")? ("L")?
>
}
// #@@}
注意javacc会尝试匹配所有的规则,然后选择匹配到的字符数目最多的,比如VoidFunction,与"Void"相比只匹配到4个,但是与Identifier的规则比能够匹配到12个,所以会被视为Identifier。
但是,如果字符数目相同,会优先选择最早定义的。因此,为了识别"void"这个单词,<VOID|"void">这个规则需要写在Identifier之前。
4.3 扫描不生成Token的单词
e.g:
// linear-white-spaces
// #@@range/lex_spaces{
SPECIAL_TOKEN: { <SPACES: ([" ", " ", "
", "
", "f"])+> }
// #@@}
SKIP:跳过,SPECIAL_TOKEN:跳过但保存跳过的token,可以通过下面的SpecialToken属性访问。
4.4 扫描具有结构的单词
javacc能够跳转状态或者从状态出发,注意没有特别指定的状态都是DEFAULT状态。
SKIP: {<"/*">: IN_BLOCK_COMMENT}
<IN_BLOCK_COMMENT> SKIP: {<~[]>}//这里因为是一个字符所以才敢写成如此,两个字符的话就会把*/忽略了
<IN_BLOCK_COMMENT> SKIP: {<"*/">: DEFAULT}
但是仅仅如此,无法在块注释没有关闭的情况下报错,也就是
int main(){
}/*
会被编译器认为是可以接受的。
所以必须使用MORE指令,说明仅仅匹配到该规则那么扫描不应该结束(遇到EOF)。
// block comment
// #@@range/lex_block_comment{
MORE: { <"/*"> : IN_BLOCK_COMMENT }
<IN_BLOCK_COMMENT> MORE: { <~[]> }
<IN_BLOCK_COMMENT> SPECIAL_TOKEN: { <BLOCK_COMMENT: "*/"> : DEFAULT }
// #@@}
扫描String Literal
// #@@range/lex_block_comment{
MORE: { <"/*"> : IN_BLOCK_COMMENT }
<IN_BLOCK_COMMENT> MORE: { <~[]> }
<IN_BLOCK_COMMENT> SPECIAL_TOKEN: { <BLOCK_COMMENT: "*/"> : DEFAULT }
// #@@}