Skip to content

Commit f385a67

Browse files
committed
[GR-23224] Make test_eof pass.
1 parent da33164 commit f385a67

File tree

9 files changed

+317
-211
lines changed

9 files changed

+317
-211
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*graalpython.lib-python.3.test.test_eof.EOFTestCase.test_EOFC
2+
*graalpython.lib-python.3.test.test_eof.EOFTestCase.test_EOFS
3+
*graalpython.lib-python.3.test.test_eof.EOFTestCase.test_line_continuation_EOF
4+
*graalpython.lib-python.3.test.test_eof.EOFTestCase.test_line_continuation_EOF_from_file_bpo2180

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/DescriptiveBailErrorListener.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,21 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
111111
entireMessage = "unexpected unindent";
112112
errorType = ErrorType.Indentation;
113113
break;
114+
case Python3Parser.LONG_QUOTES1:
115+
case Python3Parser.LONG_QUOTES2:
116+
entireMessage = "EOF while scanning triple-quoted string literal";
117+
break;
118+
case Python3Parser.LINE_JOINING_EOF_ERROR:
119+
entireMessage = "unexpected EOF while parsing";
120+
break;
121+
case Python3Parser.UNKNOWN_CHAR:
122+
String text = token.getText();
123+
if (text.startsWith("\'") || text.startsWith("\"")) {
124+
entireMessage = "EOL while scanning string literal";
125+
} else if (text.equals("\\")) {
126+
entireMessage = "unexpected character after line continuation character";
127+
}
128+
break;
114129
default:
115130
if (expectedTokens != null && expectedTokens.contains(Python3Parser.INDENT)) {
116131
entireMessage = "expected an indented block";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3.g4

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ grammar Python3;
3535
// All comments that start with "///" are copy-pasted from
3636
// The Python Language Reference
3737

38-
tokens { INDENT, DEDENT, INDENT_ERROR, TAB_ERROR }
38+
tokens { INDENT, DEDENT, INDENT_ERROR, TAB_ERROR,
39+
LINE_JOINING_EOF_ERROR // This is error token emitted, there is line continuation just before EOF.
40+
// Line continuation is in the hidden channel, so normally is not emitted.
41+
}
3942

4043
@lexer::members {
4144
// new version with semantic actions in parser
@@ -178,6 +181,15 @@ tokens { INDENT, DEDENT, INDENT_ERROR, TAB_ERROR }
178181
return dedent;
179182
}
180183

184+
private Token createLineContinuationEOFError() {
185+
// this has to be called only at the end of the file
186+
CommonToken errorToken = commonToken(Python3Parser.LINE_JOINING_EOF_ERROR, "");
187+
// set the position at the previous char, which has to be line continuation
188+
errorToken.setStartIndex(_input.index() - 1);
189+
errorToken.setStopIndex(_input.index() - 1);
190+
return errorToken;
191+
}
192+
181193
private Token createIndentError(int type) {
182194
// For some reason, CPython sets the error position to the end of line
183195
int cur = getCharIndex();
@@ -1960,13 +1972,29 @@ LONG_QUOTES1 : '"""' {usedQuote1();};
19601972
LONG_QUOTES2 : '\'\'\'' {usedQuote2();};
19611973

19621974
SKIP_
1963-
: ( SPACES | COMMENT | LINE_JOINING ) -> skip
1975+
: ( SPACES
1976+
| COMMENT
1977+
| LINE_JOINING
1978+
{
1979+
// We need to hanle line continuation here, because normally is hidden for the parser
1980+
// but we need to handle the case, where is just before EOF.
1981+
if (_input.size() == _input.index()) {
1982+
this.emit(createLineContinuationEOFError());
1983+
}
1984+
}
1985+
) -> skip
19641986
;
19651987

19661988
BOM : '\uFEFF';
19671989

19681990
UNKNOWN_CHAR
1969-
: .
1991+
: .
1992+
{
1993+
// check the case when the char is line continuation just before EOF
1994+
if (_input.size() == _input.index() && "\\".equals(_input.getText(Interval.of(_input.size()- 1, _input.size())))) {
1995+
this.emit(createLineContinuationEOFError());
1996+
}
1997+
}
19701998
;
19711999

19722000
/*

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3.interp

Lines changed: 3 additions & 1 deletion
Large diffs are not rendered by default.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3.tokens

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ INDENT=99
100100
DEDENT=100
101101
INDENT_ERROR=101
102102
TAB_ERROR=102
103+
LINE_JOINING_EOF_ERROR=103
103104
'def'=2
104105
'return'=3
105106
'raise'=4

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3Lexer.interp

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3Lexer.java

Lines changed: 244 additions & 203 deletions
Large diffs are not rendered by default.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3Parser.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public class Python3Parser extends Parser {
8686
MOD_ASSIGN=86, AND_ASSIGN=87, OR_ASSIGN=88, XOR_ASSIGN=89, LEFT_SHIFT_ASSIGN=90,
8787
RIGHT_SHIFT_ASSIGN=91, POWER_ASSIGN=92, IDIV_ASSIGN=93, LONG_QUOTES1=94,
8888
LONG_QUOTES2=95, SKIP_=96, BOM=97, UNKNOWN_CHAR=98, INDENT=99, DEDENT=100,
89-
INDENT_ERROR=101, TAB_ERROR=102;
89+
INDENT_ERROR=101, TAB_ERROR=102, LINE_JOINING_EOF_ERROR=103;
9090
public static final int
9191
RULE_single_input = 0, RULE_file_input = 1, RULE_withArguments_input = 2,
9292
RULE_eval_input = 3, RULE_decorator = 4, RULE_decorators = 5, RULE_decorated = 6,
@@ -167,7 +167,7 @@ private static String[] makeSymbolicNames() {
167167
"MOD_ASSIGN", "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN", "LEFT_SHIFT_ASSIGN",
168168
"RIGHT_SHIFT_ASSIGN", "POWER_ASSIGN", "IDIV_ASSIGN", "LONG_QUOTES1",
169169
"LONG_QUOTES2", "SKIP_", "BOM", "UNKNOWN_CHAR", "INDENT", "DEDENT", "INDENT_ERROR",
170-
"TAB_ERROR"
170+
"TAB_ERROR", "LINE_JOINING_EOF_ERROR"
171171
};
172172
}
173173
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
@@ -8577,7 +8577,7 @@ public final Yield_exprContext yield_expr() throws RecognitionException {
85778577
}
85788578

85798579
public static final String _serializedATN =
8580-
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3h\u067b\4\2\t\2\4"+
8580+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3i\u067b\4\2\t\2\4"+
85818581
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
85828582
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
85838583
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+

graalpython/lib-graalpython/exceptions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,24 @@ def SyntaxError__init__(self, *args, **kwargs):
106106
self.offset = info[2]
107107
self.text = info[3]
108108

109+
def SyntaxError__str__(self):
110+
111+
def isNumber(x):
112+
return hasattr(x, "__index__")
113+
114+
hasLineno = self.lineno and isNumber(self.lineno)
115+
if not self.filename and not hasLineno:
116+
return "%s" % (self.msg)
117+
if self.filename and hasLineno:
118+
return "%s (%s, line %d)" % (self.msg, self.filename, self.lineno)
119+
if self.filename:
120+
return "%s (%s)" % (self.msg, self.filename)
121+
return "%s (line %d)" % (self.msg, self.lineno)
109122

110123
SyntaxError.__init__ = SyntaxError__init__
124+
SyntaxError.__str__ = SyntaxError__str__
111125
del SyntaxError__init__
126+
del SyntaxError__str__
112127

113128

114129
def UnicodeEncodeError__init__(self, encoding, object, start, end, reason):

0 commit comments

Comments
 (0)