解决可能的ANTLR语法歧义(以及一般改进提示)

时间:2012-03-25 07:40:18

标签: antlr antlr3 abstract-syntax-tree antlrworks

我遇到了一个构建语法的问题,该语法能够解析Python 3的AST转储格式并将其转换为AST格式,这对我来说更容易使用。我决定编写一个ANTLR语法,但是我遇到了处理关键字块的问题(但由于某种原因,只有关键字块)。我将关键字语法分离出来,如图所示:

grammar kwds;
options {output=AST;}

keywords:   'keywords=['((', '?)keyword)*']' -> keyword*
    ;

keyword :   'keyword(arg='STRING', value='str')'
    ;
str :   'Str(s='STRING')' -> STRING
    ;

STRING
    :  '\'' ( ESC_SEQ | ~('\\'|'\'') )* '\''
    ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

EMPTYBRACKETS
    :   '[]';

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

这是为了接受关键字列表(0或更多逗号分隔符),格式显示在关键字规则中。

如果您给上述语法提供以下(有效)输入,

  

keywords = [keyword(arg ='name',value = Str(s ='UGA')),keyword(arg ='rank',value = Str(s ='2'))]

语法会认识到这一点,正如它应该的那样。

然而,使用我编写的“完整”python 3 AST格式语法(在http://pastebin.com/ETrSVXvf找到以节省空间,分别在第106和109行上找到上述两条规则),使用几乎完全相同的语法规则,在解析上面显示的示例中的第一个关键字匹配后,令牌流似乎是几个字符,在解析关键字规则时产生以下输出:

sample3.txt line 1:52 mismatched character 'e' expecting 'w'
sample3.txt line 1:53 no viable alternative at character 'y'
sample3.txt line 1:54 no viable alternative at character 'w'
sample3.txt line 1:55 no viable alternative at character 'o'
sample3.txt line 1:56 no viable alternative at character 'r'
sample3.txt line 1:57 no viable alternative at character 'd'
sample3.txt line 1:58 no viable alternative at character '('
sample3.txt line 1:59 missing ENDBR at 'arg='

我只能想到这种情况发生的一种可能性:由于语法含糊不清,某些东西被错误地标记化,因为我用来检测多个关键字语句的模式适用于其他类型的语句。但是,我完全不知道语法中的歧义究竟在哪里。

此外,任何关于如何提高我的语法的一般改进提示将不胜感激!

1 个答案:

答案 0 :(得分:1)

如果添加规则:

parse
 : (t=. {System.out.printf("type=\%-20s text='\%s'\n", tokenNames[$t.type], $t.text);})* EOF
 ;

只是匹配零个或多个标记并打印出这些标记的类型和文本,您将看到词法分析器无法处理示例中的输入, keyword

keywords=[keyword(arg='name', value=Str(s='UGA')), keyword(arg='rank', value=Str(s='2'))]
                                                 ^^^^^^^^^

因此,您的某个解析器规则中没有问题,但在词汇层面出现问题。

我建议您从解析器中删除所有文字标记,并为它们创建词法分析器规则。然后添加一个我在上面发布的parse规则,您可以使用该规则测试词法分析器以查看是否创建了正确的令牌。一旦创建了正确的令牌,请编写解析器规则。

我很确定这里的问题是你没有', keyword'令牌,而且一旦词法分子“看到”', k',它就会尝试创建一个{{1}当然,令牌失败了。所以我也建议你在你的标记中包含逗号和空格,但让它们成为自己的标记。

此外,您不希望有这样的重写规则:

', kwargs'

可能没有任何匹配。如果发生这种情况,ANTLR将在创建AST时抛出异常。始终让重写规则生成某事

stmtlist:       ((', '?) stmt)* -> stmt*
        ;
相关问题