From ee8526c62b2eb1a77da391cd749284b9cab2262d Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Tue, 30 Jul 2024 13:15:11 +0100 Subject: [PATCH] Stricter prefix matching (fixes #28) (#29) This PR adds the requirement that the `CHECK` be preceded by either a new-line, or a character that is not `[A-Za-z]`. This fixes #28 It also adds diagnostic printing when checking fails inside a DAG region by printing all currently considered input and greying out regions that are already consumed. --- filecheck/finput.py | 9 +++++++++ filecheck/matcher.py | 13 +++++++++++++ filecheck/parser.py | 11 ++++++----- tests/filecheck/flags/check-prefix.test | 1 + 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/filecheck/finput.py b/filecheck/finput.py index f614a9d..218548b 100644 --- a/filecheck/finput.py +++ b/filecheck/finput.py @@ -10,6 +10,7 @@ from dataclasses import dataclass, field from typing import Iterable +from filecheck.colors import FMT from filecheck.options import Options ANY_NEWLINES = re.compile(r"\n*") @@ -297,6 +298,14 @@ def match_and_add_hole(self, pattern: re.Pattern[str]) -> re.Match[str] | None: self.range.add_hole(InputRange(match.start(0), match.end(0))) return match + def print_current_range(self): + end = self.range.start + for a, b in self.range.ranges(): + yield f"{FMT.GRAY}{self.content[end:a]}{FMT.RESET}" + yield f"{self.content[a:b]}" + end = b + yield f"{FMT.GRAY}{self.content[end:self.range.end]}{FMT.RESET}" + def advance_to_last_hole(self): """ Advance to end of the last hole in the discontigous region diff --git a/filecheck/matcher.py b/filecheck/matcher.py index 2211fd5..5ad4a99 100644 --- a/filecheck/matcher.py +++ b/filecheck/matcher.py @@ -126,6 +126,13 @@ def run(self) -> int: ) print("Current position at " + self.file.print_line(), file=sys.stderr) + if self.file.is_discontigous(): + print( + "\nCurrently matching in range (grey is already matched):", + file=sys.stderr, + ) + print("".join(self.file.print_current_range()), file=sys.stderr) + # try to look for a shorter match, and print that if possible prefix_match = self.find_prefix_match_for(ex.op) if prefix_match is not None: @@ -143,6 +150,12 @@ def run(self) -> int: self.file.print_line(ex.match.start(0), ex.match.end(0)), file=sys.stderr, ) + if self.file.is_discontigous(): + print( + "\nCurrently matching in range (grey is already matched):", + file=sys.stderr, + ) + print("".join(self.file.print_current_range()), file=sys.stderr) return 1 return 0 diff --git a/filecheck/parser.py b/filecheck/parser.py index 574a35c..ade0dca 100644 --- a/filecheck/parser.py +++ b/filecheck/parser.py @@ -19,7 +19,8 @@ def pattern_for_opts(opts: Options) -> tuple[re.Pattern[str], re.Pattern[str]]: prefixes = f"({'|'.join(map(re.escape, opts.check_prefixes))})" return re.compile( - prefixes + r"(^|[^a-zA-Z])" + + prefixes + r"(-(DAG|COUNT-\d+|NOT|EMPTY|NEXT|SAME|LABEL))?(\{LITERAL})?:\s?([^\n]*)\n?" ), re.compile(f"({'|'.join(map(re.escape, opts.comment_prefixes))}).*{prefixes}") @@ -86,10 +87,10 @@ def __next__(self) -> CheckOp: # no check line = skip if match is None: continue - prefix = match.group(1) - kind = match.group(3) - literal = match.group(4) - arg = match.group(5) + prefix = match.group(2) + kind = match.group(4) + literal = match.group(5) + arg = match.group(6) if kind is None: kind = "CHECK" if arg is None: diff --git a/tests/filecheck/flags/check-prefix.test b/tests/filecheck/flags/check-prefix.test index db12208..4961203 100644 --- a/tests/filecheck/flags/check-prefix.test +++ b/tests/filecheck/flags/check-prefix.test @@ -3,3 +3,4 @@ hallo welt // TEST: hallo welt +// NOTEST: will not be matched