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)*