Skip to content

Commit d6930c7

Browse files
committed
Add ignore tag to the match.py script
1 parent bdf2918 commit d6930c7

File tree

1 file changed

+111
-56
lines changed

1 file changed

+111
-56
lines changed

cmake/match.py

Lines changed: 111 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,132 @@
55
# See LICENSE.TXT
66
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
77

8-
# check if all lines match in a file
9-
# lines in a match file can contain regex inside of double curly braces {{}}
8+
# Check if all input file content matches match file content.
9+
# Lines in a match file can contain regex inside of double curly braces {{}}.
10+
# Regex patterns are limited to single line.
11+
#
12+
# List of available special tags:
13+
# {{OPT}} - makes content in the same line as the tag optional
14+
# {{IGNORE}} - ignores all content until the next successfully matched line or the end of the input
15+
# Special tags are mutually exclusive and are expected to be located at the start of a line.
16+
#
1017

18+
import os
1119
import sys
1220
import re
21+
from enum import Enum
1322

1423

1524
## @brief print the whole content of input and match files
16-
def print_content(input_lines, match_lines):
25+
def print_content(input_lines, match_lines, ignored_lines):
1726
print("--- Input Lines " + "-" * 64)
1827
print("".join(input_lines).strip())
1928
print("--- Match Lines " + "-" * 64)
2029
print("".join(match_lines).strip())
30+
print("--- Ignored Lines " + "-" * 62)
31+
print("".join(ignored_lines).strip())
2132
print("-" * 80)
2233

2334

24-
if len(sys.argv) != 3:
25-
print("Usage: python match.py <input_file> <match_file>")
26-
sys.exit(1)
27-
28-
input_file = sys.argv[1]
29-
match_file = sys.argv[2]
30-
31-
with open(input_file, 'r') as input, open(match_file, 'r') as match:
32-
input_lines = input.readlines()
33-
match_lines = match.readlines()
34-
35-
if len(match_lines) < len(input_lines):
36-
print(f"Match length < input length (input: {len(input_lines)}, match: {len(match_lines)})")
37-
print_content(input_lines, match_lines)
38-
sys.exit(1)
39-
40-
input_idx = 0
41-
opt = "{{OPT}}"
42-
for i, match_line in enumerate(match_lines):
43-
if match_line.startswith(opt):
44-
optional_line = True
45-
match_line = match_line[len(opt):]
46-
else:
47-
optional_line = False
48-
49-
# split into parts at {{ }}
50-
match_parts = re.split(r'\{{(.*?)\}}', match_line.strip())
51-
pattern = ""
52-
for j, part in enumerate(match_parts):
53-
if j % 2 == 0:
54-
pattern += re.escape(part)
55-
else:
56-
pattern += part
35+
## @brief print the incorrect match line
36+
def print_incorrect_match(match_line, present, expected):
37+
print("Line " + str(match_line) + " does not match")
38+
print("is: " + present)
39+
print("expected: " + expected)
5740

58-
# empty input file or end of input file, from now on match file must be optional
59-
if not input_lines:
60-
if optional_line is True:
61-
continue
62-
else:
63-
print("End of input file or empty file.")
64-
print("expected: " + match_line.strip())
41+
42+
## @brief pattern matching script status values
43+
class Status(Enum):
44+
INPUT_END = 1
45+
MATCH_END = 2
46+
INPUT_AND_MATCH_END = 3
47+
PROCESSING = 4
48+
49+
50+
## @brief check matching script status
51+
def check_status(input_lines, match_lines):
52+
if not input_lines and not match_lines:
53+
return Status.INPUT_AND_MATCH_END
54+
elif not input_lines:
55+
return Status.INPUT_END
56+
elif not match_lines:
57+
return Status.MATCH_END
58+
return Status.PROCESSING
59+
60+
61+
## @brief pattern matching tags.
62+
## Tags are expected to be at the start of the line.
63+
class Tag(Enum):
64+
OPT = "{{OPT}}" # makes the line optional
65+
IGNORE = "{{IGNORE}}" # ignores all input until next match or end of input file
66+
67+
68+
## @brief main function for the match file processing script
69+
def main():
70+
if len(sys.argv) != 3:
71+
print("Usage: python match.py <input_file> <match_file>")
72+
sys.exit(1)
73+
74+
input_file = sys.argv[1]
75+
match_file = sys.argv[2]
76+
77+
with open(input_file, 'r') as input, open(match_file, 'r') as match:
78+
input_lines = input.readlines()
79+
match_lines = match.readlines()
80+
81+
ignored_lines = []
82+
83+
input_idx = 0
84+
match_idx = 0
85+
tags_in_effect = []
86+
while True:
87+
# check file status
88+
status = check_status(input_lines[input_idx:], match_lines[match_idx:])
89+
if (status == Status.INPUT_AND_MATCH_END) or (status == Status.MATCH_END and Tag.IGNORE in tags_in_effect):
90+
# all lines matched or the last line in match file is an ignore tag
91+
sys.exit(0)
92+
elif status == Status.MATCH_END:
93+
print_incorrect_match(match_idx + 1, input_lines[input_idx].strip(), "");
94+
print_content(input_lines, match_lines, ignored_lines)
6595
sys.exit(1)
6696

67-
input_line = input_lines[input_idx].strip()
68-
if not re.fullmatch(pattern, input_line):
69-
if optional_line is True:
70-
continue
97+
input_line = input_lines[input_idx].strip() if input_idx < len(input_lines) else ""
98+
match_line = match_lines[match_idx]
99+
100+
# check for tags
101+
if match_line.startswith(Tag.OPT.value):
102+
tags_in_effect.append(Tag.OPT)
103+
match_line = match_line[len(Tag.OPT.value):]
104+
elif match_line.startswith(Tag.IGNORE.value):
105+
tags_in_effect.append(Tag.IGNORE)
106+
match_idx += 1
107+
continue # line with ignore tag should be skipped
108+
109+
# split into parts at {{ }}
110+
match_parts = re.split(r'\{{(.*?)\}}', match_line.strip())
111+
pattern = ""
112+
for j, part in enumerate(match_parts):
113+
if j % 2 == 0:
114+
pattern += re.escape(part)
115+
else:
116+
pattern += part
117+
118+
# match or process tags
119+
if re.fullmatch(pattern, input_line):
120+
input_idx += 1
121+
match_idx += 1
122+
tags_in_effect = []
123+
elif Tag.OPT in tags_in_effect:
124+
match_idx += 1
125+
tags_in_effect.remove(Tag.OPT)
126+
elif Tag.IGNORE in tags_in_effect:
127+
ignored_lines.append(input_line + os.linesep)
128+
input_idx += 1
71129
else:
72-
print("Line " + str(i+1) + " does not match")
73-
print("is: " + input_line)
74-
print("expected: " + match_line.strip())
75-
print_content(input_lines, match_lines)
130+
print_incorrect_match(match_idx + 1, input_line, match_line.strip())
131+
print_content(input_lines, match_lines, ignored_lines)
76132
sys.exit(1)
77-
else:
78-
if (input_idx == len(input_lines) - 1):
79-
input_lines = []
80-
else:
81-
input_idx += 1
133+
134+
135+
if __name__ == "__main__":
136+
main()

0 commit comments

Comments
 (0)