elisp: Operator Precedence Grammars

 
 22.7.1.2 Operator Precedence Grammars
 .....................................
 
 SMIE’s precedence grammars simply give to each token a pair of
 precedences: the left-precedence and the right-precedence.  We say ‘T1 <
 T2’ if the right-precedence of token ‘T1’ is less than the
 left-precedence of token ‘T2’.  A good way to read this ‘<’ is as a kind
 of parenthesis: if we find ‘... T1 something T2 ...’ then that should be
 parsed as ‘... T1 (something T2 ...’ rather than as ‘... T1 something)
 T2 ...’.  The latter interpretation would be the case if we had ‘T1 >
 T2’.  If we have ‘T1 = T2’, it means that token T2 follows token T1 in
 the same syntactic construction, so typically we have ‘"begin" = "end"’.
 Such pairs of precedences are sufficient to express left-associativity
 or right-associativity of infix operators, nesting of tokens like
 parentheses and many other cases.
 
  -- Function: smie-prec2->grammar table
      This function takes a _prec2_ grammar TABLE and returns an alist
      suitable for use in ‘smie-setup’.  The _prec2_ TABLE is itself
      meant to be built by one of the functions below.
 
  -- Function: smie-merge-prec2s &rest tables
      This function takes several _prec2_ TABLES and merges them into a
      new _prec2_ table.
 
  -- Function: smie-precs->prec2 precs
      This function builds a _prec2_ table from a table of precedences
      PRECS.  PRECS should be a list, sorted by precedence (for example
      ‘"+"’ will come before ‘"*"’), of elements of the form ‘(ASSOC OP
      ...)’, where each OP is a token that acts as an operator; ASSOC is
      their associativity, which can be either ‘left’, ‘right’, ‘assoc’,
      or ‘nonassoc’.  All operators in a given element share the same
      precedence level and associativity.
 
  -- Function: smie-bnf->prec2 bnf &rest resolvers
      This function lets you specify the grammar using a BNF notation.
      It accepts a BNF description of the grammar along with a set of
      conflict resolution rules RESOLVERS, and returns a _prec2_ table.
 
      BNF is a list of nonterminal definitions of the form ‘(NONTERM RHS1
      RHS2 ...)’ where each RHS is a (non-empty) list of terminals (aka
      tokens) or non-terminals.
 
      Not all grammars are accepted:
         • An RHS cannot be an empty list (an empty list is never needed,
           since SMIE allows all non-terminals to match the empty string
           anyway).
         • An RHS cannot have 2 consecutive non-terminals: each pair of
           non-terminals needs to be separated by a terminal (aka token).
           This is a fundamental limitation of operator precedence
           grammars.
 
      Additionally, conflicts can occur:
         • The returned _prec2_ table holds constraints between pairs of
           tokens, and for any given pair only one constraint can be
           present: T1 < T2, T1 = T2, or T1 > T2.
         • A token can be an ‘opener’ (something similar to an
           open-paren), a ‘closer’ (like a close-paren), or ‘neither’ of
           the two (e.g., an infix operator, or an inner token like
           ‘"else"’).
 
      Precedence conflicts can be resolved via RESOLVERS, which is a list
      of _precs_ tables (see ‘smie-precs->prec2’): for each precedence
      conflict, if those ‘precs’ tables specify a particular constraint,
      then the conflict is resolved by using this constraint instead,
      else a conflict is reported and one of the conflicting constraints
      is picked arbitrarily and the others are simply ignored.