@staticmethod<EOL><INDENT>def make_tables(grammar, precedence):<DEDENT>
ACTION = {}<EOL>GOTO = {}<EOL>labels = {}<EOL>def get_label(closure):<EOL><INDENT>if closure not in labels:<EOL><INDENT>labels[closure] = len(labels)<EOL><DEDENT>return labels[closure]<EOL><DEDENT>def resolve_shift_reduce(lookahead, s_action, r_action):<EOL><INDENT>s_assoc, s_level = precedence[lookahead]<EOL>r_assoc, r_level = precedence[r_action[<NUM_LIT:1>]]<EOL>if s_level < r_level:<EOL><INDENT>return r_action<EOL><DEDENT>elif s_level == r_level and r_assoc == LEFT:<EOL><INDENT>return r_action<EOL><DEDENT>else:<EOL><INDENT>return s_action<EOL><DEDENT><DEDENT>initial, closures, goto = grammar.closures()<EOL>for closure in closures:<EOL><INDENT>label = get_label(closure)<EOL>for rule in closure:<EOL><INDENT>new_action, lookahead = None, rule.lookahead<EOL>if not rule.at_end:<EOL><INDENT>symbol = rule.rhs[rule.pos]<EOL>is_terminal = symbol in grammar.terminals<EOL>has_goto = symbol in goto[closure]<EOL>if is_terminal and has_goto:<EOL><INDENT>next_state = get_label(goto[closure][symbol])<EOL>new_action, lookahead = ('<STR_LIT>', next_state), symbol<EOL><DEDENT><DEDENT>elif rule.production == grammar.start and rule.at_end:<EOL><INDENT>new_action = ('<STR_LIT>',)<EOL><DEDENT>elif rule.at_end:<EOL><INDENT>new_action = ('<STR_LIT>', rule.production)<EOL><DEDENT>if new_action is None:<EOL><INDENT>continue<EOL><DEDENT>prev_action = ACTION.get((label, lookahead))<EOL>if prev_action is None or prev_action == new_action:<EOL><INDENT>ACTION[label, lookahead] = new_action<EOL><DEDENT>else:<EOL><INDENT>types = (prev_action[<NUM_LIT:0>], new_action[<NUM_LIT:0>])<EOL>if types == ('<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>chosen = resolve_shift_reduce(lookahead,<EOL>prev_action,<EOL>new_action)<EOL><DEDENT>elif types == ('<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>chosen = resolve_shift_reduce(lookahead,<EOL>new_action,<EOL>prev_action)<EOL><DEDENT>else:<EOL><INDENT>raise TableConflictError(prev_action, new_action)<EOL><DEDENT>ACTION[label, lookahead] = chosen<EOL><DEDENT><DEDENT>for symbol in grammar.nonterminals:<EOL><INDENT>if symbol in goto[closure]:<EOL><INDENT>GOTO[label, symbol] = get_label(goto[closure][symbol])<EOL><DEDENT><DEDENT><DEDENT>return get_label(initial), ACTION, GOTO<EOL>
Generates the ACTION and GOTO tables for the grammar.

        Returns:
            action - dict[state][lookahead] = (action, ...)
            goto - dict[state][just_reduced] = new_state