link-grammar-5.8.0/link-grammar/parse/fast-match.c
/**
 * Forms and returns a list of disjuncts coming from word w, that
 * actually matches lc or rc or both. The lw and rw are the words from
 * which lc and rc came respectively.
 *
 * The list is returned in an array of Match_nodes.  This list
 * contains no duplicates, because when processing the ml list, only
 * elements whose match_left is true are included, and such elements are
 * not included again when processing the mr list.
 *
 * Note that if both lc and rc match the corresponding connectors of w,
 * match_left is set to true when the ml list is processed and the
 * disjunct is then added to the result list, and match_right of the
 * same disjunct is set to true when the mr list is processed, and this
 * disjunct is not added again.
 *
 * "lc optimization" (see below) marks here a special optimization for the
 * left connector (lc): If it is non-NULL and doesn't match a disjunct,
 * there is no need to try to match the right connector (rc), since the
 * linkage count would be 0 in any case. See do_count() for details. In
 * that case we can skip the corresponding match list element, or even
 * immediately return an empty match list if there are no matches for lc.
 */
Forms and returns a list of disjuncts coming from word w, that
actually matches lc or rc or both. The lw and rw are the words from
which lc and rc came respectively.

The list is returned in an array of Match_nodes.  This list
contains no duplicates, because when processing the ml list, only
elements whose match_left is true are included, and such elements are
not included again when processing the mr list.

Note that if both lc and rc match the corresponding connectors of w,
match_left is set to true when the ml list is processed and the
disjunct is then added to the result list, and match_right of the
same disjunct is set to true when the mr list is processed, and this
disjunct is not added again.

"lc optimization"  marks here a special optimization for the
left connector (lc): If it is non-NULL and doesn't match a disjunct,
there is no need to try to match the right connector (rc), since the
linkage count would be 0 in any case. See do_count() for details. In
that case we can skip the corresponding match list element, or even
immediately return an empty match list if there are no matches for lc.
Forms and returns a list of disjuncts coming from word w that actually matches lc or rc or both . The lw and rw are the words from which lc and rc came respectively . The list is returned in an array of Match_nodes . This list contains no duplicates because when processing the ml list only elements whose match_left is true are included and such elements are not included again when processing the mr list . Note that if both lc and rc match the corresponding connectors of w match_left is set to true when the ml list is processed and the disjunct is then added to the result list and match_right of the same disjunct is set to true when the mr list is processed and this disjunct is not added again . " lc optimization " marks here a special optimization for the left connector ( lc ) : If it is non - NULL and doesn ' t match a disjunct there is no need to try to match the right connector ( rc ) since the linkage count would be 0 in any case . See do_count () for details . In that case we can skip the corresponding match list element or even immediately return an empty match list if there are no matches for lc .
size_t
form_match_list(fast_matcher_t *ctxt, int w,
                Connector *lc, int lw,
                Connector *rc, int rw)
{
	Match_node *mx, *mr_end;
	size_t front = get_match_list_position(ctxt);
	Match_node *ml = NULL, *mr = NULL; 
	match_cache mc;
	gword_cache gc = { .same_alternative = false };
	if ((lc != NULL) )
	{
		ml = *get_match_table_entry(ctxt->l_table_size[w], ctxt->l_table[w], lc, 0);
	}
	if ((lc != NULL) && (ml == NULL)) 
		return terminate_match_list(ctxt, -1, front, w, lc, lw, rc, rw);
	if ((rc != NULL) && (w >= rc->farthest_word))
	{
		mr = *get_match_table_entry(ctxt->r_table_size[w], ctxt->r_table[w], rc, 1);
	}
	if ((ml == NULL) && (mr == NULL))
		return terminate_match_list(ctxt, -2, front, w, lc, lw, rc, rw);
#ifdef VERIFY_MATCH_LIST
	static int id = 0;
	int lid = ++id; 
#else
	const int lid = 0;
#endif
	for (mx = mr; mx != NULL; mx = mx->next)
	{
		if (mx->d->right->nearest_word > rw) break;
		mx->d->match_left = false;
	}
	mr_end = mx;
	mc.desc = NULL;
	gc.gword = NULL;
	for (mx = ml; mx != NULL; mx = mx->next)
	{
		if (mx->d->left->nearest_word < lw) break;
		if (lw < mx->d->left->farthest_word) continue;
		mx->d->match_left = do_match_with_cache(mx->d->left, lc, &mc) &&
		                    alt_connection_possible(mx->d->left, lc, &gc);
		if (!mx->d->match_left) continue;
		mx->d->match_right = false;
#ifdef VERIFY_MATCH_LIST
		mx->d->match_id = lid;
#endif
		push_match_list_element(ctxt, mx->d);
	}
	if ((lc != NULL) && is_no_match_list(ctxt, front)) 
		return terminate_match_list(ctxt, -3, front, w, lc, lw, rc, rw);
	mc.desc = NULL;
	gc.gword = NULL;
	for (mx = mr; mx != mr_end; mx = mx->next)
	{
		if (rw > mx->d->right->farthest_word) continue;
		if ((lc != NULL) && !mx->d->match_left) continue; 
		mx->d->match_right = do_match_with_cache(mx->d->right, rc, &mc) &&
			                  alt_connection_possible(mx->d->right, rc, &gc);
		if (!mx->d->match_right || mx->d->match_left) continue;
#ifdef VERIFY_MATCH_LIST
		mx->d->match_id = lid;
#endif
		push_match_list_element(ctxt, mx->d);
	}
	return terminate_match_list(ctxt, lid, front, w, lc, lw, rc, rw);
}
size_t form_match_list ( fast_matcher_t * ctxt , int w , Connector * lc , int lw , Connector * rc , int rw ) { Match_node * mx , * mr_end ; size_t front = get_match_list_position ( ctxt ) ; Match_node * ml = NULL , * mr = NULL ; match_cache mc ; gword_cache gc = { . same_alternative = false } ; if ( ( lc != NULL ) ) { ml = * get_match_table_entry ( ctxt -> l_table_size [ w ] , ctxt -> l_table [ w ] , lc , 0 ) ; } if ( ( lc != NULL ) && ( ml == NULL ) ) return terminate_match_list ( ctxt , -1 , front , w , lc , lw , rc , rw ) ; if ( ( rc != NULL ) && ( w >= rc -> farthest_word ) ) { mr = * get_match_table_entry ( ctxt -> r_table_size [ w ] , ctxt -> r_table [ w ] , rc , 1 ) ; } if ( ( ml == NULL ) && ( mr == NULL ) ) return terminate_match_list ( ctxt , -2 , front , w , lc , lw , rc , rw ) ; #ifdef VERIFY_MATCH_LIST static int id = 0 ; int lid = ++ id ; #else const int lid = 0 ; #endif for ( mx = mr ; mx != NULL ; mx = mx -> next ) { if ( mx -> d -> right -> nearest_word > rw ) break ; mx -> d -> match_left = false ; } mr_end = mx ; mc . desc = NULL ; gc . gword = NULL ; for ( mx = ml ; mx != NULL ; mx = mx -> next ) { if ( mx -> d -> left -> nearest_word < lw ) break ; if ( lw < mx -> d -> left -> farthest_word ) continue ; mx -> d -> match_left = do_match_with_cache ( mx -> d -> left , lc , & mc ) && alt_connection_possible ( mx -> d -> left , lc , & gc ) ; if ( ! mx -> d -> match_left ) continue ; mx -> d -> match_right = false ; #ifdef VERIFY_MATCH_LIST mx -> d -> match_id = lid ; #endif push_match_list_element ( ctxt , mx -> d ) ; } if ( ( lc != NULL ) && is_no_match_list ( ctxt , front ) ) return terminate_match_list ( ctxt , -3 , front , w , lc , lw , rc , rw ) ; mc . desc = NULL ; gc . gword = NULL ; for ( mx = mr ; mx != mr_end ; mx = mx -> next ) { if ( rw > mx -> d -> right -> farthest_word ) continue ; if ( ( lc != NULL ) && ! mx -> d -> match_left ) continue ; mx -> d -> match_right = do_match_with_cache ( mx -> d -> right , rc , & mc ) && alt_connection_possible ( mx -> d -> right , rc , & gc ) ; if ( ! mx -> d -> match_right || mx -> d -> match_left ) continue ; #ifdef VERIFY_MATCH_LIST mx -> d -> match_id = lid ; #endif push_match_list_element ( ctxt , mx -> d ) ; } return terminate_match_list ( ctxt , lid , front , w , lc , lw , rc , rw ) ; }
Forms and returns a list of disjuncts coming from word w, that
 actually matches lc or rc or both.
Forms and returns a list of disjuncts coming from word w that actually matches lc or rc or both .
/* Initialize in case of NULL lc or rc. */ /* Get the lists of candidate matching disjuncts of word w for lc and
	 * rc. Consider each of these lists only if the farthest_word of lc/rc
	 * reaches at least the word w.
	 * Note: The commented out (w <= lc->farthest_word) is checked at the
	 * callers and is left here for documentation. */ /* && (w <= lc->farthest_word) */ /* lc optimization */ /* A local copy, for multi-threading support. */ /* Construct the list of things that could match the left. */ /* lc optimization */ /* Append the list of things that could match the right.
	 * Note that it is important to set here match_right correctly even
	 * if we are going to skip this element here because its match_left
	 * is true, since then it means it is already included in the match
	 * list. */ /* lc optimization */