@@ -45,7 +45,7 @@ extern YY_BUFFER_STATE exp__scan_string(const char* buffer, yyscan_t scanner);
45
45
/* * returns parsed tree, otherwise returns nullptr and sets parserErrorMsg
46
46
(interface function to be called from QgsExpression)
47
47
*/
48
- QgsExpressionNode* parseExpression (const QString& str, QString& parserErrorMsg, QgsExpression::ParserError& parserError);
48
+ QgsExpressionNode* parseExpression (const QString& str, QString& parserErrorMsg, QList< QgsExpression::ParserError> & parserError);
49
49
50
50
/* * error handler for bison */
51
51
void exp_error (YYLTYPE* yyloc, expression_parser_context* parser_ctx, const char * msg);
@@ -55,9 +55,11 @@ struct expression_parser_context
55
55
// lexer context
56
56
yyscan_t flex_scanner;
57
57
58
- // varible where the parser error will be stored
58
+ // List of all errors.
59
+ QList<QgsExpression::ParserError> parserErrors;
59
60
QString errorMsg;
60
- QgsExpression::ParserError parserError;
61
+ // Current parser error.
62
+ QgsExpression::ParserError::ParserErrorType currentErrorType = QgsExpression::ParserError::Unknown;
61
63
// root node of the expression
62
64
QgsExpressionNode* rootNode;
63
65
};
@@ -172,6 +174,11 @@ void addParserLocation(YYLTYPE* yyloc, QgsExpressionNode *node)
172
174
%%
173
175
174
176
root : expression { parser_ctx->rootNode = $1 ; }
177
+ | error expression
178
+ {
179
+ delete $2 ;
180
+ yyerrok ;
181
+ }
175
182
;
176
183
177
184
expression :
@@ -205,7 +212,7 @@ expression:
205
212
// this should not actually happen because already in lexer we check whether an identifier is a known function
206
213
// (if the name is not known the token is parsed as a column)
207
214
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionUnknown;
208
- parser_ctx->parserError.errorType = errorType;
215
+ parser_ctx->currentErrorType = errorType;
209
216
exp_error (&yyloc, parser_ctx, " Function is not known" );
210
217
delete $3 ;
211
218
YYERROR ;
@@ -214,7 +221,7 @@ expression:
214
221
if ( !QgsExpressionNodeFunction::validateParams( fnIndex, $3 , paramError ) )
215
222
{
216
223
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionInvalidParams;
217
- parser_ctx->parserError.errorType = errorType;
224
+ parser_ctx->currentErrorType = errorType;
218
225
exp_error ( &yyloc, parser_ctx, paramError.toLocal8Bit().constData() );
219
226
delete $3 ;
220
227
YYERROR ;
@@ -224,7 +231,7 @@ expression:
224
231
&& QgsExpression::Functions()[fnIndex]->minParams() <= $3->count() ) )
225
232
{
226
233
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionWrongArgs;
227
- parser_ctx->parserError . errorType = errorType;
234
+ parser_ctx->currentErrorType = errorType;
228
235
exp_error (&yyloc, parser_ctx, QString ( " %1 function is called with wrong number of arguments" ).arg ( QgsExpression::Functions ()[fnIndex]->name () ).toLocal8Bit ().constData () );
229
236
delete $3 ;
230
237
YYERROR;
@@ -242,7 +249,7 @@ expression:
242
249
// this should not actually happen because already in lexer we check whether an identifier is a known function
243
250
// (if the name is not known the token is parsed as a column)
244
251
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionUnknown;
245
- parser_ctx->parserError.errorType = errorType;
252
+ parser_ctx->currentErrorType = errorType;
246
253
exp_error (&yyloc, parser_ctx, " Function is not known" );
247
254
YYERROR ;
248
255
}
@@ -251,7 +258,7 @@ expression:
251
258
if ( QgsExpression::Functions()[fnIndex]->params () > 0 )
252
259
{
253
260
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionWrongArgs;
254
- parser_ctx->parserError . errorType = errorType;
261
+ parser_ctx->currentErrorType = errorType;
255
262
exp_error (&yyloc, parser_ctx, QString ( " %1 function is called with wrong number of arguments" ).arg ( QgsExpression::Functions ()[fnIndex]->name () ).toLocal8Bit ().constData () );
256
263
YYERROR;
257
264
}
@@ -282,7 +289,7 @@ expression:
282
289
else
283
290
{
284
291
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionUnknown;
285
- parser_ctx->parserError.errorType = errorType;
292
+ parser_ctx->currentErrorType = errorType;
286
293
exp_error (&yyloc, parser_ctx, QString(" %1 function is not known" ).arg(*$1 ).toLocal8Bit().constData());
287
294
YYERROR ;
288
295
}
@@ -318,7 +325,7 @@ exp_list:
318
325
if ( $1 ->hasNamedNodes () )
319
326
{
320
327
QgsExpression::ParserError::ParserErrorType errorType = QgsExpression::ParserError::FunctionNamedArgsError;
321
- parser_ctx->parserError . errorType = errorType;
328
+ parser_ctx->currentErrorType = errorType;
322
329
exp_error (&yyloc, parser_ctx, " All parameters following a named parameter must also be named." );
323
330
delete $1 ;
324
331
YYERROR;
@@ -346,7 +353,7 @@ when_then_clause:
346
353
347
354
348
355
// returns parsed tree, otherwise returns nullptr and sets parserErrorMsg
349
- QgsExpressionNode* parseExpression (const QString& str, QString& parserErrorMsg, QgsExpression::ParserError &parserError )
356
+ QgsExpressionNode* parseExpression (const QString& str, QString& parserErrorMsg, QList< QgsExpression::ParserError> &parserErrors )
350
357
{
351
358
expression_parser_context ctx;
352
359
ctx.rootNode = 0 ;
@@ -357,14 +364,14 @@ QgsExpressionNode* parseExpression(const QString& str, QString& parserErrorMsg,
357
364
exp_lex_destroy (ctx.flex_scanner );
358
365
359
366
// list should be empty when parsing was OK
360
- if (res == 0 ) // success?
367
+ if (res == 0 && ctx. parserErrors . count () == 0 ) // success?
361
368
{
362
369
return ctx.rootNode ;
363
370
}
364
371
else // error?
365
372
{
366
373
parserErrorMsg = ctx.errorMsg ;
367
- parserError = ctx.parserError ;
374
+ parserErrors = ctx.parserErrors ;
368
375
delete ctx.rootNode ;
369
376
return nullptr ;
370
377
}
@@ -373,9 +380,16 @@ QgsExpressionNode* parseExpression(const QString& str, QString& parserErrorMsg,
373
380
374
381
void exp_error (YYLTYPE* yyloc,expression_parser_context* parser_ctx, const char * msg)
375
382
{
376
- parser_ctx->errorMsg = msg;
377
- parser_ctx->parserError .firstColumn = yyloc->first_column ;
378
- parser_ctx->parserError .firstLine = yyloc->first_line ;
379
- parser_ctx->parserError .lastColumn = yyloc->last_column ;
380
- parser_ctx->parserError .lastLine = yyloc->last_line ;
383
+ QgsExpression::ParserError error = QgsExpression::ParserError ();
384
+ error.firstColumn = yyloc->first_column ;
385
+ error.firstLine = yyloc->first_line ;
386
+ error.lastColumn = yyloc->last_column ;
387
+ error.lastLine = yyloc->last_line ;
388
+ error.errorMsg = msg;
389
+ error.errorType = parser_ctx->currentErrorType ;
390
+ parser_ctx->parserErrors .append (error);
391
+ // Reest the current error type for the next error.
392
+ parser_ctx->currentErrorType = QgsExpression::ParserError::Unknown;
393
+
394
+ parser_ctx->errorMsg = parser_ctx->errorMsg + " \n " + msg;
381
395
}
0 commit comments