• 自制编译器 青木峰郎 笔记 Ch4 基于JavaCC的扫描器的描述


    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 }
    // #@@}
    
    
  • 相关阅读:
    HDU6768 The Oculus(Hash)
    HDU6672 Lead of Wisdom(爆搜)
    外一章
    深度学习笔记一
    ACM International Collegiate Programming Contest, Arab Collegiate Programming Contest 2013
    python局部变量&全局变量
    每日日报
    每日日报
    每日日报
    每日日报
  • 原文地址:https://www.cnblogs.com/xuesu/p/14377498.html
Copyright © 2020-2023  润新知