コード例 #1
0
    def __init__(self, input_data: Input) -> None:
        self.input = input_data

        self.imports = set(
            ["java.io.BufferedReader", "java.io.InputStreamReader"])
        existing_names = [var.name for var in input_data.input
                          ] + [var_name(input_data.name)]
        self.iterator = IteratorName(existing_names)
        self.words = WordsName(existing_names)
コード例 #2
0
ファイル: parser_perl.py プロジェクト: prologin/iorgen
def read_line(name: str, decl: str, type_: Type, input_data: Input,
              words: WordsName) -> List[str]:
    """Generate the Ruby code to read a line of given type"""
    assert type_.fits_in_one_line(input_data.structs)
    if type_.main == TypeEnum.INT:
        return [decl.format("int <>")]
    if type_.main == TypeEnum.CHAR:
        return [decl.format("substr <>, 0, 1")]
    if type_.main == TypeEnum.STR:
        read = "<>" if decl.startswith("my") else "scalar(<>)"
        return [decl.format(read), "chomp {};".format(name)]
    if type_.main == TypeEnum.LIST:
        assert type_.encapsulated is not None
        decl2 = decl
        if not decl.startswith("my"):
            decl2 = format_keep_braces(decl, "\\@{{[{}]}}")
        if type_.encapsulated.main == TypeEnum.INT:
            return [decl2.format("map { int } split(/[ \\n]/, <>)")]
        assert type_.encapsulated.main == TypeEnum.CHAR
        return [decl2.format("split /\\n?/, <>")]
    assert type_.main == TypeEnum.STRUCT
    struct = input_data.get_struct(type_.struct_name)
    decl2 = decl
    if not decl.startswith("my"):
        decl2 = format_keep_braces(decl, "\\%{{{{{}}}}}")
    split = words.next_name()
    fields = ('"{}" => {}'.format(
        f.name,
        ("int(${}[{}])" if f.type.main == TypeEnum.INT else
         "substr(${}[{}], 0, 1)").format(split, i),
    ) for i, f in enumerate(struct.fields))
    return [
        "my @{} = split /[ \\n]/, <>;".format(split),
        decl2.format("({})".format(", ".join(fields))),
    ]
コード例 #3
0
ファイル: parser_perl.py プロジェクト: prologin/iorgen
def read_lines(var: Variable, decl: str, size: str, input_data: Input,
               words: WordsName) -> List[str]:
    """Generate the Ruby code to read the lines for a given type"""
    if var.fits_in_one_line(input_data.structs):
        return read_line(var.name, decl, var.type, input_data, words)
    if var.type.main == TypeEnum.LIST:
        assert var.type.encapsulated is not None
        lines = [
            decl.format("()" if var.name[0] == "@" else "[]"),
            "for (1..{}) {{".format(size),
        ]
        words.push_scope()
        array_name = var.name.replace("{", "{{").replace("}", "}}")
        if array_name[0] != "@":
            array_name = "@{{" + array_name + "}}"
        lines.extend([
            INDENTATION + i for i in read_lines(
                Variable("$" + var.name[1:] +
                         "[-1]", "", var.type.encapsulated),
                "push({}, {{}});".format(array_name),
                size_name(var.type.encapsulated.size),
                input_data,
                words,
            )
        ])
        words.pop_scope()
        return lines + ["}"]
    assert var.type.main == TypeEnum.STRUCT
    struct = input_data.get_struct(var.type.struct_name)
    sizes = [size_name(field.type.size) for field in struct.fields]
    if struct.is_sized_struct():
        sizes = ["", f"{var.name}{{'{struct.fields[0].name}'}}"]
    lines = [decl.format("()" if var.name[0] == "%" else "{}")]
    for (field, f_size) in zip(struct.fields, sizes):
        f_name = f"${var.name[1:]}{{'{field.name}'}}"
        lines.extend(
            read_lines(
                Variable(f_name, "", field.type),
                f_name.replace("{", "{{").replace("}", "}}") + " = {};",
                f_size,
                input_data,
                words,
            ))
    return lines
コード例 #4
0
ファイル: parser_perl.py プロジェクト: prologin/iorgen
def gen_perl(input_data: Input, reprint: bool = False) -> str:
    """Generate a Perl code to parse input"""
    words = WordsName([var.name for var in input_data.input])
    output = "#!/usr/bin/perl\nuse strict;\nuse warnings;\n\n"
    output += "\n".join(call(input_data, reprint)) + "\n\n"
    for line in read_vars(input_data, words):
        output += line + "\n"
    args = (("\\" + var_name(i)).replace("\\$", "$") for i in input_data.input)
    output += "\n{}({});\n".format(sub_name(input_data.name), ", ".join(args))
    return output
コード例 #5
0
ファイル: parser_perl.py プロジェクト: prologin/iorgen
def read_vars(input_data: Input, words: WordsName) -> List[str]:
    """Read all input variables"""
    lines = []
    for variables in input_data.get_all_vars():
        if len(variables) == 1:
            var = variables[0]
            lines.extend(
                read_lines(
                    Variable(var_name(var), "", var.type, var.format_style),
                    "my {} = {{}};".format(var_name(var)),
                    size_name(var.type.size),
                    input_data,
                    words,
                ))
        else:
            split = words.next_name()
            lines.append(f"my @{split} = split / /, <>;")
            for i, var in enumerate(variables):
                lines.append(f"my {var_name(var)} = int(${split}[{i}]);")

    return lines
コード例 #6
0
ファイル: parser_csharp.py プロジェクト: prologin/iorgen
    def __init__(self, input_data: Input) -> None:
        self.input = input_data

        existing_names = [var.name for var in input_data.input]
        self.iterator = IteratorName(existing_names)
        self.words = WordsName(existing_names, cs_mode=True)
コード例 #7
0
ファイル: parser_csharp.py プロジェクト: prologin/iorgen
class ParserCS:
    """Create the C# code to parse an input"""
    def __init__(self, input_data: Input) -> None:
        self.input = input_data

        existing_names = [var.name for var in input_data.input]
        self.iterator = IteratorName(existing_names)
        self.words = WordsName(existing_names, cs_mode=True)

    def read_line(self, decl: bool, name: str, type_: Type,
                  indent_lvl: int) -> List[str]:
        """Read an entire line and store it into the right place(s)"""
        assert type_.fits_in_one_line(self.input.structs)
        indent = INDENTATION * indent_lvl
        if type_.main == TypeEnum.STRUCT:
            struct = self.input.get_struct(type_.struct_name)
            s_name = pascal_name(struct.name) + " "
            words = self.words.next_name()
            lines = [
                indent +
                "string[] {} = Console.ReadLine().Split(' ');".format(words)
            ]
            return lines + [
                "{}{}{} = new {}{{{}}};".format(
                    indent,
                    s_name if decl else "",
                    name,
                    s_name,
                    ", ".join("{} = {}".format(
                        var_name(f.name),
                        "int.Parse({}[{}])".format(words, i) if f.type.main ==
                        TypeEnum.INT else "{}[{}][0]".format(words, i),
                    ) for i, f in enumerate(struct.fields)),
                )
            ]
        type_decl = (type_str(type_) + " ") if decl else ""
        command = ""
        if type_.main == TypeEnum.INT:
            command = "int.Parse(Console.ReadLine())"
        elif type_.main == TypeEnum.CHAR:
            command = "Console.ReadLine()[0]"
        elif type_.main == TypeEnum.STR:
            command = "Console.ReadLine()"
        else:
            assert type_.main == TypeEnum.LIST
            assert type_.encapsulated is not None
            if type_.encapsulated.main == TypeEnum.CHAR:
                command = "Console.ReadLine().ToCharArray()"
            else:
                assert type_.encapsulated.main == TypeEnum.INT
                command = (
                    "Array.ConvertAll(Console.ReadLine().Split({}), "
                    "int.Parse)"
                ).format(
                    "new char[] {' '}, StringSplitOptions.RemoveEmptyEntries"
                    if type_.can_be_empty else "' '")

        assert command
        return ["{}{}{} = {};".format(indent, type_decl, name, command)]

    def read_lines(
        self,
        decl: bool,
        name: str,
        type_: Type,
        size: str,
        indent_lvl: int,
        style: FormatStyle = FormatStyle.DEFAULT,
    ) -> List[str]:
        # pylint: disable=too-many-arguments
        # pylint: disable=too-many-locals
        """Read one or several lines and store them into the right place(s)"""
        if type_.fits_in_one_line(self.input.structs, style):
            return self.read_line(decl, name, type_, indent_lvl)
        indent = INDENTATION * indent_lvl
        if type_.main == TypeEnum.STRUCT:
            lines = []
            if decl:
                lines.append("{}{} {};".format(indent,
                                               pascal_name(type_.struct_name),
                                               name))
            struct = self.input.get_struct(type_.struct_name)
            for f_name, f_type, f_size in struct.fields_name_type_size(
                    "{}.{{}}".format(name), var_name):
                lines.extend(
                    self.read_lines(False, f_name, f_type, f_size, indent_lvl))
            return lines
        assert type_.main == TypeEnum.LIST
        assert type_.encapsulated is not None
        far_inner_type = type_.encapsulated
        list_suffix = ""
        while far_inner_type.main == TypeEnum.LIST:
            assert far_inner_type.encapsulated is not None
            far_inner_type = far_inner_type.encapsulated
            list_suffix += "[]"
        lines = [
            "{}{}{} = new {}[{}]{};".format(
                indent,
                (type_str(type_) + " ") if decl else "",
                name,
                type_str(far_inner_type),
                size,
                list_suffix,
            )
        ]
        index = self.iterator.new_it()
        self.words.push_scope()
        lines.append("{0}for (int {1} = 0; {1} < {2}; ++{1})".format(
            indent, index, size))
        lines.append(indent + "{")
        lines.extend(
            self.read_lines(
                False,
                "{}[{}]".format(name, index),
                type_.encapsulated,
                var_name(type_.encapsulated.size),
                indent_lvl + 1,
            ))
        self.words.pop_scope()
        self.iterator.pop_it()
        return lines + [indent + "}"]

    def call(self, reprint: bool) -> List[str]:
        """Declare and call the function take all inputs in arguments"""
        lines = []
        arguments = []
        for arg in self.input.input:
            arg_name = var_name(arg.name)
            lines.append(INDENTATION +
                         "/// \\param {} {}".format(arg_name, arg.comment))
            arguments.append("{} {}".format(type_str(arg.type), arg_name))
        lines.append("{0}static void {1}({2})\n{0}{{".format(
            INDENTATION, pascal_name(self.input.name), ", ".join(arguments)))
        if reprint:
            for variables in self.input.get_all_vars():
                if len(variables) == 1:
                    var = variables[0]
                    lines.extend(
                        self.print_lines(var_name(var.name), var.type, 2,
                                         var.format_style))
                else:
                    fmt = " ".join(f"{{{i}}}" for i in range(len(variables)))
                    lines.append(
                        INDENTATION * 2 + f'Console.WriteLine("{fmt}", ' +
                        f"{', '.join(var_name(i.name) for i in variables)});")
        else:
            lines.extend([
                2 * INDENTATION + i for i in textwrap.wrap(
                    "/* TODO " + self.input.output + " */",
                    79 - 2 * len(INDENTATION),
                )
            ])
        return lines + [INDENTATION + "}"]

    def print_line(self, name: str, type_: Type) -> str:
        """Print the content of a var that holds in one line"""
        assert type_.fits_in_one_line(self.input.structs)
        if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR):
            return "Console.WriteLine({});".format(name)
        if type_.main == TypeEnum.LIST:
            assert type_.encapsulated is not None
            if type_.encapsulated.main == TypeEnum.CHAR:
                return "Console.WriteLine(new string({}));".format(name)
            assert type_.encapsulated.main == TypeEnum.INT
            return 'Console.WriteLine(String.Join(" ", {}));'.format(name)
        assert type_.main == TypeEnum.STRUCT
        fields = self.input.get_struct(type_.struct_name).fields
        return 'Console.WriteLine("{}", {});'.format(
            " ".join("{{{}}}".format(i) for i in range(len(fields))),
            ", ".join("{}.{}".format(name, var_name(f.name)) for f in fields),
        )

    def print_lines(
        self,
        name: str,
        type_: Type,
        indent_lvl: int,
        style: FormatStyle = FormatStyle.DEFAULT,
    ) -> List[str]:
        """Print the content of a var that holds in one or more lines"""
        if type_.fits_in_one_line(self.input.structs, style):
            return [INDENTATION * indent_lvl + self.print_line(name, type_)]
        if type_.main == TypeEnum.STRUCT:
            struct = self.input.get_struct(type_.struct_name)
            lines = []
            for field in struct.fields:
                lines.extend(
                    self.print_lines(
                        "{}.{}".format(name, var_name(field.name)),
                        field.type,
                        indent_lvl,
                    ))
            return lines
        assert type_.main == TypeEnum.LIST
        assert type_.encapsulated is not None
        index = self.iterator.new_it()
        self.words.push_scope()
        lines = [
            "{}foreach ({} {} in {})".format(INDENTATION * indent_lvl,
                                             type_str(type_.encapsulated),
                                             index, name)
        ]
        lines.append(INDENTATION * indent_lvl + "{")
        lines.extend(
            self.print_lines(index, type_.encapsulated, indent_lvl + 1))
        lines.append(INDENTATION * indent_lvl + "}")
        self.words.pop_scope()
        self.iterator.pop_it()
        return lines

    def content(self, reprint: bool) -> str:
        """Return the parser content"""
        output = "using System;\n\n"
        for struct in self.input.structs:
            output += "/// {}\n".format(struct.comment)
            output += "struct {}\n{{\n".format(pascal_name(struct.name))
            for field in struct.fields:
                output += INDENTATION + "public {} {}; //!< {}\n".format(
                    type_str(field.type), var_name(field.name), field.comment)
            output += "}\n\n"
        output += "class Program\n{\n"
        output += "\n".join(self.call(reprint)) + "\n"
        output += "\n{0}static void Main()\n{0}{{\n".format(INDENTATION)
        for variables in self.input.get_all_vars():
            if len(variables) == 1:
                var = variables[0]
                for line in self.read_lines(
                        True,
                        var_name(var.name),
                        var.type,
                        var_name(var.type.size),
                        2,
                        var.format_style,
                ):
                    output += line + "\n"
            else:
                words = self.words.next_name()
                output += (f"{INDENTATION * 2}string[] {words}"
                           " = Console.ReadLine().Split(' ');\n")
                for i, var in enumerate(variables):
                    assert var.type.main == TypeEnum.INT
                    output += (
                        INDENTATION * 2 +
                        f"int {var_name(var.name)} = int.Parse({words}[{i}]);\n"
                    )
        args = (var_name(var.name) for var in self.input.input)
        output += "\n{}{}({});\n".format(INDENTATION * 2,
                                         pascal_name(self.input.name),
                                         ", ".join(args))
        output += INDENTATION + "}\n}\n"
        return output
コード例 #8
0
class ParserJava:
    """Create the Java code to parse an input"""
    def __init__(self, input_data: Input) -> None:
        self.input = input_data

        self.imports = set(
            ["java.io.BufferedReader", "java.io.InputStreamReader"])
        existing_names = [var.name for var in input_data.input
                          ] + [var_name(input_data.name)]
        self.iterator = IteratorName(existing_names)
        self.words = WordsName(existing_names)

    def read_line(self, decl: bool, name: str, type_: Type,
                  indent_lvl: int) -> List[str]:
        """Read an entire line and store it into the right place(s)"""
        assert type_.fits_in_one_line(self.input.structs)
        indent = INDENTATION * indent_lvl
        if type_.main == TypeEnum.STRUCT:
            struct = self.input.get_struct(type_.struct_name)
            words = self.words.next_name()
            lines = [
                indent + f'String[] {words} = reader.readLine().split(" ");'
            ]
            lines.append(indent + "{}{} = new {}();".format(
                class_name(type_.struct_name) + " " if decl else "",
                name,
                class_name(type_.struct_name),
            ))
            lines.extend("{}{}.{} = {};".format(
                indent,
                name,
                var_name(f.name),
                f"Integer.parseInt({words}[{i}])" if f.type.main ==
                TypeEnum.INT else f"{words}[{i}].charAt(0)",
            ) for i, f in enumerate(struct.fields))
            return lines
        type_decl = (type_str(type_) + " ") if decl else ""
        command = ""
        if type_.main == TypeEnum.INT:
            command = "Integer.parseInt(reader.readLine())"
        elif type_.main == TypeEnum.CHAR:
            command = "reader.readLine().charAt(0)"
        elif type_.main == TypeEnum.STR:
            command = "reader.readLine()"
        else:
            assert type_.main == TypeEnum.LIST
            assert type_.encapsulated is not None
            if type_.encapsulated.main == TypeEnum.CHAR:
                command = "reader.readLine().toCharArray()"
            else:
                assert type_.encapsulated.main == TypeEnum.INT
                self.imports.add("java.util.Arrays")
                command = ('Arrays.stream(reader.readLine().split(" ")).{}'
                           "mapToInt(Integer::parseInt).toArray()"
                           ).format("filter(x -> !x.isEmpty())." if type_.
                                    can_be_empty else "")
        assert command
        return ["{}{}{} = {};".format(indent, type_decl, name, command)]

    def read_lines(self, decl: bool, var: Variable, size: str,
                   indent_lvl: int) -> List[str]:
        # pylint: disable=too-many-arguments
        # pylint: disable=too-many-locals
        """Read one or several lines and store them into the right place(s)"""
        if var.fits_in_one_line(self.input.structs):
            return self.read_line(decl, var.name, var.type, indent_lvl)
        indent = INDENTATION * indent_lvl
        if var.type.main == TypeEnum.STRUCT:
            lines = [
                indent + "{}{} = new {}();".format(
                    class_name(var.type.struct_name) + " " if decl else "",
                    var.name,
                    class_name(var.type.struct_name),
                )
            ]
            struct = self.input.get_struct(var.type.struct_name)
            for f_name, f_type, f_size in struct.fields_name_type_size(
                    f"{var.name}.{{}}", var_name):
                lines.extend(
                    self.read_lines(False, Variable(f_name, "", f_type),
                                    f_size, indent_lvl))
            return lines
        assert var.type.main == TypeEnum.LIST
        assert var.type.encapsulated is not None
        far_inner_type = var.type.encapsulated
        list_suffix = ""
        while far_inner_type.main == TypeEnum.LIST:
            assert far_inner_type.encapsulated is not None
            far_inner_type = far_inner_type.encapsulated
            list_suffix += "[]"
        lines = [
            "{}{}{} = new {}[{}]{};".format(
                indent,
                (type_str(var.type) + " ") if decl else "",
                var.name,
                type_str(far_inner_type),
                size,
                list_suffix,
            )
        ]
        index = self.iterator.new_it()
        self.words.push_scope()
        lines.append("{0}for (int {1} = 0; {1} < {2}; ++{1}) {{".format(
            indent, index, size))
        lines.extend(
            self.read_lines(
                False,
                Variable(f"{var.name}[{index}]", "", var.type.encapsulated),
                var_name(var.type.encapsulated.size),
                indent_lvl + 1,
            ))
        self.words.pop_scope()
        self.iterator.pop_it()
        return lines + [indent + "}"]

    def call(self, reprint: bool) -> List[str]:
        """Declare and call the function take all inputs in arguments"""
        lines = [INDENTATION + "/**"]
        arguments = []
        for arg in self.input.input:
            arg_name = var_name(arg.name)
            lines.append(INDENTATION +
                         " * @param {} {}".format(arg_name, arg.comment))
            arguments.append("{} {}".format(type_str(arg.type), arg_name))
        lines.append(INDENTATION + " */")
        lines.append("{}static void {}({}) {{".format(
            INDENTATION, var_name(self.input.name), ", ".join(arguments)))
        if reprint:
            for variables in self.input.get_all_vars():
                if len(variables) == 1:
                    var = variables[0]
                    lines.extend(
                        self.print_lines(
                            Variable(var_name(var.name), "", var.type,
                                     var.format_style),
                            var_name(var.type.size),
                            2,
                        ))
                else:
                    lines.append(INDENTATION * 2 +
                                 'System.out.printf("{}\\n", {});'.format(
                                     " ".join(["%d"] * len(variables)),
                                     ", ".join(
                                         var_name(i.name) for i in variables),
                                 ))
        else:
            lines.extend([
                2 * INDENTATION + i for i in textwrap.wrap(
                    "/* TODO " + self.input.output + " */",
                    79 - 2 * len(INDENTATION),
                )
            ])
        return lines + [INDENTATION + "}"]

    def print_line(self, name: str, type_: Type) -> str:
        """Print the content of a var that holds in one line"""
        assert type_.fits_in_one_line(self.input.structs)
        if type_.main in (TypeEnum.INT, TypeEnum.CHAR, TypeEnum.STR):
            return f"System.out.println({name});"
        if type_.main == TypeEnum.LIST:
            assert type_.encapsulated is not None
            if type_.encapsulated.main == TypeEnum.CHAR:
                return f"System.out.println(new String({name}));"
            assert type_.encapsulated.main == TypeEnum.INT
            self.imports.add("java.util.Arrays")
            self.imports.add("java.util.stream.Collectors")
            return "System.out.println(Arrays.stream({}).mapToObj({}".format(
                name, 'String::valueOf).collect(Collectors.joining(" ")));')
        assert type_.main == TypeEnum.STRUCT
        fields = self.input.get_struct(type_.struct_name).fields
        return 'System.out.printf("{}\\n", {});'.format(
            " ".join("%d" if f.type.main == TypeEnum.INT else "%c"
                     for f in fields),
            ", ".join("{}.{}".format(name, var_name(f.name)) for f in fields),
        )

    def print_lines(
        self,
        var: Variable,
        size: str,
        indent_lvl: int,
    ) -> List[str]:
        """Print the content of a var that holds in one or more lines"""
        if var.fits_in_one_line(self.input.structs):
            return [
                INDENTATION * indent_lvl + self.print_line(var.name, var.type)
            ]
        if var.type.main == TypeEnum.STRUCT:
            struct = self.input.get_struct(var.type.struct_name)
            lines = []
            for f_name, f_type, f_size in struct.fields_name_type_size(
                    f"{var.name}.{{}}", var_name):
                lines.extend(
                    self.print_lines(Variable(f_name, "", f_type), f_size,
                                     indent_lvl))
            return lines
        assert var.type.main == TypeEnum.LIST
        assert var.type.encapsulated is not None
        index = self.iterator.new_it()
        self.words.push_scope()
        lines = [
            "{0}for (int {1} = 0; {1} < {2}; ++{1}) {{".format(
                INDENTATION * indent_lvl, index, size)
        ]
        lines.extend(
            self.print_lines(
                Variable(f"{var.name}[{index}]", "", var.type.encapsulated),
                var_name(var.type.encapsulated.size),
                indent_lvl + 1,
            ))
        lines.append(INDENTATION * indent_lvl + "}")
        self.words.pop_scope()
        self.iterator.pop_it()
        return lines

    def content(self, reprint: bool) -> str:
        """Return the parser content"""
        output = ""
        for struct in self.input.structs:
            output += f"/**\n * {struct.comment}\n */\n"
            output += "class {}\n{{\n".format(class_name(struct.name))
            for field in struct.fields:
                decl_field = "{0}/**\n{0} * {1}\n{0} */\n{0}public {2} {3};\n"
                output += decl_field.format(
                    INDENTATION,
                    field.comment,
                    type_str(field.type),
                    var_name(field.name),
                )
            output += "}\n\n"
        output += "class Main {\n"
        output += "\n".join(self.call(reprint)) + "\n\n"
        output += (
            INDENTATION +
            "public static void main(String[] args) throws java.io.IOException {\n"
        )
        output += 2 * INDENTATION + (
            "BufferedReader reader = "
            "new BufferedReader(new InputStreamReader(System.in));\n")
        for variables in self.input.get_all_vars():
            if len(variables) == 1:
                var = variables[0]
                for line in self.read_lines(
                        True,
                        Variable(var_name(var.name), "", var.type,
                                 var.format_style),
                        var_name(var.type.size),
                        2,
                ):
                    output += line + "\n"
            else:
                words = self.words.next_name()
                output += (f"{INDENTATION * 2}String[] {words}"
                           ' = reader.readLine().split(" ");\n')
                for i, var in enumerate(variables):
                    assert var.type.main == TypeEnum.INT
                    output += (
                        INDENTATION * 2 +
                        f"int {var_name(var.name)} = Integer.parseInt({words}[{i}]);\n"
                    )
        args = (var_name(var.name) for var in self.input.input)
        output += "\n{}{}({});\n".format(INDENTATION * 2,
                                         var_name(self.input.name),
                                         ", ".join(args))
        output += INDENTATION + "}\n}\n"
        return "".join(f"import {i};\n"
                       for i in sorted(self.imports)) + "\n" + output
コード例 #9
0
ファイル: parser_javascript.py プロジェクト: prologin/iorgen
 def __init__(self, input_data: Input) -> None:
     self.input = input_data
     existing_names = [var_name(var.name) for var in input_data.input
                       ] + [var_name(input_data.name)]
     self.iterator = IteratorName(existing_names)
     self.words = WordsName(existing_names)
コード例 #10
0
ファイル: parser_javascript.py プロジェクト: prologin/iorgen
class ParserJS:
    """Create the Javascript code to parse an input"""
    def __init__(self, input_data: Input) -> None:
        self.input = input_data
        existing_names = [var_name(var.name) for var in input_data.input
                          ] + [var_name(input_data.name)]
        self.iterator = IteratorName(existing_names)
        self.words = WordsName(existing_names)

    def read_line(self, decl: bool, name: str, type_: Type, size: str,
                  indent_lvl: int) -> List[str]:
        # pylint: disable = too-many-arguments
        """Generate the Javascript code to read a line of given type"""
        assert type_.fits_in_one_line(self.input.structs)
        indent = INDENTATION * indent_lvl
        start = indent + ("const " if decl else "") + name + " = "
        if type_.main == TypeEnum.LIST:
            assert type_.encapsulated is not None
            if type_.encapsulated.main == TypeEnum.CHAR:
                return [start + 'stdin[line++].split("");']
            assert type_.encapsulated.main == TypeEnum.INT
            return [
                start +
                'stdin[line++].split(" ", {}).map(Number);'.format(size)
            ]
        if type_.main == TypeEnum.STRUCT:
            struct = self.input.get_struct(type_.struct_name)
            words = self.words.next_name()
            lines = [
                indent + 'const {} = stdin[line++].split(" ");'.format(words),
                start + "{",
            ]
            lines.extend(indent + INDENTATION + "{}: {}{}".format(
                var_name(field.name),
                "{}[{}]".format(words, i) if field.type.main ==
                TypeEnum.CHAR else "Number({}[{}])".format(words, i),
                "," if i != len(struct.fields) - 1 else "",
            ) for i, field in enumerate(struct.fields))
            return lines + [indent + "};"]
        return [
            start + {
                TypeEnum.INT: "Number(stdin[line++]);",
                TypeEnum.CHAR: "stdin[line++];",
                TypeEnum.STR: "stdin[line++];",
            }[type_.main]
        ]

    def read_lines(self, decl: bool, var: Variable, size: str,
                   indent_lvl: int) -> List[str]:
        # pylint: disable=too-many-arguments
        """Generate the Javascript code to read the lines for a given type"""
        if var.fits_in_one_line(self.input.structs):
            return self.read_line(decl, var.name, var.type, size, indent_lvl)
        indent = INDENTATION * indent_lvl
        if var.type.main == TypeEnum.LIST:
            assert var.type.encapsulated is not None
            lines = [indent + f"{'const ' if decl else ''}{var.name} = [];"]
            iterator = self.iterator.new_it()
            inner_name = self.iterator.new_it()
            lines.append(indent +
                         "for (let {0} = 0; {0} < {1}; {0}++) {{".format(
                             iterator, size))
            self.words.push_scope()
            lines.extend(
                self.read_lines(
                    True,
                    Variable(inner_name, "", var.type.encapsulated),
                    var_name(var.type.encapsulated.size),
                    indent_lvl + 1,
                ))
            lines.append(indent + INDENTATION +
                         f"{var.name}.push({inner_name});")
            self.words.pop_scope()
            self.iterator.pop_it()
            self.iterator.pop_it()
            return lines + [indent + "}"]
        assert var.type.main == TypeEnum.STRUCT
        struct = self.input.get_struct(var.type.struct_name)
        lines = [indent + f"{'const ' if decl else ''}{var.name} = {{}};"]
        for f_name, f_type, f_size in struct.fields_name_type_size(
                f"{var.name}.{{}}", var_name):
            lines.extend(
                self.read_lines(False, Variable(f_name, "", f_type), f_size,
                                indent_lvl))
        return lines

    def read_vars(self) -> List[str]:
        """Generate the Javascript code to read all input variables"""
        lines = []
        for variables in self.input.get_all_vars():
            if len(variables) == 1:
                var = variables[0]
                lines.extend(
                    self.read_lines(
                        True,
                        Variable(var_name(var.name), "", var.type,
                                 var.format_style),
                        var_name(var.type.size),
                        1,
                    ))
            else:
                lines.append(INDENTATION + "const [" +
                             ", ".join(var_name(i.name) for i in variables) +
                             '] = stdin[line++].split(" ").map(Number);')
        return lines