1 #include "word-tag.hpp"
2 #include "fast-sprintf.hpp"
3 
4 extern "C" {
5 #ifdef DEBUG
6 #include "prepare/build-disjuncts.h"    // prt_exp_mem()
7 #endif
8 #include "error.h"
9 #include "tokenize/tok-structures.h"
10 #include "utilities.h"
11 }
12 
13 #define D_IC 8
insert_connectors(Exp * exp,int & dfs_position,bool & leading_right,bool & leading_left,std::vector<int> & eps_right,std::vector<int> & eps_left,char * var,bool root,double parent_cost,Exp * parent_exp,const X_node * word_xnode)14 void WordTag::insert_connectors(Exp* exp, int& dfs_position,
15                                 bool& leading_right, bool& leading_left,
16                                 std::vector<int>& eps_right,
17                                 std::vector<int>& eps_left,
18                                 char* var, bool root, double parent_cost,
19                                 Exp* parent_exp, const X_node *word_xnode)
20 {
21   double cost = parent_cost + exp->cost;
22 
23 #ifdef DEBUG
24   if (0 && verbosity_level(+D_IC)) // Extreme debug
25   //if (_word == 2)
26   {
27     const char*type =
28       ((const char *[]) {"OR_type", "AND_type", "CONNECTOR_type"}) [exp->type-1];
29     printf("Expression type %s for Word%d, var %s:\n", type, _word, var);
30     //printf("parent_exp: %s\n", lg_exp_stringify(parent_exp));
31     printf("exp(%s) e=%.2f pc=%.2f %s\n",
32            word_xnode->string,exp->cost, parent_cost, lg_exp_stringify(exp));
33     if (exp->cost > 0 || root) prt_exp_mem(exp, 0);
34   }
35 #endif
36 
37   if (exp->type == CONNECTOR_type) {
38     dfs_position++;
39 
40     switch (exp->dir) {
41     case '+':
42       _position.push_back(_right_connectors.size());
43       _dir.push_back('+');
44       _right_connectors.push_back(
45            PositionConnector(parent_exp, exp, '+', _word, dfs_position,
46                              cost, parent_cost, leading_right, false,
47                              eps_right, eps_left, word_xnode, _opts));
48       leading_right = false;
49       break;
50     case '-':
51       _position.push_back(_left_connectors.size());
52       _dir.push_back('-');
53       _left_connectors.push_back(
54            PositionConnector(parent_exp, exp, '-', _word, dfs_position,
55                              cost, parent_cost, false, leading_left,
56                              eps_right, eps_left, word_xnode, _opts));
57       leading_left = false;
58       break;
59     default:
60       throw std::string("Unknown connector direction: ") + exp->dir;
61     }
62   } else if (exp->type == AND_type) {
63     if (exp->operand_first == NULL) {
64       /* zeroary and */
65       if (cost != 0)
66       {
67         lgdebug(+D_IC, "EmptyConnector var=%s(%d) cost %.2f pcost %.2f\n",
68                 var, _variables->string(var), cost, parent_cost);
69         _empty_connectors.push_back(EmptyConnector(_variables->string(var),cost));
70       }
71     } else
72       if (exp->operand_first->operand_next == NULL) {
73         /* unary and - skip */
74         insert_connectors(exp->operand_first, dfs_position, leading_right,
75              leading_left, eps_right, eps_left, var, root, cost, parent_exp, word_xnode);
76       } else {
77         int i;
78         Exp* opd;
79 
80         char new_var[MAX_VARIABLE_NAME];
81         char* last_new_var = new_var;
82         char* last_var = var;
83         while ((*last_new_var = *last_var)) {
84           last_new_var++;
85           last_var++;
86         }
87 
88         for (i = 0, opd = exp->operand_first; opd != NULL; opd = opd->operand_next, i++) {
89           char* s = last_new_var;
90           *s++ = 'c';
91           fast_sprintf(s, i);
92 
93           double and_cost = (i == 0) ? cost : 0;
94           insert_connectors(opd, dfs_position, leading_right, leading_left,
95                 eps_right, eps_left, new_var, false, and_cost, parent_exp, word_xnode);
96 
97           if (leading_right) {
98             eps_right.push_back(_variables->epsilon(new_var, '+'));
99           }
100           if (leading_left) {
101             eps_left.push_back(_variables->epsilon(new_var, '-'));
102           }
103         }
104       }
105   } else if (exp->type == OR_type) {
106     if (exp->operand_first != NULL && exp->operand_first->operand_next == NULL) {
107       /* unary or - skip */
108       insert_connectors(exp->operand_first, dfs_position, leading_right, leading_left,
109           eps_right, eps_left, var, root, cost, exp->operand_first, word_xnode);
110     } else {
111       int i;
112       Exp* opd;
113       bool ll_true = false;
114       bool lr_true = false;
115 
116       char new_var[MAX_VARIABLE_NAME];
117       char* last_new_var = new_var;
118       char* last_var = var;
119       while ((*last_new_var = *last_var)) {
120         last_new_var++;
121         last_var++;
122       }
123 
124 #ifdef DEBUG
125       if (0 && verbosity_level(+D_IC)) { // Extreme debug
126         printf("Word%d, var %s OR_type:\n", _word, var);
127         printf("exp mem: "); prt_exp_mem(exp, 0);
128       }
129 #endif
130 
131       for (i = 0, opd = exp->operand_first; opd != NULL; opd = opd->operand_next, i++) {
132         bool lr = leading_right, ll = leading_left;
133         std::vector<int> er = eps_right, el = eps_left;
134 
135         char* s = last_new_var;
136         *s++ = 'd';
137         fast_sprintf(s, i);
138 
139         assert(word_xnode != NULL, "NULL X_node for var %s", new_var);
140         if (root)
141         {
142           lgdebug(+D_IC, "Word%d: var: %s; exp%d=%p; X_node: %s\n",
143                   _word, new_var, i, opd, word_xnode->word->subword);
144         }
145 
146         insert_connectors(opd, dfs_position, lr, ll, er, el, new_var, false, cost, opd, word_xnode);
147 
148         /* For the toplevel X_node-joined OR_type, get the next X_node. */
149         if (root && (word_xnode->next != NULL))
150           word_xnode = word_xnode->next;
151 
152         if (lr)
153           lr_true = true;
154         if (ll)
155           ll_true = true;
156       }
157       leading_right = lr_true;
158       leading_left = ll_true;
159     }
160   }
161 }
162 #undef D_IC
163 
find_matches(int w,Connector * search_cntr,char dir,std::vector<PositionConnector * > & matches)164 void WordTag::find_matches(int w, Connector* search_cntr, char dir, std::vector<PositionConnector*>& matches)
165 {
166   // cout << "Look connection on: ." << _word << ". ." << w << ". " << connector_string(search_cntr) << dir << endl;
167 
168   std::vector<PositionConnector>* connectors;
169   switch(dir) {
170   case '+':
171     connectors = &_left_connectors;
172     break;
173   case '-':
174     connectors = &_right_connectors;
175     break;
176   default:
177     throw std::string("Unknown connector direction: ") + dir;
178   }
179 
180   std::vector<PositionConnector>::iterator i;
181   for (i = connectors->begin(); i != connectors->end(); i++) {
182     if (WordTag::match(w, *search_cntr, dir, (*i).word, ((*i).connector))) {
183       matches.push_back(&(*i));
184     }
185   }
186 }
187 
add_matches_with_word(WordTag & tag)188 void WordTag::add_matches_with_word(WordTag& tag)
189 {
190   std::vector<PositionConnector>::iterator i;
191   for (i = _right_connectors.begin(); i != _right_connectors.end(); i++) {
192     std::vector<PositionConnector*> connector_matches;
193     tag.find_matches(_word, &(*i).connector, '+', connector_matches);
194     std::vector<PositionConnector*>::iterator j;
195     for (j = connector_matches.begin(); j != connector_matches.end(); j++) {
196       i->matches.push_back(*j);
197       set_match_possible((*j)->word, (*j)->position);
198       (*j)->matches.push_back(&(*i));
199       tag.set_match_possible(_word, (*i).position);
200     }
201   }
202 }
203