ANTLR4:隐式或显式标记定义

时间:2016-04-19 16:09:09

标签: token antlr antlr4 antlrworks

在ANTLR4中使用显式令牌定义有什么好处和缺点?我发现单个括号中的文本比创建单独的标记更具描述性且更易于使用,并使用它来代替文本。

E.g:

public class Constants {
    public static String SSO_URL = null;
    public static String SSO_API_USERNAME = null;
    public static String SSO_API_PASSWORD = null;
    public static String SSO_API_SCOPE = null;
    public static boolean SSO_IS_PROXY_ENABLED = false;
    public static int SSO_MAX_RETRY_COUNT = 0;
    public static float SSO_FLOAT_VALUE = 0;
}

生成的令牌是:

grammar SimpleTest;

top: library | module ;

library: 'library' library_name ';' ;
library_name: IDENTIFIER;         

module: MODULE module_name ';' ;
module_name: IDENTIFIER;

MODULE: 'module' ;
IDENTIFIER: [a-zA-Z0-9]+;

如果我对T__0=1 T__1=2 MODULE=3 IDENTIFIER=4 'library'=1 ';'=2 'module'=3 “令牌”不感兴趣,因为该规则已经确定了我所匹配的内容,而且无论如何我都会跳过它,用{{替换它是否有意义? 1}}和一个令牌声明? (然后令牌的数量会增加。)为什么这是ANTLRWorks中的警告?

2 个答案:

答案 0 :(得分:5)

Antlr(和大多数编译器/编译器生成器)实现使用单独的词法分析器和解析器的概念,主要是出于性能原因。在这个模型中,词法分析器负责读取输入字符串中的实际字符,并以更简洁的表示形式返回找到的标记列表,如每个标记的枚举或int代码。解析器将使用这些令牌而不是原始输入,以便于实现和性能。

有两种方法可以在Antlr中“声明”一个令牌的使用,一个是显式的,有一个常规的模式表达式,另一个是隐式的,总是一个固定的字符串。

ExplicitRegExp: [A-Z][a-z]+; // lexer rule starts with uppercase letter
ExplicitFixed: 'fixed';
parserRule: 'implicit' ExplicitRegExp; // parser rules starts with lowercase letter

当显式声明一个标记时,它被分配了一个在解析状态机中使用的int-code。假设ExplicitRegExp变为1而ExplicitFixed变为2.但解析器还需要implicit标记才能正确解析语法,因此implicit标记已分配代码3 隐式

那有多糟糕?你可能在语法的不同部分有拼写错误:

a : 'implicit' c;
b : 'implcit' d; // typo here

你的语法不会按预期工作,因为implcit将是一个有效的标记,分配了int-code 4.它还使你的语法/词法分析器更难调试,因为Antlr自动生成名称隐式规则,如T___0。另一件事是你失去了词法规则的排序,可以产生差异(通常不是因为隐式令牌都是固定内容)。

Antlr编译器可以选择向您提供错误消息并要求您明确地编写令牌,但它会选择放弃它,并且只是警告您不应该这样做,可能是出于原型设计/测试原因。

为了让Antlr高兴,请以冗长的方式进行并声明所有令牌:

grammar SimpleTest;

top: library | module ;

library: 'library' library_name=IDENTIFIER ';' ; // I'm using aliasing instead of different parser rule here, just a preference

module: 'module' module_name=IDENTIFIER ';' ;

MODULE: 'module' ;
LIBRARY: 'library' ;
IDENTIFIER: [a-zA-Z0-9]+;

如果您通过显式名称(如MODULE)或其内容(如'module')引用固定令牌,则没有任何区别。

答案 1 :(得分:3)

实际上,隐式和显式令牌之间存在差异:

来自“最终的ANTLR4参考”,第76页:

  

ANTLR收集并分离所有字符串文字和词法分析器   解析器规则中的规则。诸如“enum”之类的文字成为词汇   规则并在解析器规则之后但在之前立即执行   明确的词汇规则

     

ANTLR词法分析器解决了两者之间的歧义   通过支持首先指定的规则的词法规则。

来自我的亮点。