-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse_norminette.py
105 lines (95 loc) · 3.87 KB
/
parse_norminette.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
from typing import List
from config import NORMINETTE_EXECUTABLE
from subprocess import check_output, CalledProcessError
ERROR_UNRECOGNIZED_TOKEN = "Error: Unrecognized token line "
ERROR_UNRECOGNIZED_LINE = "Error: Unrecognized line ("
ERROR_STRING_LITERAL_UNTERMINATED = "String literal unterminated detected at line "
ERROR_NESTED_BRACKETS = "Error: Nested parentheses, braces or brackets are not correctly closed"
ERROR_INVALID_PREPROCESSING_DIRECTIVE = "Invalid preprocessing directive"
ERROR_EXTRA_TOKEN_ENDIF = "Extra tokens at end of #endif directive"
ERROR_INCLUDE_FILE_ARGUMENT = "Invalid file argument for #include directive"
ERROR_INVALID_MACRO = "Invalid macro function definition"
ERROR_NO_SUCH_FILE = "no such file or directory"
ERROR_NO_VALID_C_FILE = "is not valid C or C header file"
ERROR_WITH_LINE_INFO = [ERROR_UNRECOGNIZED_LINE, ERROR_UNRECOGNIZED_TOKEN, ERROR_STRING_LITERAL_UNTERMINATED]
ERROR_WITH_LINE_INFO_TO_FIND = [ERROR_NESTED_BRACKETS, ERROR_EXTRA_TOKEN_ENDIF, ERROR_INVALID_PREPROCESSING_DIRECTIVE, ERROR_INCLUDE_FILE_ARGUMENT]
ERROR_WITHOUT_LINE_INFO = [ERROR_NO_VALID_C_FILE, ERROR_NO_SUCH_FILE]
def find_from_list(line: str, needles: List[str]):
for needle in needles:
if (res := line.find(needle)) != -1:
return needle
return ""
def get_errors_from_norminette(files: List[str]):
errors = {}
skipped = {}
if files == []:
return errors
try:
output = check_output([NORMINETTE_EXECUTABLE, *files], )
except CalledProcessError as err:
output = err.output
output = output.decode("utf-8").split("\n")
current_file = None
for line in output:
if line[-5:] == ": OK!" or line == "":
continue
elif line[-8:] == ": Error!":
current_file = line[:-8]
elif (error := find_from_list(line, ERROR_WITHOUT_LINE_INFO)) != "":
line = line.replace("Error:", "").strip()
current_file = line[:line.find(" ")].strip().replace("'", "")
skipped[current_file] = error.strip()
elif (error := find_from_list(line, ERROR_WITH_LINE_INFO)) != "":
skipped[current_file] = error[:-1].replace("Error: ", "").strip()
elif (error := find_from_list(line, ERROR_WITH_LINE_INFO_TO_FIND)) != "":
skipped[current_file] = error.replace("Error: ", "").strip()
else:
front, detail = line.split("):")
code, position = front.strip().split("(")
code = code[7:].strip()
position = position.split(",")
line_number = int(position[0].split(":")[1].strip())
column_number = int(position[1].split(":")[1].strip())
if not current_file in errors:
errors[current_file] = []
errors[current_file].append({"error_code": code, "error_msg": detail.strip(), "line": line_number, "column": column_number})
return errors, skipped
def error_codes_for_file(file):
error_codes = []
try:
output = check_output([NORMINETTE_EXECUTABLE, file], )
except CalledProcessError as err:
output = err.output
output = output.decode("utf-8").split("\n")
#current_file = None
for line in output:
if line[-5:] == ": OK!" or line == "":
next
elif line[-8:] == ": Error!":
pass
# current_file = line[:-8]
else:
if line.find(ERROR_UNRECOGNIZED_TOKEN) != -1:
error_codes.append(ERROR_UNRECOGNIZED_TOKEN)
continue
if line.find(ERROR_UNRECOGNIZED_LINE) != -1:
error_codes.append(ERROR_UNRECOGNIZED_LINE)
continue
if line.find(ERROR_NESTED_BRACKETS) != -1:
error_codes.append(ERROR_NESTED_BRACKETS)
continue
if line.find(ERROR_EXTRA_TOKEN_ENDIF) != -1:
error_codes.append(ERROR_EXTRA_TOKEN_ENDIF)
continue
if line.find(ERROR_STRING_LITERAL_UNTERMINATED) != -1:
error_codes.append(ERROR_STRING_LITERAL_UNTERMINATED)
continue
if line.find(ERROR_INVALID_MACRO) != -1:
error_codes.append(ERROR_INVALID_MACRO)
continue
front, _ = line.split("):")
code, _ = front.strip().split("(")
code = code[7:].strip()
error_codes.append(code)
error_codes = [code for code in error_codes if code != "LINE_TOO_LONG"]
return error_codes