Next: , Previous: Bison style, Up: Grammar styles

4.1.3 Mixed style

     %start grammar
     ;; Reparse
     %start prologue epilogue declaration nonterminal rule
     ...
     
     %%
     
     grammar:
         prologue
       | epilogue
       | declaration
       | nonterminal
       | PERCENT_PERCENT
       ;
     ...
     
     nonterminal:
         SYMBOL COLON rules SEMI
         (TAG $1 'nonterminal :children $3)
       ;
     
     rules:
         lifo_rules
         (apply 'nconc (nreverse $1))
       ;
     
     lifo_rules:
         lifo_rules OR rule
         (cons $3 $1)
       | rule
         (list $1)
       ;
     
     rule:
         rhs
         (let* ((rhs $1)
                name type comps prec action elt)
           ...
           (EXPANDTAG
            (TAG name 'rule :type type :value comps :prec prec :expr action)
            ))
       ;

This example shows how iterative and Bison styles can be combined in the same grammar to obtain a good compromise between grammar complexity and an efficient parsing strategy in an interactive environment.

nonterminal’ is parsed using iterative style via the main ‘grammar’ rule. The semantic action uses the TAG macro to produce a raw tag, automagically expanded by Semantic.

But ‘rules’ part is parsed in Bison style! Why?

Rule delimiters are the colon (:), that follows the nonterminal name, and a final semicolon (;). Unfortunately these delimiters are not open-paren/close-paren type, and the Emacs' syntactic analyzer can't easily isolate data between them to produce a ‘RULES_PART’ parenthesis-block-like lexical token. Consequently it is not possible to use EXPANDFULL to iterate in ‘RULES_PART’, like this:

     nonterminal:
         SYMBOL COLON rules SEMI
         (TAG $1 'nonterminal :children $3)
       ;
     
     rules:
         RULES_PART  ;; Map a parenthesis-block-like lexical token
         (EXPANDFULL $1 'rules)
       ;
     
     rules:
         COLON
         ()
         OR
         ()
         SEMI
         ()
         rhs
         rhs
         (let* ((rhs $1)
                name type comps prec action elt)
           ...
           (TAG name 'rule :type type :value comps :prec prec :expr action)
           )
       ;

In such cases, when it is difficult for Emacs to obtain parenthesis-block-like lexical tokens, the best solution is to use the traditional Bison style with error recovery!

In some extreme cases, it can also be convenient to extend the lexer, to deliver new lexical tokens, to simplify the grammar.