def possRole(semR, env, opts): traceSyntR("possRole", semR) if semR.get_concept() == "amr-unknown": env.push(PP(P("of"), Pro("whom"))) opts.add("a", "?") else: syntR = makeSyntR(semR) if isinstance(syntR, D): env.put(":D", syntR) elif isinstance(syntR, Pro): concept = semR.concept if concept != None: env.put(":D", makePoss(concept)) elif isinstance(semR.instance, SemanticRep.SemanticRep): ref = semR.instance.get_concept() poss = D("my") if isNoun(ref): g = nouns[ref]["g"] env.put(":D", poss.g(g if g != None else "n")) elif isPronoun(ref): poss.props = pronounOptions[ref] env.put( ":D", poss.g(pronounOptions[ref]["g"] if "g" in pronounOptions[ref] else "m")) else: env.put(":D", poss) else: env.put(":D", makePoss(syntR.lemma)) else: env.push(PP(P("of"), syntR))
def scaleRole(semR, env, opts): traceSyntR("scaleRole", semR) semR_c = semR.get_concept() if (semR_c == "celsius"): env.push(PP(makeSyntR(semR), N("degree"), Q("Celsius"))) else: env.push(PP(P("on"), D("the"), makeSyntR(semR), N("scale")))
def timeRole(semR, env, opts): 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) traceSyntR("timeRole", semR) syntR = makeSyntR(semR) concept = semR.get_concept() if concept == 'date-entity': # very frequent case env.push(PP(P("on"), syntR)) return return processTime(concept, syntR)
def durationRole(semR, env, opts): traceSyntR("durationRole", semR) if semR.get_concept() == "amr-unknown": env.unshift(Q("how long")) opts.add("a", "?") else: addPrep("for", semR, env)
def ageRole(semR, env, opts): traceSyntR("ageRole", semR) if semR.get_concept() == "amr-unknown": env.unshift(Q("how old")) opts.add("a", "?") else: env.push(makeSyntR(semR).lier()) env.push(A("old"))
def modRole(semR, env, opts): def simpleModNoun(concept, neg): ## check for "simple" cases if concept in [ "all", "many", "both", "no", "too", "any", "other", "some", "one", "kind-yy", "then", "such" ]: env.put(":D", Q("kind of" if concept == "kind-yy" else concept)) if neg: env.unshift(Q("not")) if concept in ["all", "many", "both"]: opts.add("n", "p") elif concept in determiners: env.put(":D", D(concept)) elif is_number(concept): env.push(NO(concept)) elif isNoun(concept): ## prefix the :mod for nouns newNoun = N(nouns[concept].lemma) # keep only noun from NP if ":A" in env: env.insertAfter(":A", ":A", newNoun) else: env.put(":A", newNoun) if neg: env.insertBefore(":A", ":A", Q("non")) elif isAdjective(concept): ## postfix the :mod for adjectives newAdj = A(adjectives[concept].lemma) if ":A" in env: env.insertAfter(":A", ":A", newAdj) else: env.put(":A", newAdj) if neg: env.insertBefore(":A", ":A", Q("non")) elif isAdverb(concept): env.put(":D", Adv(concept)) elif isVerb(concept): env.push(V(re.sub(r"-\d+$", '', concept)).t("pr")) elif semR.roles.areEmpty(): ## equivalent to processSimpleModOther env.push(Q(generateConceptWord(concept))) else: return False return True traceSyntR("modRole", semR) concept = semR.get_concept() if concept == None: env.push(makeSyntR(semR)) return roles = semR.roles neg = False if hasNegPolarity( roles): # negation will be applied to the generated relative neg = True if roles.areEmpty(): simpleModNoun(concept, neg) return syntR = makeSyntR(semR) if isinstance(syntR, (N, NP)): env.push(PP(P("of"), syntR)) else: rel = relative(concept, syntR) if neg: rel.typ({"neg": True}) env.push(rel)
def makeSyntR(semR, checkSpecial=True): # checkSpecial is False when called from within specialConcept.checkSpecialConcept # to avoid infinite loop traceSyntR("makeSyntR", semR) concept = semR.concept if concept == None: # l'instance réfère à un autre AMR return instance2SyntR(semR) if checkSpecial: sConcept = specialConcept.checkSpecialConcept(semR) if sConcept != None: traceSyntR("special concept", concept) return sConcept # evaluate each role to build the environment dictInfo = getSyntR(concept) env = Env() opts = Options() roles = semR.get_roles() if isVerb(concept): #only for verbs # HACK for passive : seem to be too aggressive.... so we keep it only for top-level AMR # generate a passive sentence if concept has an :ARG0 and the actual roles does not have :ARG0 but has :ARG1 # %% do not passivate the special case of bear-02 because it is already passive if concept!="bear-02" and semR.parent==None and \ ":ARG0" in verbs[concept].args and ":ARG0" not in semR.roles and ":ARG1" in semR.roles: opts.add("typ", {"pas": True}) roleProcessing.processRoles(concept, roles, [], dictInfo, env, opts) ## patch the syntactic structures for frequent special cases if isVerb(concept): # HACK for changing nominative pronoun to accusative for :ARG1 when :ARG0 is also present if ":ARG1" in env and ":ARG0" in env and isinstance( env[":ARG1"], Pro) and env[":ARG1"].lemma == "I": env[":ARG1"].lemma = "me" elif isAdjective(concept): # adjective with :ARG0 and :ARG1 adj = dictInfo.lemma if ":ARG0" in env and ":ARG1" in env: if isinstance(env[":ARG0"], Pro) and env[":ARG0"].lemma == "me": env[":ARG0"].lemma = "I" if isinstance(env[":ARG1"], Pro) and env[":ARG1"].lemma == "I": env[":ARG0"].lemma = "me" dictInfo = LexSem( adj, "S", [":ARG0", ":ARG1"], lambda arg0, arg1: S( arg0, VP(V("be"), A(adj), pp("for", arg1)))) elif ":ARG1" in env and ":ARG2" in env: if isinstance(env[":ARG1"], Pro) and env[":ARG1"].lemma == "me": env[":ARG1"].lemma = "I" if isinstance(env[":ARG2"], Pro) and env[":ARG2"].lemma == "I": env[":ARG2"].lemma = "me" dictInfo = LexSem( adj, "S", [":ARG1", ":ARG2"], lambda arg1, arg2: S( arg1, VP(V("be"), A(adj), pp("for", arg2)))) elif ":ARG1" in env: if isinstance(env[":ARG1"], Pro) and env[":ARG1"].lemma == "me": env[":ARG1"].lemma = "I" dictInfo = LexSem(adj, "S", [":ARG1"], lambda arg1: S(arg1, VP(V("be"), A(adj)))) syntR = dictInfo.apply(env, opts) return syntR
def politeRole(semR, env, opts): traceSyntR("politeRole", semR) instance = unquote(semR.get_instance()) if instance == "+": env.unshift(Q("Please")) elif instance == "-": env.unshift(Q("F...")) else: errorSyntR(":polite strange value:%s" % instance)
def partOfRole(semR, env, opts): traceSyntR("partOfRole", semR) syntR = makeSyntR(semR) if isinstance(syntR, Pro): poss = makePoss(syntR.lemma) poss.props = syntR.props env.put(":D", poss) else: addPrep("of", semR, env)
def person(concept,roles,env,opts): traceSyntR("person",concept) ## with a single :named role ignore person if ":named" in roles and len(roles)==1: return makeSyntR(roles[":named"]) ## deal with frequent patterns associated with a person #### (p/person :ARG0-of (v / verb)) == ((p/person :*:ARG0 (v / verb :ARG0 p))) #### ==> find verbalization starARG0=roles[":*:ARG0"] if starARG0!=None: starARG0_ARG0=starARG0.roles[":ARG0"] if ":ARG0" in starARG0.roles else None if starARG0_ARG0!=None: if len(starARG0_ARG0.roles)==1: verb=starARG0_ARG0.get_concept() nom=getNominalization(verb) if nom!=None: return addRoles(concept, roles, [":*:ARG0"], nounInfo(nom), env, opts) if re.match(r"have-(org|rel)-role-91",starARG0.get_concept()) and len(starARG0.roles)==2: ##### shortcut : https://www.isi.edu/~ulf/amr/lib/amr-dict.html#shortcuts ### (p2 / person :ARG0-of (h / have-org-role-91 :ARG2 (m / mayor))) == ### [person,\p2,[':*:ARG0',['have-org-role-91',h,[':ARG0',p2], [':ARG2',[mayor,m]]] ==> ### mayor !!! starARG0_ARG2=starARG0.roles[":ARG2"] if starARG0_ARG2!=None: nom=makeSyntR(starARG0_ARG2) if isinstance(nom,(NP,N)): return addRoles(concept, roles, [":*:ARG0"], LexSem("person","NP",[],lambda:nom), env, opts) if re.match(r"have-(org|rel)-role-91",starARG0.get_concept()) and len(starARG0.roles)==3: ##### shortcut : https://www.isi.edu/~ulf/amr/lib/amr-dict.html#shortcuts ### (p / person ### :ARG0-of (h / have-rel-role-91 :ARG1 (i / i):ARG2 (g / mother))) == ### (p person [:*:ARG0 (h2 have-rel-role-91 [:ARG1 ^h ↑h2, ### :ARG2 (m mother [] ↑h2), ### :ARG0 ^p ↑h2] ↑p) ^_]) ### (his/her) mother !!! starARG0_ARG1=starARG0.roles[":ARG1"] starARG0_ARG2=starARG0.roles[":ARG2"] person=None if starARG0_ARG1!=None and starARG0_ARG2!=None and isNoun(starARG0_ARG2.get_concept()): conceptSyntR=makeSyntR(starARG0_ARG2) if starARG0_ARG1.instanceIsRef(): env.put(":D",makePoss(SemR2SyntR.instance2SyntR(starARG0_ARG1))) person=addRoles(concept, starARG0_ARG2.roles,[":ARG1",":ARG2"], LexSem("person","NP",[],lambda:conceptSyntR), env, opts) elif starARG0_ARG1.roles.areEmpty(): starARG0_ARG1concept=starARG0_ARG1.get_concept() if isNoun(starARG0_ARG1concept): env.put(":D",makeSyntR(starARG0_ARG1)) person=addRoles(concept,starARG0_ARG2.roles,[":ARG1",":ARG2",":ARG0"], LexSem("person","NP",[],lambda:conceptSyntR),env,opts) elif isPronoun(starARG0_ARG1concept): conceptSyntR.elements[0]=makePoss(starARG0_ARG1concept) person=addRoles(concept,starARG0_ARG2.roles,[":ARG1",":ARG2",":ARG0"], LexSem("person","NP",[],lambda:conceptSyntR),env,opts) if person!=None: return addRoles(concept, roles, [":*:ARG0"],LexSem("person","NP",[],lambda:person), env, opts) return namedEntity(concept,roles,env,opts)
def wikiRole(semR, env, opts): traceSyntR("wikiRole", semR) name = semR.get_instance() if name == "-": return None ## uncomment the following line for adding links to Wikipedia # it is now commented to ease comparisons... opts.add("tag", ("a", { "href": "https://en.wikipedia.org/wiki/" + unquote(name) }))
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 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 number(concept,roles,env,opts): traceSyntR("number", concept) if ":*:quant" in roles: roles1=roles[":*:quant"].get_roles() if ":quant" in roles1: del roles1[":quant"] dictInfo=nounInfo(concept) env.push(PP(P("of"),makeSyntR(roles[":*:quant"],False).n("p"))) return addRoles(concept,roles,[":*:quant"],dictInfo,env,opts) return addRoles(concept, roles, [":*:quant"], nounInfo(concept), env, opts)
def modal(concept,roles,env,opts): traceSyntR("modal",concept) (adj,arg,option,t)=modals[concept] # print("roles:"+str(roles)) if arg not in roles: return A(adj) argSyntR=makeSyntR(roles[arg]) opts.add("t",t) opts.add("typ",{"mod":option}) return addRoles(concept,roles,[arg],LexSem("modal","S",[],lambda:argSyntR),env,opts)
def comparedToRole(semR, env, opts): traceSyntR("comparedToRole", semR) global comp if comp == "co": env.push(PP(P("than"), makeSyntR(semR))) return if comp == "su": env.push(PP(P("in"), makeSyntR(semR))) return errorSyntR(" :compared-to without :degree:%s in %s" % (semR, semR.parent))
def multisentence(concept,roles,env,opts): traceSyntR("multisentence",concept) # HACK: only works for :snt[1-9] sntKeys=sorted([key for key in roles.keys() if re.fullmatch(r":snt\d",key)]) last=len(sntKeys)-1 multiS=S() for i in range(len(sntKeys)): si=S(makeSyntR(roles[sntKeys[i]])).cap("") if i<last:si.a(".") multiS.add(si) return addRoles(concept, roles, sntKeys,LexSem("multi-sentence","S",[],lambda:multiS), env, opts)
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 liRole(semR, env, opts): traceSyntR("liRole", semR) semR_i = unquote(semR.get_instance()) if semR_i == "-1": env.unshift(Adv("lastly")) elif semR_i == "1": env.unshift(Adv("first")) elif is_number(semR_i): env.unshift(Q("(" + str(semR_i) + ")")) elif semR_i[0] == '"': env.unshift(Q("(" + semR_i + ")"))
def purposeRole(semR, env, opts): traceSyntR("purposeRole", semR) roles = semR.get_roles() if ":ARG0" in roles: # remove useless subject reference to a variable del roles[":ARG0"] syntR = makeSyntR(semR) if isinstance(syntR, S) and isinstance(syntR.elements[0], VP): env.push(PP(P("for"), syntR.elements[0].t("pr"))) else: env.push(PP(P("for"), 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 polarityRole(semR, env, opts): traceSyntR("polarityRole", semR) if unquote(semR.get_instance()) == "-": parent_concept = semR.get_parent_concept() if isVerb(parent_concept): opts.add("typ", {"neg": True}) elif isNoun(parent_concept): env.put(":D", Adv("no")) else: env.unshift(Adv("not")) elif semR.get_concept() == "amr-unknown": opts.add("typ", {"int": "yon"})
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 frequencyRole(semR, env, opts): traceSyntR("frequencyRole", semR) concept = semR.get_concept() instance = semR.get_instance() if concept == None and is_number(instance): if instance == 1: env.push(Adv("once")) elif instance == 2: env.push(D("twice")) else: env.push(NP(NO(instance), N("time"))) else: env.push(makeSyntR(semR))
def governmentOrganization(concept,roles,env,opts): traceSyntR("governmentOrganization", concept) if ":*:ARG0" in roles: if roles[":*:ARG0"].get_concept()=="govern-01": starArg0Roles=roles[":*:ARG0"].roles if len(roles)==1: return addRoles(concept, starArg0Roles, [":ARG0"], nounInfo("government"), env, opts) elif ":ARG1" in starArg0Roles: dictInfo=nounInfo("government") env.push(PP(P("of"),makeSyntR(starArg0Roles[":ARG1"]))) return addRoles(concept, starArg0Roles,[":ARG0",":ARG1"], dictInfo, env, opts) dictInfo=nounInfo("organization") env.put(":A",A("governmental")) return addRoles(concept, roles, [":*:ARG0"], dictInfo, env, opts)
def pathRole(semR, env, opts): traceSyntR("pathRole", semR) concept = semR.get_concept() if concept == "past" and ":op1" in semR.roles: env.push(AdvP(Adv("past"), makeSyntR(semR.roles[":op1"]))) else: syntR = makeSyntR(semR) if isinstance(syntR, Pro): syntR.lemma = "me" else: if isinstance(syntR, (Adv, P, PP)): env.push(syntR) else: env.push(PP(P("via"), syntR))
def locationRole(semR, env, opts): traceSyntR("locationRole", semR) concept = semR.get_concept() roles = semR.roles if concept == "amr-unknown": opts.add("typ", {"int": "whe"}) elif concept == "between" and ":op1" in roles and ":op2" in roles: env.push( CP(C("and"), PP(P("between"), makeSyntR(roles[":op1"])), makeSyntR(roles[":op2"]))) del roles[":op1"] del roles[":op2"] else: if isPreposition(concept) or isAdverb(concept): env.push(makeSyntR(semR)) else: env.push(PP(P("in"), makeSyntR(semR)))
def mannerRole(semR, env, opts): traceSyntR("mannerRole", semR) cManner = semR.get_concept() if cManner == "amr-unknown": opts.add("typ", {"int": "how"}) else: syntR = makeSyntR(semR) if isinstance(syntR, Q): env.push(syntR) elif isinstance(syntR, A): adv = Adv(adverbFromAdjective(syntR.lemma)) adv.props = syntR.props env.push(adv) elif isinstance(syntR, (S, V, VP)): env.push(PP(P("by"), syntR.typ({"prog": True}))) else: addPrep("with", semR, env)
def checkNominalization(concept,roles,env,opts): traceSyntR("checkNominalization", concept) if roles.areEmpty(): if concept in verbalizations and "" in verbalizations[concept]: nominalization=verbalizations[concept][""] return addRoles(nominalization,roles,[],nounInfo(nominalization),env,opts) elif isVerb(concept): verbLemma=re.sub(r"-\d+$","",concept) if verbLemma in morphVerbalizations and "noun" in morphVerbalizations[verbLemma]: nominalization=morphVerbalizations[verbLemma]["noun"] return addRoles(nominalization,roles,[],nounInfo(nominalization),env,opts) else: return None if concept in verbalizations: verbArgs=[key for key in verbalizations[concept].keys() if key!=""] if len(verbArgs)==0:return None for verbArg in verbArgs: if verbArg in roles: subSemR=roles[verbArg] if subSemR.concept in verbalizations[concept][verbArg]: nominalization=verbalizations[concept][verbArg][subSemR.concept] del subSemR.roles[verbArg[2:]] # remove added :ARGi corresponding to the :*:ARGi # splice rest of roles of subSemR into parent roles for rl,sem in subSemR.roles.items(): roles.addRole(rl,sem) del roles[verbArg] return addRoles(nominalization,roles,[],nounInfo(nominalization),env,opts) # process morphVerbalizations if isVerb(concept): verbLemma=re.sub(r"(-\d+)?$",r"",concept) if verbLemma in morphVerbalizations: morphVerb=morphVerbalizations[verbLemma] if ":polarity" in roles: return None #fail if :polarity role is present if ":ARG1" in roles: verbArgs=[key for key in roles.keys() if key!=":ARG1"] if any([isArgOp(arg) for arg in verbArgs]): return None #fail if any :ARGi or :opi is present # OK if :ARG1 is a pronoun that refers to the :ARG0 of the verb of the upper level if roles[":ARG1"].instanceIsRef(): refARG1=roles[":ARG1"].instance instanceRole=refARG1.get_my_role() if ":ARG0" == instanceRole and "noun" in morphVerb: morphVerb=morphVerb["noun"] return addRoles(morphVerb,roles,[":ARG1"],nounInfo(morphVerb),env,opts) # TODO: should check for "actor"... return None
def haveRelRole91(concept,roles,env,opts): traceSyntR("haveRelRole91",concept) # syntR_A=makeSyntR(roles[":ARG0"]) if ":ARG0" in roles else None syntR_B=makeSyntR(roles[":ARG1"]) if ":ARG1" in roles else None if ":ARG2" in roles: relation=makeSyntR(roles[":ARG2"]) if isinstance(syntR_B,Pro) and isinstance(relation,NP): relation.elements[0]=makePoss(syntR_B.lemma) return addRoles(concept, roles, [":ARG1",":ARG2"], LexSem("relation","NP",[":ARG0"],lambda arg0:S(arg0,VP(V("be"),relation))), env, opts) if syntR_B!=None: dictInfo=LexSem("have-relation","S",[":ARG0",":ARG3",":ARG4"], lambda arg0,arg3,arg4:S(arg0,VP(V("be"),relation,syntR_B,arg3,arg4))) return addRoles(concept, roles, [":ARG1",":ARG2"], dictInfo, env, opts) else: return addRoles(concept, roles, [":ARG2"],LexSem("rel-role","NP",[],lambda:relation), env, opts) else: errorSyntR("haveRelRole91 with no :ARG2:\n%s"%concept) return Q("*rel*")