void gwordlist_append(Gword ***arrp, Gword *p) { size_t n = gwordlist_len((const Gword **)*arrp); *arrp = gwordlist_resize(*arrp, n); (*arrp)[n] = p; }
/** * Replace "count" words from the position "start" by word "wnew". */ static void wordlist_replace(Gword ***arrp, size_t start, size_t count, const Gword *wnew) { size_t n = gwordlist_len((const Gword **)(*arrp+start+count)); memmove(*arrp+start+1, *arrp+start+count, (n+1) * sizeof(Gword *)); (*arrp)[start] = (Gword *)wnew; }
/** * Construct word paths (one or more) through the Wordgraph. * * Add 'current_word" to the potential path. * Add "p" to the path queue, which defines the start of the next potential * paths to be checked. * * Each path is up to the current word (not including). It doesn't actually * construct a full path if there are null words - they break it. The final path * is constructed when the Wordgraph termination word is encountered. * * Note: The final path doesn't match the linkage word indexing if the linkage * contains empty words, at least until empty words are eliminated from the * linkage (in compute_chosen_words()). Further processing of the path is done * there in case morphology splits are to be hidden or there are morphemes with * null linkage. */ static void wordgraph_path_append(Wordgraph_pathpos **nwp, const Gword **path, Gword *current_word, /* add to the path */ Gword *p) /* add to the path queue */ { size_t n = wordgraph_pathpos_len(*nwp); assert(NULL != p, "Tried to add a NULL word to the word queue"); /* Check if the path queue already contains the word to be added to it. */ if (NULL != *nwp) { const Wordgraph_pathpos *wpt; for (wpt = *nwp; NULL != wpt->word; wpt++) { if (p == wpt->word) { /* If we are here, there are 2 or more paths leading to this word * (p) that end with the same number of consecutive null words that * consist an entire alternative. These null words represent * different ways to split the subword upward in the hierarchy, but * since they don't have linkage we don't care which of these * paths is used. */ return; /* The word is already in the queue */ } } } /* Not already in the path queue - add it. */ *nwp = wordgraph_pathpos_resize(*nwp, n); (*nwp)[n].word = p; if (MT_INFRASTRUCTURE == p->prev[0]->morpheme_type) { /* Previous word is the Wordgraph dummy word. Initialize the path. */ (*nwp)[n].path = NULL; } else { /* We branch to another path. Duplicate it from the current path and add * the current word to it. */ size_t path_arr_size = (gwordlist_len(path)+1)*sizeof(*path); (*nwp)[n].path = malloc(path_arr_size); memcpy((*nwp)[n].path, path, path_arr_size); } /* FIXME (cast) but anyway gwordlist_append() doesn't modify Gword. */ gwordlist_append((Gword ***)&(*nwp)[n].path, current_word); }
GNUC_UNUSED void print_hier_position(const Gword *word) { const Gword **p; fflush(stdout); fprintf(stderr, "[Word %zu:%s hier_position(hier_depth=%zu): ", word->node_num, word->subword, word->hier_depth); assert(2*word->hier_depth==gwordlist_len(word->hier_position), "word '%s'", word->subword); for (p = word->hier_position; NULL != *p; p += 2) { fprintf(stderr, "(%zu:%s/%zu:%s)", p[0]->node_num, debug_show_subword(p[0]), p[1]->node_num, debug_show_subword(p[1])); } fprintf(stderr, "]\n"); }