|
|
| version 1.20, 2003/11/20 16:34:26 | version 1.27, 2015/10/26 01:21:58 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: dictionary class impl. | Parser: dictionary class impl. |
| Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2015 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 * const IDENT_DICTIONARY_C="$Date$"; | |
| #include "pa_dictionary.h" | #include "pa_dictionary.h" |
| #include "pa_exception.h" | #include "pa_exception.h" |
| // could not make this static: gcc complains "prev decl was extern" | volatile const char * IDENT_PA_DICTIONARY_C="$Id$" IDENT_PA_DICTIONARY_H; |
| void pa_dictionary_add_first(Table::element_type row, Dictionary* self) { | |
| // get a=>b values | |
| const String* a=row->get(0); | |
| // empty 'a' check | |
| if(a->is_empty()) { | |
| throw Exception("parser.runtime", | |
| 0, //&a, | |
| "dictionary table 'from' column elements must not be empty"); | |
| } | |
| const String* b; | |
| if(row->count()>1) { // are there any b? | |
| b=row->get(1); | |
| if(b->is_empty()) | |
| b=0; | |
| } else | |
| b=0; | |
| // record simplier 'a' for quick comparisons in 'starts' extremely-tight-callback | Dictionary::Dictionary(Table& atable): substs(atable.count()) { |
| self->substs+=Dictionary::Subst(a->cstr(), b); | // clear starting_lines |
| memset(starting_line_of, 0, sizeof(starting_line_of)); | |
| // grab first letters of first column of a table | |
| constructor_line=1; | |
| unsigned char c=(unsigned char)a->first_char(); | for(Array_iterator<ArrayString*> i(atable); i.has_next(); ) { |
| if(!self->starting_line_of[c]) | ArrayString* row=i.next(); |
| self->starting_line_of[c]=self->constructor_line; | |
| self->constructor_line++; | 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): substs(atable.count()) { | |
| 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; atable.for_each(pa_dictionary_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 |
| Line 61 static bool starts(Dictionary::Subst sub | Line 69 static bool starts(Dictionary::Subst sub |
| } | } |
| Dictionary::Subst Dictionary::first_that_begins(const char* str) const { | Dictionary::Subst Dictionary::first_that_begins(const char* str) const { |
| First_that_begins_info info; | First_that_begins_info info; |
| if(info.line=starting_line_of[(unsigned char)*str]) { | if((info.line=starting_line_of[(unsigned char)*str])) { |
| info.str=str; | info.str=str; |
| return substs.first_that(starts, &info); | return substs.first_that(starts, &info); |
| } else | } else |