struct pakfire* pakfire_parser_get_pakfire(struct pakfire_parser* parser);
+struct pakfire_parser_state {
+ unsigned int lineno;
+
+ // Indentation level
+ unsigned int indent_level;
+
+ // Remember current indentation
+ unsigned int current_indent;
+ unsigned int readline_indent;
+};
+
struct pakfire_parser_declaration {
char namespace[NAME_MAX];
char name[NAME_MAX];
#endif
typedef void* yyscan_t;
-extern int yylex_init(yyscan_t* scanner);
+extern int yylex_init_extra(struct pakfire_parser_state* state, yyscan_t* scanner);
int yylex_destroy(yyscan_t scanner);
typedef struct yy_buffer_state* YY_BUFFER_STATE;
extern YY_BUFFER_STATE yy_scan_bytes(const char* buffer, int len, yyscan_t scanner);
extern void yy_delete_buffer(YY_BUFFER_STATE buffer, yyscan_t scanner);
+#define YY_EXTRA_TYPE struct pakfire_parser_state*
+YY_EXTRA_TYPE yyget_extra(yyscan_t scanner);
+
#include "grammar.h"
extern int yylex (YYSTYPE* yylval_param, yyscan_t yyscanner);
-extern int num_lines;
-
#define ABORT do { YYABORT; } while (0);
enum operator {
static void yyerror(yyscan_t* scanner, struct pakfire* pakfire, struct pakfire_parser** parser,
struct pakfire_parser* parent, struct pakfire_parser_error** error, const char* s) {
- ERROR(pakfire, "Error (line %d): %s\n", num_lines, s);
+ const struct pakfire_parser_state* state = yyget_extra(scanner);
+
+ ERROR(pakfire, "Error (line %d): %s\n", state->lineno, s);
// Create a new error object
if (error) {
- int r = pakfire_parser_error_create(error, *parser, NULL, num_lines, s);
+ int r = pakfire_parser_error_create(error, *parser, NULL, state->lineno, s);
if (r) {
ERROR(pakfire, "Could not create error object: %s\n", strerror(errno));
}
struct pakfire* pakfire = pakfire_parser_get_pakfire(parent);
yyscan_t scanner;
+ // Initialize the parser's state
+ struct pakfire_parser_state state = {
+ .lineno = 1,
+ .indent_level = 0,
+ .current_indent = 0,
+ .readline_indent = 0,
+ };
+
#ifdef ENABLE_DEBUG
DEBUG(pakfire, "Parsing the following data (%zu):\n%.*s\n",
len, (int)len, data);
#endif
// Initialise scanner
- yylex_init(&scanner);
+ yylex_init_extra(&state, &scanner);
// Create a new sub-parser
struct pakfire_parser* parser = NULL;
- num_lines = 1;
-
YY_BUFFER_STATE buffer = yy_scan_bytes(data, len, scanner);
int r = yyparse(scanner, pakfire, &parser, parent, error);
yy_delete_buffer(buffer, scanner);
%option reentrant
%option stack noyy_top_state
%option warn
+%option extra-type="struct pakfire_parser_state*"
/* Enable to debug the scanner */
/* %option debug */
%{
#define YY_DECL int yylex (YYSTYPE* yylval_param, yyscan_t yyscanner)
-int num_lines;
-
#include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
#include "grammar.h"
-// Indentation level
-unsigned int indent_level = 0;
-
-// Remember current indentation
-unsigned int current_indent = 0;
-unsigned int readline_indent = 0;
-
static char* unquote(const char* input) {
size_t length = strlen(input);
<*>\n {
// Handles line numbers without consuming the newline character
- num_lines++; REJECT;
+ yyextra->lineno++; REJECT;
}
#.*$ {
\n {
// Jump back into indentation processing after a newline
- current_indent = 0;
+ yyextra->current_indent = 0;
yy_push_state(INDENT, yyscanner);
}
<READLINES>\t {
- if (readline_indent && current_indent >= readline_indent)
+ if (yyextra->readline_indent &&
+ yyextra->current_indent >= yyextra->readline_indent)
REJECT;
- current_indent++;
+ yyextra->current_indent++;
}
<READLINES>\n {
// Jump back into indentation processing after a newline
- current_indent = 0;
+ yyextra->current_indent = 0;
return T_EOL;
}
yyless(0);
// This is the first line
- if (!readline_indent) {
+ if (!yyextra->readline_indent) {
// If indentation is above indent level,
// we are good to continue
- if (current_indent > indent_level) {
- readline_indent = current_indent;
+ if (yyextra->current_indent > yyextra->indent_level) {
+ yyextra->readline_indent = yyextra->current_indent;
return T_INDENT;
// If we found the same or less indentation we go back
}
// <-- ?
- else if (current_indent < readline_indent) {
- readline_indent = 0;
+ else if (yyextra->current_indent < yyextra->readline_indent) {
+ yyextra->readline_indent = 0;
yy_pop_state(yyscanner);
return T_OUTDENT;
}
}
-<INDENT>\t { current_indent++; }
-<INDENT>\n { current_indent = 0; }
+<INDENT>\t { yyextra->current_indent++; }
+<INDENT>\n { yyextra->current_indent = 0; }
<INDENT>. {
// Put the read character back for the next round
yyless(0);
// Mark beginning of line to match ^
- if (current_indent == 0)
+ if (yyextra->current_indent == 0)
yy_set_bol(1);
// --> - More indentation?
- if (current_indent > indent_level) {
- indent_level++;
+ if (yyextra->current_indent > yyextra->indent_level) {
+ yyextra->indent_level++;
yy_pop_state(yyscanner);
return T_INDENT;
// <-- - If indentation has become less
- } else if (current_indent < indent_level) {
- indent_level--;
+ } else if (yyextra->current_indent < yyextra->indent_level) {
+ yyextra->indent_level--;
yy_pop_state(yyscanner);
return T_OUTDENT;