# Buggy code
def _parse_ctx_free(self, input, mode="exec"):
    last_error_line = last_error_col = -1
    parsed = False
    original_error = None
    while not parsed:
        try:
            tree = self.parser.parse(
                input, filename=self.filename, mode=mode, debug_level=self.debug_level
            )
            parsed = True
        except IndentationError as e:
            if original_error is None:
                raise e
            else:
                raise original_error
        except SyntaxError as e:
            if original_error is None:
                original_error = e
            if (e.loc is None) or (
                last_error_line == e.loc.lineno
                and last_error_col in (e.loc.column + 1, e.loc.column)
            ):
                raise original_error
            last_error_col = e.loc.column
            last_error_line = e.loc.lineno
            idx = last_error_line - 1
            lines = input.splitlines()
            line = lines[idx]
            if input.endswith("\n"):
                lines.append("")
            if len(line.strip()) == 0:
                # whitespace only lines are not valid syntax in Python's
                # interactive mode='single', who knew?! Just ignore them.
                # this might cause actual sytax errors to have bad line
                # numbers reported, but should only effect interactive mode
                del lines[idx]
                last_error_line = last_error_col = -1
                input = "\n".join(lines)
                continue
            maxcol = line.find(";", last_error_col)
            maxcol = None if maxcol < 0 else maxcol + 1
            sbpline = subproc_toks(
                line, returnline=True, maxcol=maxcol, lexer=self.parser.lexer
            )
            if sbpline is None:
                # subprocess line had no valid tokens, likely because
                # it only contained a comment.
                del lines[idx]
                last_error_line = last_error_col = -1
                input = "\n".join(lines)
                continue
            else:
                lines[idx] = sbpline
            last_error_col += 3
            input = "\n".join(lines)
    return tree


# Traceback (SyntaxError)
$ bash -c "echo 'hey'; ls" > test.out
................
Traceback (most recent call last):
File "/usr/local/lib/python3.4/site-packages/xonsh/execer.py", line 135, in _parse_ctx_free
debug_level=self.debug_level)
File "/usr/local/lib/python3.4/site-packages/xonsh/parser.py", line 258, in parse
tree = self.parser.parse(input=s, lexer=self.lexer, debug=debug_level)
File "/usr/local/lib/python3.4/site-packages/ply/yacc.py", line 265, in parse
return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
File "/usr/local/lib/python3.4/site-packages/ply/yacc.py", line 1047, in parseopt_notrack
tok = self.errorfunc(errtoken)
File "/usr/local/lib/python3.4/site-packages/xonsh/parser.py", line 2357, in p_error
column=p.lexpos))
File "/usr/local/lib/python3.4/site-packages/xonsh/parser.py", line 329, in _parse_error
raise err
File "<string>", line None
SyntaxError: <xonsh-code>:1:11: ('code: "echo \'hey\'; ls"',)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.4/site-packages/xonsh/shell.py", line 149, in push
locs=self.ctx)
File "/usr/local/lib/python3.4/site-packages/xonsh/execer.py", line 92, in compile
tree = self.parse(input, ctx, mode=mode)
File "/usr/local/lib/python3.4/site-packages/xonsh/execer.py", line 70, in parse
tree = self._parse_ctx_free(input, mode=mode)
File "/usr/local/lib/python3.4/site-packages/xonsh/execer.py", line 148, in _parse_ctx_free
raise original_error
File "/usr/local/lib/python3.4/site-packages/xonsh/execer.py", line 135, in _parse_ctx_free
debug_level=self.debug_level)
File "/usr/local/lib/python3.4/site-packages/xonsh/parser.py", line 258, in parse
tree = self.parser.parse(input=s, lexer=self.lexer, debug=debug_level)
File "/usr/local/lib/python3.4/site-packages/ply/yacc.py", line 265, in parse
return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
File "/usr/local/lib/python3.4/site-packages/ply/yacc.py", line 1047, in parseopt_notrack
tok = self.errorfunc(errtoken)
File "/usr/local/lib/python3.4/site-packages/xonsh/parser.py", line 2357, in p_error
column=p.lexpos))
File "/usr/local/lib/python3.4/site-packages/xonsh/parser.py", line 329, in _parse_error
raise err
File "<string>", line None
SyntaxError: <xonsh-code>:1:8: ('code: "echo \'hey\'; ls"',)

# Fixed code
def _parse_ctx_free(self, input, mode="exec"):
    last_error_line = last_error_col = -1
    parsed = False
    original_error = None
    while not parsed:
        try:
            tree = self.parser.parse(
                input, filename=self.filename, mode=mode, debug_level=self.debug_level
            )
            parsed = True
        except IndentationError as e:
            if original_error is None:
                raise e
            else:
                raise original_error
        except SyntaxError as e:
            if original_error is None:
                original_error = e
            if (e.loc is None) or (
                last_error_line == e.loc.lineno
                and last_error_col in (e.loc.column + 1, e.loc.column)
            ):
                raise original_error
            last_error_col = e.loc.column
            last_error_line = e.loc.lineno
            idx = last_error_line - 1
            lines = input.splitlines()
            line = lines[idx]
            if input.endswith("\n"):
                lines.append("")
            if len(line.strip()) == 0:
                # whitespace only lines are not valid syntax in Python's
                # interactive mode='single', who knew?! Just ignore them.
                # this might cause actual sytax errors to have bad line
                # numbers reported, but should only effect interactive mode
                del lines[idx]
                last_error_line = last_error_col = -1
                input = "\n".join(lines)
                continue
            sbpline = subproc_toks(
                line, returnline=True, maxcol=None, lexer=self.parser.lexer
            )
            if sbpline is None:
                # subprocess line had no valid tokens, likely because
                # it only contained a comment.
                del lines[idx]
                last_error_line = last_error_col = -1
                input = "\n".join(lines)
                continue
            else:
                lines[idx] = sbpline
            last_error_col += 3
            input = "\n".join(lines)
    return tree