--- parser3/src/main/pa_dictionary.C 2001/08/02 07:00:08 1.2 +++ parser3/src/main/pa_dictionary.C 2012/03/16 09:24:13 1.26 @@ -1,41 +1,77 @@ /** @file Parser: dictionary class impl. - Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - - Author: Alexander Petrosyan (http://design.ru/paf) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char *RCSId="$Id: pa_dictionary.C,v 1.2 2001/08/02 07:00:08 parser Exp $"; #include "pa_dictionary.h" +#include "pa_exception.h" + +volatile const char * IDENT_PA_DICTIONARY_C="$Id: pa_dictionary.C,v 1.26 2012/03/16 09:24:13 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 i(atable); i.has_next(); ) { + ArrayString* row=i.next(); -static void add_first(Array::Item *value, void *info) { - Dictionary& self=*static_cast(info); - self.first[(unsigned char)static_cast(value)->get_string(0)->first_char()]=true; + append_subst( + row->get(0), + (row->count()>1) ? row->get(1) : 0, + "dictionary table 'from' column elements must not be empty" + ); + } } -Dictionary::Dictionary(Table& atable) : Pooled(atable.pool()), table(atable) { - // clear firsts - memset(first, 0, sizeof(first)); - // grab first letters of first column of a table - table.for_each(add_first, this); +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); } -static bool starts(Array::Item *value, const void *info) { - Array *row=static_cast(value); - const char *src=static_cast(info); - - int partial; - row->get_string(0)->cmp(partial, src); - return - partial==0 || // full match - partial==1; // typo left column starts 'src' + +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++; } -void* Dictionary::first_that_starts(const char *src) const { - if(first[(unsigned char)*src]) - return table.first_that(starts, src); - else +#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; }