Q:

Parsing complex text file in Python

I have a text file like the following:
#some_line
    @another_line
        original_string1|new_string1
#some_other_line
    @and_another_line
        original_string2|new_string2

I want to be able to associate every line with an @ to the preceding line with a #.
I cannot seem to figure out a strategy to achieve this in python.
Here is my current code:
    with open(self.file, 'r') as f:
        for i, line in enumerate(f):
            line = line.strip(' \t\n\r')
            if '#' in line[:1]:
                self.parent[i] = line[1:]
            if '@' in line[:1]:
                self.child[i] = line[1:]
            if '|' in line:
                key, value = line.split('|')
                self.strings[key] = value

I need to be able to reference each parent entry and associate the child entries with it.
The lines with a '|' also need to be associated with the parent as well.

A:

I think what you want is a mapping from child strings to parent strings. Or maybe you want a mapping from child strings and parent strings back to line numbers.
So here's what I'll do: build those mappings from strings to line numbers (I'm assuming each one is unique, but it should be easy to fix if not), and also build a mapping from child line numbers to parent line numbers. If you actually needed the string-to-string mapping, or anything else, you should be able to figure it out from this.
The strings-to-line-numbers part is trivial, but for the child-to-parent part, we need to keep track of the last parent line number we've seen.
child_lines, parent_lines, child_parents = {}. {}. {}
last_parent_line = None
with open(self.file) as f:
    for i, line in enumerate(f):
        line = line.strip(' \t\n\r')
        marker, value = line[0], line[1:]
        if marker == '#':
            parent_lines[value] = i
            last_parent_line = i
        elif marker == '@':
            child_lines[value] = i
            child_parents[i] = last_parent_line

That's it.

