| 130 | categ_pattern = re.compile(r'\\p{[A-Za-z_]+}') |
| 131 | |
| 132 | def get_regexp_width(expr: str) -> Union[Tuple[int, int], List[int]]: |
| 133 | if _has_regex: |
| 134 | # Since `sre_parse` cannot deal with Unicode categories of the form `\p{Mn}`, we replace these with |
| 135 | # a simple letter, which makes no difference as we are only trying to get the possible lengths of the regex |
| 136 | # match here below. |
| 137 | regexp_final = re.sub(categ_pattern, 'A', expr) |
| 138 | else: |
| 139 | if re.search(categ_pattern, expr): |
| 140 | raise ImportError('`regex` module must be installed in order to use Unicode categories.', expr) |
| 141 | regexp_final = expr |
| 142 | try: |
| 143 | # Fixed in next version (past 0.960) of typeshed |
| 144 | return [int(x) for x in sre_parse.parse(regexp_final).getwidth()] |
| 145 | except sre_constants.error: |
| 146 | if not _has_regex: |
| 147 | raise ValueError(expr) |
| 148 | else: |
| 149 | # sre_parse does not support the new features in regex. To not completely fail in that case, |
| 150 | # we manually test for the most important info (whether the empty string is matched) |
| 151 | c = regex.compile(regexp_final) |
| 152 | # Python 3.11.7 introducded sre_parse.MAXWIDTH that is used instead of MAXREPEAT |
| 153 | # See lark-parser/lark#1376 and python/cpython#109859 |
| 154 | MAXWIDTH = getattr(sre_parse, "MAXWIDTH", sre_constants.MAXREPEAT) |
| 155 | if c.match('') is None: |
| 156 | # MAXREPEAT is a none pickable subclass of int, therefore needs to be converted to enable caching |
| 157 | return 1, int(MAXWIDTH) |
| 158 | else: |
| 159 | return 0, int(MAXWIDTH) |
| 160 | |
| 161 | ###} |
| 162 | |