|
|
| version 1.15, 2002/08/01 11:26:50 | version 1.29, 2020/12/15 17:10:35 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: dictionary class impl. | Parser: dictionary class impl. |
| Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2020 Art. Lebedev Studio (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| */ | */ |
| static const char* IDENT_DICTIONARY_C="$Id$"; | |
| #include "pa_dictionary.h" | #include "pa_dictionary.h" |
| #include "pa_exception.h" | #include "pa_exception.h" |
| void Dictionary::add_first(Array::Item *value, void *info) { | volatile const char * IDENT_PA_DICTIONARY_C="$Id$" IDENT_PA_DICTIONARY_H; |
| Dictionary& self=*static_cast<Dictionary *>(info); | |
| Array *row=static_cast<Array *>(value); | Dictionary::Dictionary(Table& atable): substs(atable.count()) { |
| // get a=>b values | // clear starting_lines |
| const String& a=*row->get_string(0); | memset(starting_line_of, 0, sizeof(starting_line_of)); |
| const String& b=*row->get_string(1); | // grab first letters of first column of a table |
| // empty 'a' check | constructor_line=1; |
| if(a.is_empty()) { | |
| Pool& pool=self.pool(); | |
| throw Exception("parser.runtime", | |
| &a, | |
| "dictionary table 'from' column elements must not be empty"); | |
| } | |
| unsigned char c=(unsigned char)a.first_char(); | |
| if(!self.starting_line_of[c]) | |
| self.starting_line_of[c]=self.constructor_line; | |
| double ratio=((double)b.size())/a.size(); | |
| if(ratio>self.fmax_ratio) | |
| self.fmax_ratio=ratio; | |
| self.constructor_line++; | 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(Table& atable, double amin_ratio) : Pooled(atable.pool()), | |
| table(atable), | |
| fmax_ratio(amin_ratio) { | |
| Dictionary::Dictionary(const String& from, const String& to): substs(1) { | |
| // clear starting_lines | // clear starting_lines |
| memset(starting_line_of, 0, sizeof(starting_line_of)); | memset(starting_line_of, 0, sizeof(starting_line_of)); |
| // grab first letters of first column of a table | constructor_line=1; |
| constructor_line=1; table.for_each(add_first, this); | |
| 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 | #ifndef DOXYGEN |
| struct First_that_starts_info { | struct First_that_begins_info { |
| int line; | int line; |
| const char *src; size_t src_size; | const char* str; |
| }; | }; |
| #endif | #endif |
| static void *starts(Array::Item *value, void *info) { | static bool starts(Dictionary::Subst subst, First_that_begins_info* info) { |
| First_that_starts_info& i=*static_cast<First_that_starts_info *>(info); | |
| // skip irrelevant lines | // skip irrelevant lines |
| if(i.line>1) { | if(info->line>1) { |
| --i.line; | --info->line; |
| return 0; | return 0; |
| } | } |
| Array *row=static_cast<Array *>(value); | |
| int partial; | return strncmp(subst.from, info->str, subst.from_length)==0; |
| row->get_string(0)->cmp(partial, i.src, i.src_size); | |
| return ( | |
| partial==0 || // full match | |
| partial==1) // typo left column starts 'src' | |
| ?value:0; | |
| } | } |
| Dictionary::Subst Dictionary::first_that_begins(const char* str) const { | |
| void* Dictionary::first_that_starts(const char *src, size_t src_size) const { | First_that_begins_info info; |
| First_that_starts_info info; | if((info.line=starting_line_of[(unsigned char)*str])) { |
| if(info.line=starting_line_of[(unsigned char)*src]) { | info.str=str; |
| info.src=src; | return substs.first_that(starts, &info); |
| info.src_size=src_size; | |
| return table.first_that(starts, &info); | |
| } else | } else |
| return 0; | return 0; |
| } | } |