Executing the operation inside the semantic action only works for simple calculators. Otherwise you have the problem that the line of code may run multiple times even though it's only parsed once. Usually you make the semantic actions build an AST - a data value that holds the program fragment you just parsed, e.g. new NumberLiteral(atoi(parsed_text)), new FunctionCall(function_identifier_ast, [arg1_ast, arg2_ast]), new BinaryExpression(left_ast, '+', right_ast)
Older compilers with less memory may have compiled each function as it was parsed, but it's pretty typical these days for the parser to output a whole-file AST that you process separately.