aboutsummaryrefslogtreecommitdiff
path: root/Parser.cpp
blob: e72e3f947cc18616318bafe167399edea92eeab6 (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
#include <cstring>
#include <sstream>

#include "Parser.h"
#include "Exception.h"

using std::getline;

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!");
	
		try {
			circuit->create(label, nodes);
		} catch(CircuitException & c) {
			throw ParserException("line %u: %s", linenum, c.what());
		}
	}
}

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);
}

Parser::Parser(Circuit & circuit) {
	set_circuit(circuit);
}