| 438 | has_alpha = lambda string: ALPHA.match(string) is not None |
| 439 | |
| 440 | class Constraint(object): |
| 441 | |
| 442 | def __init__(self, words=[], tags=[], chunks=[], roles=[], taxa=[], optional=False, multiple=False, first=False, taxonomy=TAXONOMY, exclude=None): |
| 443 | """ A range of words, tags and taxonomy terms that matches certain words in a sentence. |
| 444 | For example: |
| 445 | Constraint.fromstring("with|of") matches either "with" or "of". |
| 446 | Constraint.fromstring("(JJ)") optionally matches an adjective. |
| 447 | Constraint.fromstring("NP|SBJ") matches subject noun phrases. |
| 448 | Constraint.fromstring("QUANTITY|QUALITY") matches quantity-type and quality-type taxa. |
| 449 | """ |
| 450 | self.index = 0 |
| 451 | self.words = list(words) # Allowed words/lemmata (of, with, ...) |
| 452 | self.tags = list(tags) # Allowed parts-of-speech (NN, JJ, ...) |
| 453 | self.chunks = list(chunks) # Allowed chunk types (NP, VP, ...) |
| 454 | self.roles = list(roles) # Allowed chunk roles (SBJ, OBJ, ...) |
| 455 | self.taxa = list(taxa) # Allowed word categories. |
| 456 | self.taxonomy = taxonomy |
| 457 | self.optional = optional |
| 458 | self.multiple = multiple |
| 459 | self.first = first |
| 460 | self.exclude = exclude # Constraint of words that are *not* allowed, or None. |
| 461 | |
| 462 | @classmethod |
| 463 | def fromstring(cls, s, **kwargs): |
| 464 | """ Returns a new Constraint from the given string. |
| 465 | Uppercase words indicate either a tag ("NN", "JJ", "VP") |
| 466 | or a taxonomy term (e.g., "PRODUCT", "PERSON"). |
| 467 | Syntax: |
| 468 | ( defines an optional constraint, e.g., "(JJ)". |
| 469 | [ defines a constraint with spaces, e.g., "[Mac OS X | Windows Vista]". |
| 470 | _ is converted to spaces, e.g., "Windows_Vista". |
| 471 | | separates different options, e.g., "ADJP|ADVP". |
| 472 | ! can be used as a word prefix to disallow it. |
| 473 | * can be used as a wildcard character, e.g., "soft*|JJ*". |
| 474 | ? as a suffix defines a constraint that is optional, e.g., "JJ?". |
| 475 | + as a suffix defines a constraint that can span multiple words, e.g., "JJ+". |
| 476 | ^ as a prefix defines a constraint that can only match the first word. |
| 477 | These characters need to be escaped if used as content: "\(". |
| 478 | """ |
| 479 | C = cls(**kwargs) |
| 480 | s = s.strip() |
| 481 | s = s.strip("{}") |
| 482 | s = s.strip() |
| 483 | for i in range(3): |
| 484 | # Wrapping order of control characters is ignored: |
| 485 | # (NN+) == (NN)+ == NN?+ == NN+? == [NN+?] == [NN]+? |
| 486 | if s.startswith("^"): |
| 487 | s = s[1: ]; C.first = True |
| 488 | if s.endswith("+") and not s.endswith("\+"): |
| 489 | s = s[0:-1]; C.multiple = True |
| 490 | if s.endswith("?") and not s.endswith("\?"): |
| 491 | s = s[0:-1]; C.optional = True |
| 492 | if s.startswith("(") and s.endswith(")"): |
| 493 | s = s[1:-1]; C.optional = True |
| 494 | if s.startswith("[") and s.endswith("]"): |
| 495 | s = s[1:-1] |
| 496 | s = re.sub(r"^\\\^", "^", s) |
| 497 | s = re.sub(r"\\\+$", "+", s) |
no outgoing calls
no test coverage detected
searching dependent graphs…