# rules to be in the porttinari_check verificador # # function to be accessed: # # checkSent(b, dump, rep) - it performs all verifications over the sentence 'b', # it prints out the report in the output file 'dump' # it samples the sentences with problems at the 'rep' # - it returns: # - an array with verifications perceived to each rule # - the sentence total number of verifications perceived parserDef = ["P", 69, 64] # identifier of the parser problems, total number of rules, number of strict rules (not warning) ######################### #### REGRAS ######################### msg_Prule01 = "ERRO "+parserDef[0]+"01: Todo token dependente de det é DET (o inverso não é verdadeiro)." msg_Prule02 = "ERRO "+parserDef[0]+"02: Todo token dependente de amod é ADJ (o inverso não é verdadeiro)." msg_Prule03 = "ERRO "+parserDef[0]+"03: Todo token dependente de iobj é PRON, tem feature Case=Dat e lema: ['me', 'te', 'se', 'lhe', 'nos', 'vos', 'lhes'] (o inverso não é verdadeiro)." msg_Prule04 = "ERRO "+parserDef[0]+"04: Todo token dependente de obj que é PRON, tem feature Case=Acc e lema: ['me', 'te', 'se', 'o', 'a', 'nos', 'vos', 'os', 'as', 'lo', 'la', 'los', 'las', 'no', 'na', 'nos', 'nas']." msg_Prule05 = "ERRO "+parserDef[0]+"05: Nenhum ADP é head de relação - Exceções: pode ser head da relação fixed (e se for de fixed, pode ser de punct, cc e conj também), pode ser head de conj se o dependente for ADP, pode ser head de cc se o token ADP for dependente de conj." msg_Prule06 = "ERRO "+parserDef[0]+"06: Nenhum token CCONJ é head de relação - Exceção: pode ser head da relação fixed (e se for de fixed, pode ser de punct também), pode ser head de conj dependente de CCONJ." msg_Prule07 = "ERRO "+parserDef[0]+"07: Nenhum SCONJ é head de relação - Exceções: pode ser head da relação fixed (e se for de fixed, pode ser de punct, cc e conj também), pode ser head de conj se o dependente for SCONJ, pode ser head de cc se o token SCONJ for dependente de conj." msg_Prule08 = "ERRO "+parserDef[0]+"08: Nenhum DET é head de relação - Exceções: pode ser head das relações punct e fixed (e se for de fixed, pode ser de cc e conj também), pode ser head de conj se o dependente for DET, pode ser head de cc se o token DET for dependente de conj." msg_Prule09 = "ERRO "+parserDef[0]+"09: Um token AUX não pode ser head de relação (exceto punct) se for dependente de aux, aux:pass ou cop." msg_Prule10 = "ERRO "+parserDef[0]+"10: Nenhum token dependente de fixed é head de relação." msg_Prule11 = "ERRO "+parserDef[0]+"11: Todo token head de case só pode ser PROPN, NOUN, PRON, ADJ, NUM, X, INTJ, SYM ou ADV." msg_Prule12 = "ERRO "+parserDef[0]+"12: Nenhum token SCONJ pode ser dependente de nsubj, nsubj:pass, nsubj:outer, csubj, csubj:pass, csubj:outer e obj." msg_Prule13 = "ERRO "+parserDef[0]+"13: Todo token dependente de cop só pode ter lema 'estar' ou 'ser' e sempre deve ser AUX." msg_Prule14 = "ERRO "+parserDef[0]+"14: Dois ou mais tokens dependentes de case não podem apontar para um mesmo token head." msg_Prule15 = "ERRO "+parserDef[0]+"15: Nenhum token PRON pode ser dependente de mark, exceto se for head de fixed." msg_Prule16 = "ERRO "+parserDef[0]+"16: Todo token dependente de aux só pode ter lema = 'ser', 'estar', 'ter', 'haver', 'ir' e 'vir' caso seja vir+Ger ou vir+'a'+Inf." msg_Prule17 = "ERRO "+parserDef[0]+"17: Todo token que é ponto final não pode ter como head um token que não é head de outras relações (exceto se houver apenas um outro token)." msg_Prule18 = "ERRO "+parserDef[0]+"18: Todo token dependente de nummod só pode ser head de advmod, nummod, flat, conj, case, appos, nmod e nmod:spec." msg_Prule19 = "ERRO "+parserDef[0]+"19: Todo token VERB dependente de xcomp nunca é head de uma relação de sujeito: nsubj, nsubj:outer e nsubj:pass." msg_Prule20 = "ERRO "+parserDef[0]+"20: Nenhum token ADJ pode ser head de det." msg_Prule21 = "ERRO "+parserDef[0]+"21: Todo token dependente de aux, aux:pass ou cop tem que ter ser AUX (o inverso não é verdadeiro)." msg_Prule22 = "ERRO "+parserDef[0]+"22: Todo token VERB não pode ser head de case." msg_Prule23 = "ERRO "+parserDef[0]+"23: Todo token head de obl só pode ser VERB, ADJ, ADV ou X. Exceção: também pode ser AUX se o verbo estiver elíptico (o token head de AUX não é VERB)." msg_Prule24 = "ERRO "+parserDef[0]+"24: Todo token dependente de advmod é ADV, ADJ ou qualquer token que seja head de fixed." msg_Prule25 = "ERRO "+parserDef[0]+"25: Todo token dependente de nummod é NUM (o inverso não é verdadeiro)." msg_Prule26 = "ERRO "+parserDef[0]+"26: Todo token dependente de nmod é PROPN, NOUN, NUM, INTJ, SYM, X ou PRON (o inverso não é verdadeiro)." msg_Prule27 = "ERRO "+parserDef[0]+"27: Todo token PUNCT é dependente de punct e vice-versa." msg_Prule28 = "ERRO "+parserDef[0]+"28: Todo token ADP que não é head de fixed e cujo token head é um verbo no infinitivo (VerbForm=Inf) deve ser dependente de mark." msg_Prule29 = "ERRO "+parserDef[0]+"29: Nenhum token PROPN ou NOUN pode ser dependente de appos de um token PROPN ou NOUN. Exceção: se o token head for separado por pontuação do token dependente." msg_Prule30 = "ERRO "+parserDef[0]+"30: Nenhum token head de case pode ser dependente de obj." msg_Prule31 = "ERRO "+parserDef[0]+"31: Nenhum token head de case pode ser dependente de iobj." msg_Prule32 = "ERRO "+parserDef[0]+"32: Todos tokens 'muito', 'muitos', 'muita', 'muitas' que forem ADJ devem ser dependentes de amod. Exceção: caso seja dependente de xcomp ou head de cop." msg_Prule33 = "ERRO "+parserDef[0]+"33: Todos tokens 'pouco', 'poucos', 'pouca', 'poucas' que forem ADJ devem ser dependentes de amod. Exceção: caso seja dependente de xcomp ou head de cop." msg_Prule34 = "ERRO "+parserDef[0]+"34: Todos tokens 'onde', 'quando', 'como' que forem ADV, e não forem head de cop ou fixed, devem ser dependentes de advmod, fixed ou conj (se estiverem coordenadas com outro ADV)." msg_Prule35 = "ERRO "+parserDef[0]+"35: Todo token dependente de expl só pode ser PRON." msg_Prule36 = "ERRO "+parserDef[0]+"36: Nenhum token head de cop é VERB." msg_Prule37 = "ERRO "+parserDef[0]+"37: Não deve haver Deprel projetivas (cruzamento de arcos) para nenhum token." msg_Prule38 = "ERRO "+parserDef[0]+"38: Uma sentença só pode ter um token root e ele deve ser bem formado (head 0, Deprel 'root')" msg_Prule39 = "ERRO "+parserDef[0]+"39: Nenhum token é head de mais de um nsubj." msg_Prule40 = "ERRO "+parserDef[0]+"40: Nenhum token é head de mais de um nsubj:pass." msg_Prule41 = "ERRO "+parserDef[0]+"41: Nenhum token é head de mais de um nsubj:outer." msg_Prule42 = "ERRO "+parserDef[0]+"42: Nenhum token é head de mais de um csubj." msg_Prule43 = "ERRO "+parserDef[0]+"43: Nenhum token é head de mais de um obj." msg_Prule44 = "ERRO "+parserDef[0]+"44: Nenhum token é head de mais de um xcomp." msg_Prule45 = "ERRO "+parserDef[0]+"45: Nenhum token é head de mais de um ccomp." msg_Prule46 = "ERRO "+parserDef[0]+"46: Nenhum token é head de mais de um case." msg_Prule47 = "ERRO "+parserDef[0]+"47: Todo token dependente de appos tem seu head à esquerda." msg_Prule48 = "ERRO "+parserDef[0]+"48: Todo token dependente de mark tem seu head à direita." msg_Prule49 = "ERRO "+parserDef[0]+"49: Todo token dependente de case tem seu head à direita." msg_Prule50 = "ERRO "+parserDef[0]+"50: Todo token dependente de fixed tem seu head à esquerda." msg_Prule51 = "ERRO "+parserDef[0]+"51: Todo token dependente de flat:name tem seu head à esquerda." msg_Prule52 = "ERRO "+parserDef[0]+"52: Nenhum token pode ser simultaneamente head de nsubj e head de nsubj:pass, nsubj e csubj ou nsubj:pass e csubj." msg_Prule53 = "ERRO "+parserDef[0]+"53: Todo token dependente de flat:foreign tem seu head à esquerda." msg_Prule54 = "ERRO "+parserDef[0]+"54: Todo token SCONJ só pode ser dependente de mark, fixed, conj ou discourse. Exceção: se for a palavra 'quanto' pode ser dependente de advcl." msg_Prule55 = "ERRO "+parserDef[0]+"55: Todo token head de nsubj:pass deve ter feature Voice=Pass. Exceção: se o verbo for head de expl:pass." msg_Prule56 = "ERRO "+parserDef[0]+"56: Todo token head de obl:agent deve ter feature Voice=Pass." msg_Prule57 = "ERRO "+parserDef[0]+"57: Todo token head de aux:pass deve ter feature Voice=Pass." msg_Prule58 = "ERRO "+parserDef[0]+"58: Todo token head e dependente de flat:foreign deve ser X." msg_Prule59 = "ERRO "+parserDef[0]+"59: Todo token head e dependente de flat:name deve ser PROPN ou X." msg_Prule60 = "ERRO "+parserDef[0]+"60: Todo token head e dependente de flat deve ser NUM, NOUN ou ADJ e ter NumType." msg_Prule61 = "ERRO "+parserDef[0]+"61: Todo token head de aux ou aux:pass, que não for simultaneamente head de cop, deve ser VERB." msg_Prule62 = "ERRO "+parserDef[0]+"62: A feature 'ExtPos={}' deveria ser utilizada (ou a DEPREL fixed deveria ser removida), mas a etiqueta 'ExtPos' está ausente." msg_Prule63 = "ERRO "+parserDef[0]+"63: A feature 'ExtPos={}' deveria ser utilizada (ou a DEPREL fixed deveria ser removida), mas a etiqueta 'ExtPos={}' foi utilizada." msg_Prule64 = "ERRO "+parserDef[0]+"64: A feature 'ExtPos={}' não deveria ser utilizada pois o token não é HEAD de fixed, retire 'ExtPos' ou corrija a DEPREL fixed." ######################### #### AVISOS ######################### msg_Prule65 = "AVISO "+parserDef[0]+"65: Normalmente, dois ou mais tokens dependentes de cop não podem apontar para um mesmo token head, exceto se o head for head de um nsubj:outer." msg_Prule66 = "AVISO "+parserDef[0]+"66: Normalmente, dois ou mais tokens dependentes de mark não podem apontar para um mesmo token head, exceto se o head for head de um nsubj:outer." msg_Prule67 = "AVISO "+parserDef[0]+"67: Normalmente, todo token dependente de flat:name só pode ser head de cc, case, det, punct, expl, nmod (se o dependente for um número cardinal - NUM NumType=Card) ou amod (se o dependente for um número ordinal - ADJ NumType=Ord)." msg_Prule68 = "AVISO "+parserDef[0]+"68: Normalmente, um token dependente de nmod só pode ter como head tokens PROPN, NOUN, NUM, SYM, X e PRON." msg_Prule69 = "AVISO "+parserDef[0]+"69: Normalmente, todo token PUNCT final tem como head o token root." msg_Prule70 = "AVISO "+parserDef[0]+"70: Normalmente, pontuações pareadas (aspas, parênteses, colchetes, chaves) tem o mesmo head." msg_Prule71 = "AVISO "+parserDef[0]+"71: Normalmente, nenhum token pode ser simultaneamente head de obj e head de ccomp." msg_Prule72 = "AVISO "+parserDef[0]+"72: Normalmente, nenhum token ADJ pode ser head ou dependente de appos." ######################### #### REGRAS ######################### def check01(b,dump): '''Todo dependente de det é DET (o inverso não é verdadeiro)''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "det") and (b[4][i][3] != "DET"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule01), sep="\t", file=dump) return acc def check02(b,dump): '''Todo dependente de amod é ADJ (o inverso não é verdadeiro)''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "amod") and (b[4][i][3] != "ADJ"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule02), sep="\t", file=dump) return acc def check03(b,dump): '''Todo dependente de iobj é PRON, Case=Dat e "me", "te", "se", "lhe", "nos", "vos", "lhes" (o inverso não é verdadeiro)''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "iobj") and \ ((b[4][i][3] != "PRON") or ("Case=Dat" not in b[4][i][5]) or (b[4][i][2] not in ["me", "te", "se", "lhe", "nos", "vos", "lhes"])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule03), sep="\t", file=dump) return acc def check04(b,dump): '''Todo dependente de obj que é PRON, Case=Acc e "me", "te", "se", "o", "a", "nos", "vos", "os", "as", "lo", "la", "los", "las", "no", "na", "nos", "nas" ''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if ((b[4][i][7] == "obj") and (b[4][i][3] == "PRON") and ("Case=Acc" in b[4][i][5])) and \ (b[4][i][2] not in ["me", "te", "se", "o", "a", "nos", "vos", "os", "as", "lo", "la", "los", "las", "no", "na", "nos", "nas"]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0],msg_Prule04 ), sep="\t", file=dump) return acc def check05(b,dump): '''Nenhum ADP é head de relação - Exceções: pode ser head da relação fixed (e se for de fixed, pode ser de punct, cc e conj também), pode ser head de conj se o dependente for ADP, pode ser head de cc se o token ADP for dependente de conj.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "ADP"): target = b[4][i][0] wronghead, puncthead, fixedhead = False, False, False for tk in b[4]: if (tk[6] == target) and (tk[7] not in ["fixed", "punct", "conj", "cc"]): wronghead = True break elif (tk[6] == target) and (tk[7] == "fixed"): fixedhead = True elif (tk[6] == target) and (tk[7] == "punct"): puncthead = True elif (tk[6] == target) and (tk[7] == "conj") and (tk[3] not in ["ADP"]): wronghead = True break elif (tk[6] == target) and (tk[7] == "cc") and (b[4][i][7] != "conj"): wronghead = True break if (wronghead or (puncthead and not fixedhead)): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule05), sep="\t", file=dump) return acc def check06(b,dump): '''Nenhum CCONJ é head de relação - Exceção: pode ser head da relação fixed (e se for de fixed, pode ser de punct também), pode ser head de conj dependente de CCONJ.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "CCONJ"): target = b[4][i][0] wronghead, puncthead, fixedhead = False, False, False for tk in b[4]: if (tk[6] == target) and (tk[7] not in ["fixed", "punct", "conj"]): wronghead = True break elif (tk[6] == target) and (tk[7] == "fixed"): fixedhead = True elif (tk[6] == target) and (tk[7] == "punct"): puncthead = True elif (tk[6] == target) and (tk[7] in ["conj"]) and (tk[3] not in ["CCONJ"]): wronghead = True break if (wronghead and (not puncthead or not fixedhead)): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule06), sep="\t", file=dump) return acc def check07(b,dump): '''Nenhum SCONJ é head de relação - Exceções: pode ser head da relação fixed (e se for de fixed, pode ser de punct, cc e conj também), pode ser head de conj se o dependente for SCONJ, pode ser head de cc se o token SCONJ for dependente de conj.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "SCONJ"): target = b[4][i][0] wronghead, puncthead, fixedhead = False, False, False for tk in b[4]: if (tk[6] == target) and (tk[7] not in ["fixed", "punct", "conj", "cc"]): wronghead = True break elif (tk[6] == target) and (tk[7] == "fixed"): fixedhead = True elif (tk[6] == target) and (tk[7] == "punct"): puncthead = True elif (tk[6] == target) and (tk[7] in ["conj"]) and (tk[3] not in ["SCONJ"]): wronghead = True break elif (tk[6] == target) and (tk[7] == "cc") and (b[4][i][7] != "conj"): wronghead = True break if (wronghead or (puncthead and not fixedhead)): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule07), sep="\t", file=dump) return acc def check08(b,dump): '''Nenhum DET é head de relação - Exceções: pode ser head da relação fixed (e se for de fixed, pode ser de punct, cc e conj também), pode ser head de conj se o dependente for DET, pode ser head de cc se o token DET for dependente de conj.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "DET"): target = b[4][i][0] wronghead = False for tk in b[4]: if (tk[6] == target) and (tk[7] not in ["fixed", "punct", "conj", "cc"]): wronghead = True break elif (tk[6] == target) and (tk[7] in ["conj"]) and (tk[3] not in ["DET"]): wronghead = True break elif (tk[6] == target) and (tk[7] == "cc") and (b[4][i][7] != "conj"): wronghead = True break if (wronghead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule08), sep="\t", file=dump) return acc def check09(b,dump): '''Um token AUX não pode ser head de relação (exceto punct) se for dependente de aux, aux:pass ou cop.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "AUX") and (b[4][i][7] in ["aux", "aux:pass", "cop"]): target = b[4][i][0] for tk in b[4]: if (tk[6] == target) and (tk[7] != "punct"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule09), sep="\t", file=dump) break return acc def check10(b,dump): '''Nenhum token dependente de fixed é head de relação.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "fixed"): target = b[4][i][0] head = False for tk in b[4]: if (tk[6] == target): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule10), sep="\t", file=dump) break return acc def check11(b,dump): '''O head de case só pode ser "PROPN", "NOUN", "PRON", "ADJ", "NUM", "X", "INTJ", "SYM", "ADV" ''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "case"): target = b[4][i][6] wrongHead = False for tk in b[4]: if (tk[0] == target) and (tk[3] not in ["PROPN", "NOUN", "PRON", "ADJ", "NUM", "X", "INTJ", "SYM", "ADV"]): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule11), sep="\t", file=dump) return acc def check12(b,dump): '''Regra 12 : Nenhum token SCONJ pode ser dependente de nsubj, nsubj:pass, nsubj:outer, csubj, csubj:pass, csubj:outer e obj.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "SCONJ"): if (b[4][i][7] in ["nsubj", "nsubj:pass", "nsubj:outer", "csubj", "csubj:pass", "csubj:outer", "obj"]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule12), sep="\t", file=dump) return acc def check13(b,dump): '''P13: O dependente de cop só pode ter lema "estar" ou "ser" e deve ser sempre AUX''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "cop") and ((b[4][i][2] not in ["ser", "estar"]) or (b[4][i][3] != "AUX")): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule13), sep="\t", file=dump) return acc def check14(b,dump): '''Dois ou mais tokens dependentes de case não podem apontar para um mesmo token head.''' acc = 0 heads = [] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "case") and (b[4][i][2] not in ["contra", "exceto", "menos", "salvo", "sem"]): if (b[4][i][6] in heads): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule14), sep="\t", file=dump) else: heads.append(b[4][i][6]) return acc def check15(b,dump): '''Nenhum token PRON pode ser dependente de mark, exceto se for head de fixed.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "PRON"): if (b[4][i][7] in ["mark"]): headfixed = False for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "fixed"): headfixed = True break if (not headfixed): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule15), sep="\t", file=dump) return acc def check16(b,dump): '''Todo token dependente de aux só pode ter lema = 'ser', 'estar', 'ter', 'haver', 'ir' e 'vir' caso seja vir+Ger ou vir+'a'+Inf.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "aux") and (b[4][i][2] not in ["ser", "estar", "ter", "haver", "ir", "vir"]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule16), sep="\t", file=dump) elif ((b[4][i][7] == "aux") and (b[4][i][2] == "vir")) and \ not ((b[4][i+1][3] in ["VERB", "AUX"]) and ("VerbForm=Ger" in b[4][i+1][5])) and \ not ((b[4][i+1][2] == "a") or (b[4][i+2][3] in ["VERB", "AUX"]) and ("VerbForm=Ger" in b[4][i+2][5])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule16), sep="\t", file=dump) return acc def check17(b,dump): '''O ponto final não pode ter como head um token que não é head de outras relações (exceto se houver apenas um outro token)." ''' acc = 0 headTimes = 0 for i in range(len(b[4])): if (b[4][i][6] == b[4][-1][6]): headTimes += 1 if (headTimes < 2) and (b[2] > 2): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule17), sep="\t", file=dump) return acc def check18(b,dump): '''Todo token dependente de nummod só pode ser head de advmod, nummod, flat, conj, case e appos.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nummod"): target = b[4][i][0] wrongHead = False for tk in b[4]: if (tk[6] == target) and (tk[7] not in ["advmod", "nummod", "flat", "conj", "case", "appos", "nmod", "nmod:spec"]): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule18), sep="\t", file=dump) return acc def check19(b,dump): '''Todo token VERB dependente de xcomp nunca é head de uma relação de sujeito: nsubj, nsubj:outer e nsubj:pass.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "xcomp"): target = b[4][i][0] wrongHead = False for tk in b[4]: if (tk[6] == target) and (tk[7] in ["nsubj", "nsubj:outer", "nsubj:pass"]): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule19), sep="\t", file=dump) return acc def check20(b,dump): '''Nenhum token ADJ pode ser head de det.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "det"): target = b[4][i][6] wrongHead = False for tk in b[4]: if (tk[0] == target) and (tk[3] == "ADJ"): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule20), sep="\t", file=dump) return acc def check21(b,dump): '''Todo dependente da deprel aux, aux:pass ou cop tem que ter POS = AUX (o inverso não é verdadeiro) ''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] in ["aux", "aux:pass" "cop"]) and (b[4][i][3] != "AUX"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule21), sep="\t", file=dump) return acc def check22(b,dump): '''Todo token VERB não pode ser head de case.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "case"): target = b[4][i][6] wrongHead = False for tk in b[4]: if (tk[0] == target) and (tk[3] in ["VERB", "AUX"]): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule22), sep="\t", file=dump) return acc def check23(b,dump): '''Todo token head de obl só pode ser VERB, ADJ, ADV ou X. Exceção: também pode ser AUX se o verbo estiver elíptico (o token head de AUX não é VERB).''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "obl"): target = b[4][i][6] wrongHead = False for tk in b[4]: if (tk[0] == target) and (tk[3] not in ["VERB", "ADJ", "ADV", "AUX", "X"]): wrongHead = True break elif (tk[0] == target) and (tk[3] == "AUX"): for ttk in b[4]: if (ttk[0] == tk[6]): if (ttk[3] == "VERB"): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule23), sep="\t", file=dump) return acc def check24(b,dump): '''Todo token dependente de advmod é ADV, ADJ ou qualquer token que seja head de fixed.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "advmod") and (b[4][i][3] not in ["ADV", "ADJ"]): target = b[4][i][0] headFixed = False for tk in b[4]: if (tk[6] == target) and (tk[7] == "fixed"): headFixed = True break if not headFixed: acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule24), sep="\t", file=dump) return acc def check25(b,dump): '''Todo token dependente de nummod é NUM (o inverso não é verdadeiro).''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nummod") and (b[4][i][3] != "NUM"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule25), sep="\t", file=dump) return acc def check26(b,dump): '''Todo token dependente de nmod é PROPN, NOUN, NUM, SYM, INTJ, X ou PRON (o inverso não é verdadeiro).''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nmod") and (b[4][i][3] not in ["PROPN", "NOUN", "NUM", "SYM", "INTJ", "X", "PRON"]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule26), sep="\t", file=dump) return acc def check27(b,dump): '''Todo token PUNCT é dependente de punct e vice-versa.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if ((b[4][i][3] == "PUNCT") and (b[4][i][7] != "punct")) or \ ((b[4][i][3] != "PUNCT") and (b[4][i][7] == "punct")): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule27), sep="\t", file=dump) return acc def check28(b,dump): '''Todo token ADP que não é head de fixed e cujo token head é um verbo no infinitivo (VerbForm=Inf) deve ser dependente de mark.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "ADP"): for tk in b[4]: wrong = False if (tk[6] == b[4][i][0]) and (tk[7] == "fixed"): wrong = False break if (tk[0] == b[4][i][6]) and ("VerbForm=Inf" in tk[5]) and (b[4][i][7] != "mark"): wrong = True if (wrong): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule28), sep="\t", file=dump) return acc def check29(b,dump): '''Nenhum token PROPN ou NOUN pode ser dependente de appos de um token PROPN ou NOUN. Exceção: se o token head for separado por token PUNCT do token dependente.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] in ["NOUN", "PROPN"]) and (b[4][i][7] == "appos"): for j in range(len(b[4])): if (b[4][j][0] == b[4][i][6]) and (b[4][j][3] in ["NOUN", "PROPN"]): wrong = True if (i < j): for k in range(i+1,j): if (b[4][k][3] == "PUNCT"): wrong = False break else: for k in range(j+1,i): if (b[4][k][3] == "PUNCT"): wrong = False break if (wrong): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule29), sep="\t", file=dump) break return acc def check30(b,dump): '''Nenhum token head de case pode ser dependente de obj.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "case"): for tk in b[4]: if (tk[0] == b[4][i][6]): if (tk[7] == "obj"): acc += 1 print("{}\t{}\t{}".format(b[0], tk[0], msg_Prule30), sep="\t", file=dump) break return acc def check31(b,dump): '''Nenhum token head de case pode ser dependente de iobj.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "case"): for tk in b[4]: if (tk[0] == b[4][i][6]): if (tk[7] == "iobj"): acc += 1 print("{}\t{}\t{}".format(b[0], tk[0], msg_Prule31), sep="\t", file=dump) break return acc def check32(b,dump): '''Todos tokens 'muito', 'muitos', 'muita', 'muitas' que forem ADJ devem ser dependentes de amod. Exceção: caso seja dependente de xcomp ou head de cop.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "ADJ") and (b[4][i][2] == "muito"): if (b[4][i][7] not in ["amod", "xcomp"]): wrong = True for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "cop"): wrong = False if (wrong): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule32), sep="\t", file=dump) return acc def check33(b,dump): '''Todos tokens 'pouco', 'poucos', 'pouca', 'poucas' que forem ADJ devem ser dependentes de amod. Exceção: caso seja dependente de xcomp ou head de cop.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "ADJ") and (b[4][i][2] == "pouco"): if (b[4][i][7] not in ["amod", "xcomp"]): wrong = True for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "cop"): wrong = False if (wrong): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule33), sep="\t", file=dump) return acc def check34(b,dump): '''Todos tokens 'onde', 'quando', 'como' que forem ADV, e não forem head de cop ou fixed, devem ser dependentes de advmod, fixed ou conj (se estiverem coordenadas com outro ADV).''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "ADV") and (b[4][i][2] in ["onde", "quando", "como"]): headcopfix, conjADV = False, False for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] in ["cop", "fixed"]): headcopfix = True if (tk[0] == b[4][i][6]) and (tk[3] == "ADV"): conjADV = True if (b[4][i][7] != "advmod") and (b[4][i][7] != "fixed") and (not headcopfix) and (not conjADV): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule34), sep="\t", file=dump) return acc def check35(b,dump): '''Todo token dependente de expl só pode ser PRON.''' acc = 0 for i in range(len(b[4])): if (b[4][i][7] == "expl") and (b[4][i][3] != "PRON"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule35), sep="\t", file=dump) return acc def check36(b,dump): '''Nenhum token head de cop é VERB.''' acc = 0 for i in range(len(b[4])): if (b[4][i][7] == "cop"): for tk in b[4]: if (tk[0] == b[4][i][6]) and (tk[3] == "VERB"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule36), sep="\t", file=dump) return acc def check37(b,dump): '''Não deve haver Deprel projetivas (cruzamento de arcos) para nenhum token ''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]) and (b[4][i][7] != "root") and (b[4][i][6] != "0"): if (b[4][i][0].isdigit()): tkID = eval(b[4][i][0]) else: tkID = 0 if (b[4][i][6].isdigit()): tkHead = eval(b[4][i][6]) else: tkhead = 0 if (tkID < tkHead): for j in range(i+1,len(b[4])): if (b[4][j][0] == b[4][i][6]): break elif ("-" not in b[4][j][0]): if (b[4][j][6].isdigit()): middle = eval(b[4][j][6]) else: middle = 0 if (middle < tkID) or (middle > tkHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule37), sep="\t", file=dump) break elif (tkID > tkHead): for j in range(i-1,0,-1): if (b[4][j][0] == b[4][i][6]): break elif ("-" not in b[4][j][0]): if (b[4][j][6].isdigit()): middle = eval(b[4][j][6]) else: middle = 0 if (middle > tkID) or (middle < tkHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule37), sep="\t", file=dump) break return acc def check38(b,dump): '''Uma sentença só pode ter um root e ele deve ser bem formado (head 0, Deprel 'root') ''' acc = 0 count, x = 0, 0 for i in range(len(b[4])): if (b[4][i][7] == "root") and (b[4][i][6] == "0"): count += 1 if (count > 1): x = i elif ((b[4][i][7] == "root") and (b[4][i][6] != "0")) or \ ((b[4][i][7] != "root") and (b[4][i][6] == "0")): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule38), sep="\t", file=dump) if (count != 1): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][x][0], msg_Prule38), sep="\t", file=dump) return acc def check39(b,dump): '''Nenhum token é head de mais de um nsubj.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nsubj"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule39), sep="\t", file=dump) return acc def check40(b,dump): '''Nenhum token é head de mais de um nsubj:pass.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nsubj:pass"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule40), sep="\t", file=dump) return acc def check41(b,dump): '''Nenhum token é head de mais de um nsubj:outer.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nsubj:outer"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule41), sep="\t", file=dump) return acc def check42(b,dump): '''Nenhum token é head de mais de um csubj.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "csubj"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule42), sep="\t", file=dump) return acc def check43(b,dump): '''Nenhum token é head de mais de um obj.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "csubj"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule43), sep="\t", file=dump) return acc def check44(b,dump): '''Nenhum token é head de mais de um xcomp.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "csubj"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule44), sep="\t", file=dump) return acc def check45(b,dump): '''Nenhum token é head de mais de um ccomp.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "csubj"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule45), sep="\t", file=dump) return acc def check46(b,dump): '''Nenhum token é head de mais de um case.''' acc = 0 deps = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "case"): if (b[4][i][6].isdigit()): deps[eval(b[4][i][6])-1] += 1 for i in range(len(deps)): if (deps[i] > 1): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule46), sep="\t", file=dump) return acc def check47(b,dump): '''Todo token dependente de appos tem seu head à esquerda.''' acc = 0 for i in range(len(b[4])): if (b[4][i][6].isdigit()) and (b[4][i][0].isdigit()): if (b[4][i][7] == "appos") and (eval(b[4][i][6]) > eval(b[4][i][0])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule47), sep="\t", file=dump) return acc def check48(b,dump): '''Todo token dependente de mark tem seu head à direita.''' acc = 0 for i in range(len(b[4])): if (b[4][i][6].isdigit()) and (b[4][i][0].isdigit()): if (b[4][i][7] == "mark") and (eval(b[4][i][6]) < eval(b[4][i][0])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule48), sep="\t", file=dump) return acc def check49(b,dump): '''Todo token dependente de case tem seu head à direita.''' acc = 0 for i in range(len(b[4])): if (b[4][i][6].isdigit()) and (b[4][i][0].isdigit()): if (b[4][i][7] == "case") and (eval(b[4][i][6]) < eval(b[4][i][0])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule49), sep="\t", file=dump) return acc def check50(b,dump): '''Todo token dependente de fixed tem seu head à esquerda.''' acc = 0 for i in range(len(b[4])): if (b[4][i][6].isdigit()) and (b[4][i][0].isdigit()): if (b[4][i][7] == "fixed") and (eval(b[4][i][6]) > eval(b[4][i][0])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule50), sep="\t", file=dump) return acc def check51(b,dump): '''Todo token dependente de flat:name tem seu head à esquerda.''' acc = 0 for i in range(len(b[4])): if (b[4][i][6].isdigit()) and (b[4][i][0].isdigit()): if (b[4][i][7] == "flat:name") and (eval(b[4][i][6]) > eval(b[4][i][0])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule51), sep="\t", file=dump) return acc def check52(b,dump): '''Nenhum token pode ser simultaneamente head de nsubj e head de nsubj:pass, nsubj e csubj ou nsubj:pass e csubj.''' acc = 0 nsubj = [0]*b[2] npass = [0]*b[2] csubj = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]) and (b[4][i][6].isdigit()): if (b[4][i][7] == "nsubj"): nsubj[eval(b[4][i][6])-1] += 1 elif (b[4][i][7] == "nsubj:pass"): npass[eval(b[4][i][6])-1] += 1 elif (b[4][i][7] == "csubj"): csubj[eval(b[4][i][6])-1] += 1 for i in range(b[2]): if ((nsubj[i] > 0) and (npass[i] > 0)) or ((nsubj[i] > 0) and (csubj[i] > 0)) or ((npass[i] > 0) and (csubj[i] > 0)): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule52), sep="\t", file=dump) return acc def check53(b,dump): '''Todo token dependente de flat:foreign tem seu head à esquerda.''' acc = 0 for i in range(len(b[4])): if (b[4][i][6].isdigit()) and (b[4][i][0].isdigit()): if (b[4][i][7] == "flat:foreign") and (eval(b[4][i][6]) > eval(b[4][i][0])): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule53), sep="\t", file=dump) return acc def check54(b,dump): '''Todo token SCONJ só pode ser dependente de mark, fixed, conj ou discourse. Exceção: se for a palavra 'quanto' pode ser dependente de advcl.''' acc = 0 for i in range(len(b[4])): if (b[4][i][3] == "SCONJ") and (b[4][i][7] not in ["mark", "fixed", "conj", "discourse"]): if (b[4][i][2] != "quanto") or (b[4][i][7] != "advcl"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule54), sep="\t", file=dump) return acc def check55(b,dump): '''Todo token head de nsubj:pass deve ter feature Voice=Pass. Exceção: se o verbo for head de expl:pass.''' acc = 0 for i in range(len(b[4])): if (b[4][i][7] == "nsubj:pass"): missingpass, explpass = False, False for tk in b[4]: if (tk[0] == b[4][i][6]) and ("Voice=Pass" not in tk[5]): missingpass = True if (tk[6] == b[4][i][6]) and (tk[7] == "expl:pass"): explpass = True if (missingpass) and (not explpass): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule55), sep="\t", file=dump) return acc def check56(b,dump): '''Todo token head de obl:agent deve ter feature Voice=Pass.''' acc = 0 for i in range(len(b[4])): if (b[4][i][7] == "obl:agent"): for tk in b[4]: if (tk[0] == b[4][i][6]) and ("Voice=Pass" not in tk[5]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule56), sep="\t", file=dump) return acc def check57(b,dump): '''Todo token head de aux:pass deve ter feature Voice=Pass.''' acc = 0 for i in range(len(b[4])): if (b[4][i][7] == "aux:pass"): for tk in b[4]: if (tk[0] == b[4][i][6]) and ("Voice=Pass" not in tk[5]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule57), sep="\t", file=dump) return acc def check58(b,dump): '''Todo token head ou dependente de flat:foreign deve ser X.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "flat:foreign"): if (b[4][i][3] != "X"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule58), sep="\t", file=dump) else: for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "flat:foreign"): if (b[4][i][3] != "X"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule58), sep="\t", file=dump) break return acc def check59(b,dump): '''Todo token head ou dependente de flat:name deve ser PROPN ou X.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "flat:name"): if (b[4][i][3] != "PROPN") and (b[4][i][3] != "X"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule59), sep="\t", file=dump) else: for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "flat:name"): if (b[4][i][3] != "PROPN") and (b[4][i][3] != "X"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule59), sep="\t", file=dump) break return acc def check60(b,dump): '''Todo token head e dependente de flat deve ser NUM, NOUN ou ADJ e ter NumType.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "flat"): if (b[4][i][3] not in ["ADJ", "NOUN", "NUM"]) or ("NumType" not in b[4][i][5]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule60), sep="\t", file=dump) else: for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "flat"): if (b[4][i][3] not in ["ADJ", "NOUN", "NUM"]) or ("NumType" not in b[4][i][5]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule60), sep="\t", file=dump) break return acc def check61(b,dump): '''Todo token head de aux ou aux:pass, que não for simultaneamente head de cop, deve ser VERB.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] in ["aux", "aux:pass"]): for tk in b[4]: if (tk[0] == b[4][i][6]): if (tk[3] != "VERB"): wrong = True for tkk in b[4]: if (tkk[6] == tk[0]) and (tkk[7] == "cop"): wrong = False break if (wrong): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule61), sep="\t", file=dump) break return acc def check62(b,dump): '''P62: A feature 'ExtPos={}' deveria ser utilizada (ou a DEPREL fixed deveria ser removida), mas a etiqueta 'ExtPos' está ausente.''' '''P63: A feature 'ExtPos={}' deveria ser utilizada (ou a DEPREL fixed deveria ser removida), mas a etiqueta 'ExtPos={}' foi utilizada.''' '''P64: A feature 'ExtPos={}' não deveria ser utilizada pois o token não é HEAD de fixed, retire 'ExtPos' ou corrija a DEPREL 'fixed'.''' acc = 0 headFixed = [] for tk in b[4]: if (tk[7] == 'fixed'): if (tk[6] not in headFixed): headFixed.append(tk[6]) for i in range(len(b[4])): if (b[4][i][0] in headFixed): if (b[4][i][7] == "cc"): extpos = "CCONJ" elif (b[4][i][7] == "advmod"): extpos = "ADV" elif (b[4][i][7] == "case"): extpos = "ADP" elif (b[4][i][7] == "mark"): extpos = "SCONJ" elif (b[4][i][3] == "PRON"): extpos = "PRON" else: extpos = b[4][i][3] if ('ExtPos=' not in b[4][i][5]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule62.format(extpos)), sep="\t", file=dump) else: errExtPosID = b[4][i][5].index('ExtPos=')+7 if ("|" in b[4][i][5][errExtPosID:]): errExtPosEnd = b[4][i][5][errExtPosID:].index('|')+errExtPosID errExtPos = b[4][i][5][errExtPosID:errExtPosEnd] else: errExtPos = b[4][i][5][errExtPosID:] if (extpos != errExtPos): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule63.format(extpos, errExtPos)), sep="\t", file=dump) elif ('ExtPos=' in b[4][i][5]): errExtPosID = b[4][i][5].index('ExtPos=')+7 if ("|" in b[4][i][5][errExtPosID:]): errExtPosEnd = b[4][i][5][errExtPosID:].index('|')+errExtPosID errExtPos = b[4][i][5][errExtPosID:errExtPosEnd] else: errExtPos = b[4][i][5][errExtPosID:] acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule64.format(errExtPos)), sep="\t", file=dump) return acc def check63(b,dump): return 0 # already handled in check62 def check64(b,dump): return 0 # already handled in check62 ######################### #### AVISOS ######################### def check65(b,dump): '''Normalmente, dois ou mais tokens dependentes de cop não podem apontar para um mesmo token head, exceto se o head for head de um nsubj:outer.''' acc = 0 heads = [] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "cop"): if (b[4][i][6] in heads): headNSUBJouter = False for j in range(len(b[4])): if (b[4][j][7] == "nsubj:outer") and (b[4][j][6] == b[4][i][6]): headNSUBJouter = True break if not headNSUBJouter: acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule65), sep="\t", file=dump) else: heads.append(b[4][i][6]) return acc def check66(b,dump): '''Normalmente, dois ou mais tokens dependentes de mark não podem apontar para um mesmo token head, exceto se o head for head de um nsubj:outer.''' acc = 0 heads = [] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "mark"): if (b[4][i][6] in heads): headNSUBJouter = False for j in range(len(b[4])): if (b[4][j][7] == "nsubj:outer") and (b[4][j][6] == b[4][i][6]): headNSUBJouter = True break if not headNSUBJouter: acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule66), sep="\t", file=dump) else: heads.append(b[4][i][6]) return acc def check67(b,dump): '''Normalmente, todo token dependente de flat:name só pode ser head de cc, case, det, punct, expl, nmod (se o dependente for um número cardinal - NUM NumType=Card) ou amod (se o dependente for um número ordinal - ADJ NumType=Ord).''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "flat:name"): target = b[4][i][0] wrongHead = False for tk in b[4]: if (tk[6] == target) and (tk[7] not in ["cc", "case", "det", "punct", "expl", "nmod", "amod", "advcl"]): wrongHead = True break elif (tk[6] == target) and (tk[7] == "nmod"): if (tk[3] != "NUM") or ("NumType=Card" not in tk[5]): wrongHead = True break elif (tk[6] == target) and (tk[7] == "amod"): if (tk[3] != "ADJ") or ("NumType=Ord" not in tk[5]): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule67), sep="\t", file=dump) return acc def check68(b,dump): '''Normalmente, um nmod só pode ter como head "PROPN", "NOUN", "NUM", "SYM", "X", "PRON" ''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "nmod"): target = b[4][i][6] wrongHead = False for tk in b[4]: if (tk[0] == target) and (tk[3] not in ["PROPN", "NOUN", "NUM", "SYM", "X", "PRON"]): wrongHead = True break if (wrongHead): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule68), sep="\t", file=dump) return acc def check69(b,dump): '''Normalmente, todo token PUNCT final tem como head o token root.''' acc = 0 for i in range(len(b[4])): if (b[4][i][0] == b[4][-1][6]): if (b[4][i][7] != "root"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][-1][0], msg_Prule69), sep="\t", file=dump) break return acc def check70(b,dump): '''Normalmente, pontuações pareadas (aspas, parênteses, colchetes, chaves) tem o mesmo head.''' acc = 0 pairedA = ['"', "'", "(", "[", "{"] pairedB = ['"', "'", ")", "]", "}"] visited = [] idxA, idxB, currentA, currentB = -1, -1, -1, -1 for i in range(len(b[4])): if (b[4][i][0] not in visited) and (b[4][i][1] in pairedA): A = b[4][i][1] idxA = i if (b[4][i][0].isdigit()): currentA = eval(b[4][i][0]) else: currentA = 0 B = pairedB[pairedA.index(A)] for j in range(i+1,len(b[4])): if (b[4][j][1] == B): idxB = j if (b[4][j][0].isdigit()): currentB = eval(b[4][j][0]) else: currentB = 0 break if (currentA != -1) and (currentB != -1): for k in range(idxA+1,idxB): if ("-" not in b[4][k][0]) and (b[4][k][6].isdigit()): if (eval(b[4][k][6]) < currentA) or (eval(b[4][k][6]) > currentB): if (b[4][idxA][6] != b[4][k][0]) or (b[4][idxB][6] != b[4][k][0]): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule70), sep="\t", file=dump) visited.append(b[4][idxA][0]) visited.append(b[4][idxB][0]) idxA, idxB, currentA, currentB = -1, -1, -1, -1 break return acc def check71(b,dump): '''Normalmente, nenhum token pode ser simultaneamente head de obj e head de ccomp.''' acc = 0 obj = [0]*b[2] ccomp = [0]*b[2] for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][7] == "obj"): if (b[4][i][6].isdigit()): obj[eval(b[4][i][6])-1] += 1 elif (b[4][i][7] == "ccomp"): if (b[4][i][6].isdigit()): ccomp[eval(b[4][i][6])-1] += 1 for i in range(b[2]): if (obj[i] > 0) and (ccomp[i] > 0): acc += 1 print("{}\t{}\t{}".format(b[0], i+1, msg_Prule71), sep="\t", file=dump) return acc def check72(b,dump): '''Normalmente, nenhum token ADJ pode ser head ou dependente de appos.''' acc = 0 for i in range(len(b[4])): if ("-" not in b[4][i][0]): if (b[4][i][3] == "ADJ"): if (b[4][i][7] == "appos"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule72), sep="\t", file=dump) else: for tk in b[4]: if (tk[6] == b[4][i][0]) and (tk[7] == "appos"): acc += 1 print("{}\t{}\t{}".format(b[0], b[4][i][0], msg_Prule72), sep="\t", file=dump) break return acc def check(i,b,dump): if (i==0): return check01(b,dump) elif (i==1): return check02(b,dump) elif (i==2): return check03(b,dump) elif (i==3): return check04(b,dump) elif (i==4): return check05(b,dump) elif (i==5): return check06(b,dump) elif (i==6): return check07(b,dump) elif (i==7): return check08(b,dump) elif (i==8): return check09(b,dump) elif (i==9): return check10(b,dump) elif (i==10): return check11(b,dump) elif (i==11): return check12(b,dump) elif (i==12): return check13(b,dump) elif (i==13): return check14(b,dump) elif (i==14): return check15(b,dump) elif (i==15): return check16(b,dump) elif (i==16): return check17(b,dump) elif (i==17): return check18(b,dump) elif (i==18): return check19(b,dump) elif (i==19): return check20(b,dump) elif (i==20): return check21(b,dump) elif (i==21): return check22(b,dump) elif (i==22): #return check23(b,dump) return 0 elif (i==23): return check24(b,dump) elif (i==24): return check25(b,dump) elif (i==25): return check26(b,dump) elif (i==26): return check27(b,dump) elif (i==27): return check28(b,dump) elif (i==28): return check29(b,dump) elif (i==29): return check30(b,dump) elif (i==30): return check31(b,dump) elif (i==31): return check32(b,dump) elif (i==32): return check33(b,dump) elif (i==33): return check34(b,dump) elif (i==34): return check35(b,dump) elif (i==35): return check36(b,dump) elif (i==36): return check37(b,dump) elif (i==37): return check38(b,dump) elif (i==38): return check39(b,dump) elif (i==39): return check40(b,dump) elif (i==40): return check41(b,dump) elif (i==41): return check42(b,dump) elif (i==42): return check43(b,dump) elif (i==43): return check44(b,dump) elif (i==44): return check45(b,dump) elif (i==45): #return check46(b,dump) return 0 elif (i==46): return check47(b,dump) elif (i==47): return check48(b,dump) elif (i==48): return check49(b,dump) elif (i==49): return check50(b,dump) elif (i==50): return check51(b,dump) elif (i==51): return check52(b,dump) elif (i==52): return check53(b,dump) elif (i==53): return check54(b,dump) elif (i==54): return check55(b,dump) elif (i==55): return check56(b,dump) elif (i==56): return check57(b,dump) elif (i==57): return check58(b,dump) elif (i==58): return check59(b,dump) elif (i==59): return check60(b,dump) elif (i==60): return check61(b,dump) elif (i==61): return check62(b,dump) elif (i==62): return check63(b,dump) elif (i==63): return check64(b,dump) elif (i==64): return check65(b,dump) elif (i==65): return check66(b,dump) elif (i==66): return check67(b,dump) elif (i==67): return check68(b,dump) elif (i==68): return check69(b,dump) elif (i==69): return check70(b,dump) elif (i==70): return check71(b,dump) elif (i==71): return check72(b,dump) def checkSent(b, dump, rep): total, warn = 0, 0 acc = [] for i in range(parserDef[1]): acc.append(check(i,b,dump)) if (acc[i] > 0): rep.writeSent(parserDef[0], i+1, b) if (i < parserDef[2]): total += acc[i] else: warn += acc[i] return acc, total, warn