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;
	}
}
예제 #2
0
/**
* 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);
	}
}