title: Yacc - Equation Parser with function support
body: <p>i'm trying to write an equation parser for equations like: <code>4*sin(1+cos(10/2))</code>
  I use <code>lex</code> to get the tokens and <code>yacc</code> as the parser module. </p>
  
  <p>My actual problem now is that i dont know how to define the grammar for functions. A function is usually constructed like this <code>FunctionName( Expression)</code> so for the parser grammar it would be <code>function : FUNCTION LPAREN expression RPAREN</code> (i hope). </p>
  
  <p>But how im going to treat functions that are build like that <code>sin(3+cos(0)*10)</code>. This woulde a function within a function, not forgetting to care about <code>3+</code> and <code>*10</code>. Hope i've pointed out my problem good enough. </p>
  
  <p>Here's my code:</p>
  
  <pre><code>import ply.lex as lex
  import ply.yacc as yacc
  import math
  
  tokens = (
      'DIV',
      'TIMES',
      'MINUS',
      'PLUS',
      'FUNCTION',
      'NUMBER',
      'LPAREN',
      'RPAREN',
  )
  
  t_PLUS = r'\+'
  t_MINUS = r'-'
  t_TIMES = r'\*'
  t_DIV = r'/'
  t_LPAREN = r'\('
  t_RPAREN = r'\)'
  
  t_ignore = ' '
  
  def t_NUMBER(t):
      r'([0-9]*\.[0-9]+|[0-9]+)'
      t.value = float(t.value)
      return t
  
  def t_FUNCTION(t):
      r'sin|cos|tan'
      return t
  
  def t_error(t):
      print("Illegal character '%s'" % t.value[0])
      t.lexer.skip(1)
  
  # Parser
  '''
  Here i need some help
  '''
  def p_function_exp(p):
      'function : expression PLUS function'
      p[0] = p[1] + p[3]
  
  def p_function(p):
      'function : FUNCTION LPAREN expression RPAREN'
      if p[1] == 'sin':
          p[0] = math.sin(p[3])
  
  def p_expression_minus(p):
      'expression : expression MINUS term'
      p[0] = p[1] - p[3]
  
  def p_expression_plus(p):
      'expression : expression PLUS term'
      p[0] = p[1] + p[3]
  
  def p_expression_term(p):
      'expression : term'
      p[0] = p[1]
  
  def p_term_div(p):
      'term : term DIV factor'
      p[0] = p[1] / p[3]
  
  def p_term_times(p):
      'term : term TIMES factor'
      p[0] = p[1] * p[3]
  
  def p_term_factor(p):
      'term : factor'
      p[0] = p[1]
  
  def p_factor(p):
      'factor : NUMBER'
      p[0] = p[1]
  
  def p_factor_exp(p):
      'factor : LPAREN expression RPAREN'
      p[0] = p[2]
  
  # Error rule for syntax errors
  def p_error(p):
      print("Syntax error in input!")
  
  # Build the parser
  parser = yacc.yacc()
  
  while True:
      try:
          s = input('&gt;&gt; ')
          equation = lex.lex()
          equation.input(s)
          while True:
              tok = equation.token()
              if not tok: break
              print(tok)
      except EOFError:
          break
      if not s: continue
      result = parser.parse(s)
      print(result)
  </code></pre>
  
  <p>Thanks in advance! John</p>