# "inflection" here means the single concept connecting choices of verb # conjugation, personal pronoun, etc. from panoptes.etc.enum import enum from panoptes.ling.glue.grammatical_number import N2 Declension = enum("""Declension = I WE YOU YALL HE SHE IT THEY1 ONE WHO1 WHO2 THEY2 WHOEVER1 WHOEVER2""") DECLENSION2IS_INTERROGATIVE = dict(zip( sorted(Declension.values), map(lambda d: d in (Declension.WHO1, Declension.WHO2, Declension.WHOEVER1, Declension.WHOEVER2), sorted(Declension.values)))) Person = enum('Person = FIRST SECOND THIRD') Conjugation = enum('Conjugation = S1 S2 S3 P1 P2 P3') CONJ2INDEX = dict(zip(sorted(Conjugation.values), range(len(Conjugation.values)))) N2_TO_CONJ = { N2.SING: Conjugation.S3, N2.PLUR: Conjugation.P3,
# quantifiers, as in Zamenhoff's table of correlatives. # # https://en.wikipedia.org/wiki/Pro-form # # Different types of elective and universal correlatives use different # determiners/pronouns and may have different grammatical numbers (eg, "all cats # are black" but "every cat is black"), so those entries are split. Correlative = enum("""Correlative = INDEF DEF INTR PROX DIST EXIST ELECT_ANY ELECT_EVER UNIV_EVERY UNIV_ALL NEG ALT """) CountRestriction = enum("""CountRestriction = NONE ANY ONE_OF_PLURAL SOME ALL_ONE ALL""") # CountRestriction -> implementation that compares compints. COUNT_RESTRICTION2CHECK = { # Negative.
from collections import defaultdict import re import yaml from panoptes.etc.dicts import v2k_from_k2v from panoptes.etc.enum import enum ComparativeDegree = enum('ComparativeDegree = BASE COMP SUPER') ComparativePolarity = enum('ComparativePolarity = POS NEG') class ComparativeManager(object): def __init__(self, syllable_counter, exception_triples, base_is_er_est, erable, not_erable): self.syllable_counter = syllable_counter self.exception_bases = set(map(lambda ss: ss[0], exception_triples)) self.exception_degree_base2ss = defaultdict(list) self.exception_s2degrees_bases = defaultdict(list) degrees = [ ComparativeDegree.BASE, ComparativeDegree.COMP, ComparativeDegree.SUPER ] for triple in exception_triples: base = triple[0] for degree, word in zip(degrees, triple): self.exception_degree_base2ss[(degree, base)].append(word) self.exception_s2degrees_bases[word].append((degree, base))
def make_relation_enum(relation_text): dd = yaml.load(relation_text) relations = map(lambda d: d['relation'], dd) enum_content = 'Relation = %s' % ' '.join(relations) return enum(enum_content)
# Purpose in communicating. # # Whether you're giving or receiving information. Mostly about kinds of # questions. # # Used for deciding sentence-ending punctuation, whether to do-split a verb, if # there are wh-roles to possibly front, etc. # # TODO: replace ind_cond with is_modality_not_squirrely or something. from collections import defaultdict from itertools import product from panoptes.etc.enum import enum Purpose = enum('Purpose = WH_Q TF_Q VERIFY_Q INFO') class PurposeInfo(object): def __init__(self, purpose, has_q_args, override_split_verb_yes, unstressed_end_punct, stressed_end_punct, is_ind_cond_only): # Enum value of this purpose. self.purpose = purpose assert Purpose.is_valid(self.purpose) # Whether question words must or must not be in a clause with this # intent. self.has_q_args = has_q_args assert isinstance(self.has_q_args, bool) # Whether to split the verb words ("don't you know" vs "you don't
from panoptes.ling.glue.relation import Relation from panoptes.ling.tree.base import ArgPosRestriction from panoptes.ling.tree.common.personal_pronoun import PersonalPronoun from panoptes.ling.tree.deep.base import DeepArgument from panoptes.ling.tree.surface.content_clause import Complementizer, \ SurfaceContentClause from panoptes.ling.verb.verb import DeepVerb, ModalFlavor, \ RelativeContainment, SubjunctiveHandling, SurfaceVerb, Voice # The truth value of the clause. # # Examples: # * "I know [that] you did it last summer" # * "I know [whether] you did it last summer" Status = enum('Status = ACTUAL WHETHER') COMPLEMENTIZER2STATUS = { Complementizer.ZERO: Status.ACTUAL, Complementizer.THAT: Status.ACTUAL, Complementizer.WHETHER: Status.WHETHER, Complementizer.IF: Status.WHETHER, } STATUS2COMPLEMENTIZER = { Status.ACTUAL: Complementizer.ZERO, Status.WHETHER: Complementizer.WHETHER, }
# # * Instead of 'conditional' being a modality, modalities have normal and # conditional forms (so conditional + indicative is bare 'conditional'). This # is because of relations like 'can + would = could'. # # * The two subjunctives: # SUBJUNCTIVE_CF ('subjunctive-counterfactual') "if he [were] smart" # SUBJUNCTIVE_IMP ('subjunctive-imperative') "he requests you [come]" ModalFlavor = enum("""ModalFlavor = INDICATIVE SUBJUNCTIVE_CF DEDUCTIVE ALMOST_CERTAIN PROBABLE POSSIBLE IMPERATIVE SUBJUNCTIVE_IMP ABILITY PERMISSIVE NORMATIVE NECESSITY """) class Modality(object): def __init__(self, flavor, is_cond): self.flavor = flavor self.is_cond = is_cond # TODO: check where is_cond is wildcarded. self.check()
from collections import defaultdict import re import yaml from panoptes.etc.dicts import v2k_from_k2v from panoptes.etc.enum import enum ComparativeDegree = enum('ComparativeDegree = BASE COMP SUPER') ComparativePolarity = enum('ComparativePolarity = POS NEG') class ComparativeManager(object): def __init__(self, syllable_counter, exception_triples, base_is_er_est, erable, not_erable): self.syllable_counter = syllable_counter self.exception_bases = set(map(lambda ss: ss[0], exception_triples)) self.exception_degree_base2ss = defaultdict(list) self.exception_s2degrees_bases = defaultdict(list) degrees = [ComparativeDegree.BASE, ComparativeDegree.COMP, ComparativeDegree.SUPER] for triple in exception_triples: base = triple[0] for degree, word in zip(degrees, triple): self.exception_degree_base2ss[(degree, base)].append(word) self.exception_s2degrees_bases[word].append((degree, base))
# Support for grammatical number. # # Grammatical number shows up in different ways in English with varying levels # of ambiguity, such as singular/plural, which/what, verb conjugation, etc. from collections import defaultdict from panoptes.etc.enum import enum N2 = enum('N2 = SING PLUR') N3 = enum('N3 = ZERO SING PLUR') N5 = enum('N5 = ZERO SING DUAL FEW MANY') def join_disjoint_sets(ss): r = set() for s in ss: for a in s: r.add(a) return r def join_disjoint_dicts(k2vs): r = {} for k2v in k2vs: for k, v in k2v.iteritems(): r[k] = v
from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Gender from panoptes.ling.glue.relation import Relation from panoptes.mind.idea.base import Idea from panoptes.mind.know.location import LocationHistory # What about it? # # What we are looking up, if anything. # # If query is None, the Idea is an instance. Query = enum("Query = CARDINALITY IDENTITY GENERIC") class Noun(Idea): def __init__( self, query=None, name=None, gender=None, is_animate=None, attributes=None, kind=None, rel2xxx=None, carrying=None, ): if attributes is None: attributes = [] if rel2xxx is None: rel2xxx = {}
Detects whether a token ends in something vaguely resembling an "s" sound. """ def __init__(self): self.regexes = map(re.compile, [ '[sxz]$', '[cszt]h$', '[iy][sz]ed?$', '[aeiourl][cs]e$', '[aeiourl]the$' ]) def detect(self, s): for r in self.regexes: if r.search(s): return True return False Contract = enum('Contract = IF_NOT_S_SOUND ALWAYS') class BigramContractionManager(object): def __init__(self, bigram2exception, bigrams_to_contract, last2contract, last2contraction): # Exceptions (maps bigrams to their weird contractions). self.bigram2exception = bigram2exception # Set of bigrams to contract. self.bigrams_to_contract = bigrams_to_contract # Contraction behavior given last word in a bigram. self.last2contract = last2contract # How to contract the last word of a bigram.
from collections import defaultdict from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import CONJ2INDEX, Conjugation from panoptes.ling.verb.annotation import annotate_as_pro_verb from panoptes.ling.verb.conjugation import Conjugator from panoptes.ling.verb.verb import * # Whether. # # Like polarity, but also "does" in "she *does* know!"). # # NO no # YES yes # EMPH emphatic yes (yes + you were expecting no) Whether = enum('Whether = NO YES EMPH') # Ephemeral tense. # # Gotcha warning: it is loosely related to time. # # PAST past # NONPAST present and future (+ will) # SBJ_PAST past subjunctive # SBJ_PRES present subjunctive # SBJ_FUT future subjunctive EphemeralTense = enum( 'EphemeralTense = PAST NONPAST SBJ_PAST SBJ_PRES SBJ_FUT') # Ephemeral verb form. #
from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Gender from panoptes.ling.glue.relation import Relation from panoptes.mind.idea.base import Idea from panoptes.mind.know.location import LocationHistory # What about it? # # What we are looking up, if anything. # # If query is None, the Idea is an instance. Query = enum('Query = CARDINALITY IDENTITY GENERIC') class Noun(Idea): def __init__(self, query=None, name=None, gender=None, is_animate=None, attributes=None, kind=None, rel2xxx=None, carrying=None): if attributes is None: attributes = [] if rel2xxx is None: rel2xxx = {} if carrying is None: carrying = []
self.regexes = map(re.compile, [ '[sxz]$', '[cszt]h$', '[iy][sz]ed?$', '[aeiourl][cs]e$', '[aeiourl]the$' ]) def detect(self, s): for r in self.regexes: if r.search(s): return True return False Contract = enum('Contract = IF_NOT_S_SOUND ALWAYS') class BigramContractionManager(object): def __init__(self, bigram2exception, bigrams_to_contract, last2contract, last2contraction): # Exceptions (maps bigrams to their weird contractions). self.bigram2exception = bigram2exception # Set of bigrams to contract. self.bigrams_to_contract = bigrams_to_contract # Contraction behavior given last word in a bigram. self.last2contract = last2contract # How to contract the last word of a bigram.
from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Conjugation, Declension from panoptes.ling.glue.relation import RelationArgType from panoptes.ling.tree.common.personal_pronoun import PersonalPronoun, \ PersonalPronounCase from panoptes.ling.tree.surface.base import SayContext, SayResult, \ SurfaceArgument from panoptes.ling.verb.verb import SurfaceVerb Complementizer = enum('Complementizer = ZERO THAT WHETHER IF') COMPLEMENTIZER2WORD = { Complementizer.ZERO: None, Complementizer.THAT: 'that', Complementizer.WHETHER: 'whether', Complementizer.IF: 'if', } class SurfaceContentClause(SurfaceArgument): def __init__(self, complementizer, verb, adverbs, preps_vargs, vmain_index): # Complementizer. # # If we are the content of a relative clause, can only be ZERO. self.complementizer = complementizer # Complementizer. # SurfaceVerb. Some of its fields are tield to other parameters. self.verb = verb # SurfaceVerb.
from panoptes.ling.glue.purpose import Purpose from panoptes.ling.glue.relation import Relation from panoptes.ling.tree.base import ArgPosRestriction from panoptes.ling.tree.common.personal_pronoun import PersonalPronoun from panoptes.ling.tree.deep.base import DeepArgument from panoptes.ling.tree.surface.content_clause import Complementizer, \ SurfaceContentClause from panoptes.ling.verb.verb import DeepVerb, ModalFlavor, \ RelativeContainment, SubjunctiveHandling, SurfaceVerb, Voice # The truth value of the clause. # # Examples: # * "I know [that] you did it last summer" # * "I know [whether] you did it last summer" Status = enum('Status = ACTUAL WHETHER') COMPLEMENTIZER2STATUS = { Complementizer.ZERO: Status.ACTUAL, Complementizer.THAT: Status.ACTUAL, Complementizer.WHETHER: Status.WHETHER, Complementizer.IF: Status.WHETHER, } STATUS2COMPLEMENTIZER = { Status.ACTUAL: Complementizer.ZERO, Status.WHETHER: Complementizer.WHETHER, } def is_you(n):
from panoptes.etc.dicts import v2k_from_k2v from panoptes.etc.enum import enum Conjunction = enum('Conjunction = ALL_OF ONE_OF') CONJUNCTION2STR = { Conjunction.ALL_OF: 'and', Conjunction.ONE_OF: 'or', } STR2CONJUNCTION = v2k_from_k2v(CONJUNCTION2STR)
from panoptes.etc.dicts import v2k_from_k2v from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Conjugation from panoptes.ling.tree.common.base import CommonArgument from panoptes.ling.tree.surface.base import SayResult DaySection = enum('DaySection = MORNING AFTERNOON EVENING NIGHT') class TimeOfDay(CommonArgument): def __init__(self, day_offset, section): self.day_offset = day_offset assert isinstance(self.day_offset, int) self.section = section if self.section: assert DaySection.is_valid(self.section) # -------------------------------------------------------------------------- # From base. def dump(self): section = DaySection.to_str[self.section] if self.section else None return { 'type': 'TimeOfDay', 'day_offset': self.day_offset, 'section': section, } # --------------------------------------------------------------------------
# # Whether you're giving or receiving information. Mostly about kinds of # questions. # # Used for deciding sentence-ending punctuation, whether to do-split a verb, if # there are wh-roles to possibly front, etc. # # TODO: replace ind_cond with is_modality_not_squirrely or something. from collections import defaultdict from itertools import product from panoptes.etc.enum import enum Purpose = enum("Purpose = WH_Q TF_Q VERIFY_Q INFO") class PurposeInfo(object): def __init__( self, purpose, has_q_args, override_split_verb_yes, unstressed_end_punct, stressed_end_punct, is_ind_cond_only ): # Enum value of this purpose. self.purpose = purpose assert Purpose.is_valid(self.purpose) # Whether question words must or must not be in a clause with this # intent. self.has_q_args = has_q_args assert isinstance(self.has_q_args, bool)
from panoptes.etc.enum import enum from panoptes.ling.glue.relation import RelationArgType ArgPosRestriction = enum('ArgPosRestriction = SUBJECT NOT_SUBJECT ANYWHERE') class BaseArgument(object): """ A standalone (a) verb argument or (b) child of a noun phrase. These objects are used in surface structure and deep structure. We use two different levels of structure in order to apply and reverse transformations like fronting, keeping everything else pretty much the same. These are not directly instantiated. Instead, instantiate a SurfaceArgument or DeepArgument, which inherit from this. CommonArgument, which is pretty much everything that does not have complicated structure, inherits from both of those. Technically, sometimes an argument can be used as a non-standalone component of another argument, such as Attributes and Numbers inside a CommonNoun, but it will always be able to be used on its own. """ def dump(self): """ -> dict Return a dict that can be used to reconstruct ourselves, containing nothing but primitive types and the string names of enum values.
from panoptes.etc.dicts import v2k_from_k2v from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Conjugation from panoptes.ling.tree.common.base import CommonArgument from panoptes.ling.tree.surface.base import SayResult DaySection = enum('DaySection = MORNING AFTERNOON EVENING NIGHT') class TimeOfDay(CommonArgument): def __init__(self, day_offset, section): self.day_offset = day_offset assert isinstance(self.day_offset, int) self.section = section if self.section: assert DaySection.is_valid(self.section) # -------------------------------------------------------------------------- # From base. def dump(self): section = DaySection.to_str[self.section] if self.section else None return { 'type': 'TimeOfDay', 'day_offset': self.day_offset, 'section': section, } # -------------------------------------------------------------------------- # From surface.
RELATION_TEXT = RELATION_TEXT.replace('<PLACE_PREP>', PLACE_PREP) RELATION_TEXT = RELATION_TEXT.replace('<REASON_PREP>', REASON_PREP) RELATION_TEXT = RELATION_TEXT.replace('<TIME_PREP>', TIME_PREP) RELATION_TEXT = RELATION_TEXT.replace('<WAY_PREP>', WAY_PREP) def make_relation_enum(relation_text): dd = yaml.load(relation_text) relations = map(lambda d: d['relation'], dd) enum_content = 'Relation = %s' % ' '.join(relations) return enum(enum_content) Relation = make_relation_enum(RELATION_TEXT) RelationPosition = enum(""" RelationPosition = NOMINATIVE DATIVE ACCUSATIVE OBLIQUE""") def is_core_position(pos): return pos != RelationPosition.OBLIQUE # INERT is most args, and non-finite clauses. # FINITE_CLAUSE is finite clauses. RelationArgType = enum('RelationArgType = INERT FINITE_CLAUSE PREPLESS_GERUND') class RelationInfo(object): def __init__(self, relation, core, order, preps_types): self.relation = relation assert Relation.is_valid(self.relation)
from panoptes.etc.dicts import v2kk_from_k2v, v2k_from_k2v from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Conjugation, Declension, \ DECLENSION2IS_INTERROGATIVE from panoptes.ling.glue.magic_token import POSSESSIVE_MARK from panoptes.ling.tree.base import ArgPosRestriction from panoptes.ling.tree.common.base import CommonArgument from panoptes.ling.tree.surface.base import SayResult PersonalPronounCase = enum('PersonalPronounCase = SUBJECT OBJECT REFLEXIVE') # PersonalPronounCase -> ArgPosRestriction. PPCASE2ARG_POS_RES = { PersonalPronounCase.SUBJECT: ArgPosRestriction.SUBJECT, PersonalPronounCase.OBJECT: ArgPosRestriction.NOT_SUBJECT, PersonalPronounCase.REFLEXIVE: ArgPosRestriction.NOT_SUBJECT, } class PersonalPronoun(CommonArgument): """ (Non-possessive) personal pronouns. """ def __init__(self, declension, ppcase): self.declension = declension assert Declension.is_valid(self.declension) self.ppcase = ppcase
from collections import defaultdict from panoptes.etc.dicts import v2k_from_k2vv, v2kk_from_k2v from panoptes.etc.enum import enum from panoptes.ling.glue.grammatical_number import N2, nx_to_nx from panoptes.ling.glue.inflection import N2_TO_CONJ from panoptes.ling.glue.magic_token import PLACE_PREP, REASON_PREP, TIME_PREP, \ WAY_PREP from panoptes.ling.tree.common.util.selector import Correlative, \ CountRestriction, Selector from panoptes.ling.tree.surface.base import SayResult ProAdverbColumn = enum("""ProAdverbColumn = ONE BODY THING PLACE SOURCE SOURCE_FROM GOAL TIME WAY WAY_BY REASON REASON_FORE REASON_LATIN""") def parse_partial(text): lines = text.strip().split('\n') sss = map(lambda line: line.split(), lines) n = len(sss[0]) for ss in sss[1:]: assert len(ss) == n + 1 rows = [] for s in map(lambda ss: ss[0], sss[1:]): row = Correlative.from_str[s] rows.append(row) assert set(rows) == Correlative.values
from panoptes.etc.dicts import v2kk_from_k2v, v2k_from_k2v from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import Conjugation, Declension, \ DECLENSION2IS_INTERROGATIVE from panoptes.ling.glue.magic_token import POSSESSIVE_MARK from panoptes.ling.tree.base import ArgPosRestriction from panoptes.ling.tree.common.base import CommonArgument from panoptes.ling.tree.surface.base import SayResult PersonalPronounCase = enum('PersonalPronounCase = SUBJECT OBJECT REFLEXIVE') # PersonalPronounCase -> ArgPosRestriction. PPCASE2ARG_POS_RES = { PersonalPronounCase.SUBJECT: ArgPosRestriction.SUBJECT, PersonalPronounCase.OBJECT: ArgPosRestriction.NOT_SUBJECT, PersonalPronounCase.REFLEXIVE: ArgPosRestriction.NOT_SUBJECT, } class PersonalPronoun(CommonArgument): """ (Non-possessive) personal pronouns. """ def __init__(self, declension, ppcase): self.declension = declension assert Declension.is_valid(self.declension) self.ppcase = ppcase assert PersonalPronounCase.is_valid(self.ppcase) # --------------------------------------------------------------------------
from panoptes.etc.enum import enum NumeralVerbosity = enum('NumeralVerbosity = DIGITS AUTO WORDS') class NumeralManager(object): def say_as_digits(self, n): raise NotImplementedError def is_in_use_words_range(self, n): raise NotImplementedError def say_as_words(self, n): raise NotImplementedError def say(self, n, verbo=NumeralVerbosity.AUTO): if verbo == NumeralVerbosity.DIGITS: words = False elif verbo == NumeralVerbosity.AUTO: words = self.is_in_use_words_range(n) elif verbo == NumeralVerbosity.WORDS: words = True else: assert False if words: r = self.say_as_words(n) else: r = self.say_as_digits(n)
# "inflection" here means the single concept connecting choices of verb # conjugation, personal pronoun, etc. from panoptes.etc.enum import enum from panoptes.ling.glue.grammatical_number import N2 Declension = enum("""Declension = I WE YOU YALL HE SHE IT THEY1 ONE WHO1 WHO2 THEY2 WHOEVER1 WHOEVER2""") DECLENSION2IS_INTERROGATIVE = dict( zip( sorted(Declension.values), map( lambda d: d in (Declension.WHO1, Declension.WHO2, Declension. WHOEVER1, Declension.WHOEVER2), sorted(Declension.values)))) Person = enum('Person = FIRST SECOND THIRD') Conjugation = enum('Conjugation = S1 S2 S3 P1 P2 P3') CONJ2INDEX = dict( zip(sorted(Conjugation.values), range(len(Conjugation.values)))) N2_TO_CONJ = { N2.SING: Conjugation.S3, N2.PLUR: Conjugation.P3, } Gender = enum('Gender = MALE FEMALE NEUTER')
from panoptes.etc.enum import enum from panoptes.ling.glue.inflection import CONJ2INDEX, Conjugation from panoptes.ling.verb.annotation import annotate_as_pro_verb from panoptes.ling.verb.conjugation import Conjugator from panoptes.ling.verb.verb import * # Whether. # # Like polarity, but also "does" in "she *does* know!"). # # NO no # YES yes # EMPH emphatic yes (yes + you were expecting no) Whether = enum('Whether = NO YES EMPH') # Ephemeral tense. # # Gotcha warning: it is loosely related to time. # # PAST past # NONPAST present and future (+ will) # SBJ_PAST past subjunctive # SBJ_PRES present subjunctive # SBJ_FUT future subjunctive EphemeralTense = enum( 'EphemeralTense = PAST NONPAST SBJ_PAST SBJ_PRES SBJ_FUT')
from panoptes.etc.enum import enum from panoptes.ling.glue.relation import RelationArgType ArgPosRestriction = enum('ArgPosRestriction = SUBJECT NOT_SUBJECT ANYWHERE') class BaseArgument(object): """ A standalone (a) verb argument or (b) child of a noun phrase. These objects are used in surface structure and deep structure. We use two different levels of structure in order to apply and reverse transformations like fronting, keeping everything else pretty much the same. These are not directly instantiated. Instead, instantiate a SurfaceArgument or DeepArgument, which inherit from this. CommonArgument, which is pretty much everything that does not have complicated structure, inherits from both of those. Technically, sometimes an argument can be used as a non-standalone component of another argument, such as Attributes and Numbers inside a CommonNoun, but it will always be able to be used on its own. """ def dump(self): """ -> dict Return a dict that can be used to reconstruct ourselves, containing nothing but primitive types and the string names of enum values. """ raise NotImplementedError
# quantifiers, as in Zamenhoff's table of correlatives. # # https://en.wikipedia.org/wiki/Pro-form # # Different types of elective and universal correlatives use different # determiners/pronouns and may have different grammatical numbers (eg, "all cats # are black" but "every cat is black"), so those entries are split. Correlative = enum("""Correlative = INDEF DEF INTR PROX DIST EXIST ELECT_ANY ELECT_EVER UNIV_EVERY UNIV_ALL NEG ALT """) CountRestriction = enum("""CountRestriction = NONE ANY ONE_OF_PLURAL SOME ALL_ONE ALL""") # CountRestriction -> implementation that compares compints.
RELATION_TEXT = RELATION_TEXT.replace('<REASON_PREP>', REASON_PREP) RELATION_TEXT = RELATION_TEXT.replace('<TIME_PREP>', TIME_PREP) RELATION_TEXT = RELATION_TEXT.replace('<WAY_PREP>', WAY_PREP) def make_relation_enum(relation_text): dd = yaml.load(relation_text) relations = map(lambda d: d['relation'], dd) enum_content = 'Relation = %s' % ' '.join(relations) return enum(enum_content) Relation = make_relation_enum(RELATION_TEXT) RelationPosition = enum(""" RelationPosition = NOMINATIVE DATIVE ACCUSATIVE OBLIQUE""") def is_core_position(pos): return pos != RelationPosition.OBLIQUE # INERT is most args, and non-finite clauses. # FINITE_CLAUSE is finite clauses. RelationArgType = enum('RelationArgType = INERT FINITE_CLAUSE PREPLESS_GERUND') class RelationInfo(object): def __init__(self, relation, core, order, preps_types): self.relation = relation assert Relation.is_valid(self.relation)