Q:

Yacc - Equation Parser with function support

i'm trying to write an equation parser for equations like: 4*sin(1+cos(10/2))
I use lex to get the tokens and yacc as the parser module. 
My actual problem now is that i dont know how to define the grammar for functions. A function is usually constructed like this FunctionName( Expression) so for the parser grammar it would be function : FUNCTION LPAREN expression RPAREN (i hope). 
But how im going to treat functions that are build like that sin(3+cos(0)*10). This woulde a function within a function, not forgetting to care about 3+ and *10. Hope i've pointed out my problem good enough. 
Here's my 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('>> ')
        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)

Thanks in advance! John

A:

A traditional Yacc-grammar for simple expressions usually looks something like this:
expression
    : add_sub_expr
    ;

add_sub_expr
    : mul_div_expr
    | mul_div_expr '+' add_sub_expr
    | mul_div_expr '-' add_sub_expr
    ;

mul_div_expr
    : funcall_expr
    | funcall_expr '*' mul_div_expr
    | funcall_expr '/' mul_div_expr
    ;

funcall_expr
    : prim_expr
    | FUNCTION_NAME '(' expression_list ')'
    ;

prim_expr
    : NUMBER
    | '(' expression ')'
    ;

expression_list
    : expression
    | expression ','  expression_list
    ;

The above grammar will make function calls a direct part of the expression, with higher precedence than multiplication and division.
For FUNCTION_NAME you can either have one line each for each function (if you list of functions is short) or a non-terminal that contains a list of the function identifiers, or a special terminal (like in my grammar) or just a generic identifier terminal.

