Improve syntax errors for unmatched (){}[]

This commit is contained in:
Daniel Marjamäki 2019-01-05 11:56:21 +01:00
parent 32a5d66e5b
commit 615903c6be
4 changed files with 48 additions and 29 deletions

View File

@ -3188,10 +3188,10 @@ static void linkBrackets(const Tokenizer * const tokenizer, std::stack<const Tok
} else if (token->str()[0] == close) { } else if (token->str()[0] == close) {
if (links.empty()) { if (links.empty()) {
// Error, { and } don't match. // Error, { and } don't match.
tokenizer->syntaxError(token, open); tokenizer->unmatchedToken(token);
} }
if (type.top()->str()[0] != open) { if (type.top()->str()[0] != open) {
tokenizer->syntaxError(type.top(), type.top()->str()[0]); tokenizer->unmatchedToken(type.top());
} }
type.pop(); type.pop();
@ -3220,17 +3220,17 @@ void Tokenizer::createLinks()
if (!links1.empty()) { if (!links1.empty()) {
// Error, { and } don't match. // Error, { and } don't match.
syntaxError(links1.top(), '{'); unmatchedToken(links1.top());
} }
if (!links2.empty()) { if (!links2.empty()) {
// Error, ( and ) don't match. // Error, ( and ) don't match.
syntaxError(links2.top(), '('); unmatchedToken(links2.top());
} }
if (!links3.empty()) { if (!links3.empty()) {
// Error, [ and ] don't match. // Error, [ and ] don't match.
syntaxError(links3.top(), '['); unmatchedToken(links3.top());
} }
} }
@ -7930,16 +7930,11 @@ void Tokenizer::syntaxError(const Token *tok) const
throw InternalError(tok, "syntax error", InternalError::SYNTAX); throw InternalError(tok, "syntax error", InternalError::SYNTAX);
} }
void Tokenizer::syntaxError(const Token *tok, char c) const void Tokenizer::unmatchedToken(const Token *tok) const
{ {
printDebugOutput(0); printDebugOutput(0);
if (mConfiguration.empty())
throw InternalError(tok, throw InternalError(tok,
std::string("Invalid number of character '") + c + "' when no macros are defined.", "Unmatched '" + tok->str() + "'. Configuration: '" + mConfiguration + "'.",
InternalError::SYNTAX);
else
throw InternalError(tok,
std::string("Invalid number of character '") + c + "' when these macros are defined: '" + mConfiguration + "'.",
InternalError::SYNTAX); InternalError::SYNTAX);
} }

View File

@ -594,8 +594,8 @@ public:
/** Syntax error */ /** Syntax error */
void syntaxError(const Token *tok) const; void syntaxError(const Token *tok) const;
/** Syntax error. Example: invalid number of ')' */ /** Syntax error. Unmatched character. */
void syntaxError(const Token *tok, char c) const; void unmatchedToken(const Token *tok) const;
/** Syntax error. C++ code in C file. */ /** Syntax error. C++ code in C file. */
void syntaxErrorC(const Token *tok, const std::string &what) const; void syntaxErrorC(const Token *tok, const std::string &what) const;

View File

@ -1 +1 @@
[samples\syntaxError\bad.c:2]: (error) Invalid number of character '{' when no macros are defined. [samples\syntaxError\bad.c:2]: (error) Unmatched '{'. Configuration: ''.

View File

@ -284,6 +284,19 @@ private:
return tokenizer.tokens()->stringifyList(false, false, false, true, false, 0, 0); return tokenizer.tokens()->stringifyList(false, false, false, true, false, 0, 0);
} }
std::string getSyntaxError(const char code[]) {
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
try {
tokenizer.tokenize(istr, "test.cpp");
} catch (InternalError& e) {
if (e.id != "syntaxError")
return "";
return "[test.cpp:" + MathLib::toString(e.token->linenr()) + "] " + e.errorMessage;
}
return "";
}
void wrong_syntax1() { void wrong_syntax1() {
{ {
const char code[] ="TR(kvmpio, PROTO(int rw), ARGS(rw), TP_(aa->rw;))"; const char code[] ="TR(kvmpio, PROTO(int rw), ARGS(rw), TP_(aa->rw;))";
@ -1007,23 +1020,34 @@ private:
"}\n"), InternalError); "}\n"), InternalError);
{ {
errout.str("");
const char code[] = "{\n" const char code[] = "{\n"
" a(\n" " a(\n" // <- error
"}\n" "}\n"
"{\n" "{\n"
" b());\n" " b());\n"
"}\n"; "}\n";
Tokenizer tokenizer(&settings, this); ASSERT_EQUALS("[test.cpp:2] Unmatched '('. Configuration: ''.", getSyntaxError(code));
std::istringstream istr(code);
try {
tokenizer.tokenize(istr, "test.cpp");
assertThrowFail(__FILE__, __LINE__);
} catch (InternalError& e) {
ASSERT_EQUALS("Invalid number of character '(' when no macros are defined.", e.errorMessage);
ASSERT_EQUALS("syntaxError", e.id);
ASSERT_EQUALS(2, e.token->linenr());
} }
{
const char code[] = "void f() {\n"
" int x = 3) + 0;\n" // <- error: unmatched )
"}\n";
ASSERT_EQUALS("[test.cpp:2] Unmatched ')'. Configuration: ''.", getSyntaxError(code));
}
{
const char code[] = "void f() {\n"
" int x = (3] + 0;\n" // <- error: unmatched ]
"}\n";
ASSERT_EQUALS("[test.cpp:2] Unmatched ']'. Configuration: ''.", getSyntaxError(code));
}
{
const char code[] = "void f() {\n" // <- error: unmatched {
" {\n"
"}\n";
ASSERT_EQUALS("[test.cpp:1] Unmatched '{'. Configuration: ''.", getSyntaxError(code));
} }
} }