diff options
| author | Bobby <[email protected]> | 2022-08-31 14:20:32 -0400 |
|---|---|---|
| committer | Bobby <[email protected]> | 2022-08-31 14:20:32 -0400 |
| commit | f6681de8304c0894d87bec3af8ee53f5ae55682a (patch) | |
| tree | 64b90b76eebd905661012f4d9d989933a3101c30 | |
| parent | 45fff43e5ff2e6de1a22a8c6bf99be6496540dc9 (diff) | |
| download | edify-f6681de8304c0894d87bec3af8ee53f5ae55682a.tar.xz edify-f6681de8304c0894d87bec3af8ee53f5ae55682a.zip | |
Added Basic Regex Builder
| -rw-r--r-- | src/edify/builder/__init__.py | 0 | ||||
| -rw-r--r-- | src/edify/builder/abc.py | 10 | ||||
| -rw-r--r-- | src/edify/builder/builder.py | 33 | ||||
| -rw-r--r-- | src/edify/builder/constants.py | 10 | ||||
| -rw-r--r-- | src/edify/builder/datatypes.py | 73 | ||||
| -rw-r--r-- | src/edify/builder/errors.py | 2 | ||||
| -rw-r--r-- | src/edify/builder/escaped.py | 9 | ||||
| -rw-r--r-- | src/edify/builder/part.py | 30 | ||||
| -rw-r--r-- | src/edify/builder/quantifier.py | 64 |
9 files changed, 147 insertions, 84 deletions
diff --git a/src/edify/builder/__init__.py b/src/edify/builder/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/edify/builder/__init__.py diff --git a/src/edify/builder/abc.py b/src/edify/builder/abc.py new file mode 100644 index 0000000..a918b5a --- /dev/null +++ b/src/edify/builder/abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class Builder(ABC): + @abstractmethod + def build(self): + pass + + def __str__(self): + return self.build() diff --git a/src/edify/builder/builder.py b/src/edify/builder/builder.py index 2150314..e139ec1 100644 --- a/src/edify/builder/builder.py +++ b/src/edify/builder/builder.py @@ -1,14 +1,25 @@ -"""This is the main module for the edify builder. It is responsible for building -Regular Expressions from simple function chains. -""" +from .abc import Builder +from .part import Part +from .errors import NotPart +from re import match -class RegexBuilder: - """RegexBuilder helps build and use regular expressions using its methods. - """ - - regex = None +class RegexBuilder(Builder): def __init__(self): - """Initialize the RegexBuilder. - """ - self.regex = "" + self.parts = [] + + def build(self): + return "".join(map(str, self.parts)) + + def add(self, part): + self.parts.append(part) + + def part(self, part): + if not (issubclass(type(part), Builder) or isinstance(part, str)): + raise NotPart(f"{part} is not a valid Part") + + self.parts.append(part) + return self + + def match(self, regex): + return match(self.build(), regex) diff --git a/src/edify/builder/constants.py b/src/edify/builder/constants.py new file mode 100644 index 0000000..c1e7f68 --- /dev/null +++ b/src/edify/builder/constants.py @@ -0,0 +1,10 @@ +ANY = "." +WHITESPACE = "\\s" +NON_WHITESPACE = "\\S" +DIGIT = "\\d" +NON_DIGIT = "\\D" +WORD = "\\w" +NON_WORD = "\\W" +NEWLINE = "\\n" +TAB = "\\t" +NULL = "\\0" diff --git a/src/edify/builder/datatypes.py b/src/edify/builder/datatypes.py deleted file mode 100644 index cb3ea13..0000000 --- a/src/edify/builder/datatypes.py +++ /dev/null @@ -1,73 +0,0 @@ -""" - This file contains the datatypes used by the edify regex builder. - - The datatypes are: - - letter: A single upper or lowercase letter (a-z or A-Z) - - digit: A single digit (0-9) - - word: A single word (a-z, A-Z, 0-9, _) - - space: A single space (\s) - - any: Any character or special character -""" - - -def letter(type: str = "all") -> str: - """Returns a regex that matches a single letter. - - Parameters: - type (str): The type of letter to match. - - "all" (default): Matches any letter (a-z or A-Z) - - "upper": Matches any upper case letter (A-Z) - - "lower": Matches any lower case letter (a-z) - - Returns: - str: A regex that matches a single letter. - - Raises: - ValueError: If any of the parameters are invalid. - """ - letters = "abcdefghijklmnopqrstuvwxyz" - if type == "upper": - letters = letters.upper() - elif type == "lower": - letters = letters - elif type == "all": - letters = letters + letters.upper() - else: - raise ValueError("Invalid letter type: " + type) - return "[" + letters + "]" - - -def digit() -> str: - """Returns a regex that matches a single digit. - - Returns: - str: A regex that matches a single digit. - """ - return "[1234567890]" - - -def word() -> str: - """Returns a regex that matches a single word. - - Returns: - str: A regex that matches a single word. - """ - return "[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_]" - - -def space() -> str: - """Returns a regex that matches a single space. - - Returns: - str: A regex that matches a single space. - """ - return "[\s]" - - -def any() -> str: - """Returns a regex that matches any character. - - Returns: - str: A regex that matches any character. - """ - return "." diff --git a/src/edify/builder/errors.py b/src/edify/builder/errors.py new file mode 100644 index 0000000..6f880f8 --- /dev/null +++ b/src/edify/builder/errors.py @@ -0,0 +1,2 @@ +class NotPart(Exception): + pass diff --git a/src/edify/builder/escaped.py b/src/edify/builder/escaped.py new file mode 100644 index 0000000..b081706 --- /dev/null +++ b/src/edify/builder/escaped.py @@ -0,0 +1,9 @@ +from .abc import Builder + + +class Escaped(Builder): + def __init__(self, target): + self.target = target + + def build(self): + return f"\\{self.target}" diff --git a/src/edify/builder/part.py b/src/edify/builder/part.py new file mode 100644 index 0000000..e49ace2 --- /dev/null +++ b/src/edify/builder/part.py @@ -0,0 +1,30 @@ +from .abc import Builder +from abc import abstractmethod + + +class Part(Builder): + def __init__(self, target): + self.target = target + + @abstractmethod + def build(self): + pass + + +class Any(Part): + def __init__(self, *targets, capture = True, name = None): + if not capture and name: + raise ValueError("Cannot specify group name without capturing") + + if name == "": + raise ValueError("Cannot specify empty group name") + + super().__init__(targets) + self.capture = capture + self.name = name + + def build(self): + targets = "|".join(map(str, self.target)) + capture = "" if self.capture else "?: " + name = f"<{self.name}>" if self.name else "" + return f"{capture}{name}{targets}" diff --git a/src/edify/builder/quantifier.py b/src/edify/builder/quantifier.py new file mode 100644 index 0000000..c26fbad --- /dev/null +++ b/src/edify/builder/quantifier.py @@ -0,0 +1,64 @@ +from .abc import Builder +from abc import abstractmethod + + +class Quantifier(Builder): + def __init__(self, target): + self.target = target + + @abstractmethod + def build(self): + pass + + +class Optional(Quantifier): + def build(self): + return f"{self.target}?" + + +class ZeroOrMore(Quantifier): + def build(self): + return f"{self.target}*" + + +class OneOrMore(Quantifier): + def build(self): + return f"{self.target}+" + + +class Exact(Quantifier): + def __init__(self, target, count): + super().__init__(target) + self.count = count + + def build(self): + return f"{self.target}{{self.count}}" + + +class Range(Quantifier): + def __init__(self, target, min, max): + super().__init__(target) + self.min = min + self.max = max + + def build(self): + return f"{self.target}{{self.min, self.max}}" + + +class AtLeast(Quantifier): + def __init__(self, target, min): + super().__init__(target) + self.min = min + + def build(self): + return f"{self.target}{{self.min,}}" + + +class AtMost(Quantifier): + def __init__(self, target, max): + super().__init__(target) + self.max = max + + def build(self): + return f"{self.target}{{,self.max}}" + |
