mfcalc.y
%{
#include <iostream>
#include <string>
#include <cmath>

#define YYDEBUG 1							<-- set debug on

typedef struct symrec
{
    char *name;  			
    int type;    			
    union {
	double var;           		
	double (*fnctptr)(double);  	
    } value;
    struct symrec *next;    		
} symrec;

%}

%union  {								<-- yystype
double  val;  				
symrec  *tptr;   			
}

%token <val>  NUM        		
%token <tptr> VAR FNCT   		
%type  <val>  exp

%right '='
%left '-' '+'
%left '*' '/'
%left NEG     				
%right '^'    				
%name-prefix="Mfcalc"							<-- classname prefix (MfcalcPushParser)
%%
input:  								|
        | input line							|
	;								|
									|
line:									|
          '\n'								|
        | exp '\n'   { printf ("\t%.10g\n", $1); }			|
        | error '\n' { yyerrok();                  }			|
	;								|
									|
exp:      NUM                { $$ = $1;                         }       |
        | VAR                { $$ = $1->value.var;              }       |	pull grammar == push grammar
        | VAR '=' exp        { $$ = $3; $1->value.var = $3;     }       |
        | FNCT '(' exp ')'   { $$ = (*($1->value.fnctptr))($3); }       |
        | exp '+' exp        { $$ = $1 + $3;                    }       |
        | exp '-' exp        { $$ = $1 - $3;                    }       |
        | exp '*' exp        { $$ = $1 * $3;                    }       |
        | exp '/' exp        { $$ = $1 / $3;                    }       |
        | '-' exp  %prec NEG { $$ = -$2;                        }       |
        | exp '^' exp        { $$ = pow ($1, $3);               }	|
        | '(' exp ')'        { $$ = $2;                         }	|
	;								|
%%

class MyMfcalcPushParser:public MfcalcPushParser			<-- implement debugPrint(...) and yyerror(...)
{
    private:
    virtual void debugPrint(int aInt) const
    {
	std::cout << aInt;
    }
    virtual void debugPrint(std::string s) const
    {
	std::cout << s;
    }
    public:
    MyMfcalcPushParser() {}
    virtual void yyerror(const char* s) const
    {
	std::cout << s <<  std::endl;
    }
    virtual void accept()						<-- called if parser state == accept
    {
        std::cout << "\taccept!" << std::endl;
    }
    virtual void error()						<-- called if parser state == error || parser state == abort
    {
        std::cout << "\terror!" << std::endl;
    }
};
									<-- Lexer
symrec *sym_table;
struct init
{
    char *fname;
    double (*fnct)(double);
};
symrec *putsym(char *sym_name,int sym_type)
{
    symrec *ptr;
    ptr = (symrec *) malloc (sizeof (symrec));
    ptr->name = (char *) malloc (strlen (sym_name) + 1);
    strcpy (ptr->name,sym_name);
    ptr->type = sym_type;
    ptr->value.var = 0; 
    ptr->next = (struct symrec *)sym_table;
    sym_table = ptr;
    return ptr;
}
symrec *getsym(char *sym_name)
{
    symrec *ptr;
    for (ptr=sym_table;ptr!=NULL;ptr=(symrec *)ptr->next) {
	if (strcmp (ptr->name,sym_name) == 0) {
	    return ptr;
	}
    }
    return 0;
}
void init_sym_table ()  		
{
    int i;
    symrec *ptr;
    struct init arith_fncts[] = {
	"sin" ,sin,
	"cos" ,cos,
	"atan",atan,
	"ln"  ,log,
	"exp" ,exp,
	"sqrt",sqrt,
	0     ,0
    };
    for (i=0;arith_fncts[i].fname!=0;i++) {
	ptr=putsym(arith_fncts[i].fname,FNCT);
	ptr->value.fnctptr=arith_fncts[i].fnct;
    }
}
int lex(MyMfcalcPushParser *parser)
{
    int c;
    MyMfcalcPushParser::SemanticType yylval;

    while(1) {
	while ((c=getchar())==' ' || c=='\t'); 

	if (c==EOF) {
	    yylval.val=EOF;
	    parser->parseToken(0,yylval);				<-- parse EOF
	    return 0;
	}
	if (c == '.' || isdigit(c)) {
	    ungetc(c,stdin);
	    scanf("%lf",&yylval.val);
	    parser->parseToken(NUM,yylval);				<-- instead of return(...) parseToken(...)
	} else if(isalpha(c)) {
	    symrec *s;
	    static char *symbuf=0;
	    static int length=0;
	    int i;

	    if (length==0) {
		length=40,symbuf=(char *)malloc(length+1);
	    }
	    i=0;
	    do {
		if (i == length) {
		    length *= 2;
		    symbuf=(char *)realloc(symbuf,length+1);
		}
		symbuf[i++] = c;
		c=getchar();
	    }
	    while (c!=EOF && isalnum(c));
	    ungetc (c,stdin);
	    symbuf[i]='\0';
	    s=getsym(symbuf);
	    if(s==0) {
		s = putsym (symbuf, VAR);
		yylval.tptr = s;
		parser->parseToken(VAR,yylval);
	    }
	    yylval.tptr = s;
	    parser->parseToken(FNCT,yylval);
	} else {
	  parser->parseToken(c,yylval);
	}
    }
}
int main ()
{
    MyMfcalcPushParser *parser=new MyMfcalcPushParser();
    parser->setDebug(1);
    init_sym_table();
    lex(parser);
    delete parser;
    return 0;
}