code: def operatorPrecedence(base, operators):
      expression = Forward()
      last = base | Suppress('(') + expression + Suppress(')')
      def parse_operator(expr, arity, association, action=None, extra=None):
          return expr, arity, association, action, extra
      for op in operators:
          expr, arity, association, action, extra = parse_operator(*op)
          if arity < 1 or arity > 2:
              raise Exception("Arity must be unary (1) or binary (2)")
          if association not in (opAssoc.LEFT, opAssoc.RIGHT):
              raise Exception("Association must be LEFT or RIGHT")
          this = Forward()
          if association is opAssoc.LEFT:
              new_last = (last | extra) if extra else last
              if arity == 1:
                  operator_expression = new_last + OneOrMore(expr)
              elif arity == 2:
                  operator_expression = last + OneOrMore(expr + new_last)
          elif association is opAssoc.RIGHT:
              new_this = (this | extra) if extra else this
              if arity == 1:
                  operator_expression = expr + new_this
              elif arity == 2:
                  operator_expression = last + OneOrMore(new_this)
          if action is not None:
              operator_expression.setParseAction(action)
          this <<= (operator_expression | last)
          last = this
      expression <<= last
      return expression