【发布时间】:2017-03-12 13:37:35
【问题描述】:
我正在词法分析的语言需要能够根据运行时配置热交换关键字。
只要您可以在语法 (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 文件中删除所有特定于目标的代码,因为我的 .g4s 将用于不同项目的多种目标语言。
在Parser 中,您可以使用Listener 删除嵌入的操作并将语法与特定于应用程序的代码分离。但是,如果在 Lexer 级别2 存在这样做的方法,我还没有找到它(因此提出这个问题)。
实现这一点的方法似乎是包装从Lexer 中提取的TokenStream。此包装 TokenStream 将在提供时读取 Tokens,并将当前在嵌入式操作中的转换应用于存在的任何 ID 标记。
这(理论上)并不难实现;然而,这感觉就像只使用已经定义的 ANTLR 符号就应该可以实现的功能。所以,问题是:是否有可能在现有的 ANTLR 系统中有条件地更改通过 TokenStream 的令牌类型? 如果不能,那么完成该任务的最低摩擦方式是什么?使用 Java 库的示例将是首选,因为这是我最熟悉的。
作为一个子问题:如果我最终为我所需的目标创建了一个TokenTransformationStream,是否值得建议将其添加到现有库中? (我可以为所有当前提供的目标创建符号。)
1 是的,如果您使用常规构造函数构造 Lexer,这将崩溃。在实际应用程序中,可能值得修复它,但对于本示例,这并不重要。
2 我觉得这对于词法分析器级别来说是一项合适的任务,原因有几个。主要原因是总是将关键字作为关键字标记传递似乎很常见,然后,如有必要,允许它们作为解析器级别的标识符(例如上下文相关的关键字)。此外,其他简单地询问如何 来实现此效果的问题建议了一种与上述提供的嵌入式操作解决方案基本等效的方法。
【问题讨论】:
-
我可以为这个任务找到的最有希望的符号是
org.antlr.v4.runtime.TokenStreamRewriter,但如果我正确地阅读了它的 javadoc,它只是用于更改文本表示。 -
你能在词法分析/解析开始之前以某种方式知道这个
runtime configuration吗? -
@cantSleepNow 是的,它以前是已知的,并且在每个运行时都是不变的。
-
你能使用词法分析器模式吗?因为与它相结合,您可以在没有特定语言代码的情况下设置类型。
-
@cantSleepNow 我看不出有什么理由我不能,但我也看不出模式在这种情况下会有什么帮助。如果您认为模式可以解决问题,请添加答案