icpc-snippet

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub EarthMessenger/icpc-snippet

:warning: tools/libexp.py

Code

#!/usr/bin/env python3
# Adapted from ACL expander.py.

import re
import argparse
from logging import Logger, basicConfig, getLogger
from os import getenv, environ, pathsep
from pathlib import Path
from typing import List, Set


logger = getLogger(__name__)  # type: Logger


class Expander:

    def is_ignored_line(self, line) -> bool:
        if self.include_guard.match(line):
            return True
        if line.strip() == "#pragma once":
            return True
        if line.strip().startswith('//'):
            return True
        return False

    def __init__(self, lib_paths: List[Path], lib_name: str):
        self.lib_paths = lib_paths
        self.lib_include = re.compile(
        fr'#include\s*["<]({lib_name}/[a-z_/]*(|.hpp))[">]\s*')
        self.include_guard = re.compile(fr'#.*{lib_name.capitalize()}_[A-Z_]*_HPP')

    included = set()  # type: Set[Path]

    def find_lib(self, lib_name: str) -> Path:
        for lib_path in self.lib_paths:
            path = lib_path / lib_name
            if path.exists():
                return path
        logger.error('cannot find: {}'.format(lib_name))
        raise FileNotFoundError()

    def expand_lib(self, lib_file_path: Path) -> List[str]:
        if lib_file_path in self.included:
            logger.info('already included: {}'.format(lib_file_path.name))
            return []
        self.included.add(lib_file_path)
        logger.info('include: {}'.format(lib_file_path.name))

        lib_source = open(str(lib_file_path), encoding='utf-8').read()

        result = []  # type: List[str]
        for line in lib_source.splitlines():
            if self.is_ignored_line(line):
                continue

            m = self.lib_include.match(line)
            if m:
                name = m.group(1)
                result.extend(self.expand_lib(self.find_lib(name)))
                continue

            result.append(line)
        return result

    def expand(self, source: str) -> str:
        self.included = set()
        result = []  # type: List[str]
        for line in source.splitlines():
            m = self.lib_include.match(line)
            if m:
                lib_path = self.find_lib(m.group(1))
                result.extend(self.expand_lib(lib_path))
                continue

            result.append(line)
        return '\n'.join(result)


if __name__ == "__main__":
    basicConfig(
        format="%(asctime)s [%(levelname)s] %(message)s",
        datefmt="%H:%M:%S",
        level=getenv('LOG_LEVEL', 'INFO'),
    )
    parser = argparse.ArgumentParser(description='Expander')
    parser.add_argument('source', help='Source File')
    parser.add_argument('--console', '-c',
                        action='store_true', help='Print to Console')
    parser.add_argument('--libname', '-ln', help='Name List of Libraries', nargs='+', default=['lib'])
    parser.add_argument("--libpath", '-lp', help='Path List to Libraries', nargs='*')
    parser.add_argument('--inplace', '-i', action="store_true", 
                        help = "Replace the Old File with the Expanded One")
    parser.add_argument('--output', '-o', help="Output Filename", default="combined.cpp")

    opts = parser.parse_args()

    lib_paths = []
    if opts.libpath != None:
        for p in opts.libpath:
            lib_paths.append(Path(p))
    if 'CPLUS_INCLUDE_PATH' in environ:
        lib_paths.extend(
            map(Path, filter(None, environ['CPLUS_INCLUDE_PATH'].split(pathsep))))
    lib_paths.append(Path.cwd())
    lib_names = opts.libname

    expander = Expander(lib_paths, lib_names[-1])
    output = expander.expand(open(opts.source, encoding='utf-8').read())
    while len(lib_names) > 1:
        lib_names.pop()
        expander = Expander(lib_paths, lib_names[-1])
        output = expander.expand(output)

    if opts.console:
        print(output)
    else:
        if opts.inplace:
            with open(opts.source, 'w', encoding='utf-8') as f:
                f.write(output)
        else:
            with open(opts.output, 'w', encoding='utf-8') as f:
                f.write(output)
Traceback (most recent call last):
  File "/home/runner/.local/lib/python3.10/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
    bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
  File "/home/runner/.local/lib/python3.10/site-packages/onlinejudge_verify/languages/python.py", line 96, in bundle
    raise NotImplementedError
NotImplementedError
Back to top page