File: pa_dictionary.C

package info (click to toggle)
parser 3.4.5-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 7,552 kB
  • sloc: cpp: 32,375; sh: 11,487; ansic: 10,849; yacc: 1,361; makefile: 248; awk: 5
file content (77 lines) | stat: -rw-r--r-- 2,113 bytes parent folder | download
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
/**	@file
	Parser: dictionary class  impl.

	Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com)
	Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
*/

#include "pa_dictionary.h"
#include "pa_exception.h"

volatile const char * IDENT_PA_DICTIONARY_C="$Id: pa_dictionary.C,v 1.28 2017/02/07 22:00:42 moko Exp $" IDENT_PA_DICTIONARY_H;

Dictionary::Dictionary(Table& atable): substs(atable.count()) {
	// clear starting_lines
	memset(starting_line_of, 0, sizeof(starting_line_of));
	// grab first letters of first column of a table
	constructor_line=1;

	for(Array_iterator<ArrayString*> i(atable); i.has_next(); ) {
		ArrayString* row=i.next();

		append_subst(
			row->get(0),
			(row->count()>1) ? row->get(1) : 0,
			"dictionary table 'from' column elements must not be empty"
		);
	}
}

Dictionary::Dictionary(const String& from, const String& to): substs(1) {
	// clear starting_lines
	memset(starting_line_of, 0, sizeof(starting_line_of));
	constructor_line=1;

	append_subst(&from, &to);
}


void Dictionary::append_subst(const String* from, const String* to, const char* exception_cstr) {
	if(from->is_empty())
		throw Exception(PARSER_RUNTIME,
			0,
			exception_cstr ? exception_cstr : "'from' must not be empty");

	// record simplier 'from' for quick comparisons in 'starts' extremely-tight-callback
	substs+=Dictionary::Subst(from->cstr(), (to && !to->is_empty()) ? to : 0);

	unsigned char c=(unsigned char)from->first_char();
	if(!starting_line_of[c])
		starting_line_of[c]=constructor_line;

	constructor_line++;
}

#ifndef DOXYGEN
struct First_that_begins_info {
	int line;
	const char* str;
};
#endif
static bool starts(Dictionary::Subst subst, First_that_begins_info* info) {
	// skip irrelevant lines
	if(info->line>1) {
		--info->line;
		return 0;
	}

	return strncmp(subst.from, info->str, subst.from_length)==0;
}
Dictionary::Subst Dictionary::first_that_begins(const char* str) const {
	First_that_begins_info info;
	if((info.line=starting_line_of[(unsigned char)*str])) {
		info.str=str;
		return substs.first_that(starts, &info);
	} else
		return 0;
}