Better syntax errors through catch all statement
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Freeode |
New
|
Wishlist
|
Unassigned |
Bug Description
Currently most syntax errors produce an error message like "Expecting unindent ...." or "Expecting end of file ..." which is not very helpful.
The cause is IMHO that Pyparsing's backtracking. When the rules for all statements have failed Pyparsing tries to match rules from the indentation logic. The error message is then generated in/for the last rule (parser in Pyparsing's terminology) that was tried.
Therefore I propose to introduce an additional rule on the level of the statements, that comes last. I matches any word and any punctuation. The parser's parse action then raises a ParseFatalException with the message "Unknown keyword ..." or "Unknown operator ...". This would improve the error messages much.
The issue has been already tried unsuccessfully. See comment #1
The issue has been already tried unsuccessfully.
https:/
The relation between the "indentedBlock" Parser and Siml's "statement" parser are quite intricate and the issue is not easy to solve. It is probably necessary to implement a special version of "indentedBlock" which works better with Siml.
A parser that matches anything has been inserted as the last possible match for statements. For wrong keywords it works as intended; but for broken expressions, error messages become much worse. Somewhere in "indentedBlock" there is backtracking. The line:
{{{
h = V/A_bott+
}}}
Now leads to the error message "Unknown syntax: "h" ", it reports the error at the beginning of the statement, instead of the end.
The ideal error would have been: "Unknown syntax: "+" "
The old error was: "Expected end of line ... (line:7, col:21)" which points to the right character.
Here are the snippets that were inserted into Siml's parser:
{{{
class Parser(...):
....
def _action_
'''
Raise a ParseFatalExcep
'''
err_word = toks[0]
msg = 'Unknown syntax: "%s"' % err_word
raise ParseFatalExcep
...
...
def _defineLanguage
...
#Generate an error when no statement parser could match the text
error_stmt = CharsNotIn(
...
#Statement: one line of code, or a compound (if, class, func) statement
statement = ( simple_stmt + newline
}}}
Changed in freeode: | |
importance: | Undecided → Wishlist |
milestone: | none → 0.4.1 |
Changed in freeode: | |
assignee: | nobody → Eike (eike-welk) |
Changed in freeode: | |
milestone: | 0.4.1 → none |
description: | updated |
Changed in freeode: | |
assignee: | Eike (eike-welk) → nobody |
description: | updated |
Changed in freeode: | |
milestone: | none → 0.4.2 |
The relation between the "indentedBlock" Parser and Siml's "statement" parser are quite intricate and the issue is not easy to solve. It is probably necessary to implement a special version of "indentedBlock" which works better with Siml.
A parser that matches anything has been inserted as the last possible match for statements. For wrong keywords it works as intended; but for broken expressions, error messages become much worse. Somewhere in "indentedBlock" there is backtracking. The line:
h = V/A_bott+
Now leads to the error message "Unknown syntax: "h" ", it reports the error at the beginning of the statement, instead of the end.
The ideal error would have been: "Unknown syntax: "+" "
The old error was: "Expected end of line ... (line:7, col:21)" which points to the right character.
Here are the snippets that were inserted into Siml's parser: error_stmt( self, s, loc, toks): tion, because a syntax error was detected. tion(s, loc, msg, elem=None ) Syntax) whitespace_ chars) .setParseAction (self._ action_ error_stmt)
| stmt_list_1 + newline
| compound_stmt
| error_stmt
)
...(in classParser)
def _action_
'''
Raise a ParseFatalExcep
'''
err_word = toks[0]
msg = 'Unknown syntax: "%s"' % err_word
raise ParseFatalExcep
...
...(in def _defineLanguage
#Generate an error when no statement parser could match the text
error_stmt = CharsNotIn(
...
#Statement: one line of code, or a compound (if, class, func) statement
statement = ( simple_stmt + newline