void TranslateGetFeatures(PNode *pn, int tgtlang, int pos, /* RESUTS */ int *tense, int *gender, int *number, int *person, int *degree) { *tense = FeatureGet(pn->lexitem->features, FT_TENSE); *gender = FeatureGet(pn->lexitem->features, FT_GENDER); *number = FeatureGet(pn->lexitem->features, FT_NUMBER); *person = FeatureGet(pn->lexitem->features, FT_PERSON); *degree = FeatureGet(pn->lexitem->features, FT_DEGREE); FeatureDefault(tgtlang, pos, tense, gender, number, person, degree); }
void WordFormBuildLeFeat(char *in, /* RESULTS */ char *out) { int c; if (F_NULL != (c = FeatureGet(in, FT_GENDER))) { *out = c; out++; } *out = FeatureGet(in, FT_POS); out++; *out = FeatureGet(in, FT_LANG); out++; *out = TERM; }
/* Determine whether an adverb can be "shifted" into the VP from the NP, * PP, or AdjP. This is to eliminate supposedly redundant parses. * [W * [W * [B n] * [W [V était]]] * [X * [E * [B pas] * [E [A une]]] * [X [N belle journée]]]] */ Bool Syn_Parse_IsAdvShiftableToVP(PNode *w, PNode *x, int lang) { int w_pos; LexEntry *w_le; PNode *adv_pn; if ((adv_pn = PNodeLeftmost(x)) && adv_pn->feature == F_ADVERB) { if (0.0 == Syn_ParseFilterBW_WB_W(adv_pn, w, 0, lang)) { return(0); } if (!(w_le = PNodeRightmostLexEntry(w))) { return(0); } w_pos = FeatureGet(w_le->features, FT_POS); if (w_pos == F_VERB || w_pos == F_ADVERB) { /* The adverb which is the leftmost terminal of <x> can modify verbs * and it is already to the right of a verb or adverb, so this adverb can * be "shifted" into the verb phrase to its left. No shifting actually * occurs here but this parse is ruled out and it is left to other rules * to introduce the adverb inside the verb phrase. */ return(1); } } return(0); }
void ThetaRoleTextPrint(Text *text, int html, LexEntry *le, ThetaRole *theta_roles, Obj *con, Discourse *dc) { int lang; char buf[DWORDLEN]; lang = FeatureGet(le->features, FT_LANG); ThetaRoleTextPrint1(text, html, lang, TRPOS_NA, N("subj"), theta_roles, con, dc); ThetaRoleTextPrint1(text, html, lang, TRPOS_NA, N("aobj"), theta_roles, con, dc); ThetaRoleTextPrint1(text, html, lang, TRPOS_PRE_VERB, N("expl"), theta_roles, con, dc); LexEntryAddSep(le, le->srcphrase, DWORDLEN-1, buf); if (html) { HTML_TextPrintBoldBeginIfEnglish(text, lang); HTML_TextPrint(text, buf); TextPutc(SPACE, text); HTML_TextPrintBoldEndIfEnglish(text, lang); } else { TextPutword(buf, TERM, text); } ThetaRoleTextPrint1(text, html, lang, TRPOS_POST_VERB_PRE_OBJ, N("expl"), theta_roles, con, dc); ThetaRoleTextPrint1(text, html, lang, TRPOS_NA, N("obj"), theta_roles, con, dc); ThetaRoleTextPrint1(text, html, lang, TRPOS_POST_VERB_POST_OBJ, N("expl"), theta_roles, con, dc); ThetaRoleTextPrint1(text, html, lang, TRPOS_NA, N("iobj"), theta_roles, con, dc); }
void WordFormBuildLinkFeat(char *in, /* RESULTS */ char *out) { int c; if (F_NULL != (c = FeatureGet(in, FT_PARUNIV))) { *out = c; out++; } *out = TERM; }
/* Accepts: * [W [V vais]] * [W [H me] [W [V va]]] * [W [H vraiment] [W [V va]]] * Rejects: * [W [W [V vais]] [B pas]] */ Float Syn_ParseFilter_Verb_Or_InterHB(PNode *w) { int pos; LexEntry *le; if (w->pn1 && w->pn1->feature == F_VERB && w->pn2 == NULL) return(1.0); if (NULL == (le = PNodeLeftmostLexEntry(w))) return(0.0); pos = FeatureGet(le->features, FT_POS); if (pos != F_PRONOUN && pos != F_ADVERB) return(0.0); return(1.0); }
Lexitem *TransformPronoun(Lexitem *in, Obj *to_pronoun_class, Discourse *dc) { LexEntry *le; Word *infl; int gender, number, person; gender = FeatureGet(in->features, FT_GENDER); number = FeatureGet(in->features, FT_NUMBER); person = FeatureGet(in->features, FT_PERSON); if (!(le = ObjToLexEntryGet(to_pronoun_class, F_PRONOUN, F_NULL, dc))) { Dbg(DBGGENER, DBGBAD, "TransformPronoun: 1"); return(in); } if (!(infl = LexEntryGetInflection(le, F_NULL, gender, number, person, F_NULL, F_NULL, 1, dc))) { Dbg(DBGGENER, DBGBAD, "TransformPronoun: 2"); return(in); } return(LexitemCreate(infl->word, le, le->features)); }
/* Used during parsing when parent is not available. */ Bool XBarValidY_MAX(PNode *y) { LexEntry *le; le = PNodeLeftmostLexEntry(y); if (le && F_PREPOSITION == FeatureGet(le->features, FT_POS)) { return(1); } if (y->pn1 && y->pn1->feature == F_ADVERB && y->pn2 && y->pn2->feature == F_PP) { return(XBarValidY_MAX(y->pn2)); } return(0); }
LexEntry *ObjToAbbrev(Obj *obj, int force, Discourse *dc) { int pos; ObjToLexEntry *ole; if (!obj) return(NULL); for (ole = obj->ole; ole; ole = ole->next) { if (F_NULL != FeatureGet(ole->features, FT_PARUNIV)) continue; if (DC(dc).lang != FeatureGet(ole->le->features, FT_LANG)) continue; pos = FeatureGet(ole->le->features, FT_POS); if (pos != F_NOUN && pos != F_ADJECTIVE) continue; if (F_LITERARY == FeatureGet(ole->features, FT_STYLE) && !MorphIsWord(ole->le->srcphrase)) { return(ole->le); } } if (force) { if ((ole = ObjToLexEntryGet1(obj, NULL, "NA", F_NULL, F_NULL, NULL, dc))) { return(ole->le); } } return(NULL); }
/* Find ObjToLexEntry (lexical entry) with similar arguments and usage * to ole_src. * * Example: * obj: N("like-human") * ole_src->theta_roles: 1:subj, 2:obj * ole_src->features: TÔ * tgtlang: F_FRENCH * Returns: * ole->theta_roles: 1:iobj:à 2:subj * ole->le: plaire.Vy * * Multiple possibilities are generated only in the case of multiple * interpretations. todo: Possibly provide more synonyms as an option. */ ObjToLexEntry *ObjToLexEntryTransGet(Obj *obj, int pos, int *theta_filled, int tgtlang, ObjToLexEntry *ole_src, Discourse *dc) { char feat[2]; int save_lang, save_style; GenAdvice save_ga; ObjToLexEntry *ole; /* Set up dc environment. */ save_lang = DC(dc).lang; save_style = DC(dc).style; save_ga = dc->ga; DC(dc).lang = tgtlang; DC(dc).style = FeatureGet(ole_src->features, FT_STYLE); if (DC(dc).style == F_SLANG) DC(dc).style = F_INFORMAL; dc->ga.consistent = 1; /* Prepare features */ feat[0] = pos; feat[1] = TERM; ole = ObjToLexEntryTransGet1(obj, NULL, feat, FeatureGet(ole_src->features, FT_PARUNIV), 0, theta_filled, dc); if (ole == NULL) { Dbg(DBGGENER, DBGBAD, "lexical gap <%s> <%c%c>", M(obj), pos, tgtlang); } /* Restore previous dc environment. */ DC(dc).lang = save_lang; DC(dc).style = save_style; dc->ga = save_ga; return(ole); }
void ObjToLexEntryClearLastused(ObjToLexEntry *ole, Discourse *dc) { int i; for (i = 0; ole; i++, ole = ole->next) { /* * "if (consider[i])" was a nice idea but it doesn't work well when doing * generation to multiple dialects: the dialect-common items get reset * whenever a given dialect finishes the list of lexical items and the * result is that the frequent items for other dialects aren't generated. */ if (DC(dc).lang == FeatureGet(ole->le->features, FT_LANG)) { ole->lastused = UNIXTSNA; } } }
/* Assumes dc is set according to type of speaker. (Generation would normally * be set the same way: generate in American English when talking to an * American...) * todo: Add FT_ADDRESS (useful only for French, to reduce probability of * singular "vous" interpretation when "tu" is expected) * todo: If a parse is accepted using a noncongruent lexical item, consider * updating the speaker model. */ Float LexEntryToObjScore(LexEntryToObj *leo, Discourse *dc) { Float score; if (leo == NULL) return(SCORE_MAX); switch (FeatureGet(leo->features, FT_FREQ)) { /* todoSCORE */ case F_FREQUENT: score = 1.0; break; case F_INFREQUENT: score = 0.2; break; default: score = 0.9; break; } score = ScoreCombine(score, StyleScore(FeatureGet(leo->features, FT_STYLE), DC(dc).style)); score = ScoreCombine(score, DialectScore(FeatureGet(leo->features, FT_DIALECT), DC(dc).dialect)); return(score); }
PNode *TranslateAWord(PNode *pn, PNode *pnp, Obj *max, int pos, int tense, int gender, int number, int person, int degree, int srclang, int tgtlang, Discourse *dc) { int number1; ObjList *p; ObjToLexEntry *ole_src, *ole_tgt; Word *infl; PNode *r, *r1; r = NULL; for (p = TranslateGetAllcons(pn, pn->lexitem ? pn->lexitem->le : NULL); p; p = p->next) { if (ObjIsList(p->obj)) { continue; } /* todo: Put FT_FILTER checks here. */ if (!TranslateGetOles(pos, p->obj, pn->lexitem->le, NULL, tgtlang, dc, &ole_src, &ole_tgt)) { continue; } if (StringIn(F_COMMON_INFL, ole_tgt->features)) { number1 = FeatureGet(ole_tgt->features, FT_NUMBER); } else { number1 = number; } if (!(infl = LexEntryGetInflection(ole_tgt->le, tense, gender, number1, person, F_NULL, degree, 1, dc))) { continue; } r1 = PNodeWord(pos, infl->word, infl->features, ole_tgt->le, p->obj); if (pn->punc[0]) TranslatePunc(r1->punc, pn->punc, srclang, tgtlang); r1->ole = ole_tgt; r1->obj = p->obj; r1->next_altern = r; r = r1; } if (r == NULL) { return(pn); } return(r); }
Float Syn_ParseFilterRX_Y(PNode *r, PNode *x, int lang) { PNode *v_pn; if (x->pn1 && x->pn1->feature == F_S) { if (lang == F_FRENCH) { if (LexEntryConceptIsAncestor(N("conj-pp-subord"), PNodeLeftmostLexEntry(x->pn1)) && LexEntryConceptIsAncestor(N("prep-to"), PNodeLeftmostLexEntry(r))) { /* "à ce que" + indic */ return(1.0); } else if (LexEntryConceptIsAncestor(N("prep-to"), PNodeLeftmostLexEntry(r))) { /* "à" + inf todo: Enforce infinitive? Already enforced by * Syn_ParseFilterZ_X. */ return(1.0); } else if (LexEntryConceptIsAncestor(N("prep-of"), PNodeLeftmostLexEntry(r))) { /* "de" + inf */ return(1.0); } } else { if (Syn_ParsePresPartPrep(PNodeLeftmostLexEntry(r)) && (v_pn = PNodeLeftmost(x)) && v_pn->lexitem && (F_PRESENT_PARTICIPLE == FeatureGet(v_pn->lexitem->features, FT_TENSE))) { /* "to" + pres part */ return(1.0); } else { return(0.0); } } } else { if (!XBarSatisfiesCaseFilter(x, NULL, N("iobj"), lang)) return(0.0); } return(1.0); }
Float Syn_ParseFilterXW_Z(PNode *x, PNode *w, int lang) { int noun_gender, noun_number, noun_person, verb_tense; Obj *cas; PNode *auxverb, *mainverb; if (Syn_Parse_IsOnlyRelativeW(w, lang)) return(0.0); verb_tense = F_NULL; PNodeFindHeadVerb(w, &auxverb, &mainverb); if (auxverb && auxverb->lexitem && (verb_tense = FeatureGet(auxverb->lexitem->features, FT_TENSE)) && (!StringIn(verb_tense, FS_FINITE_TENSE))) { /* Subjects of nonfinite verbs are in objective case. * See Chomsky (1982/1987, p. 207). */ cas = N("obj"); } else { cas = N("subj"); } if (!XBarSatisfiesCaseFilter(x, NULL, cas, lang)) return(0.0); if (x->pn1 && x->pn1->feature == F_S && x->pn2 == NULL && x->pn1->pn1 && x->pn1->pn1->feature == F_VP && x->pn1->pn2 == NULL && x->pn1->pn1->pn1 && x->pn1->pn1->pn1->feature == F_VERB && x->pn1->pn1->pn2 == NULL) { /* The case of an infinitive subject. [X [Z [W [V <garder.fVy¸>]]]] * "Aimer" * This is indeed possible, but it is causing a lot of extra parses. * "Aimer quelqu'un" is allowed. */ return(0.1); /* todoSCORE */ } /* Subject-verb agreement check. */ if (auxverb == NULL) return(1.0); if (auxverb->lexitem == NULL) return(1.0); if (F_IMPERATIVE == FeatureGet(auxverb->lexitem->features, FT_MOOD)) { /* Imperative with subject. */ return(0.2); /* todoSCORE */ } if (!PNodeGetHeadNounFeatures(x, 0, &noun_gender, &noun_number, &noun_person)) { return(1.0); } if (x->pn1 && x->pn2 && x->pn1->feature == F_NP && x->pn2->feature == F_NP && x->pn2->pn1 && x->pn2->pn1->feature == F_CONJUNCTION) { return(1.0); /* todo: Real conjunction agreement rules? */ } #ifdef notdef /* Seems unnecessary in light of FeatureMatch below */ if (F_NULL == noun_person && F_NULL == noun_number) { /* todoSCORE: This is too relaxed? In any case it allows parsing of * Où étais (sic) mon pied gauche ? * Où étaient mes... ? * When would noun_number be F_NULL? */ return(0.6); /* todoSCORE */ } #endif if (F_NULL == noun_person) { /* This is necessary to rule out "I am" where "I" = "isospin". */ noun_person = F_THIRD_PERSON; } if (FeatureMatch(noun_number, FeatureGet(auxverb->lexitem->features, FT_NUMBER)) && FeatureMatch(noun_person, FeatureGet(auxverb->lexitem->features, FT_PERSON))) { return(1.0); } if (Syn_ParseIsNPVerbInversionVP(w, lang)) { /* "What color are elephants? */ return(1.0); } return(0.0); }
/* "Je ne vais pas m'en aller" */ Bool Syn_ParseRightmostIsPronoun(PNode *w) { LexEntry *le; le = PNodeRightmostLexEntry(w); return(le && (F_PRONOUN == FeatureGet(le->features, FT_POS))); }
ThetaRole *ThetaRoleBuild(char *features, LexEntry **les, int lelen, int *delims, int *subcats, Obj *con, ThetaRole *theta_roles_expl) { int i, j, pos, subjfound, subcat, is_optional; LexEntry *le; ThetaRole *trs[MAXCPSIZE], *r; for (j = 0; j < MAXCPSIZE; j++) { trs[j] = NULL; } pos = FeatureGetRequired("ThetaRoleBuild", features, FT_POS); subjfound = 0; if (pos == F_ADJECTIVE || pos == F_NOUN || pos == F_VERB) { #ifdef maxchecking ThetaRoleCheckSubcat(features); #endif /* subj */ if (StringIn(F_SUBJ3, features)) { trs[3] = ThetaRoleCreate(0, ThetaRoleSubjCase(pos), NULL, F_NULL, NULL); subjfound = 1; } if (StringIn(F_SUBJ2, features)) { if (subjfound) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: multiple subjects"); } trs[2] = ThetaRoleCreate(0, ThetaRoleSubjCase(pos), NULL, F_NULL, NULL); subjfound = 1; } if (pos == F_NOUN) { if (subjfound) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: subj defined for noun"); } } else { if (!subjfound) { trs[1] = ThetaRoleCreate(0, ThetaRoleSubjCase(pos), NULL, F_NULL, NULL); subjfound = 1; } } /* obj */ if (ThetaRoleGetSubcat(F_OBJ3, features, &is_optional, &subcat)) { if (trs[3]) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: object index same as subject"); } trs[3] = ThetaRoleCreate(is_optional, N("obj"), NULL, subcat, NULL); } if (ThetaRoleGetSubcat(F_OBJ2, features, &is_optional, &subcat)) { if (trs[2]) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: object index same as subject"); } trs[2] = ThetaRoleCreate(is_optional, N("obj"), NULL, subcat, NULL); } if (ThetaRoleGetSubcat(F_OBJ1, features, &is_optional, &subcat)) { if (trs[1]) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: object index same as subject"); } trs[1] = ThetaRoleCreate(is_optional, N("obj"), NULL, subcat, NULL); } } else { subcat = FeatureGet(features, FT_SUBCAT); if (pos == F_CONJUNCTION || pos == F_PREPOSITION || pos == F_PRONOUN) { if (subcat != F_NULL) { /* todo: Inelegant. In order to hold the subcategorization restriction * for later use by ObjToLexEntryGet2 in generating conjunctions. */ trs[1] = ThetaRoleCreate(0, N("kobj1"), NULL, subcat, NULL); } } else { #ifdef maxchecking if (subcat != F_NULL) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: <%s> unexpected FT_SUBCAT", features); } #endif } #ifdef maxchecking if (F_NULL != FeatureGet(features, FT_SUBJLOC) || F_NULL != FeatureGet(features, FT_OBJLOC)) { Dbg(DBGLEX, DBGBAD, "inapplicable subj/obj location specs <%s>", features); } #endif } if (les) { for (i = 0; i < lelen; i++) { if (delims[i] == LE_PHRASE_PREP || delims[i] == LE_PHRASE_OPT_PREP) { if (!(le = les[i])) { Dbg(DBGLEX, DBGBAD, "ThetaRoleBuild: empty le"); } else { for (j = ThetaRoleIOBJStart(features); j < MAXCPSIZE; j++) { if (trs[j] == NULL) { trs[j] = ThetaRoleCreate(delims[i] == LE_PHRASE_OPT_PREP, N("iobj"), le, subcats[i], NULL); break; } } } } } } for (j = MAXCPSIZE-1; j >= 1; j--) { if (trs[j]) { for (j = j-1; j >= 1; j--) { if (trs[j] == NULL) { trs[j] = ThetaRoleCreate(1, ObjNA, NULL, F_NULL, NULL); } } r = theta_roles_expl; for (j = MAXCPSIZE-1; j >= 1; j--) { if (trs[j]) { trs[j]->next = r; r = trs[j]; } } return(r); } } return(NULL); }
/* todo: Something compatible with the dialect is chosen. * Alter this to PREFER dialect-specific choices? * <value_prop> can also just be value number. */ ObjToLexEntry *ObjToLexEntryGet3(Obj *obj, Obj *value_prop, char *features, char *not_usagefeat, int subcat, int paruniv, int *theta_filled, int pass_two, Discourse *dc) { int i, pos, address; char features1[FEATLEN]; ObjToLexEntry *ole, *p; ole = obj->ole; address = DiscourseAddress(dc); if (dc->ga.qwq && (ISA(N("question-word"), obj) || ISA(N("copula"), obj))) { StringCpy(features1, features, FEATLEN); StringElimChar(features1, F_NOUN); features = features1; } for (i = 0, p = ole; p; i++, p = p->next) { if (i >= MAXOLELEN) { Dbg(DBGGENER, DBGBAD, "increase MAXOLELEN"); break; } pos = FeatureGet(p->le->features, FT_POS); /* todo: For super debugging, if we return NULL from this function, * print out list of why each lexical entry failed. */ consider[i] = ((DC(dc).lang == FeatureGetRequired("ObjToLexEntryGet", p->le->features, FT_LANG)) && StringAnyIn(features, p->le->features) && paruniv == FeatureGet(p->features, FT_PARUNIV) && (subcat == F_NULL || subcat == ThetaRoleGetAnySubcat(p->theta_roles)) && F_NULL == FeatureGet(p->features, FT_CONNOTE) /* todo */ && FeatureDialectMatch(DC(dc).dialect, FeatureGet(p->features, FT_DIALECT)) && DC(dc).style == FeatureGet(p->features, FT_STYLE) && FeatureTaskOK(p->features, dc->task) && FeatureMatch(address, FeatureGet(p->features, FT_ADDRESS)) && (not_usagefeat == NULL || (!StringAnyIn(not_usagefeat, p->features))) && ((pos != F_NOUN) || ISA(N("relation"), obj) || ThetaRoleMatch(theta_filled, p->theta_roles, pass_two))); Nop(); /* Debugging anchor. */ } if (!dc->ga.consistent) { for (i = 0, p = ole; p && i < MAXOLELEN; i++, p = p->next) { if (consider[i] && F_FREQUENT == ((uc)FeatureGet(p->features, FT_FREQ)) && p->lastused == UNIXTSNA) { p->lastused = time(NULL); return(p); } } for (i = 0, p = ole; p && i < MAXOLELEN; i++, p = p->next) { if (consider[i] && F_NULL == FeatureGet(p->features, FT_FREQ) && p->lastused == UNIXTSNA) { p->lastused = time(NULL); return(p); } } if (DC(dc).infrequent_ok) { for (i = 0, p = ole; p && i < MAXOLELEN; i++, p = p->next) { if (consider[i] && F_INFREQUENT == FeatureGet(p->features, FT_FREQ) && p->lastused == UNIXTSNA) { p->lastused = time(NULL); return(p); } } } } if (pass_two) { /* In this case ObjToLexEntryClearLastused has already been done. */ return(NULL); } ObjToLexEntryClearLastused(ole, dc); for (i = 0, p = ole; p && i < MAXOLELEN; i++, p = p->next) { if (consider[i] && F_FREQUENT == FeatureGet(p->features, FT_FREQ)) { p->lastused = time(NULL); return(p); } } for (i = 0, p = ole; p && i < MAXOLELEN; i++, p = p->next) { if (consider[i] && F_NULL == FeatureGet(p->features, FT_FREQ)) { p->lastused = time(NULL); return(p); } } /* Note in this case we do permit the generation of infrequent. */ for (i = 0, p = ole; p && i < MAXOLELEN; i++, p = p->next) { if (consider[i] && F_INFREQUENT == FeatureGet(p->features, FT_FREQ)) { p->lastused = time(NULL); return(p); } } return(NULL); }
/* todo: Avoid enumeration of subjunctive, indicative, and imperative cases? * But these have distinct meanings. */ void TA_LexEntryEnter(Channel *ch, IndexEntry *ie, int prepunc, char *postpunc, char *phrase, char *begin, char *rest, HashTable *ht) { int i, phrase_len, pos, le_len, elision_infl, elision_in; int contraction_infl, contraction_in, noun_added; Float score; Lexitem *lexitem; LexEntry *le_le[MAXLES]; char *le_feat[MAXLES], feat[FEATLEN]; noun_added = 0; le_len = 0; phrase_len = strlen(phrase); /* Inflection collapsing and elimination of noncompatible * contractions/elisions: */ for (; ie; ie = ie->next) { if (ie->lexentry == NULL) continue; if (LexEntryFilterOut(ie->lexentry)) continue; pos = FeatureGet(ie->lexentry->features, FT_POS); if (pos == F_NOUN) noun_added = 1; if (phrase_len == 1 && (pos == F_NOUN || pos == F_ADJECTIVE)) { /* Noun or adjective meanings of single characters are ruled out * here because they should be handled by specialized TAs such as * TA_MediaObject, TA_Name, TA_Product, a formula TA. todoSCORE * todo: Some TA's assume lexical PNodes have been generated here. * If so, they could be marked as "to be ignored by Syn_Parse". * todoSCORE: An adjective followed by single quote (as in I') * is rare? * MRBEGIN * Note this prevents R (MPAA rating) from being parsed. * MREND */ continue; } contraction_infl = StringIn(F_CONTRACTION, ie->features); contraction_in = ((prepunc == SQUOTE) || (prepunc == SQUOTE2)); elision_infl = StringIn(F_ELISION, ie->features); elision_in = ((postpunc[1] == TERM) && ((postpunc[0] == SQUOTE) || (((uc *)postpunc)[0] == SQUOTE2))); if ((elision_infl ? elision_in : 1) && (contraction_infl ? contraction_in : 1)) { /* If an inflection is marked for elision or contraction, then * the input must have a contraction mark. cf "I'm", "isn't" todoSCORE */ TA_LELAdd(ie->lexentry, ie->features, MAXLES, le_le, le_feat, &le_len); } } for (i = 0; i < le_len; i++) { lexitem = LexitemCreate(phrase, le_le[i], HashTableIntern(ht, le_feat[i])); score = 1.0; /* todoSCORE: LexEntryFind phrase should return a score that * indicates the degree of relaxation. */ ChannelAddPNode(ch, PNTYPE_LEXITEM, score, lexitem, postpunc, begin, rest); } if ((!noun_added) && ((prepunc == SQUOTE && StringIn(SQUOTE, postpunc)) || (prepunc == SQUOTE2 && StringIn(SQUOTE2, postpunc)) || (prepunc == LGUILLEMETS && StringIn(RGUILLEMETS, postpunc)) || (prepunc == DQUOTE && StringIn(DQUOTE, postpunc)))) { /* Duplicate quoted lexical items (metalinguistic) as nouns. * Example: What does (the word) "stupid" mean? */ for (i = 0; i < le_len; i++) { FeatSubstPOS(le_feat[i], F_NOUN, feat); lexitem = LexitemCreate(phrase, le_le[i], HashTableIntern(ht, feat)); score = 1.0; ChannelAddPNode(ch, PNTYPE_LEXITEM, score, lexitem, postpunc, begin, rest); } } for (i = 0; i < le_len; i++) { MemFree(le_feat[i], "char TA_LELAdd"); } }