代码之家  ›  专栏  ›  技术社区  ›  Bryan Kyle

处理javacc中的令牌模糊性

  •  0
  • Bryan Kyle  · 技术社区  · 15 年前

    我正在尝试用Javacc编写一个解析器,它可以识别在令牌级别有一些模糊性的语言。在这种特殊情况下,语言本身支持将“/”标记作为除法运算符,同时也支持正则表达式文本。

    考虑以下javacc语法:

    TOKEN : 
    {
        ...
        < VAR : "var" > |
        < DIV : "/" > |
        < EQUALS : "=" > |
        < SEMICOLON : ";" > |
        ...
    }
    
    TOKEN :
    {
        < IDENTIFIER : <IDENTIFIER_START> (<IDENTIFIER_START> | <IDENTIFIER_CHAR>)* > |
        < #IDENTIFIER_START : ( [ "$","_","A"-"Z","a"-"z" ] )> |
        < #IDENTIFIER_CHAR : ( [ "$","_","A"-"Z","a"-"z","0"-"9" ] ) >  |
    
        < REGEX_LITERAL : ("/" <REGEX_BODY> "/" ( <REGEX_FLAGS> )? ) > |
        < #REGEX_BODY : ( <REGEX_FIRST_CHAR> <REGEX_CHARS> ) > |
        < #REGEX_CHARS : ( <REGEX_CHAR> )* > |
        < #REGEX_FIRST_CHAR : ( ~["\r", "\n", "*", "/", "\\"] | <BACKSLASH_SEQUENCE> ) > |
        < #REGEX_CHAR : ( ~[ "\r", "\n", "/", "\\" ] | <BACKSLASH_SEQUENCE> ) > |
        < #BACKSLASH_SEQUENCE : ("\\" ~[ "\r", "\n"] ) > |
        < #REGEX_FLAGS : ( <IDENTIFIER_CHAR> )* >
    
    }
    

    给出以下代码:

    var y = a/b/c;
    

    可以生成两组不同的令牌。令牌流应为:

    <VAR> <IDENTIFIER> <EQUALS> <IDENTIFIER> <DIV> <IDENTIFIER> <DIV> <SEMICOLON>
    

    <VAR> <IDENTIFIER> <EQUALS> <IDENTIFIER> <REGEX_LITERAL> <SEMICOLON>
    

    我如何确保令牌管理器生成我在本例中期望的令牌流?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Bryan Kyle    15 年前

    Javacc将始终使用最大的可用令牌,否则无法对其进行配置。实现这一点的唯一方法是添加一个词法状态,例如 IGNORE_REGEX ,不包括令牌,在本例中 <REGEX_LITERAL> . 然后,当一个令牌被识别为不能跟在后面 <regex_literal> 词法状态必须切换到 伊格丽尼奥格雷克斯 .

    输入:

    var y = a/b/c
    

    会发生以下情况:

    1. <VAR> 已使用,词法状态设置为 DEFAULT
    2. <IDENTIFIER> 已使用,词法状态设置为 伊格丽尼奥格雷克斯
    3. <EQUALS> 已使用,词法状态设置为 违约
    4. <标识符& 已使用,词法状态设置为 伊格丽尼奥格雷克斯

      在这一点上,语法中存在歧义,或者 <DIV> 或A <regex_literal> 将被消耗。因为词汇状态是 伊格丽尼奥格雷克斯 这种状态不匹配 <regex_literal> <DIV & GT; 将被消耗。

    5. <DIV & GT; 已使用,词法状态设置为 违约

    6. <标识符& 已使用,词法状态设置为 伊格丽尼奥格雷克斯
    7. <DIV & GT; 已使用,词法状态设置为 违约
    8. <标识符& 已使用,词法状态设置为 伊格丽尼奥格雷克斯
        2
  •  0
  •   smhx    15 年前

    据我所知(我以前和Javacc一起工作过)

    编写每个规则的顺序就是解析规则的顺序,因此,编写规则的顺序始终会生成所需的表达式。

        3
  •  0
  •   Laurence Gonsalves    15 年前

    因为javascript/ecmascript做了相同的事情(也就是说,它包含regex文本和一个类似于示例中的divide操作符),所以您可能希望寻找一个现有的javacc语法来学习。我发现一个链接到 this blog entry 可能还有其他的。