-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrx.py
164 lines (84 loc) · 2.33 KB
/
rx.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import re
def rx(*patterns):
return re.compile(r''.join([p for p in patterns]))
def compose(*patterns):
return r''.join(patterns)
# Matching
def match(value):
return f'{re.escape(value)}'
then = match
def any_of(value):
return f'[{re.escape(value)}]'
def anything_but(value):
return f'[^{re.escape(value)}]*'
char_class = any_of
def char_range(start, end):
return f'{start}-{end}'
def something_but(value):
return f'[^{re.escape(value)}]+'
# Groups
# https://docs.python.org/3/howto/regex.html#grouping
def group(*patterns):
return f'({compose(*patterns)})'
def named_group(name, *patterns):
return f'(?P<{name}>{compose(*patterns)})'
def non_capturing_group(*patterns):
return f'(?:{compose(*patterns)})'
# Lookaheads
# https://docs.python.org/3/howto/regex.html#lookahead-assertions
def followed_by(value):
return f'(?={re.escape(value)})'
def not_followed_by(value):
return f'(?!{re.escape(value)})'
# Lookbehinds
# https://docs.python.org/3/library/re.html
def preceded_by(value):
return f'(?<={re.escape(value)})'
def not_preceded_by(value):
return f'(?<!{re.escape(value)})'
# Modifiers
# https://docs.python.org/3/howto/regex.html#matching-characters
# https://thepythonguru.com/python-regular-expression/#basic-patterns-used-in-regular-expression
def between_n_and_m_times(n, m):
return '{' + str(n) + ',' + str(m) + '}'
def between_n_and_m_times_lazy(n, m):
return '{' + str(n) + ',' + str(m) + '}?'
def exactly_n_times(n):
return f'{ {n} }'
def maybe():
return '?'
def one_or_more_times():
return '+'
def OR():
return r'|'
def zero_or_more_times():
return '*'
# Metacharacters
def digit():
return r'\d'
def end_of_line():
return '$'
def space():
return r'\s'
def spaces():
return compose(space(), one_or_more_times())
def start_of_line():
return '^'
def tab():
return r'\t'
def word():
return r'\w+'
def word_boundary():
return r'\b'
# Some common character patterns
# https://thepythonguru.com/python-regular-expression/#basic-patterns-used-in-regular-expression
def anything():
return '.*'
def dot():
return match('.')
def dots():
return compose(dot(), one_or_more_times())
def linebreak():
return r'(?:(?:\n)|(?:\r\n))'
def something():
return '.+'