aboutsummaryrefslogtreecommitdiff
path: root/Parser.cpp
blob: 84c321707c5448d563d9529a46ed2045ba2a7fcb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <cstring>
#include <sstream>
#include <cstdarg>

#include "Parser.h"

using std::getline;

ParserException::ParserException(const char * fmt, ...) {
	va_list args;
	va_start(args, fmt);
	size_t sz = vsnprintf(NULL, 0, fmt, args) + 1;
	if (error != NULL) free(error);
	error = (char *) malloc(sz);
	vsnprintf(error, sz, fmt, args);
	va_end(args);
}

ParserException::~ParserException() {
	if (error != NULL)
		free(error);
}

const char * ParserException::what() {
	return error;
}

size_t Parser::filter(char * input) {
	size_t
		len = strlen(input),
		offset = 0,
		i = 0;

	while (i < len) {
		if(input[i] == '#') {
			offset += len - i;
			break;
		}

		size_t skip = strspn(input + i, " \t\n");
		if (skip > 0) {
			offset += skip;
			i += skip;
			continue;
		}

		input[i - offset] = input[i];
		i++;
	}

	input[len - offset] = '\0';
	return len - offset;
}

void Parser::set_circuit(Circuit & circuit) {
	this->circuit = &circuit;
}

void Parser::parse(istream & input) {
	unsigned linenum = 0;
	string line_str;
	while (getline(input, line_str)) {
		linenum++;
		char* line = line_str.data();
		size_t len = Parser::filter(line);

		if (len == 0) continue; // ignore empty lines

		char* label = strtok(line, ":");
		if (label == NULL) throw ParserException("syntax error on line %u", linenum);

		char* content = strtok(NULL, ";");
		if (content == NULL) throw ParserException("syntax error on line %u", linenum);

		vector<string> nodes;
		while ((content = strtok(content, ",")) != NULL) {
			nodes.push_back(content);
			content = NULL;
		}
		
		if (circuit == nullptr) throw ParserException("circuit is not initialized!");
		circuit->create(label, nodes);
	}
}


istream & operator >> (istream & s, Parser & parser) {
	parser.parse(s);
	return s;
}

istream & operator << (Parser & parser, istream & s) {
	parser.parse(s);
	return s;
}

void Parser::parse(string input) {
	std::istringstream s(input);
	parse(s);
}