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(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))), ]
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
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
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
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)
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
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
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)
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