2012-03-25 73 views
2

我有一个问题,建立一个语法,它能够解析Python 3的AST转储格式,并将其转换为AST格式,我更容易玩弄。我决定编写一个ANTLR语法来完成这项工作,但我在处理关键字块(但由于某些原因只能使用关键字块)时遇到问题。余中分离出来的关键字语法,如下所示:解决可能的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或更多逗号分隔符)的列表,其中在关键字规则所示的格式。

如果给上面的语法以下的(有效的)输入,

关键字= [关键字(ARG = '名称',值= STR(S = 'UGA')),关键字(ARG = 'rank',value = Str(s ='2'))]

语法会识别它,因为它应该。

然而,使用“完全”蟒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=' 

我只能想到的出现这种情况的一种可能性:由于语法中的模糊性,某物正在被不正确地标记,因为我用来检测多个关键字语句的模式适用于其他的t报表的类型。然而,我完全停留在语法中实际存在歧义的地方。

另外,任何一般的改进提示,以我如何能改善我的语法一般将不胜感激!

回答

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',它试图创建一个', kwargs'令牌,该令牌失败,当然。所以我也建议你做而不是在你的代币中包含逗号和空格,但让它们成为它们自己的代币。

而且,你不希望有一个重写规则是这样的:

stmtlist:  ((', '?) stmt)* -> stmt* 
     ; 

这有可能匹配什么。如果发生这种情况,ANTLR将在创建AST时抛出异常。总是让重写规则产生东西

... 

tokens { 
    ... 
    STMTLST; 
    ... 
} 

... 

stmtlist:  ((', '?) stmt)* -> ^(STMTLST stmt*) 
     ; 
+0

啊哈,我明白了。这很有道理,词法分析师会混淆',k',这也会解释一些角色是如何被消费的,而另一些则不是。另外,感谢关​​于重写规则的提示! – wibarr 2012-03-25 14:17:23

+0

@ Webs961,不客气。 – 2012-03-25 14:21:59