From 790bc459edf2393f77129f1ea68adf43e40b9eb4 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 18 Jul 2017 17:53:04 +0200 Subject: [PATCH] Make a proper recovery for only error statements in a suite. --- parso/pgen2/grammar.py | 1 + parso/pgen2/pgen.py | 1 + parso/python/grammar27.txt | 4 +--- parso/python/grammar34.txt | 4 +--- parso/python/grammar35.txt | 4 +--- parso/python/grammar36.txt | 5 +---- parso/python/parser.py | 11 +++++++++++ 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/parso/pgen2/grammar.py b/parso/pgen2/grammar.py index 8f9bfbf..82774e5 100644 --- a/parso/pgen2/grammar.py +++ b/parso/pgen2/grammar.py @@ -82,6 +82,7 @@ class Grammar(object): self.keywords = {} self.tokens = {} self.symbol2label = {} + self.label2symbol = {} self.start = 256 def dump(self, filename): diff --git a/parso/pgen2/pgen.py b/parso/pgen2/pgen.py index 7310359..029466d 100644 --- a/parso/pgen2/pgen.py +++ b/parso/pgen2/pgen.py @@ -65,6 +65,7 @@ class ParserGenerator(object): else: c.labels.append((c.symbol2number[label], None)) c.symbol2label[label] = ilabel + c.label2symbol[ilabel] = label return ilabel else: # A named token (NAME, NUMBER, STRING) diff --git a/parso/python/grammar27.txt b/parso/python/grammar27.txt index cbee141..4c3f33d 100644 --- a/parso/python/grammar27.txt +++ b/parso/python/grammar27.txt @@ -75,9 +75,7 @@ with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [('as' | ',') test]] -# Edit by David Halter: The stmt is now optional. This reflects how Jedi allows -# classes and functions to be empty, which is beneficial for autocompletion. -suite: simple_stmt | NEWLINE INDENT stmt* DEDENT +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: # [ x for x in lambda: True, lambda: False if x() ] diff --git a/parso/python/grammar34.txt b/parso/python/grammar34.txt index 5dc8c8e..05c3181 100644 --- a/parso/python/grammar34.txt +++ b/parso/python/grammar34.txt @@ -78,9 +78,7 @@ with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] -# Edit by David Halter: The stmt is now optional. This reflects how Jedi allows -# classes and functions to be empty, which is beneficial for autocompletion. -suite: simple_stmt | NEWLINE INDENT stmt* DEDENT +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond diff --git a/parso/python/grammar35.txt b/parso/python/grammar35.txt index 9acc7f5..c38217f 100644 --- a/parso/python/grammar35.txt +++ b/parso/python/grammar35.txt @@ -84,9 +84,7 @@ with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] -# Edit by David Halter: The stmt is now optional. This reflects how Jedi allows -# classes and functions to be empty, which is beneficial for autocompletion. -suite: simple_stmt | NEWLINE INDENT stmt* DEDENT +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond diff --git a/parso/python/grammar36.txt b/parso/python/grammar36.txt index d34eaca..4696983 100644 --- a/parso/python/grammar36.txt +++ b/parso/python/grammar36.txt @@ -83,10 +83,7 @@ with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] -# Edit by Francisco Souza/David Halter: The stmt is now optional. This reflects -# how Jedi allows classes and functions to be empty, which is beneficial for -# autocompletion. -suite: simple_stmt | NEWLINE INDENT stmt* DEDENT +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond diff --git a/parso/python/parser.py b/parso/python/parser.py index 377e432..50211d6 100644 --- a/parso/python/parser.py +++ b/parso/python/parser.py @@ -221,6 +221,17 @@ class Parser(BaseParser): error_leaf = tree.PythonErrorLeaf(tok_name[typ].lower(), value, start_pos, prefix) stack[-1][2][1].append(error_leaf) + if symbol == 'suite': + dfa, state, node = stack[-1] + states, first = dfa + arcs = states[state] + intended_label = pgen_grammar.symbol2label['stmt'] + # Introduce a proper state transition. We're basically allowing + # there to be no valid statements inside a suite. + if [x[0] for x in arcs] == [intended_label]: + new_state = arcs[0][1] + stack[-1] = dfa, new_state, node + def _stack_removal(self, pgen_grammar, stack, arcs, start_index, value, start_pos): failed_stack = False found = False