add utils.parse.sed.
This commit is contained in:
parent
f3ac154fe2
commit
29f0a282a8
2 changed files with 75 additions and 1 deletions
|
@ -1,9 +1,10 @@
|
|||
import decimal, io, typing
|
||||
import decimal, io, re, typing
|
||||
from src.utils import datetime, errors
|
||||
|
||||
from .spec import *
|
||||
from .time import duration
|
||||
from .types import try_int
|
||||
from . import sed
|
||||
|
||||
COMMENT_TYPES = ["#", "//"]
|
||||
def hashflags(filename: str
|
||||
|
|
73
src/utils/parse/sed.py
Normal file
73
src/utils/parse/sed.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
import dataclasses, re, typing
|
||||
|
||||
class Sed(object):
|
||||
type: str
|
||||
def match(self, s: str) -> typing.Optional[str]:
|
||||
return None
|
||||
|
||||
@dataclasses.dataclass
|
||||
class SedReplace(Sed):
|
||||
type: str
|
||||
pattern: typing.Pattern
|
||||
replace: str
|
||||
count: int
|
||||
|
||||
def match(self, s):
|
||||
return self.pattern.sub(self.replace, s, self.count)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class SedMatch(Sed):
|
||||
type: str
|
||||
pattern: typing.Pattern
|
||||
|
||||
def match(self, s):
|
||||
match = self.pattern.search(s)
|
||||
if match:
|
||||
return match.group(0)
|
||||
return None
|
||||
|
||||
def _sed_split(s):
|
||||
backslash = False
|
||||
forward_slash = []
|
||||
for i, c in enumerate(s):
|
||||
if not backslash:
|
||||
if c == "/":
|
||||
forward_slash.append(i)
|
||||
if c == "\\":
|
||||
backslash = True
|
||||
else:
|
||||
backslash = False
|
||||
if forward_slash and (not forward_slash[-1] == (len(s)-1)):
|
||||
forward_slash.append(len(s))
|
||||
|
||||
last = 0
|
||||
out = []
|
||||
for i in forward_slash:
|
||||
out.append(s[last:i])
|
||||
last = i+1
|
||||
return out
|
||||
|
||||
def _sed_flags(s: str) -> typing.Tuple[int, int]:
|
||||
count = 1
|
||||
re_flags = 0
|
||||
if "g" in s:
|
||||
count = 0
|
||||
if "i" in s:
|
||||
re_flags |= re.I
|
||||
return count, re_flags
|
||||
|
||||
def parse_sed(sed_s: str) -> typing.Optional[Sed]:
|
||||
type, pattern, *args = _sed_split(sed_s)
|
||||
if type == "s":
|
||||
replace, *args = args
|
||||
count, flags = _sed_flags((args or [""])[0])
|
||||
pattern = re.compile(pattern, flags)
|
||||
return SedReplace(type, pattern, replace, count)
|
||||
elif type == "m":
|
||||
count, flags = _sed_flags((args or [""])[0])
|
||||
return SedMatch(type, re.compile(pattern, flags))
|
||||
return None
|
||||
|
||||
def sed(sed_obj: Sed, s: str) -> typing.Tuple[str, typing.Optional[str]]:
|
||||
out = sed_obj.match(s)
|
||||
return sed_obj.type, out
|
Loading…
Reference in a new issue