-
Notifications
You must be signed in to change notification settings - Fork 0
/
args.py
105 lines (92 loc) · 3.49 KB
/
args.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 enum import Enum, auto
from typing import Iterator, Union
from errors import Error
from statp import Stat, StatType
class Action(Enum):
"""Action based on CLI arguments."""
HELP = auto()
PARSE = auto()
ERR = auto()
class StatFile:
def __init__(self, filename: str) -> None:
self.filename = filename
self.stats: list[Stat] = []
class Args:
"""CLI parser"""
def __init__(self, args: Iterator[str]) -> None:
self.action = Action.PARSE
self.err_code = Error.NONE
self.err_msg = ""
self.stats: list[StatFile] = []
self.cur: Union[str, None] = None
self.args = args
def parse(self) -> None:
"""Parses the arguments"""
# skip the first argument
self._next()
self._next()
while self.cur is not None:
match self.cur:
case "-h" | "-?" | "--help":
if self.action != Action.PARSE:
return self._error("Cannot set action multiple times")
self.action = Action.HELP
case "--loc":
self._add_stat(Stat(StatType.LOC))
case "--comments":
self._add_stat(Stat(StatType.COMMENTS))
case "--labels":
self._add_stat(Stat(StatType.LABELS))
case "--jumps":
self._add_stat(Stat(StatType.JUMPS))
case "--fwjumps":
self._add_stat(Stat(StatType.FWJUMPS))
case "--backjumps":
self._add_stat(Stat(StatType.BACKJUMPS))
case "--badjumps":
self._add_stat(Stat(StatType.BADJUMPS))
case "--frequent":
self._add_stat(Stat(StatType.FREQUENT))
case "--eol":
self._add_stat(Stat(StatType.EOL))
case _:
if self.cur.startswith("--stats="):
spl = self.cur.split("=", 1)
self._add_stats(spl[1])
elif self.cur.startswith("--print="):
spl = self.cur.split("=", 1)
self._add_stat(Stat(StatType.PRINT, spl[1]))
else:
return self._error(f"Unknown argument '{self.cur}'")
self._next()
def _add_stat(self, stat: Stat) -> None:
# check if there is any --stats file to associate this stat with
if len(self.stats) == 0:
self._error("Cannot use '" + str(self.cur) + "' before --stats")
return
self.stats[-1].stats.append(stat)
def _add_stats(self, filename: str) -> None:
# check if the file is unique
for s in self.stats:
if s.filename == filename:
self._error(
f"Cannot output twice to the same file '{filename}'",
Error.FILE_WRITE
)
return
self.stats.append(StatFile(filename))
def _next(self) -> Union[str, None]:
self.cur = next(self.args, None)
return self.cur
def _error(self, msg: str, code: Error = Error.ARGS) -> None:
# save only the first error
if self.err_code == Error.NONE:
self.err_msg = msg
self.err_code = code
self.action = Action.ERR
def parse_args(args: list[str]) -> Args:
"""Parses the CLI arguments"""
it = iter(args)
res = Args(it)
res.parse()
return res