view src/ploki/op.c @ 8427:1fc808cd5b1f

<b_jonas> learn can\'t is the most frequent word whose pronunciation varies between /\xc9\x91\xcb\x90/ and /\xc3\xa6/ depending on dialect. The list is: advance after answer ask aunt brass can\'t cast castle chance class command dance demand draft enhance example fast father glass graph grass half last laugh mask master nasty pass past path plant rather sample shan\'t staff task vast
author HackBot
date Thu, 09 Jun 2016 21:28:47 +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);
}