static void record_choice( Parse_set *lset, Connector * llc, Connector * lrc, Parse_set *rset, Connector * rlc, Connector * rrc, Disjunct *ld, Disjunct *md, Disjunct *rd, Parse_set *s) { put_choice_in_set(s, make_choice(lset, llc, lrc, rset, rlc, rrc, ld, md, rd)); }
/** * returns NULL if there are no ways to parse, or returns a pointer * to a set structure representing all the ways to parse. * * This code is similar to do_count() in count.c -- for a good reason: * the do_count() function did a full parse, but didn't actually * allocate an memory structures to hold the parse. This also does * a full parse, but it also allocates and fills out the various * parse structures. */ static Parse_set * mk_parse_set(Sentence sent, fast_matcher_t *mchxt, count_context_t * ctxt, Disjunct *ld, Disjunct *rd, int lw, int rw, Connector *le, Connector *re, unsigned int null_count, bool islands_ok, Parse_info pi) { Disjunct * d, * dis; int start_word, end_word, w; bool Lmatch, Rmatch; unsigned int lnull_count, rnull_count; int i, j; Parse_set *ls[4], *rs[4], *lset, *rset; Parse_choice * a_choice; Match_node * m, *m1; X_table_connector *xt; s64 count; assert(null_count < 0x7fff, "mk_parse_set() called with null_count < 0."); count = table_lookup(ctxt, lw, rw, le, re, null_count); /* assert(count >= 0, "mk_parse_set() called on params that were not in the table."); Actually, we can't assert this, because of the pseudocount technique that's used in count(). It's not the case that every call to mk_parse_set() has already been put into the table. */ if ((count == 0) || (count == -1)) return NULL; xt = x_table_pointer(lw, rw, le, re, null_count, pi); if (xt != NULL) return xt->set; /* we've already computed it */ /* Start it out with the empty set of options. */ /* This entry must be updated before we return. */ xt = x_table_store(lw, rw, le, re, null_count, pi); xt->set->count = count; /* the count we already computed */ /* this count is non-zero */ if (rw == 1 + lw) return xt->set; if ((le == NULL) && (re == NULL)) { if (!islands_ok && (lw != -1)) return xt->set; if (null_count == 0) return xt->set; w = lw + 1; for (dis = sent->word[w].d; dis != NULL; dis = dis->next) { if (dis->left == NULL) { rs[0] = mk_parse_set(sent, mchxt, ctxt, dis, NULL, w, rw, dis->right, NULL, null_count-1, islands_ok, pi); if (rs[0] == NULL) continue; a_choice = make_choice(dummy_set(), lw, w, NULL, NULL, rs[0], w, rw, NULL, NULL, NULL, NULL, NULL); put_choice_in_set(xt->set, a_choice); } } rs[0] = mk_parse_set(sent, mchxt, ctxt, NULL, NULL, w, rw, NULL, NULL, null_count-1, islands_ok, pi); if (rs[0] != NULL) { a_choice = make_choice(dummy_set(), lw, w, NULL, NULL, rs[0], w, rw, NULL, NULL, NULL, NULL, NULL); put_choice_in_set(xt->set, a_choice); } return xt->set; } if (le == NULL) { start_word = lw + 1; } else { start_word = le->word; } if (re == NULL) { end_word = rw; } else { end_word = re->word + 1; } /* This condition can never be true here. It is included so GCC will be able * to optimize the loop over "null_count". Without this check, GCC thinks this * loop may be an infinite loop and it may omit some optimizations. */ if (UINT_MAX == null_count) return NULL; for (w = start_word; w < end_word; w++) { m1 = m = form_match_list(mchxt, w, le, lw, re, rw); for (; m!=NULL; m=m->next) { d = m->d; for (lnull_count = 0; lnull_count <= null_count; lnull_count++) { rnull_count = null_count-lnull_count; /* now lnull_count and rnull_count are the null_counts we're assigning to * those parts respectively */ /* Now, we determine if (based on table only) we can see that the current range is not parsable. */ Lmatch = (le != NULL) && (d->left != NULL) && do_match(le, d->left, lw, w); Rmatch = (d->right != NULL) && (re != NULL) && do_match(d->right, re, w, rw); for (i=0; i<4; i++) { ls[i] = rs[i] = NULL; } if (Lmatch) { ls[0] = mk_parse_set(sent, mchxt, ctxt, ld, d, lw, w, le->next, d->left->next, lnull_count, islands_ok, pi); if (le->multi) ls[1] = mk_parse_set(sent, mchxt, ctxt, ld, d, lw, w, le, d->left->next, lnull_count, islands_ok, pi); if (d->left->multi) ls[2] = mk_parse_set(sent, mchxt, ctxt, ld, d, lw, w, le->next, d->left, lnull_count, islands_ok, pi); if (le->multi && d->left->multi) ls[3] = mk_parse_set(sent, mchxt, ctxt, ld, d, lw, w, le, d->left, lnull_count, islands_ok, pi); } if (Rmatch) { rs[0] = mk_parse_set(sent, mchxt, ctxt, d, rd, w, rw, d->right->next, re->next, rnull_count, islands_ok, pi); if (d->right->multi) rs[1] = mk_parse_set(sent, mchxt, ctxt, d, rd, w,rw,d->right,re->next, rnull_count, islands_ok, pi); if (re->multi) rs[2] = mk_parse_set(sent, mchxt, ctxt, d, rd, w, rw, d->right->next, re, rnull_count, islands_ok, pi); if (d->right->multi && re->multi) rs[3] = mk_parse_set(sent, mchxt, ctxt, d, rd, w, rw, d->right, re, rnull_count, islands_ok, pi); } for (i=0; i<4; i++) { /* this ordering is probably not consistent with that * needed to use list_links */ if (ls[i] == NULL) continue; for (j=0; j<4; j++) { if (rs[j] == NULL) continue; a_choice = make_choice(ls[i], lw, w, le, d->left, rs[j], w, rw, d->right, re, ld, d, rd); put_choice_in_set(xt->set, a_choice); } } if (ls[0] != NULL || ls[1] != NULL || ls[2] != NULL || ls[3] != NULL) { /* evaluate using the left match, but not the right */ rset = mk_parse_set(sent, mchxt, ctxt, d, rd, w, rw, d->right, re, rnull_count, islands_ok, pi); if (rset != NULL) { for (i=0; i<4; i++) { if (ls[i] == NULL) continue; /* this ordering is probably not consistent with * that needed to use list_links */ a_choice = make_choice(ls[i], lw, w, le, d->left, rset, w, rw, NULL /* d->right */, re, /* the NULL indicates no link*/ ld, d, rd); put_choice_in_set(xt->set, a_choice); } } } if ((le == NULL) && (rs[0] != NULL || rs[1] != NULL || rs[2] != NULL || rs[3] != NULL)) { /* evaluate using the right match, but not the left */ lset = mk_parse_set(sent, mchxt, ctxt, ld, d, lw, w, le, d->left, lnull_count, islands_ok, pi); if (lset != NULL) { for (i=0; i<4; i++) { if (rs[i] == NULL) continue; /* this ordering is probably not consistent with * that needed to use list_links */ a_choice = make_choice(lset, lw, w, NULL /* le */, d->left, /* NULL indicates no link */ rs[i], w, rw, d->right, re, ld, d, rd); put_choice_in_set(xt->set, a_choice); } } } } } put_match_list(mchxt, m1); } xt->set->current = xt->set->first; return xt->set; }
Parse_set * parse_set(Disjunct *ld, Disjunct *rd, int lw, int rw, Connector *le, Connector *re, int cost, Parse_info * pi) { /* returns NULL if there are no ways to parse, or returns a pointer to a set structure representing all the ways to parse */ Disjunct * d, * dis; int start_word, end_word, w; int lcost, rcost, Lmatch, Rmatch; int i, j; Parse_set *ls[4], *rs[4], *lset, *rset; Parse_choice * a_choice; Match_node * m, *m1; X_table_connector *xt; int count; assert(cost >= 0, "parse_set() called with cost < 0."); count = table_lookup(lw, rw, le, re, cost); /* assert(count >= 0, "parse_set() called on params that were not in the table."); Actually, we can't assert this, because of the pseudocount technique that's used in count(). It's not the case that every call to parse_set() has already been put into the table. */ if ((count == 0) || (count == -1)) return NULL; xt = x_table_pointer(lw, rw, le, re, cost, pi); if (xt == NULL) { xt = x_table_store(lw, rw, le, re, cost, empty_set(), pi); /* start it out with the empty set of options */ /* this entry must be updated before we return */ } else { return xt->set; /* we've already computed it */ } xt->set->count = count; /* the count we already computed */ /* this count is non-zero */ if (rw == 1+lw) return xt->set; if ((le == NULL) && (re == NULL)) { if (!islands_ok && (lw != -1)) { return xt->set; } if (cost == 0) { return xt->set; } else { w = lw+1; for (dis = local_sent[w].d; dis != NULL; dis = dis->next) { if (dis->left == NULL) { rs[0] = parse_set(dis, NULL, w, rw, dis->right, NULL, cost-1, pi); if (rs[0] == NULL) continue; a_choice = make_choice(dummy_set(), lw, w, NULL, NULL, rs[0], w, rw, NULL, NULL, NULL, NULL, NULL); put_choice_in_set(xt->set, a_choice); } } rs[0] = parse_set(NULL, NULL, w, rw, NULL, NULL, cost-1, pi); if (rs[0] != NULL) { a_choice = make_choice(dummy_set(), lw, w, NULL, NULL, rs[0], w, rw, NULL, NULL, NULL, NULL, NULL); put_choice_in_set(xt->set, a_choice); } return xt->set; } } if (le == NULL) { start_word = lw+1; } else { start_word = le->word; } if (re == NULL) { end_word = rw-1; } else { end_word = re->word; } for (w=start_word; w <= end_word; w++) { m1 = m = form_match_list(w, le, lw, re, rw); for (; m!=NULL; m=m->next) { d = m->d; for (lcost = 0; lcost <= cost; lcost++) { rcost = cost-lcost; /* now lcost and rcost are the costs we're assigning to those parts respectively */ /* Now, we determine if (based on table only) we can see that the current range is not parsable. */ Lmatch = (le != NULL) && (d->left != NULL) && match(le, d->left, lw, w); Rmatch = (d->right != NULL) && (re != NULL) && match(d->right, re, w, rw); for (i=0; i<4; i++) {ls[i] = rs[i] = NULL;} if (Lmatch) { ls[0] = parse_set(ld, d, lw, w, le->next, d->left->next, lcost, pi); if (le->multi) ls[1] = parse_set(ld, d, lw, w, le, d->left->next, lcost, pi); if (d->left->multi) ls[2] = parse_set(ld, d, lw, w, le->next, d->left, lcost, pi); if (le->multi && d->left->multi) ls[3] = parse_set(ld, d, lw, w, le, d->left, lcost, pi); } if (Rmatch) { rs[0] = parse_set(d, rd, w, rw, d->right->next, re->next, rcost, pi); if (d->right->multi) rs[1] = parse_set(d, rd, w,rw,d->right,re->next, rcost, pi); if (re->multi) rs[2] = parse_set(d, rd, w, rw, d->right->next, re, rcost, pi); if (d->right->multi && re->multi) rs[3] = parse_set(d, rd, w, rw, d->right, re, rcost, pi); } for (i=0; i<4; i++) { /* this ordering is probably not consistent with that needed to use list_links */ if (ls[i] == NULL) continue; for (j=0; j<4; j++) { if (rs[j] == NULL) continue; a_choice = make_choice(ls[i], lw, w, le, d->left, rs[j], w, rw, d->right, re, ld, d, rd); put_choice_in_set(xt->set, a_choice); } } if (ls[0] != NULL || ls[1] != NULL || ls[2] != NULL || ls[3] != NULL) { /* evaluate using the left match, but not the right */ rset = parse_set(d, rd, w, rw, d->right, re, rcost, pi); if (rset != NULL) { for (i=0; i<4; i++) { if (ls[i] == NULL) continue; /* this ordering is probably not consistent with that needed to use list_links */ a_choice = make_choice(ls[i], lw, w, le, d->left, rset, w, rw, NULL /* d->right */, re, /* the NULL indicates no link*/ ld, d, rd); put_choice_in_set(xt->set, a_choice); } } } if ((le == NULL) && (rs[0] != NULL || rs[1] != NULL || rs[2] != NULL || rs[3] != NULL)) { /* evaluate using the right match, but not the left */ lset = parse_set(ld, d, lw, w, le, d->left, lcost, pi); if (lset != NULL) { for (i=0; i<4; i++) { if (rs[i] == NULL) continue; /* this ordering is probably not consistent with that needed to use list_links */ a_choice = make_choice(lset, lw, w, NULL /* le */, d->left, /* NULL indicates no link */ rs[i], w, rw, d->right, re, ld, d, rd); put_choice_in_set(xt->set, a_choice); } } } } } put_match_list(m1); } xt->set->current = xt->set->first; return xt->set; }