I'm trying to create a program that uses multithreading with flex/bison to parse large amounts of data. I am slightly lost on how to get yyerror
in a reentrant way.
In a previous non-reentrant test with bison/flex I used extern
to get yyerror
extern void yyerror(const char*);
void yyerror(const char* msg) {
std::cout << " Error: " + std::string(msg) << std::endl;
...
calling appropriate code to handle error etc
...
}
Now I'm trying to implement this using reentrant bison and flex.
Using the example code from the user @rici Thread-safe / reentrant bison + flex, I'm trying to get understand how I'd be able to get the error message after yyparse
is called. How could I implement the following?
class container {
public:
bool errorOccured;
std::string errorMessage;
void parse() {
yyscan_t scanner;
yylex_init(&scanner);
yy_scan_string("123 + + 123 \n", scanner);
yyparse(scanner);
yylex_destroy(scanner);
//errorOccured = ?;
//errorMessage = ?;
}
bool checkIfErrorOccured() {
std::cout << errorMessage << std::endl;
return errorOccured;
}
}
Thread-safe / reentrant bison + flex For reference here is the lex code I am using, written by the user @rici
%option noinput nounput noyywrap 8bit nodefault
%option yylineno
%option reentrant bison-bridge bison-locations
%{
#include <stdlib.h>
#include <string.h>
#include "parser.tab.h"
#define YY_USER_ACTION \
yylloc->first_line = yylloc->last_line; \
yylloc->first_column = yylloc->last_column; \
if (yylloc->last_line == yylineno) \
yylloc->last_column += yyleng; \
else { \
yylloc->last_line = yylineno; \
yylloc->last_column = yytext + yyleng - strrchr(yytext, '\n'); \
}
%}
%%
[ \t]+ ;
#.* ;
[[:digit:]]+ *yylval = strtol(yytext, NULL, 0); return NUMBER;
.|\n return *yytext;
bison
%define api.pure full
%define parse.error verbose
%locations
%param { yyscan_t scanner }
%code top {
#include <stdio.h>
#include <string.h>
}
%code requires {
typedef void* yyscan_t;
}
%code {
int yylex(YYSTYPE* yylvalp, YYLTYPE* yyllocp, yyscan_t scanner);
void yyerror(YYLTYPE* yyllocp, yyscan_t unused, const char* msg);
}
%token NUMBER UNOP
%left '+' '-'
%left '*' '/' '%'
%precedence UNOP
%%
input: %empty
| input expr '\n' { printf("[%d]: %d\n", @2.first_line, $2); }
| input '\n'
| input error '\n' { yyerrok; }
expr : NUMBER
| '(' expr ')' { $$ = $2; }
| '-' expr %prec UNOP { $$ = -$2; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| expr '%' expr { $$ = $1 % $3; }
%%
void yyerror(YYLTYPE* yyllocp, yyscan_t unused, const char* msg) {
fprintf(stderr, "[%d:%d]: %s\n",
yyllocp->first_line, yyllocp->first_column, msg);
}