Skip to content

Commit

Permalink
Better diagnostic output
Browse files Browse the repository at this point in the history
Print the place in the code where the (ambiguous) parser error was
emitted (currently only for GCC and MSVC)
  • Loading branch information
usiems committed Jun 28, 2024
1 parent e66848a commit c2075c9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 26 deletions.
73 changes: 50 additions & 23 deletions generator/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,32 @@
#include <iostream>
#include <vector>

#define STRINGIZE(x) STRINGIZE2(x)
#define STRINGIZE2(x) #x

#if defined(_MSC_VER)
#define PARSER_METHOD_NAME __FUNCTION__ ":" STRINGIZE(__LINE__)
#elif defined(__GNUC__)
#include <sstream>
// on gcc __FUNCTION__ is a variable, not a string constant
// - solution found here: https://stackoverflow.com/a/61546848
#define PARSER_METHOD_NAME \
[](auto fn, auto ln) { \
std::stringstream ss; \
ss << fn << ":" << ln; \
return ss.str(); \
}(__FUNCTION__, __LINE__).c_str()
#else
#define PARSER_METHOD_NAME ""
#endif


#define SYNTAX_ERROR() syntaxError(PARSER_METHOD_NAME)

#define ADVANCE(tk, descr) \
{ \
if (token_stream.lookAhead() != tk) { \
tokenRequiredError(tk); \
tokenRequiredError(tk, PARSER_METHOD_NAME); \
return false; \
} \
nextToken(); \
Expand All @@ -64,7 +86,7 @@
#define ADVANCE_NR(tk, descr) \
do { \
if (token_stream.lookAhead() != tk) { \
tokenRequiredError(tk); \
tokenRequiredError(tk, PARSER_METHOD_NAME); \
} \
else \
nextToken(); \
Expand Down Expand Up @@ -165,7 +187,7 @@ bool Parser::parseWinDeclSpec(WinDeclSpecAST *&node)
return true;
}

void Parser::tokenRequiredError(int token)
void Parser::tokenRequiredError(int token, const char* functionName)
{
QString err;

Expand All @@ -176,11 +198,10 @@ void Parser::tokenRequiredError(int token)
err += token_name(token_stream.lookAhead());
err += "''";


reportError(err);
reportError(err, functionName);
}

void Parser::syntaxError()
void Parser::syntaxError(const char* functionName)
{
QString err;

Expand All @@ -189,10 +210,10 @@ void Parser::syntaxError()
err += token_name(token_stream.lookAhead());
err += "''";

reportError(err);
reportError(err, functionName);
}

void Parser::reportError(const QString& msg)
void Parser::reportError(const QString& msg, const char* functionName)
{
if (!_M_block_errors)
{
Expand All @@ -208,6 +229,10 @@ void Parser::reportError(const QString& msg)
errmsg.setColumn(column);
errmsg.setFileName(fileName);
errmsg.setMessage(QLatin1String("** PARSER ERROR ") + msg);
if (functionName && *functionName) {
errmsg.setMessage(errmsg.message() + " in " + functionName);
}

control->reportError(errmsg);
}
}
Expand Down Expand Up @@ -852,7 +877,7 @@ bool Parser::parseOperatorFunctionId(OperatorFunctionIdAST *&node)

if (!parseSimpleTypeSpecifier(ast->type_specifier))
{
syntaxError();
SYNTAX_ERROR();
return false;
}

Expand Down Expand Up @@ -886,7 +911,7 @@ bool Parser::parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&no
{
if (reportError)
{
syntaxError();
SYNTAX_ERROR();
break;
}

Expand Down Expand Up @@ -1642,7 +1667,7 @@ bool Parser::parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&

if (!parseTemplateParameter(param))
{
syntaxError();
SYNTAX_ERROR();
break;
}
else
Expand Down Expand Up @@ -1721,7 +1746,7 @@ bool Parser::parseTypeParameter(TypeParameterAST *&node)

if(!parseTypeId(ast->type_id))
{
//syntaxError();
//SYNTAX_ERROR();
rewind(start);
return false;
}
Expand Down Expand Up @@ -1758,7 +1783,7 @@ bool Parser::parseTypeParameter(TypeParameterAST *&node)

if (!parseTypeId(ast->type_id))
{
syntaxError();
SYNTAX_ERROR();
return false;
}
}
Expand Down Expand Up @@ -1857,7 +1882,7 @@ bool Parser::parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node)

if (!parseInitDeclarator(decl))
{
syntaxError();
SYNTAX_ERROR();
break;
}
node = snoc(node, decl, _M_pool);
Expand Down Expand Up @@ -2933,7 +2958,7 @@ bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
block_errors(blocked);

if (!node)
syntaxError();
SYNTAX_ERROR();

return node != 0;
}
Expand Down Expand Up @@ -3203,7 +3228,7 @@ bool Parser::parseSwitchStatement(StatementAST *&node)
StatementAST *stmt = 0;
if (!parseCompoundStatement(stmt))
{
syntaxError();
SYNTAX_ERROR();
return false;
}

Expand Down Expand Up @@ -3490,7 +3515,7 @@ bool Parser::parseDeclarationInternal(DeclarationAST *&node)
const ListNode<InitDeclaratorAST*> *declarators = 0;
if (!parseInitDeclaratorList(declarators))
{
syntaxError();
SYNTAX_ERROR();
return false;
}

Expand Down Expand Up @@ -3534,7 +3559,7 @@ bool Parser::parseDeclarationInternal(DeclarationAST *&node)
rewind(startDeclarator);
if (!parseInitDeclaratorList(declarators))
{
syntaxError();
SYNTAX_ERROR();
return false;
}
}
Expand All @@ -3546,7 +3571,7 @@ bool Parser::parseDeclarationInternal(DeclarationAST *&node)
TypeSpecifierAST* trailingReturnTypeSpec = 0;
if (!parseTypeSpecifier(trailingReturnTypeSpec)) {
// todo: replace "auto" return type? But I doubt we can handle these return types anyway.
syntaxError();
SYNTAX_ERROR();
return false;
}
maybeFunctionDefinition = true;
Expand Down Expand Up @@ -3575,7 +3600,7 @@ bool Parser::parseDeclarationInternal(DeclarationAST *&node)
{
if (!maybeFunctionDefinition)
{
syntaxError();
SYNTAX_ERROR();
return false;
}

Expand All @@ -3602,7 +3627,7 @@ bool Parser::parseDeclarationInternal(DeclarationAST *&node)
} // end switch
}

syntaxError();
SYNTAX_ERROR();
return false;
}

Expand Down Expand Up @@ -3670,7 +3695,7 @@ bool Parser::parseTryBlockStatement(StatementAST *&node)
StatementAST *stmt = 0;
if (!parseCompoundStatement(stmt))
{
syntaxError();
SYNTAX_ERROR();
return false;
}

Expand Down Expand Up @@ -3699,7 +3724,7 @@ bool Parser::parseTryBlockStatement(StatementAST *&node)
StatementAST *body = 0;
if (!parseCompoundStatement(body))
{
syntaxError();
SYNTAX_ERROR();
return false;
}
}
Expand Down Expand Up @@ -3758,6 +3783,8 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node)
CHECK('}');
break;

// case '[': // TODO: parse lambda expression

default:
if (!parseName(ast->name, true)) // this can also be a template
return false;
Expand Down
6 changes: 3 additions & 3 deletions generator/parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ class Parser
TranslationUnitAST *parse(const char *contents, std::size_t size, pool *p);

private:
void reportError(const QString& msg);
void syntaxError();
void tokenRequiredError(int expected);
void reportError(const QString& msg, const char* functionName = nullptr);
void syntaxError(const char* functionName = nullptr);
void tokenRequiredError(int expected, const char* functionName = nullptr);

public:
bool skipFunctionBody(StatementAST *&node);
Expand Down

0 comments on commit c2075c9

Please sign in to comment.