view src/ploki/op.c @ 5556:f2e89077ff1d

<oerjan> learn Turkey was the center of an empire that gobbled up much of Eastern Europe and the Middle East, something which brought them into conflict with Ostrich. In the 19th century the overstuffed empire started declining, and after the Great War it was cut up like so much Shish Kebab.
author HackBot
date Fri, 12 Jun 2015 06:39:15 +0000
parents ac0403686959
children
line wrap: on
line source

#include "IO.h"
#include "Str.h"
#include "expr.h"
#include "main_label.h"
#include "mars.h"
#include "op.h"

#include <ctype.h>
#include <stddef.h>
#include <string.h>

void op_init(struct op *op) {
	St_init(&op->txt);
	op->type = OP_NOP;
	op->arg = NULL;
	op->arh.expr = NULL;
	op->next = NULL;
	op->line = 0;
}

void op_end(struct op *op) {
	St_clear(&op->txt);
	free_expr(op->arg);
	switch (op->type) {
		case OP_ASSIGN:
		case OP_CALL_BACK:
		case OP_MODIFY:
		case OP_PRINT:
		case OP_PUTC:
		case OP_SET_VAL:
		case OP_TEMP:
			free_expr(op->arh.expr);
			break;

		default:
			break;
	}
}

void op_getop(struct op *p) {
	p->next = NULL;

	switch (ST_FIRSTCHAR(&p->txt)) {
		case '#':
			if (ST_INDEX(&p->txt, 1) == '!') {
				p->type = OP_NOP;
				break;
			}
			p->type = OP_SYSTEM;
			St_shift(&p->txt);
			p->arg = get_expr(p);
			break;

		case 'A':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'B':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "ABRUF", 5)) {
						goto defualt;
					}
					p->type = OP_CALL_BACK;
					St_del(&p->txt, 0, 5);
					p->arh.expr = get_iobj(p);
					p->arg = get_expr(p);
					break;

				case 'N':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "ANRUF", 5)) {
						goto defualt;
					}
					p->type = OP_CALL_DYN;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'C':
			if (St_len(&p->txt) < 6 || St_ncmp_m(&p->txt, "CLAUDS", 6)) {
				goto defualt;
			}
			p->type = OP_CLOSE;
			St_del(&p->txt, 0, 6);
			p->arg = get_expr(p);
			break;

		case 'E':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'L':
					if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "ELSE", 4)) {
						goto defualt;
					}
					p->type = OP_ELSE;
					St_del(&p->txt, 0, 4);
					break;

				case 'N':
					if (St_len(&p->txt) >= 6 && St_ncmp_m(&p->txt, "END IF", 6) == 0) {
						p->type = OP_FI;
						break;
					}
					if (St_len(&p->txt) < 3 || St_ncmp_m(&p->txt, "END", 3)) {
						goto defualt;
					}
					p->type = OP_EXIT;
					St_del(&p->txt, 0, 3);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'F':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'I':
					p->type = OP_FI;
					break;

				case 'L':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "FLUSH", 5)) {
						goto defualt;
					}
					p->type = OP_FLUSH;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'G':
			if (ST_INDEX(&p->txt, 1) != 'O') {
				goto defualt;
			}
			switch (ST_INDEX(&p->txt, 2)) {
				case 'F':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "GOFOR", 5)) {
						goto defualt;
					}
					p->type = OP_GOBACK;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				case 'T':
					if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "GOTO", 4)) {
						goto defualt;
					}
					p->type = OP_GOTO;
					St_del(&p->txt, 0, 4);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'I':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'A':
					if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "IACS", 4)) {
						goto defualt;
					}
					p->type = OP_THROW;
					St_del(&p->txt, 0, 4);
					p->arg = get_expr(p);
					break;

				case 'F':
					p->type = OP_IF;
					St_del(&p->txt, 0, 2);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'K':
			if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "KTHX", 4)) {
				goto defualt;
			}
			p->type = OP_RETURN;
			St_del(&p->txt, 0, 4);
			p->arg = get_expr(p);
			break;

		case 'L':
			if (ST_INDEX(&p->txt, 1) != 'E') {
				goto defualt;
			}
			switch (ST_INDEX(&p->txt, 2)) {
				case 'E':
					if (ST_INDEX(&p->txt, 3) != 'T') {
						goto defualt;
					}
					p->type = OP_TEMP;
					St_del(&p->txt, 0, 4);
					p->arh.expr = get_lval(p);
					p->arg = get_expr(p);
					break;

				case 'T':
					p->type = OP_ASSIGN;
					St_del(&p->txt, 0, 3);
					p->arh.expr = get_lval(p);
					St_shiftws(&p->txt);
					if (p->arh.expr && ST_INDEX(&p->txt, 1) == '=' && OPERATOR_P(ST_FIRSTCHAR(&p->txt))) {
						p->arh.expr->op = expr_binop(ST_FIRSTCHAR(&p->txt));
						St_del(&p->txt, 0, 2);
						p->type = OP_MODIFY;
					}
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'N':
			if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "NEXT", 4)) {
				goto defualt;
			} else {
				size_t tmp;
				p->type = OP_NOP;
				St_del(&p->txt, 0, 4);
				tmp = St_shiftws(&p->txt);
				if (!(p->next = ma_find(&Mars, &p->txt))) {
					St_tac_m(&p->txt, "NEXT ", 4 + !!tmp);
					p->arg = get_expr(p);
					p->arh.expr = NULL;
					p->type = OP_PRINT;
				}
			}
			break;

		case 'R':
			if (ST_INDEX(&p->txt, 1) != 'E') {
				goto defualt;
			}
			switch (ST_INDEX(&p->txt, 2)) {
				case 'M':
					p->type = OP_NOP;
					break;

				case 'S':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "RESET", 5)) {
						goto defualt;
					}
					p->type = OP_RESET;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'S':
			if (St_len(&p->txt) < 3 || St_ncmp_m(&p->txt, "SET", 3)) {
				goto defualt;
			}
			p->type = OP_PUTC;
			St_del(&p->txt, 0, 3);
			p->arg = get_iobj(p);
			p->arh.expr = NULL;
			St_shiftws(&p->txt);
			if (ST_FIRSTCHAR(&p->txt) == ',') {
				St_shift(&p->txt);
				p->arh.expr = p->arg;
				p->arg = get_expr(p);
			}
			break;

		case 'W':
			if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "WUNT", 4)) {
				goto defualt;
			}
			p->type = OP_PRINT;
			St_del(&p->txt, 0, 4);
			p->arg = get_iobj(p);
			p->arh.expr = NULL;
			St_shiftws(&p->txt);
			if (ST_FIRSTCHAR(&p->txt) != EOF) {
				p->arh.expr = p->arg;
				p->arg = get_expr(p);
			}
			break;

defualt:
		default:
			if ((p->arh.op = ma_find(&Mars, &p->txt))) {
				p->type = OP_CALL;
				p->arg = get_expr(p);
			} else {
				p->type = OP_PRINT;
				p->arg = get_expr(p);
				p->arh.expr = NULL;
			}
			break;
	}

	St_clear(&p->txt);
}