Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
exp_AHC.py
[詳解]
1HEAD = True
2CONST = True
3
4#!/usr/bin/env python3
5
6# https://github.com/atcoder/ac-library/blob/master/expander.py のコードを元にしています。
7
8import re
9import sys
10import argparse
11from logging import Logger, basicConfig, getLogger
12from os import getenv, environ, pathsep
13from pathlib import Path
14from typing import List, Set, Optional
15
16
17logger = getLogger(__name__) # type: Logger
18
19
20
22 """
23 Expander class is responsible for expanding libraries in the source code.
24
25 Attributes:
26 - include (re.Pattern): Regular expression pattern to match #include statements.
27 - lib_paths (List[Path]): List of library paths.
28 - included (Set[Path]): Set of included library file paths.
29
30 Methods:
31 - is_ignored_line(line: str) -> bool: Checks if a line should be ignored during expansion.
32 - find_library(library_name: str) -> Path: Finds the path of a library file.
33 - expand_library(library_file_path: Path) -> List[str]: Expands a library file.
34 - expand(source: str) -> str: Expands libraries in the source code.
35
36 """
37
38 include = re.compile(r'#include\s*["<](kyopro_library/[a-z0-9_/]*(|.hpp))[">]\s*')
39
40 def is_ignored_line(self, line) -> bool:
41 """
42 Checks if a line should be ignored during expansion.
43
44 Args:
45 - line (str): The line to be checked.
46
47 Returns:
48 - bool: True if the line should be ignored, False otherwise.
49
50 """
51 if line.strip() == "#pragma once":
52 return True
53 #if line.strip().startswith("//"):
54 # return True
55 if line.strip().startswith("using std::"):
56 return True
57 if line.strip() in ["#ifdef LOCAL","#include \"./debug.hpp\"","#else","#define debug(...)","#define print_line","#endif"] and not HEAD:
58 return True
59 if line.strip() in ["const int INF=1e9+10;","const ll INFL=4e18;"] and not CONST:
60 return True
61
62
63
64
65 return False
66
67 def __init__(self, lib_paths: List[Path]):
68 """
69 Initializes an Expander object.
70
71 Args:
72 - lib_paths (List[Path]): List of library paths.
73
74 """
75 self.lib_paths = lib_paths
76
77 included = set() # type: Set[Path]
78
79 def find_library(self, library_name: str) -> Path:
80 """
81 Finds the path of a library file.
82
83 Args:
84 - library_name (str): The name of the library file.
85
86 Returns:
87 - Path: The path of the library file.
88
89 Raises:
90 - FileNotFoundError: If the library file cannot be found.
91
92 """
93 for lib_path in self.lib_paths:
94 path = lib_path / library_name
95 if path.exists():
96 return path
97 logger.error("cannot find: {}".format(library_name))
98 raise FileNotFoundError()
99
100 def expand_library(self, library_file_path: Path) -> List[str]:
101 """
102 Expands a library file.
103
104 Args:
105 - library_file_path (Path): The path of the library file.
106
107 Returns:
108 - List[str]: The expanded lines of the library file.
109
110 """
111 if library_file_path in self.included:
112 logger.info("already included: {}".format(library_file_path.name))
113 return []
114 self.included.add(library_file_path)
115 logger.info("include: {}".format(library_file_path.name))
116
117 library_source = open(str(library_file_path)).read()
118
119 result = [] # type: List[str]
120 for line in library_source.splitlines():
121 if self.is_ignored_line(line):
122 continue
123
124 line = line.replace("../../../../", "")
125 line = line.replace("../../../", "")
126 line = line.replace("../../", "")
127 # line = line.replace("../", "")
128
129 # if "debug" in line:
130 # line = "//" + line
131 # if "print_line" in line:
132 # line = "//" + line
133
134 m = self.include.match(line)
135 if m:
136 name = m.group(1)
137 result.extend(self.expand_library(self.find_library(name)))
138 continue
139
140 result.append(line)
141
142 result.append("")
143 return result
144
145 def expand(self, source: str) -> str:
146 """
147 Expands libraries in the source code.
148
149 Args:
150 - source (str): The source code to be expanded.
151
152 Returns:
153 - str: The expanded source code.
154
155 """
156 self.included = set()
157 result = [] # type: List[str]
158 for line in source.splitlines():
159 m = self.include.match(line)
160 if m:
161 acl_path = self.find_library(m.group(1))
162 result.extend(self.expand_library(acl_path))
163 continue
164
165 if not HEAD:
166 if "debug" in line or "print_line" in line:
167 continue
168
169 # if line.startswith("ll ") or " ll " in line or "(ll)" in line or "<ll>" in line or "ll," in line or ",ll" in line:
170 # line=line.replace("ll","long long")
171
172 result.append(line)
173 return "\n".join(result)
174
175
176if __name__ == "__main__":
177 basicConfig(
178 format="%(asctime)s [%(levelname)s] %(message)s",
179 datefmt="%H:%M:%S",
180 level=getenv("LOG_LEVEL", "INFO"),
181 )
182 parser = argparse.ArgumentParser(description="Expander")
183 parser.add_argument("source", help="Source File")
184 parser.add_argument("-c", "--console", action="store_true", help="Print to Console")
185 parser.add_argument("--lib", help="Path to Atcoder Library")
186 opts = parser.parse_args()
187
188 lib_paths = []
189 if opts.lib:
190 lib_paths.append(Path(opts.lib))
191 if "CPLUS_INCLUDE_PATH" in environ:
192 lib_paths.extend(
193 map(Path, filter(None, environ["CPLUS_INCLUDE_PATH"].split(pathsep)))
194 )
195 lib_paths.append(Path.cwd())
196 expander = Expander(lib_paths)
197 source = open(opts.source).read()
198 output = expander.expand(source)
199
200 if opts.console:
201 print(output)
202 else:
203 with open("main.cpp", "w") as f:
204 f.write(output)
205 with open("combined.cpp", "w") as f:
206 f.write(output)
207
Expander class is responsible for expanding libraries in the source code.
Definition exp_AHC.py:21
bool is_ignored_line(self, line)
Checks if a line should be ignored during expansion.
Definition exp_AHC.py:40
List[str] expand_library(self, Path library_file_path)
Expands a library file.
Definition exp_AHC.py:100
Path find_library(self, str library_name)
Finds the path of a library file.
Definition exp_AHC.py:79
__init__(self, List[Path] lib_paths)
Initializes an Expander object.
Definition exp_AHC.py:67
str expand(self, str source)
Expands libraries in the source code.
Definition exp_AHC.py:145