def parse_specifier(string, graph, layer_node_map):
    pos = string.find(b'(')
    if (pos == (- 1)):
        input_name = str(string.split(b' ')[0]).strip('b').replace("'", '').replace('\\n', '')
        if (input_name not in layer_node_map):
            node_name = graph.unique_id(prefix=input_name)
            graph.add_node(node_name, parameters=[], op='', kind='op')
            layer_node_map[input_name] = node_name
        else:
            node_name = layer_node_map[input_name]
        return node_name
    spec = string[:pos]
    args = get_args_for_specifier(string[pos:])
    if (spec == b'Append'):
        nodes = []
        for i in range(len(args)):
            nodes.append(parse_specifier(args[i], graph, layer_node_map))
        layer_name = 'Append_'
        for node in nodes:
            layer_name = ((layer_name + node) + '_')
        if (layer_name not in layer_node_map):
            concat_name = graph.unique_id(prefix=layer_name)
            graph.add_node(concat_name, parameters=None, op='concat', kind='op')
            layer_node_map[layer_name] = concat_name
            i = 0
            Node(graph, concat_name).add_sequence_of_ports('in', range(len(nodes)))
            for node in nodes:
                out_port = len(Node(graph, node).out_nodes())
                Node(graph, node).add_output_port(out_port)
                graph.create_edge(Node(graph, node), Node(graph, concat_name), out_port, i, create_edge_attrs(node, concat_name, node, i, out_port))
                i = (i + 1)
        else:
            concat_name = layer_node_map[layer_name]
        return concat_name
    elif (spec == b'Offset'):
        node = parse_specifier(args[0], graph, layer_node_map)
        t = int(args[1])
        if (len(args) > 2):
            raise Error('ModelOptimizer supports only 2 arguments for Offset')
        layer_name = (('Offset_' + node) + '_')
        if (t < 0):
            layer_name = ((layer_name + '_') + str((- t)))
        else:
            layer_name = (layer_name + str(t))
        if (layer_name not in layer_node_map):
            memory_name = graph.unique_id(prefix=layer_name)
            layer_node_map[layer_name] = memory_name
            memory_name_2 = (memory_name + '_out')
            graph.add_node(memory_name, parameters=dict(t=t, pair_name=memory_name_2, has_default=False), op='MemoryOffset', kind='op')
            out_port = len(Node(graph, node).out_nodes())
            in_port = len(Node(graph, memory_name).in_nodes())
            Node(graph, memory_name).add_input_port(in_port)
            Node(graph, node).add_output_port(out_port, skip_if_exist=True)
            graph.create_edge(Node(graph, node), Node(graph, memory_name), out_port, in_port, create_edge_attrs(node, memory_name, node, in_port, out_port))
        else:
            memory_name = layer_node_map[layer_name]
        return memory_name
    elif (spec == b'Sum'):
        nodes = []
        for i in range(len(args)):
            nodes.append(parse_specifier(args[i], graph, layer_node_map))
        layer_name = 'Sum_'
        for node in nodes:
            layer_name = ((layer_name + node) + '_')
        if (layer_name not in layer_node_map):
            sum_name = graph.unique_id(prefix=layer_name)
            graph.add_node(sum_name, parameters=None, op='Add', kind='op')
            layer_node_map[layer_name] = sum_name
        else:
            sum_name = layer_node_map[layer_name]
        for (i, node) in enumerate(nodes):
            out_port = len(Node(graph, node).out_nodes())
            Node(graph, node).add_output_port(out_port, skip_if_exist=True)
            Node(graph, sum_name).add_input_port(i)
            graph.add_edge(node, sum_name, **create_edge_attrs(node, sum_name, node, i))
        return sum_name
    elif (spec == b'IfDefined'):
        node_id = parse_specifier(args[0], graph, layer_node_map)
        node = Node(graph, node_id)
        if (node.op == 'MemoryOffset'):
            node['parameters']['has_default'] = True
        return node_id
    elif (spec == b'ReplaceIndex'):
        node = parse_specifier(args[0], graph, layer_node_map)
        return node
    elif (spec == b'Scale'):
        node_name = parse_specifier(args[1], graph, layer_node_map)
        scale_value = float(args[0])
        layer_name = '{}/Mul/{}'.format(node_name, scale_value)
        if (layer_name not in layer_node_map):
            scale_name = graph.unique_id(prefix=layer_name)
            scale_node = Mul(graph, {'name': scale_name}).create_node()
            layer_node_map[layer_name] = scale_name
            scale_const_name = 'Const_{}'.format(scale_value)
            const_node = Const(graph, {'name': scale_const_name, 'value': float_array([scale_value])}).create_node()
            node = Node(graph, node_name)
            graph.create_edge(const_node, scale_node, 0, 0, create_edge_attrs(const_node.id, scale_node.id, const_node.id))
            out_port = len(node.out_nodes())
            graph.create_edge(node, scale_node, out_port, 1, create_edge_attrs(node_name, scale_node.id, node_name, 1, out_port))
        else:
            scale_name = layer_node_map[layer_name]
        return scale_name
def parse_specifier(string, graph, layer_node_map):
    pos = string.find(b'(')
    if (pos == (- 1)):
        input_name = str(string.split(b' ')[0]).strip('b').replace("'", ).replace('\\n', )
        if (input_name not in layer_node_map):
            node_name = graph.unique_id(prefix=input_name)
            graph.add_node(node_name, parameters=[], op=, kind='op')
            layer_node_map[input_name] = node_name
        else:
            node_name = layer_node_map[input_name]
        return node_name
    spec = string[:pos]
    args = get_args_for_specifier(string[pos:])
    if (spec == b'Append'):
        nodes = []
        for i in range(len(args)):
            nodes.append(parse_specifier(args[i], graph, layer_node_map))
        layer_name = 'Append_'
        for node in nodes:
            layer_name = ((layer_name + node) + '_')
        if (layer_name not in layer_node_map):
            concat_name = graph.unique_id(prefix=layer_name)
            graph.add_node(concat_name, parameters=None, op='concat', kind='op')
            layer_node_map[layer_name] = concat_name
            i = 0
            Node(graph, concat_name).add_sequence_of_ports('in', range(len(nodes)))
            for node in nodes:
                out_port = len(Node(graph, node).out_nodes())
                Node(graph, node).add_output_port(out_port)
                graph.create_edge(Node(graph, node), Node(graph, concat_name), out_port, i, create_edge_attrs(node, concat_name, node, i, out_port))
                i = (i + 1)
        else:
            concat_name = layer_node_map[layer_name]
        return concat_name
    elif (spec == b'Offset'):
        node = parse_specifier(args[0], graph, layer_node_map)
        t = int(args[1])
        if (len(args) > 2):
            raise Error('ModelOptimizer supports only 2 arguments for Offset')
        layer_name = (('Offset_' + node) + '_')
        if (t < 0):
            layer_name = ((layer_name + '_') + str((- t)))
        else:
            layer_name = (layer_name + str(t))
        if (layer_name not in layer_node_map):
            memory_name = graph.unique_id(prefix=layer_name)
            layer_node_map[layer_name] = memory_name
            memory_name_2 = (memory_name + '_out')
            graph.add_node(memory_name, parameters=dict(t=t, pair_name=memory_name_2, has_default=False), op='MemoryOffset', kind='op')
            out_port = len(Node(graph, node).out_nodes())
            in_port = len(Node(graph, memory_name).in_nodes())
            Node(graph, memory_name).add_input_port(in_port)
            Node(graph, node).add_output_port(out_port, skip_if_exist=True)
            graph.create_edge(Node(graph, node), Node(graph, memory_name), out_port, in_port, create_edge_attrs(node, memory_name, node, in_port, out_port))
        else:
            memory_name = layer_node_map[layer_name]
        return memory_name
    elif (spec == b'Sum'):
        nodes = []
        for i in range(len(args)):
            nodes.append(parse_specifier(args[i], graph, layer_node_map))
        layer_name = 'Sum_'
        for node in nodes:
            layer_name = ((layer_name + node) + '_')
        if (layer_name not in layer_node_map):
            sum_name = graph.unique_id(prefix=layer_name)
            graph.add_node(sum_name, parameters=None, op='Add', kind='op')
            layer_node_map[layer_name] = sum_name
        else:
            sum_name = layer_node_map[layer_name]
        for (i, node) in enumerate(nodes):
            out_port = len(Node(graph, node).out_nodes())
            Node(graph, node).add_output_port(out_port, skip_if_exist=True)
            Node(graph, sum_name).add_input_port(i)
            graph.add_edge(node, sum_name, **create_edge_attrs(node, sum_name, node, i))
        return sum_name
    elif (spec == b'IfDefined'):
        node_id = parse_specifier(args[0], graph, layer_node_map)
        node = Node(graph, node_id)
        if (node.op == 'MemoryOffset'):
            node['parameters']['has_default'] = True
        return node_id
    elif (spec == b'ReplaceIndex'):
        node = parse_specifier(args[0], graph, layer_node_map)
        return node
    elif (spec == b'Scale'):
        node_name = parse_specifier(args[1], graph, layer_node_map)
        scale_value = float(args[0])
        layer_name = '{}/Mul/{}'.format(node_name, scale_value)
        if (layer_name not in layer_node_map):
            scale_name = graph.unique_id(prefix=layer_name)
            scale_node = Mul(graph, {'name': scale_name}).create_node()
            layer_node_map[layer_name] = scale_name
            scale_const_name = 'Const_{}'.format(scale_value)
            const_node = Const(graph, {'name': scale_const_name, 'value': float_array([scale_value])}).create_node()
            node = Node(graph, node_name)
            graph.create_edge(const_node, scale_node, 0, 0, create_edge_attrs(const_node.id, scale_node.id, const_node.id))
            out_port = len(node.out_nodes())
            graph.create_edge(node, scale_node, out_port, 1, create_edge_attrs(node_name, scale_node.id, node_name, 1, out_port))
        else:
            scale_name = layer_node_map[layer_name]
        return scale_name