Antlr消除左遞歸心得


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM