void primary(expr_rec * x) { token tok = next_token(); switch (tok){ case LPAREN: /*<primary> ::= (<expression>) */ match(LPAREN); expression(x); match(RPAREN); break; case ID: /*<primary> ::= ID*/ match(ID); expr_rec p; p=process_id(); *x=p; break; case INTLITERAL: /*<primary> ::= INTLITERAL*/ match(INTLITERAL); expr_rec y; y=process_literal(); *x=y; break; default: syntax_error(tok); break; } }
/** * Will attempt to parse the rest of the input line according to the * restrictions given by the format string. The format string is used to * specify, in the given order, how to parse the next token. The following * format is accepted (strictly): * * s -> Source register * d -> Destination register * l -> Label * c -> Constant * n -> Literal number * t -> Place an empty term after this term * [ -> Start 'or' expression (non-recursive) * ] -> End 'or' expression * * Note that the or expression works as expected, so "[lcn]" translates to * "take whichever successfully parses first, either a label, constant, or * a number". * * If the or condition fails, or any parsing fails, an error is printed * and all processing stops (the function does however return instead of * calling exit()). * * @param prog Contains general program information thus far gathered, * and is used for handling error reporting. * @param opcode The binary operation that this line started with. * @param fmt The format string for what arguments to expect. * @param misc Any bits that need to be added as the last child to the * opcode term. */ void process_instruction(struct program *prog, char *opcode, const char *fmt, char *misc){ // create a term for this instruction struct Term *t = create_term(opcode, strlen(opcode), 0); if(!t){ #ifdef DEBUG fprintf(stderr, "whoops! Looks like a nul-pointer...\n"); #endif prog->error_code = -1; return; } t->trans = 1; struct Term *child; prog->term_count++; t->pos = prog->term_count; #ifdef DEBUG fprintf(stderr, "OPCODE: '%s'\n", opcode); #endif // add term to our program if(prog->terms){ prog->end_term->next_term = t; prog->end_term = t; } else{ prog->terms = t; prog->end_term = t; } if(!*opcode) return; #ifdef DEBUG fprintf(stderr, "FMT CODE: '%s'.\n", fmt); #endif // opcode argument parsing short reg = -1; char *iden = 0; char *tok = 0; int c = 0, or = 0, val = -1; while(fmt[c]){ if(fmt[c] == 't'){ prog->end_term->next_term = create_term(0, 0, 0); prog->end_term = prog->end_term->next_term; prog->term_count++; prog->end_term->pos = prog->term_count; prog->end_term->absolute_pos = prog->line_count; } else if(or && ( (reg != -1) | (iden ? 1 : 0) | (val != -1) ) &&fmt[c] != ']'){ // do nothing... } else if(fmt[c] == '['){ or = 1; } else if(fmt[c] == ']'){ or = 0; // if all options failed, report parse error if(!reg && !iden && !val){ // TODO: create standardized error reporting.... print_compiler_error(prog, RED_C); print_asterisk(RED_C, stderr); fprintf(stderr, "\tUnexpected opcode argument.\n"); prog->error_code = GARBAGE; return; } // reset everything reg = -1; iden = 0; tok = 0; } else if(fmt[c] == 's'){ reg = read_src_reg(prog, or); if(!or && reg == -1){ return; } } else if(fmt[c] == 'd'){ reg = read_dst_reg(prog, or); if(!or && reg == -1){ return; } } else if(fmt[c] == 'l'){ if(!tok && or){ tok = strtok(0, ", \t"); iden = tok; } else if(!or){ iden = strtok(0, ", \t"); } else{ iden = tok; } // create the term and add to the end struct Term *nt = create_term(iden, strlen(iden), 0); prog->term_count++; nt->pos = prog->term_count; prog->end_term->next_term = nt; prog->end_term = nt; nt->absolute_pos = prog->line_count; #ifdef DEBUG fprintf(stderr, "GOTS A LABEL!\n"); #endif } else if(fmt[c] == 'n'){ if(!tok && or){ tok = strtok(0, ", \t"); iden = tok; } else if(!or){ iden = strtok(0, ", \t"); } else{ iden = tok; } if(!check_explicit_literal(iden, prog)){ if(!or){ print_expected_literal(iden, prog); return; } iden = 0; } else{ val = process_literal(iden, MAX_INT); iden = 0; if(val < 0){ print_literal_too_large(iden, prog); return; } else{ #ifdef DEBUG fprintf(stderr, "GOTS A LITERAL!\n"); #endif // create the term and add to the end struct Term *nt = create_term(numtob(val, WORD_SIZE), strlen(iden), 0); nt->trans = 1; prog->term_count++; nt->pos = prog->term_count; prog->end_term->next_term = nt; prog->end_term = nt; nt->absolute_pos = prog->line_count; } } } else if(fmt[c] == 'c'){ if(!tok && or){ tok = strtok(0, ", \t"); iden = tok; } else if(!or){ iden = strtok(0, ", \t"); } else{ iden = tok; } if(!check_const(iden, prog)){ if(!or){ print_expected_const(iden, prog); return; } iden = 0; } else{ #ifdef DEBUG fprintf(stderr, "GOTS A CONSTANT!\n"); #endif // create the term and add to the end struct Term *nt = create_term(iden, strlen(iden), 0); prog->term_count++; nt->pos = prog->term_count; prog->end_term->next_term = nt; prog->end_term = nt; nt->absolute_pos = prog->line_count; } } else{ fprintf(stderr, " * Error In Compiler!!!\n\tStrange format code: " "'%c'.\n", fmt[c]); } if(reg != -1){ child = create_single_char_term(dtoc(reg-1), 0); child->absolute_pos = prog->line_count; child->trans = 1; add_child_term(child, t, prog); if(!or) reg = -1; } c++; } // Finally, add miscellaneous bits to the end if(misc){ struct Term *mt = create_term(misc, strlen(misc), 0); mt->trans = 1; mt->absolute_pos = prog->line_count; add_child_term(mt, t, prog); } }