view src/ploki/parse.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 "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);
	}

}