我所使用的语言需要能够根据运行时配置热插拔关键字。
只要你可以在你的语法(Java)中嵌入特定于目标的代码,如何做到这一点相对简单: 1
lexer grammar LanguageLexer;
tokens {
If, Else, While // etc
}
@header {
import java.util.Map;
}
@members {
private Map<String, Integer> keywords;
public NafiLexer(CharStream input, Map<String, Integer> keywords) {
this(input);
this.keywords = keywords;
}
}
WS: [ \n\t\r]+ -> skip;
ID: [a-zA-Z]+ { if(keywords.containsKey(getText())) setType(keywords.get(getText())); };
但是,我想从.g4
文件中删除所有特定于目标的代码,因为我的.g4
将用于多个目标语言以用于单独的项目。
在Parser
中,您可以使用Listener
删除嵌入的操作,并将语法与特定于应用程序的代码分离。但是,如果有一种方法可以在Lexer级别 2 执行此操作,我还没有找到它(因此提出这个问题)。
实现此目的的方法似乎是将TokenStream
从Lexer
中拉出来。这封文TokenStream
将在提供时显示Token
,并将当前嵌入式操作中的转换应用于所有ID
令牌。
这(理论上)并不难实现;但是,这感觉就像只有已定义的ANTLR符号才能实现的功能。所以,问题是:是否有可能有条件地改变在现有ANTLR系统中通过TokenStream
的令牌类型?如果不是,那么实现该目标的最低摩擦方式是什么?任务?使用Java库的示例将是首选,因为这是我最熟悉的。
作为一个子问题:如果我最终为我的目标创建TokenTransformationStream
,是否值得建议将其添加到现有库中? (我可以为所有当前提供的目标创建符号。)
1 是的,如果使用常规构造函数构造Lexer,则会崩溃。在一个真实的应用程序中,可能值得修复它,但对于这个例子,它并不重要。
2 我觉得这对于词法分析者来说是一个合适的任务,原因有两个。主要原因是,将关键字作为关键字标记始终传递,然后在必要时允许它们作为解析器级别的标识符(例如上下文相关关键字)似乎是常见做法。此外,其他问题只需要如何来实现这种效果,这表明一种方法基本上等同于上面提供的嵌入式操作解决方案。
答案 0 :(得分:0)
这可能不是问题的答案,但是评论的时间太长了。
我在评论中指的是lexer模式,因为我专注于这部分hot-swap keywords
。我不知道为什么你需要更改令牌类型,但是如果你使用词法分析器模式,也许你不会关心它。
唯一的问题是需要一些关键字来表示词法模式的改变。基本上,一个词法分析器模式将是一个亚词法分析器语法(各种各样。)
RUNTIME_CFG_! : 'runtime_cfg_1' -> mode(m_CGF_1);
...
mode m_CGF_1;
KEYWORD1 : 'key1;
...
如果有相同的关键字,您也可以使用词法功能type
*来明确设置令牌的类型。
*我现在无法记住它是如何被调用的,但是通过词法分析器功能,我的意思是mode
,skip
之类的其中一种。