title: Python PLY Yacc - Parsing division of complex numbers
body: <p>I'm implementing a calculator in Python to be able to do some maths on real numbers but also complex numbers. </p>
  
  <p>I have a lexer/parser using PLY and I'm creating my own class for complex numbers, voluntarily ignoring the fact that Python already have a built-in type for complex numbers.</p>
  
  <p>The parser works fine except for this case : </p>
  
  <pre class="lang-py prettyprint-override"><code>42i/2i
  </code></pre>
  
  <p>My parser is interpreting this case like this : </p>
  
  <pre class="lang-py prettyprint-override"><code>42i/2i = (42*i)/(2*i) = 21
  </code></pre>
  
  <p>Like you can see above, each complex number is seen like a block, with a real part inseparable from the imaginary part. But the mathematical truth is different. As you might know, this case should be treated as followed : </p>
  
  <pre class="lang-py prettyprint-override"><code>42i/2i = 42*i/2*i = -21
  </code></pre>
  
  <p>I should adapt my parser rules to get the correct result, but I cannot figure how. 
  Here's a minimal reproducible example : </p>
  
  <pre class="lang-py prettyprint-override"><code>import ply.lex as lex
  import ply.yacc as yacc
  
  tokens = (
      'NUMBER',
      'DIVIDE',
      'IMAGINE',
  )
  
  ########################## LEXER ##########################
  
  t_DIVIDE    = r'\/'
  
  def t_NUMBER(t):
      r'\d+(\.\d+)?'
      t.value = int(t.value)
      return t
  
  def t_IMAGINE(t):
      r'i'
      t.value = Complex(0, 1)
      return t
  
  def t_error(t):
      print("Illegal character '%s'" % t.value[0])
      t.lexer.skip(1)
  
  ########################## PARSER #########################
  
  def p_expression_binop(t):
      '''expression : expression DIVIDE expression'''
      t[0] = t[1] / t[3]
      print(t[0])
  
  def p_expression_number(t):
      '''expression : NUMBER
                    | IMAGINE'''
      t[0] = t[1]
  
  def p_expression_imaginary(t):
      '''expression : NUMBER IMAGINE'''
      t[0] = t[1] * t[2]
  
  def p_error(t):
      print("Syntax error!")
  
  ###################### COMPLEX CLASS ######################
  
  class Complex(object):
      def __init__(self, real, imag=0):
          self.real = real
          self.imag = imag
  
      def __str__(self):
          string = ''
          if self.real != 0:
              if self.real % 1 == 0 : self.real = int(self.real)
              string += str(self.real)
          if self.imag != 0:
              if self.imag % 1 == 0 : self.imag = int(self.imag)
              if self.real != 0:
                  string += ' + ' if self.imag &gt; 0 else ' - '
              else:
                  string += '' if self.imag &gt; 0 else '-'
              if abs(self.imag) != 1:
                  string += str(abs(self.imag)) + 'i'
              else:
                  string += 'i'
          return string or '0'
  
      def __mul__(self, other):
          return Complex(self.real * other.real - self.imag * other.imag,
                         self.imag * other.real + self.real * other.imag)
  
      def __rmul__(self, other):
          return self.__mul__(other)
  
      def __truediv__(self, other):
          if isinstance(other, (float,int)):
              other = Complex(other)
          s1, s2, o1, o2 = self.real, self.imag, other.real, other.imag
          r = float(o1 ** 2 + o2 ** 2)
          return Complex((s1 * o1 + s2 * o2) / r, ( s2 * o1 - s1 * o2) / r)
  
      def __rtruediv__(self, other):
          if isinstance(other, (float,int)):
              other = Complex(other)
          return other.__truediv__(-self)
  
  ########################## MAIN ##########################
  
  lexer = lex.lex() 
  while True:
      try:
          s = raw_input('&gt; ')
      except:
          s = input('&gt; ')
      if s:
          parser = yacc.yacc()
          parser.parse(s)
  </code></pre>
  
  <p>Any help ? Thanks a lot !</p>