用 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)。
我对使用 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)。