-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompact.py
121 lines (108 loc) · 4.92 KB
/
compact.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
import string as s
def compact(inpt: str, debug: bool):
# The input needs to be a list, so we can do .pop() on it later (we will turn it back into a str with .join())
inpt = list(inpt)
char = 0
in_comment = False
in_string = False
in_preprocessor = False
alphanum = s.ascii_letters + s.digits
while char < len(inpt):
# print(f"attempt number {char + 1}")
try:
if inpt[char] == '"':
in_string = not in_string
if inpt[char] == "/" and inpt[char + 1] == "/":
# Comment!
in_comment = True
char += 2
continue
if in_comment and inpt[char] == "\n":
in_comment = False
char += 1
continue
if inpt[char] == "#" and not in_preprocessor:
in_preprocessor = True
char += 1
continue
if inpt[char] == "\n" and in_preprocessor:
in_preprocessor = False
char += 1
continue
# print("".join(inpt)[char - 10:char + 11])
# print(in_string, in_comment, in_preprocessor)
if inpt[char] in s.whitespace:
if not in_string and not in_comment and not in_preprocessor:
# If you're in normal code
if debug:
print("remove clause 1")
if inpt[char - 1] in alphanum and inpt[char + 1] in alphanum and inpt[char] in s.whitespace:
# and before and after are alpha characters then skip this one
if debug:
print("part 1")
char += 1
continue
elif (inpt[char - 1] not in alphanum and inpt[char + 1] in alphanum) or \
(inpt[char + 1] not in alphanum and inpt[char - 1] in alphanum) and\
inpt[char] in s.whitespace:
# If you have an ascii character on one side and a non-ascii on the other,
# Then it's safe to remove
if debug:
print("part 2")
if debug:
print(f"removed .{inpt[char]}.")
inpt.pop(char)
char -= 1
elif inpt[char - 1] not in alphanum and inpt[char + 1] not in alphanum and\
inpt[char] in s.whitespace:
if debug:
print("part 3")
if debug:
print(f"removed .{inpt[char]}.")
inpt.pop(char)
char -= 1
# Remember to finish this up!
elif inpt[char + 1] in s.whitespace and not in_string and not in_comment:
# If the next character is also a whitespace, then the previous or next possible keywords
# will be buffered by the second whitespace
if debug:
print("remove clause 2")
if debug:
print(f"removed .{inpt[char]}.")
inpt.pop(char)
char -= 1
if in_preprocessor and inpt[char + 1] not in alphanum and \
inpt[char - 1] not in alphanum or inpt[char + 1] in "<\"" and inpt[char] in s.whitespace:
# This one's tricky. We are in the preprocessor so the first clause, which would normally resolve
# this, fails. So we need to pay attention to a simple #include situation. But to also take care of
# #define abc xyz situations we need to do the same thing as clause 1, but this time instead of
# s.ascii_letters we need s.ascii_letters AND s.digits
if debug:
print("remove clause 3")
if debug:
print(f"removed .{inpt[char]}.")
inpt.pop(char)
char -= 1
# print("--------------------------")
except IndexError:
char += 1
continue
char += 1
result = "".join(inpt)
result.replace("\n ", "\n")
return result
# def is_next_word_keyword(inpt, keywords, index):
# if inpt[index - 1] in ";>)(}=,{":
# return False
# word = ""
# for char in range(index, len(inpt)):
# if char == " ":
# break
# word += inpt[char]
# return word in keywords
def next_two_in(inpt, index, valids):
next_two = inpt[index] + inpt[index + 1]
for valid in valids:
if valid.startswith(next_two):
return True
return False