Exemple #1
0
/**
 * 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;
}
Exemple #2
0
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;
}