view src/ploki/parse.c @ 8065:591b1467ccdf

<int-e> le/rn paste/"Paste" is a short story by Henry James. Its contents has been cut into pieces and distributed over numerous tin boxes on the World Wide Web, little pearls of wisdom buried among ordinary pastes.
author HackBot
date Sun, 15 May 2016 13:14:57 +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);
	}

}