Q:

Parser that preserves comments and recover from error

I'm working on a GUI editor for a propriety config format. Basically the editor will parse the config file, display the object properties so that users can edit from GUI and then write the objects back to the file.
I've got the parse - edit - write part done, except for:

The parsed data structure only include object properties information, so comments and whitespaces are lost on write  
If there is any syntax error, the rest of the file is skipped  

How would you address these issues? What is the usual approach to this problem? I'm using Python and Parsec module https://pythonhosted.org/parsec/documentation.html, however and help and general direction is appreciated.
I've also tried Pylens (https://pythonhosted.org/pylens/), which is really close to what I need except it can not skip syntax errors. 

A:

Eventually I ran out of research time and have to settle with a rather manual skipping. Basically each time the parser fail we try to advance the cursor one character and repeat. Any parts skipped by the process, regardless of whitespace/comment/syntax error is dump into a Text structure. The code is quite reusable, except for the part you have to incorporate it to all the places with repeated results and the original parser may fail.
Here's the code, in case it helps anyone. It is written for Parsy.
class Text(object):
    '''Structure to contain all the parts that the parser does not understand.
    A better name would be Whitespace
    '''
    def __init__(self, text=''):
        self.text = text

    def __repr__(self):
        return "Text(text='{}')".format(self.text)

    def __eq__(self, other):
        return self.text.strip() == getattr(other, 'text', '').strip()

def many_skip_error(parser, skip=lambda t, i: i + 1, until=None):
    '''Repeat the original `parser`, aggregate result into `values` 
    and error in `Text`.
    '''
    @Parser
    def _parser(stream, index):
        values, result = [], None

        while index < len(stream):
            result = parser(stream, index)
            # Original parser success
            if result.status:
                values.append(result.value)
                index = result.index
            # Check for end condition, effectively `manyTill` in Parsec
            elif until is not None and until(stream, index).status:
                break
            # Aggregate skipped text into last `Text` value, or create a new one
            else:
                if len(values) > 0 and isinstance(values[-1], Text):
                    values[-1].text += stream[index]
                else:
                    values.append(Text(stream[index]))
                index = skip(stream, index)
        return Result.success(index, values).aggregate(result)
    return _parser

# Example usage
skip_error_parser = many_skip_error(original_parser)

On other note, I guess the real issue here is I'm using a parser combinator library instead of a proper two stages parsing process. In traditional parsing, the tokenizer will handle retaining/skipping any whitespace/comment/syntax error, making them all effectively whitespace and are invisible to the parser. 

