Improve syntax errors for unmatched (){}[]
This commit is contained in:
parent
32a5d66e5b
commit
615903c6be
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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: ''.
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue