@staticmethod<EOL><INDENT>def compute_precedence(terminals, productions, precedence_levels):<DEDENT>
precedence = collections.OrderedDict()<EOL>for terminal in terminals:<EOL><INDENT>precedence[terminal] = DEFAULT_PREC<EOL><DEDENT>level_precs = range(len(precedence_levels), <NUM_LIT:0>, -<NUM_LIT:1>)<EOL>for i, level in zip(level_precs, precedence_levels):<EOL><INDENT>assoc = level[<NUM_LIT:0>]<EOL>for symbol in level[<NUM_LIT:1>:]:<EOL><INDENT>precedence[symbol] = (assoc, i)<EOL><DEDENT><DEDENT>for production, prec_symbol in productions:<EOL><INDENT>if prec_symbol is None:<EOL><INDENT>prod_terminals = [symbol for symbol in production.rhs<EOL>if symbol in terminals] or [None]<EOL>precedence[production] = precedence.get(prod_terminals[-<NUM_LIT:1>],<EOL>DEFAULT_PREC)<EOL><DEDENT>else:<EOL><INDENT>precedence[production] = precedence.get(prec_symbol,<EOL>DEFAULT_PREC)<EOL><DEDENT><DEDENT>return precedence<EOL>
Computes the precedence of terminal and production.

        The precedence of a terminal is it's level in the PRECEDENCE tuple. For
        a production, the precedence is the right-most terminal (if it exists).
        The default precedence is DEFAULT_PREC - (LEFT, 0).

        Returns:
            precedence - dict[terminal | production] = (assoc, level)