summaryrefslogtreecommitdiff
path: root/src/piraha/Matcher.cc
blob: dd189042b5fe6debc8093ec542fb893c9b8a13fe (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
#include <string.h>
#include "Piraha.hpp"

using namespace piraha;

Matcher::Matcher(smart_ptr<Grammar> g_,const char *pat_,const char *input_,int input_size_) :
    Group(pat_,input_),
    input(input_), g(g_), input_size(input_size_),
    pos(0), max_pos(-1), pat(pat_), expected(), err_pos(-1) {
    inrule = pat_;
	if(input_size < 0)
		input_size=strlen(input);
}

bool Matcher::matches() {
    smart_ptr<Pattern> p = g->patterns.get(pat);
    if(!p.valid()) {
        std::cout << "Grammar does not contain \"" << pat << "\"" << std::endl;
        std::cout << g->patterns << std::endl;
    }
    assert(p.valid());
    pos = 0;
    max_pos = -1;
    err_pos = -1;
    children.clear();
    bool b = p->match(this);
    end_ = pos;
    return b;
}

void Matcher::fail(Bracket *br) {
    for(unsigned int i=0;i<br->ranges.size();i++) {
        fail(br->ranges[i]->lo,br->ranges[i]->hi);
    }
}

void Matcher::fail(char lo,char hi) {
    if(pos == max_pos+1) {
        if(err_pos < pos)
            expected.ranges.clear();
        expected.addRange(lo,hi);
        inrule_max = inrule;
        err_pos = pos;
    }
}

void Matcher::showError() {
	int line = 1;
	int error_pos = -1;
	const int num_previous_lines = 4;
	int start_of_line = 0;
	int start_of_previous_line[num_previous_lines];
	for(int i=0;i<num_previous_lines;i++)
		start_of_previous_line[i] = 0;
	for(int i=0;i<input_size;i++) {
		if(i == max_pos) {
			error_pos = i;
			int column = i - start_of_previous_line[0]+1;
		    std::cout << "In rule '" << inrule_max
			    <<  "' Line=" << line << ", Column=" << column << std::endl;
			while(input[i] == '\n'||input[i] == '\r') {
				line++;
				for(int j=1;j<num_previous_lines;j++) {
					start_of_previous_line[j-1] = start_of_previous_line[j];
				}
				start_of_previous_line[num_previous_lines-1] = start_of_line;
				start_of_line = ++i;
			}
			break;
		}
		if(input[i] == '\n') {
			line++;
			for(int j=1;j<num_previous_lines;j++) {
				start_of_previous_line[j-1] = start_of_previous_line[j];
			}
			start_of_previous_line[num_previous_lines-1] = start_of_line;
			start_of_line = i+1;
		}
	}
    bool eol = false;
	for(int i=start_of_previous_line[0];i<input_size;i++) {
		std::cout << input[i];
		if(i > error_pos && input[i] == '\n') {
            eol = true;
			break;
        }
	}
    if(!eol) std::cout << std::endl;
	for(int i=start_of_line;i<=error_pos;i++)
		std::cout << ' ';
	std::cout << "^" << std::endl;
    std::cout << "Expected one of the following characters: " << expected << std::endl;
}