Antlr的LL(*)文法不支持左递归,虽然Antlrworks提供了一些自动消除左递归的功能,但是也不是很好用。另外,很多文法文件都包含了(大量的)左递归,比如C99标准里的
Grammar
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-listopt )
postfix-expression . identifier
postfix-expression –> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list ,}
老夫总结一些转换模板分享给大家
左递归
基本型 1
A : b
A b
to
A : b+
以C99标准里的编译单元举例子:
translation_unit:
external_declaration
translation_unit external_declaration
显然 translation_unit 就是 A, external_declaration 就是 B,套用模板后
translation_unit : external_declaration +
基本型 2
A : b
c
A b
to
A : (b | c) (b)*
基本型 3
A : b
c
A e
A f
to
A : (b | c) (e | f)*
其实就是 类型1 和 类型2的扩展,以C99标准里的direct_declarator举例子,这个例子绝对够复杂:
direct_declarator:
identifier
( declarator )
direct_declarator [ type_qualifier_list ? assignment_expression ? ]
direct_declarator [ static type_qualifier_list ? assignment_expression ]
direct_declarator [ type_qualifier_list static assignment_expression ]
direct_declarator [ type_qualifier_list ? *]
direct_declarator ( parameter_type_list )
direct_declarator ( identifier_list ? )
“direct_declarator” 就是 A
“identifier” 就是 b
“( declarator )” 就是 c
“[ type_qualifier_list ? assignment_expression ? ]” 就是 e
…省略
direct_declarator :
( identifier | ‘(‘ declarator ‘)’ )
( ‘[‘ type_qualifier_list ? assignment_expression ? ‘]’
| ‘[‘ static type_qualifier_list ? assignment_expression ‘]’
| ‘[‘ type_qualifier_list static assignment_expression ‘]’
| ‘[‘ type_qualifier_list ? ‘*’ ’]’
| ‘(‘ parameter_type_list ‘)’
| ‘(‘ identifier_list ? ‘)’
)*
扩展型
A : a
b
A ? c
A ? d
A ? e
这个稍微有些麻烦,但是也很简单,先把
A ? c
变成
c
A c
于是变成
A: a
b
c
A c
d
A d
e
A e
为了美观,排序一下
A: a
b
c
d
e
A c
A d
A e
最后套用 基本型 3
A:(a|b|c|d|e) (c|d|e)*
尾递归
尾递归基本上和左递归差不多,不多解释了…
基本型 1
A: b
b A
to
A: (b)+
基本型 2
A: b
c
b A
to
A: (b)(b|c)*
基本型 3
A: a
b
c A
d A
to
A: (c|d)(a|b)*
扩展型
A : a
b
c A?
d A?
e A?
to
A : a
b
c
c A
d
d A
e
e A
to
A : a
b
c
d
e
c A
d A
e A
to
(c | d| e)(a | b |c |d |e)*