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 src.utils import datetime, errors
|
||||||
|
|
||||||
from .spec import *
|
from .spec import *
|
||||||
from .time import duration
|
from .time import duration
|
||||||
from .types import try_int
|
from .types import try_int
|
||||||
|
from . import sed
|
||||||
|
|
||||||
COMMENT_TYPES = ["#", "//"]
|
COMMENT_TYPES = ["#", "//"]
|
||||||
def hashflags(filename: str
|
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