File:  [parser3project] / parser3 / src / main / pa_dictionary.C
Revision 1.33: download - view: text, annotated - select for diffs - revision graph
Sat Apr 25 13:38:46 2026 UTC (5 weeks, 3 days ago) by moko
Branches: MAIN
CVS tags: HEAD
Copyright year updated, websites links changed to https://

/**	@file
	Parser: dictionary class  impl.

	Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
	Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
*/

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

volatile const char * IDENT_PA_DICTIONARY_C="$Id: pa_dictionary.C,v 1.33 2026/04/25 13:38:46 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; ) {
		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;
}

E-mail: