用 Javacc 重新定义词法标记

Redefining Lexical Tokens With Javacc

我对使用 Javacc 创建语言语法还很陌生,我需要找到一种方法允许用户在代码中重新定义标记的定义。

例如,行

REDEFINE IF FOO

应将 "IF" 的定义从

更改为
  < IF: "IF" >

  < IF: "FOO" >

如果这不可能,解决这个问题的最佳方法是什么?

我认为您可以通过更改令牌类型字段的令牌操作来实现。

类似下面的内容。 [以下是未经测试的代码。如果您使用它,请更正此答案中的任何错误。]

创建哈希映射的令牌管理器声明:

TOKEN_MGR_DECLS: {
    public java.util.HashMap<String,Integer> keywordMap = new java.util.HashMap<String,Integer>()  ;
    {   keywordMap.put( "IF", ...Constants.IF); }
}

定义标识符。

TOKEN : { <ID : (["a"-"z","A"-"Z"])(["a"-"z","A"-"Z","0"-"9"])* >
               { if( keywordMap.containsKey( matchedToken.image ) ) {
                     matchedToken.kind = keywordMap.get( matchedToken.image ) ; }
               }
         }

定义关键词。这些需要在 ID 定义之后。实际上,这些只是在这里,以便创建种类。它们将无法访问并可能导致警告。

TOKEN : { <IF : "A"> | ... }

在解析器中你需要重新定义

void redefine() :
{
    Token oldToken;
    Token newToken;
}
{
    <REDEFINE> oldToken=redefinableToken() newToken=redefinableToken() 
    {
        if( ...TokenManager.keywordMap.containsKey( oldToken.image ) ) {
            ...TokenManager.keywordMap.remove( oldToken.image ) ;
            ...TokenManager.keywordMap.add( newToken.image, oldToken.kind ) ; }
        else {
             report an error }
    }
}

Token redefinableToken() : 
{ Token t ; }
{
    t=<ID>  {return t ;}
|   t=<IF>  {return t ;}
| ...
}

请参阅常见问题解答 (4.14),了解有关尝试从解析器更改词法分析器行为的警告。长话短说:避免超前。


另一种方法是简单地使用一种标记,比如 ID,并在解析器中处理所有内容。请参阅 "Replacing keywords with semantic lookahead" 上的常见问题解答 4.19。在这里,先行将不再是一个问题,因为解析器中的语义操作不会在语法先行期间执行(常见问题解答 4.10)。