/* parser.c */
/* Adapted from The C++ Programming Language by Bjarne Stroustrup
   Modified by	P.J. LaBrocca
*/

#include "mixed.h"
#include "mixcalc.h"
#include <stdio.h>

mixed_t number_value;

mixed_t expr(void)
{
    mixed_t left = term();
    mixed_t tmp;

    for(;;)
        switch(curr_tok) {
            case PLUS:
                curr_tok = gettok();
                tmp = term();
				left = mix_add( &left, &tmp );
                break;
            case MINUS:
                curr_tok = gettok();
                tmp = term();
				left = mix_sub( &left, &tmp );
                break;
            default:
                return left;
        }
}

mixed_t term()
{
    mixed_t d;
    mixed_t left = prim();

    for(;;)
        switch(curr_tok) {
            case MUL:
                curr_tok = gettok();
                d = prim();
				left = mix_mul( &left, &d );
                break;
            case DIV:
                curr_tok = gettok();
                d = prim();
				if( (d.whole == 0) && (d.num == 0) ) {
					  fprintf( stderr, "Division by 0\n");
					  fflush( stdin );
					  longjmp( startup, 1 );
				}
				left = mix_divide( &left, &d );
                break;
            default:
                return left;
        }
}

mixed_t prim()
{
    struct name *n;
    mixed_t e;

    switch(curr_tok) {
        case NUMBER:
            number_value = *M;
            curr_tok = gettok();
            return number_value;
        case MINUS:
            curr_tok = gettok();
            e = prim();
			mix_neg( &e );
            return e;
		case PLUS:
			curr_tok = gettok();
			return prim();

        case LP:
            curr_tok = gettok();
            e = expr();
			if(curr_tok != RP) {
				  fprintf( stderr, "')' expected\n");
				  fflush( stdin );
				  longjmp( startup, 1 );
			}
            curr_tok = gettok();
            return e;
        case END:
			return * mix_init( &e, 1, 0, 1 );
        default:
			  fprintf( stderr, "primary expected, found %c\n", curr_tok);
			  fflush( stdin );
			  longjmp( startup, 1 );
    }
}

