def apply(self, env=None, opts=None): if env == None: env = Env() if opts == None: opts = Options() ## process args from dictInfo building the list of arguments or None argV = [env.get(arg) if arg in env else None for arg in self.args] syntR = self.lambda_(*argV) if all([arg == None for arg in argV]) and len(env) == 0: return opts.apply(syntR) if isinstance(syntR, Terminal): if isinstance(syntR, A): if ":ARG1" in env: syntR = S(env.get(":ARG1"), VP(V("be"), syntR)) else: syntR = AP(syntR) elif isinstance(syntR, (Pro, Q, NO)): syntR = SP(syntR) elif isinstance(syntR, Adv): syntR = AdvP(syntR) elif isinstance(syntR, P): syntR = PP(syntR) else: print("** apply: strange syntR:%s:%s" % (type(syntR), syntR)) syntR = SP(syntR) ## add unprocessed args if len(env) > 0: syntR.add(env.get(":start"), 0) syntR.add(env.get(".*")) return opts.apply(syntR)
def causeRole(semR, env, opts): traceSyntR("causeRole", semR) concept = semR.get_concept() if concept == "amr-unknown": opts.add("typ", {"int": "why"}) else: syntR = makeSyntR(semR) if isinstance(syntR, (N, Q)): env.push(SP(C("because"), P("of"), syntR)) else: env.push(SP(C("because"), syntR))
def conditionRole(semR, env, opts): traceSyntR("conditionRole", semR) concept = semR.get_concept() if concept == "as-long-as": roles = semR.get_roles() if ":op1" in roles: env.push(PP(P("as"), A("long"), P("as"), makeSyntR(roles[":op1"]))) return if concept == "otherwise": env.push(SP(C("otherwise"), makeSyntR(semR))) else: env.push(SP(C("if"), makeSyntR(semR)))
def processFrameOpRole(rolei, semRi, env, opts): if semRi.get_concept() == "amr-unknown" and rolei in questionTypes: opts.add("typ", {"int": questionTypes[rolei]}) for roleii, semRii in semRi.roles.items(): env.put(roleii, makeSyntR(semRii)) elif semRi.concept == "amr-choice": opts.add("typ", {"int": "yon"}) roles = semRi.roles if ":op1" in roles: env.push(makeSyntR(roles[":op1"])) if ":op2" in roles: env.push(SP(C("or"), makeSyntR(roles[":op2"]))) else: syntRi = makeSyntR(semRi) if isinstance(syntRi, S): # infinitive when the sentence is a verb without subject if isinstance(syntRi.elements[0], VP): syntRi.elements[0].t("b") env.put(rolei, PP(P("to"), syntRi)) elif semRi.parent != None and semRi.parent.concept not in [ "or", "and" ]: env.put(rolei, syntRi.add(Pro("that"), 0)) else: env.put(rolei, syntRi) elif isinstance(syntRi, Pro) and syntRi.lemma == "I": if (rolei == ":ARG1" and ":ARG0" in env) or re.match( ":ARG[2-9]", rolei): syntRi.lemma = "me" env.put(rolei, syntRi) else: env.put(rolei, syntRi) elif isinstance(syntRi, str): env.put(rolei, Q(syntRi)) else: env.put(rolei, syntRi)
def havePolarity91(concept,roles,env,opts): if ":ARG2" in roles: pol=unquote(roles[":ARG2"].get_instance()) if pol=='-': env.push(AdvP(Adv("not"))) elif pol =='+': env.push(AdvP(Adv("yes"))) return addRoles(concept, roles, [":ARG2"], LexSem("polarity","SP",[],lambda:SP()), env, opts) return None
def ensurePhrase(syntR): if isinstance(syntR, Phrase): return syntR if isinstance(syntR, Terminal): if isinstance(syntR, N): return NP(syntR) if isinstance(syntR, A): return AP(syntR) if isinstance(syntR, V): return VP(syntR) if isinstance(syntR, Adv): return Adv(syntR) return SP(syntR) print("ensurePhrase: type inattendu:%s" % type(syntR))
def domainRole(semR, env, opts): traceSyntR("domainRole", semR) concept = semR.get_concept() if concept in determiners: env.put(":D", D(concept)) elif isPronoun(concept): env.unshift(SP(Pro(concept), V("be"))) else: env.push(VP(V("be"), makeSyntR(semR)))
def concessionRole(semR, env, opts): traceSyntR("concessionRole", semR) syntR = makeSyntR(semR) if isinstance(syntR, (S, SP)): env.push(SP(C("although"), syntR)) elif isinstance(syntR, (AdvP, Adv)): env.push(syntR) else: addPrep("despite", semR, env)
def processTime(concept, syntR): if concept == "amr-unknown": opts.add("typ", {"int": "whn"}) env.push(syntR) elif syntR == A("former"): env.unshift(Adv("formerly")) elif syntR == Q("ex"): env.unshift(syntR) elif syntR == Q("about to"): env.push(Adv("about")) env.push(P("to")) elif isVerb(concept): env.push(SP(C("when"), syntR)) elif isinstance(syntR, A): env.push(Adv(adverbFromAdjective(syntR.lemma))) else: env.push(syntR)
def streetAddress91(concept,roles,env,opts): traceSyntR("streetAddress91", concept) res=SP() for i in range(1,7): argi=":ARG"+str(i) if argi in roles: argi_role=roles[argi] if argi_role.get_concept()==None: res.add(Q(unquote(argi_role.get_instance()))) else: res.add(makeSyntR(argi_role)) return res
def precipitation(wInfo,period,lang): jsrExprs=[] prob_terms=wInfo.get_precipitation_probabilities(period) type_terms=wInfo.get_precipitation_type(period) accum_terms=wInfo.get_precipitation_accumulation(period) for prob_term in prob_terms: prob_val=round(prob_term.infos[0]/10)*10 type_term=get_term_at(type_terms,prob_term.start) if type_term!=None and prob_val>=30: # interesting precipitation if prob_val <= 70 and prob_val!=50: # show probability if lang=="en": prob=NP(NO(prob_val),Q("percent"),N("chance").n("s"),P("of")) else: prob=NP(NO(prob_val),Q("pour cent"),P("de"),N("probabilité").n("s"),P("de")) timePeriod=None else: # probability >= 80% prob=None # indicate beginning or ending start=prob_term.start end=prob_term.end if wInfo.is_in_period(start,period): timePeriod=VP(V("begin" if lang=="en" else "débuter").t("pr"),jsrHour(start%24,lang)) elif wInfo.is_in_period(end,period): timePeriod=VP(V("end" if lang=="en" else "finir").t("pr"),jsrHour(end%24,lang)) else: timePeriod=None jsrExpr=NP(prob,precipitationTypes[type_term.infos[0]][lang],timePeriod) amount_term=get_term_at(accum_terms,prob_term.start) if amount_term!=None: # check for significant amount pcpnType=amount_term.infos[0] amount=amount_term.infos[1] jsrAmount=None if pcpnType=="rain" and amount>=25: jsrAmount=NP(NO(round(amount)),Q("mm")) elif pcpnType=="snow" and amount>=2: jsrAmount=NP(NO(round(amount)),Q("cm")) if jsrAmount!=None: if lang=="en": jsrAmount.add(N("amount"),0) else: jsrAmount.add(N("accumulation"),0).add(P("de"),1) jsrExpr=SP(jsrExpr.a(","),jsrAmount) jsrExprs.append(jsrExpr) return " ".join(realize(jsrExpr,lang) for jsrExpr in jsrExprs)
def processStarRole(role, parentConcept, semR, env): ## determine the pronoun unless it is a special concept if parentConcept in gender: g = gender[parentConcept] if g != 'n': if ":ARG0" == role or (":ARG1" == role and semR.parent != None and ":ARG0" not in semR.parent.roles): pro = Pro("who") else: pro = Pro("whom") else: pro = Pro("that") if semR.get_concept() not in specialConcept.conceptSwitch: semR.roles.delRole(role) syntR = makeSyntR(semR) if isinstance(syntR, (A, AP)): env.put(":A", syntR) elif isinstance(syntR, (N, NP, Adv, AdvP)): env.push(syntR) else: env.push(SP(pro, syntR))
def processRoles(concept, roles, ignoredRoles, dictInfo, env, opts): traceSyntR("processRoles", str(dictInfo)) for (rolei, semRi) in roles.items(): if rolei not in ignoredRoles: if isArgOp(rolei) or (isinstance(dictInfo, LexSem) and rolei in dictInfo.args): processFrameOpRole(rolei, semRi, env, opts) elif rolei.startswith(':*'): processStarRole(rolei[2:], concept, semRi, env) elif rolei in roleSwitch: roleSwitch[rolei](semRi, env, opts) elif rolei.startswith(":conj-"): env.push( SP(C(generateConceptWord(rolei[6:])), makeSyntR(semRi))) elif rolei.startswith(":prep-"): env.push( PP(P(generateConceptWord(rolei[6:])), makeSyntR(semRi))) else: # print("ignored role:"+rolei+":"+semRi.shortStr()) env.push(makeSyntR(semRi)) return dictInfo
def quantity(concept,roles,env,opts): traceSyntR("quantity",concept) if ":quant" in roles: qty=makeSyntR(roles[":quant"]) if ":unit" in roles: unit=makeSyntR(roles[":unit"]) if isinstance(unit,Pro): # get the referenced unit... unit=makeSyntR(roles[":unit"].instance) if isinstance(unit,NP) and qty!=None and isinstance(qty,NO): unit.elements[0]=qty qty=unit elif isinstance(unit,Phrase): qty=unit.add(qty) else: qty=SP(unit,qty) elif len(roles)>1 and isinstance(qty,Terminal): qty=NP(qty) if ":scale" in roles: qty.add(PP(P("on"),makeSyntR(roles[":scale"]),N("scale"))) if ":*:ARG1" in roles: qty.add([D("the"),N("quantity"),Pro("that")]) env.push(qty) return addRoles(concept,roles,[":quant",":unit",":scale"],LexSem("qty","SP",[],lambda:SP()),env,opts)
def op12(lemma,np,prep): return LexSem(lemma,"P",[":op1",":op2"], lambda op1,op2:SP(np,op1,pp(prep,op2)))
addCompound("government-organisation",A("governmental"),N("organization")) addCompound("criminal-organization", A("criminal"), N("organization")) addCompound("religious-group", A("religious"), N("group")) addCompound("ethnic-group",A("ethnic"),N("group")) addCompound("political-movement", A("political"), N("movement")) addCompound("political-party", A("political"), N("party")) addCompound("world-region",N("world"),N("region")) # byline-91 frame arguments # :ARG0 news organization :ARG1 author :ARG2 photographer, illustrator :ARG3 translator :ARG4 means def optOpt(arg,key,val): # optional Option if parameter is not None return addOptions(arg,{key,val}) if arg!=None else None nouns["byline-91"]=LexSem("byline","A",[":ARG0",":ARG1",":ARG2",":ARG3",":ARG4"], lambda arg0,arg1,arg2,arg3,arg4:SP( optOpt(arg0,"a",":"), optOpt(arg1,"a",","),optOpt(arg2,"a",","), optOpt(arg3,"b","Trans:"),optOpt(arg4,optOpt("b","by:")))) nouns["name"]=LexSem("name","N",[":op1",":op2",":op3"],lambda op1,op2,op3:SP(op1,op2,op3) if op1!=None else NP(D("the"),N("name"))) delCat(nouns,"many") delCat(nouns,"less") ### nouns and verbs with specific patterns nouns["amr-choice"]=LexSem("amr-choice","N",[":op1",":op2"], lambda op1,op2:S(D("the"),N("choice"),VP(V("be"),PP(P("between"),op1,C("and"),op2)))) nouns["amr-unintelligible"]=LexSem("amr-unintelligible","N",[":value"], lambda val:SP(val,Q("(unintelligible)"))) adjectives["amr-empty"]=LexSem("amr-empty","A",[],lambda:A("empty")) adjectives["amr-unknown"]=LexSem("amr-unknown","A",[],lambda:A("unknown"))
def haveQuant91(concept,roles,env,opts): traceSyntR("haveQuant91",concept) if ":ARG1" in roles: quant=makeSyntR(roles[":ARG1"]) else: errorSyntR("haveQuant91 without entity:%s"%concept) quant=SP(Q("*entity*")) if isinstance(quant,Terminal): quant=SP(quant) if ":ARG2" in roles: quant.add(makeSyntR(roles[":ARG2"]),0) else: quant.add(NP(D("the"),N("number"),P("of")),0) if ":ARG3" in roles: quant.add(VP(V("be"),makeSyntR(roles[":ARG3"]))) if ":ARG4" in roles: quant.add(PP(P("than"), makeSyntR(roles[":ARG4"]))) if ":ARG5" in roles: quant.add(PP(P("of"),makeSyntR(roles[":ARG5"]))) if ":ARG6" in roles: quant.add(PP(P("for"),makeSyntR(roles[":ARG6"]))) return addRoles(concept, roles, [":ARG1",":ARG2",":ARG3",":ARG4",":ARG5",":ARG6"], LexSem("qty","NP",[],lambda:quant), env, opts)
def dateEntity(concept,roles,env,opts): def zPad(s): #ensure a string of length 2 padded with a 0 if len(s)==2: return s if len(s)==1: return "0"+s if len(s)>2 : return s[0:2] return s def checkDateComp(date,rName,dOptField,length,default): if rName in roles: val=roles[rName].instance if is_number(val) and len(val)<=length: date+=val.rjust(length,"0") dOpt[dOptField]=True else: print("dateEntity: strange %s:%s"%(rName,val)) date+=default else: date+=default return date traceSyntR("dateEntity",concept) if ":time" in roles and roles[":time"].get_concept()=="amr-unknown": return Q("what time is it ?") date="" # ISO format "YYYY-MM-DDTHH:mm:ss" dOpt={"year":False , "month":False , "date":False , "day":False , "hour":False , "minute":False , "second":False , "nat":True, "det":False, "rtime":False} date=checkDateComp(date,":year","year",4,"2021")+"-" date=checkDateComp(date,":month", "month", 2, "01")+"-" date=checkDateComp(date,":day", "date", 2, "01")+"T" if ":time" in roles: timeS=roles[":time"].instance if isinstance(timeS,str) and ":" in timeS: time=unquote(timeS) tParts=time.split(":") if len(tParts)==2: tParts.append("00") if len(tParts)==3: date+=zPad(tParts[0])+":"+zPad(tParts[1])+":"+zPad(tParts[2]) dOpt["hour"]=True dOpt["minute"]=True dOpt["second"]=True if not dOpt["hour"]: date+="00:00:00" dOpt["hour"]=False dOpt["minute"]=False dOpt["second"]=False sp=SP(DT(date+"-05:00").dOpt(dOpt))## HACK: force Montreal time zone if ":timezone" in roles: sp.add(makeSyntR(roles[":timezone"])) if ":weekday" in roles: sp.add(Q(unquote(roles[":weekday"].get_concept()).capitalize()),0) if ":season" in roles: sp.add(Q(unquote(roles[":season"].get_concept())),0) if ":mod" in roles: sp.add(Q(unquote(roles[":mod"].get_concept())),0) if ":dayperiod" in roles: sp.add(Q(unquote(roles[":dayperiod"].get_concept()))) if ":quarter" in roles: sp.add(NP(makeSyntR(roles[":quarter"]).dOpt({"ord":True}),N("quarter"))) if ":year2" in roles: sp.add(makeSyntR(roles[":year2"]).dOpt({"raw":True}).b("-")) if ":era" in roles: sp.add(Q(unquote(roles[":era"].get_instance()))) if ":calendar" in roles: sp.add(N("calendar").a(":")) sp.add(makeSyntR(roles[":calendar"])) if ":decade" in roles: sp.add(makeSyntR(roles[":decade"])) sp.add(Q("s")) return sp
def haveDegree91(concept,roles,env,opts): traceSyntR("haveDegree91",concept) subject=None attribute=None comp="" quant=None if ":ARG1" in roles: arg1=roles[":ARG1"] # print("haveDegree1:",arg1.instanceIsRef()) if not arg1.instanceIsRef(): # do not follow link for subject subject=makeSyntR(arg1) if ":ARG2" in roles: concept=roles[":ARG2"].concept attribute=makeSyntR(roles[":ARG2"]) # HACK: remove spurious pronouns created by starrole if isinstance(attribute, AP) and len(attribute.elements)>1 and isinstance(attribute.elements[1],Pro): del attribute.elements[1] if len(attribute.elements)==1: attribute=attribute.elements[0] else: errorSyntR("have-degree-91 without :ARG2:%s"%concept) return Q("degree-91") if ":mod" in roles: if isinstance(attribute,Terminal): attribute=AP(attribute) attribute.add(makeSyntR(roles[":mod"])) if ":ARG3" in roles: rolesARG3=roles[":ARG3"] deg=rolesARG3.get_concept() moreRoles=rolesARG3.get_roles() if moreRoles!=None and len(moreRoles)>0: if ":quant" in moreRoles: quant=makeSyntR(moreRoles[":quant"]) else: attribute.add(makeSyntR(moreRoles[0][1])) if deg=="more": attribute=attribute.f("co") if quant!=None: attribute=NP(quant,attribute) quant=None comp="co" elif deg=="most": if isinstance(attribute,A): attribute=AP(D("the"),attribute.f("su")) else: attribute=AP(attribute,D("the"),Adv("most")) comp="su" elif deg in ["too","so","less"]: attribute=AdvP(Adv(deg),attribute) if deg=="less": comp="co" elif quant!=None: attribute=AP(attribute,quant) quant=None elif deg=="equal": attribute=AdvP(Adv("as"),attribute,Adv("as")) elif deg=="times": if quant!=None: quant=NP(quant,N("time")) attribute=attribute.f("co") comp="co" else: attribute=AdvP(attribute,Adv(deg)) if ":ARG4" in roles: syntR4=makeSyntR(roles[":ARG4"]) if comp=="co": attribute=PP(attribute,P("than"),syntR4) if quant!=None: attribute.add(quant,0) elif comp=="su": attribute=AP(attribute,Adv("in"),syntR4) else: attribute.add(syntR4) if ":ARG5" in roles: attribute.add(makeSyntR(roles[":ARG5"])) if ":ARG6" in roles: attribute=NP(attribute,makeSyntR(roles[":ARG6"])) # print("have-degree-91:subject:",subject) while ":li" in roles: semR=roles[":li"] del roles[":li"] ## analogous to roleProcessing.lirole semR_i=unquote(semR.get_instance()) if semR_i=="-1": attribute.add(Adv("lastly"),0) elif semR_i=="1": attribute.add(Adv("first"),0) elif is_number(semR_i): attribute.add(Q("("+str(semR_i)+")"),0) elif semR_i[0]=='"': attribute.add(Q("("+semR_i+")"),0) restRoles=addRoles(concept, roles, [":ARG1",":ARG2",":ARG3",":ARG4",":ARG5",":ARG6",":li",":mod",":polarity"], LexSem("degree","SP",[],lambda:SP()),env, opts) if len(restRoles.elements)>0: attribute=ensurePhrase(attribute).add(restRoles) if subject!=None: attribute=predicate(subject,attribute) if hasNegPolarity(roles): return attribute.typ({"neg":True}) else: if hasNegPolarity(roles): return AdvP(Adv("not"),attribute) return attribute