// File: parse.C // // Parse arithmetic expressions involving +, -, *, / and (). #include #include #include "token.h" #include "tokenizer.h" #include "etree.h" #include "parse.h" // Global Variable char *error_msg ; // Everything -> Expression EOL ETree *ParseEverything(Tokenizer *T) { ETree *all ; token_t next ; all = ParseExpression(T) ; if (all == NULL) { T->PrintError() ; printf("%s\n", error_msg) ; return NULL ; } next = T->LookAhead() ; if (next.kind != EOL) { T->PrintError() ; error_msg = "Garbage at the end" ; fprintf(stderr, "%s\n", error_msg) ; delete all ; return NULL ; } return all ; } // Expression -> Expression + Term // -> Expression - Term ETree *ParseExpression(Tokenizer *T) { ETree *expr, *term, *temp ; token_t op ; expr = ParseTerm(T) ; if (expr == NULL) return NULL ; while(1) { op = T->LookAhead() ; switch(op.kind) { case UNDEF : // Bogus, bogus fprintf(stderr,"Oops, caught internal error\n") ; exit(1) ; case PLUS : T->EatToken() ; // consume the '+' break ; case MINUS : T->EatToken() ; // consume the '-' break ; default : return expr ; } term = ParseTerm(T) ; if (term == NULL) { delete expr ; return NULL ; } temp = new ETree(&op, expr, term) ; if (temp == NULL) { delete expr ; delete term ; error_msg = "Memory full !!!" ; return NULL ; } expr = temp ; } } // Term -> Term * Factor // -> Term / Factor ETree *ParseTerm(Tokenizer *T) { ETree *term, *factor, *temp ; token_t op ; term = ParseFactor(T) ; if (term == NULL) return NULL ; while(1) { op = T->LookAhead() ; switch(op.kind) { case UNDEF : // Bogus, bogus fprintf(stderr,"Yikes, caught internal error\n") ; exit(1) ; case TIMES : T->EatToken() ; // consume the '*' break ; case DIVIDE : T->EatToken() ; // consume the '/' break ; default : return term ; } factor = ParseFactor(T) ; if (factor == NULL) { delete term ; return NULL ; } temp = new ETree(&op, term, factor) ; if (temp == NULL) { delete term ; delete factor ; error_msg = "No more memory!!!" ; return NULL ; } term = temp ; } } // Factor -> ( Expression ) // -> Number ETree *ParseFactor(Tokenizer *T) { ETree *temp ; token_t next ; next = T->LookAhead() ; if (next.kind == NUMBER) { T->EatToken() ; // consume the number temp = new ETree(&next) ; if (temp == NULL) { error_msg = "Out of memory" ; return NULL ; } return temp ; } if (next.kind != L_PAREN) { error_msg = "Expecting a number or '('" ; return NULL ; } T->EatToken() ; /* consume the '(' */ temp = ParseExpression(T) ; if (temp == NULL) return NULL ; next = T->LookAhead() ; if (next.kind != R_PAREN) { error_msg = "Expecting ')'" ; return NULL ; } T->EatToken() ; /* consume ')' */ return temp ; }