view src/ploki/parse.c @ 12292:d51f2100210c draft

<kspalaiologos> `` cat <<<"asmbf && bfi output.b" > /hackenv/ibin/asmbf
author HackEso <hackeso@esolangs.org>
date Thu, 02 Jan 2020 15:38:21 +0000
parents ac0403686959
children
line wrap: on
line source

#include "IO.h"
#include "inc.h"
#include "main.h"
#include "main_label.h"
#include "mars.h"
#include "op.h"
#include "parse.h"
#include "text.h"
#include "venus.h"

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void skipline(IO *f) {
	int c;

	for (
			c = io_peek(f, 0);
			c != EOF && c != '\n';
			c = io_peek(f, 0)
		) {
		if (c == 'R' && io_cmppeek(f, 0, "REM", 3) == 0) {
			io_read(f, NULL, 3);
			skipline(f);
		} else {
			io_getc(f);
		}
	}
	if (c == '\n') {
		io_getc(f);
	}
}

static IO *open_inc(const char *s, enum io_flags mode) {
	size_t i;
	String cur;

	St_init(&cur);
	for (i = 0; inc_ludes[i]; ++i) {
		IO *tmp;

		St_cpy_s(&cur, s);
		St_tac_s(&cur, inc_ludes[i]);
		if ((tmp = io_open(St_ptr(&cur), mode))) {
			St_clear(&cur);
			return tmp;
		}
	}
	St_clear(&cur);

	return NULL;
}

void parse(IO *f, struct text *text, size_t *line) {
	int c;

	while ((c = io_peek(f, 0)) != EOF) {
		struct op node;
		String label;
		int is_static = 0;

		for (
				;
				c != EOF && c != '\n' && isspace(c);
				c = io_peek(f, 0)
				) {
			io_getc(f);
		}
		if (c == EOF) {
			break;
		}

		if (io_cmppeek(f, 0, "INSERT", 6) == 0) {
			size_t start;
			size_t end;
			String ifname;
			IO *ifp;
			int inc;

			if (io_cmppeek(f, 6, " DA", 3) == 0) {
				inc = 0;
				start = 9;
			} else {
				inc = 1;
				start = 6;
			}

			for (
					;
					(c = io_peek(f, start)) != '\n' && isspace(c);
					++start
				)
				;
			if (c == '\n' || c == EOF) {
				goto no_insert;
			}
			for (
					end = start + 1;
					(c = io_peek(f, end)) != '\n' && c != EOF;
					++end
				)
				;
			for (
					;
					end > start && isspace(io_peek(f, end - 1));
					--end
				)
				;
			if (io_cmppeek(f, end - 4, "HERE", 4)) {
				goto no_insert;
			}
			for (
					end -= 4;
					isspace(io_peek(f, end - 1));
					--end
				)
				;
			io_read(f, NULL, start);
			St_init(&ifname);
			if (end > start) {
				io_read(f, &ifname, end - start);
			}
			if (!(ifp = (inc ? open_inc : io_open)(St_ptr(&ifname), IO_READ | IO_BUFFERED))) {
				fprintf(stderr, "%s: %s: %s\n", Prog, St_ptr(&ifname), strerror(errno));
				St_clear(&ifname);
				exit(EXIT_FAILURE);
			} else {
				parse(ifp, text, line);
				io_decr(ifp);
			}
			St_clear(&ifname);
			io_getline(f, NULL);
			continue;
		}
no_insert:

		op_init(&node);
		node.line = *line;

		St_init(&label);
		if (io_cmppeek(f, 0, "FOR", 3) == 0) {
			size_t p;
			for (p = 3; (c = io_peek(f, p)) != '\n' && isspace(c); ++p)
				;
			if (c != EOF && c != '\n') {
				St_cat_c(&label, c);
				for (++p; (c = io_peek(f, p)) != EOF && !isspace(c); ++p) {
					St_cat_c(&label, c);
				}
				if (!ma_exists(&Mars, &label)) {
					is_static = 1;
					io_read(f, NULL, p);
				} else {
					St_zero(&label);
				}
			}
		} else {
			for (; (c = io_peek(f, 0)) == '0'; io_getc(f))
				;
			for (; isdigit(c); c = io_peek(f, 0)) {
				St_cat_c(&label, c);
				io_getc(f);
			}
		}

		for (
				c = io_peek(f, 0);
				c != EOF && c != '\n' && isspace(c);
				c = io_peek(f, 0)
			) {
			io_getc(f);
		}

		if (io_cmppeek(f, 0, "REM", 3) == 0) {
			io_read(f, &node.txt, 3);
			skipline(f);
		} else {
			size_t pos;

			io_getline(f, &node.txt);
			if ((pos = St_rstr_m(&node.txt, "?\?/\n", 4)) + 1u && pos + 4u == St_len(&node.txt)) {
				String buf;
				St_init(&buf);

				do {
					io_getline(f, &buf);
					St_del(&node.txt, St_len(&node.txt) - 4u, 4);
					St_cat(&node.txt, &buf);
				} while ((pos = St_rstr_m(&node.txt, "?\?/\n", 4)) + 1u && pos + 4u == St_len(&node.txt));
				St_clear(&buf);
			}
		}

		{
			struct op *tmp;
			tmp = text_push(text, &node);
			if (is_static) {
				ma_enter(&Mars, &label, tmp);
			} else {
				ve_enter(&Venus, &label, tmp);
				++*line;
			}
		}
		St_clear(&label);
	}

}