#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include "rkconv.h" int malloc_count = 0; Rule::Rule() { lhs = NULL; rhs = NULL; follow = NULL; } Rule::~Rule() { if (lhs){ delete[] lhs; } if (rhs){ delete[] rhs; } if (follow){ delete[] follow; } } Rule &Rule::operator=(RkRule &r) { if (r.lhs){ lhs = new char[strlen(r.lhs)+1]; strcpy (lhs, r.lhs); } else { lhs = NULL; } if (r.rhs){ rhs = new char[strlen(r.rhs)+1]; strcpy (rhs, r.rhs); } else { rhs = NULL; } if (r.follow){ follow = new char[strlen(r.follow)+1]; strcpy (follow, r.follow); } else { follow = NULL; } return *this; } RuleSet::RuleSet(RkRule *rule) { int i; for (nr_rules = 0; rule[nr_rules].lhs; nr_rules++) ; this->rule = new Rule [nr_rules]; for (i = 0; i < nr_rules; i++){ this->rule[i] = rule[i]; } } RuleSet::~RuleSet() { delete[] rule; } RKMap::RKMap(RkRule *rule) { rs = new RuleSet(rule); cl = new SlrClosure(rs, rs->get_nr_rules()); refcount = 0; } RKMap::~RKMap() { delete rs; } void RKMap::print(FILE *fp,char *prefix) { cl->print(fp, prefix); } void RKMap::convert_batch (char* src, char* dst) { cl->convert_batch(src, dst); } int RKMap::get_refcount() { return refcount; } int RKMap::inc_refcount() { return ++refcount; } int RKMap::dec_refcount() { return --refcount; } SlrClosure* RKMap::get_init(void){ return cl; } SlrClosure::SlrClosure (RuleSet* rule, int nr_rule, Rule* cur_rule,size_t pflen) { int i; char c; Rule* r; malloc_count++; // prefix if (cur_rule){ prefix = new char[pflen+1]; strncpy(prefix, cur_rule->lhs, pflen); prefix[pflen] = 0; } else { prefix = ""; } // r this->r = (Rule*)NULL; // is_reduction_only is_reduction_only = true; // next memset (next, 0, sizeof next); /* pflen == strlen(prefix) を保証しておくこと */ for (i = 0; i < nr_rule; i++){ r = rule->get_rule()+i; if (strncmp(prefix, r->lhs, pflen)) continue; if (strlen(r->lhs) == pflen){ /* 還元 */ this->r = r; if (this->r->follow){ is_reduction_only = false; } } else { /* 継続 */ is_reduction_only = false; c = r->lhs[pflen]; if (!next[c]){ next[c] = new SlrClosure (rule, nr_rule, r, pflen+1); } } } } SlrClosure::~SlrClosure(void) { int i; delete[] prefix; for (i = 0; i < 128; i++){ if (next[i]) delete next[i]; } } #define PREFIX fprintf (fp, "%s", prefix); void SlrClosure::print(FILE* fp, char* prefix) { int i; char buf[1000]; PREFIX fprintf (fp, "[%p] prefix:%s\n", this, prefix); if (r){ PREFIX fprintf (fp, " reduction: %s->%s\n", r->lhs, r->rhs); } else { PREFIX fprintf (fp, " reduction: (none)\n"); } PREFIX fprintf (fp, " reduction_only: %d\n", is_reduction_only); for (i = 0; i < 128; i++){ if (next[i]){ sprintf (buf, "%s(%c)", prefix, i); next[i]->print(fp, buf); } } } char *SlrClosure::convert_reduction(char* dst, Rule* r) { strcpy(dst, r->rhs); dst += strlen(dst); return dst; } void SlrClosure::convert_batch(char* src, char* dst) { SlrClosure* cur = this; char* p = src; char* q = dst; do { retry: if (cur->next[*p]) { cur = cur->next[*p]; if (cur->is_reduction_only){ q = convert_reduction(q, cur->r); cur = this; } } else if (cur->r && (!cur->r->follow || strchr(cur->r->follow, *p))) { q = convert_reduction(q, cur->r); cur = this; goto retry; } else if (cur != this){ cur = this; goto retry; } else { } } while (*(++p)); if (cur->r && !cur->r->follow){ convert_reduction(q, cur->r); } } SlrClosure* SlrClosure::convert_iterative(char c, char* dst, SlrClosure* cl) { *dst = '\0'; if (next[c]){ if (next[c]->is_reduction_only){ dst = convert_reduction(dst, next[c]->r); return cl; } return next[c]; } else if (r && (!r->follow || strchr(r->follow, c))){ dst = convert_reduction(dst, r); return cl->convert_iterative(c, dst, cl); // retry } else if (this != cl){ return cl->convert_iterative(c, dst, cl); // retry } return cl; } /// class RKConv RKConv::RKConv() { map = NULL; cur = NULL; flush(); } bool RKConv::push_key(int cin) { char dst[10]; char c = cin & 0x7F; if (!cur) return false; cur = map->convert_iterative(c, dst, cur); if ( !euc_to_cchar(dst) && !is_pending()){ return false; } return true; } void RKConv::flush() { if (map) cur = map->get_init(); outQ.erase(outQ.begin(), outQ.end()); } cchar RKConv::get_cchar() { cchar ret = 0; std::list::iterator i = outQ.begin(); if (i != outQ.end()){ ret = *i; outQ.pop_front(); } return ret; } RKMap* RKConv::select_map(RKMap* m) { RKMap* oldmap = map; const char* p = ""; if (cur) p = cur->get_prefix(); map = m; cur = m->get_init(); while (*p) push_key (*(p++)); map->inc_refcount(); if (oldmap) oldmap->dec_refcount(); return oldmap; } void RKConv::print_map(FILE* fp, char* prefix) { map->print(fp, prefix); } char* RKConv::get_pending_char(char* buf, size_t size) { if (!cur) return NULL; if (strlen(cur->get_prefix()) >= size) return NULL; strcpy(buf, cur->get_prefix()); return buf; } bool RKConv::is_pending() { if (!cur || strlen(cur->get_prefix()) == 0){ return false; } return true; } bool RKConv::back_space() { char buf[10]; if ( get_pending_char(buf,10)){ int l = strlen(buf); int i; flush(); for ( i = 0 ; i < l-1 ; i++){ push_key(buf[i]); } return l>0; } return false; } // private bool RKConv::euc_to_cchar(char* q) { cchar c; unsigned char* p = (unsigned char*)q; bool bConv = false; while (*p){ c = (*(p+1) | (((unsigned int) *p)<<8)) & 0x7F7F; outQ.push_back(c); p += 2; bConv = true; } return bConv; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * End: */