/* * Copyright (C) 2014 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup parser_helper parser_helper * @{ @ingroup utils */ #ifndef PARSER_HELPER_H_ #define PARSER_HELPER_H_ #include #include #include typedef struct parser_helper_t parser_helper_t; /** * Helper class for flex/bison based parsers. * * PREFIX equals whatever is configure with * %option prefix resp. %name-prefix. */ struct parser_helper_t { /** * A user defined parser context object. */ const void *context; /** * Opaque object allocated by the lexer, should be set with: * @code * PREFIXlex_init_extra(helper, &helper->scanner). * @endcode */ void *scanner; /** * Function to determine the current line number (defined by the lexer). * * Basically, this should be assigned to PREFIXget_lineno. * * @param scanner the lexer * @return current line number */ int (*get_lineno)(void *scanner); /** * Resolves the given include pattern, relative to the location of the * current file. * * Call file_next() to open the next file. * * @param pattern file pattern */ void (*file_include)(parser_helper_t *this, char *pattern); /** * Get the next file to process. * * This will return NULL if all files matching the most recent pattern * have been handled. If there are other patterns the next call will then * return the next file matching the previous pattern. * * When hitting \<\\> first call * @code * PREFIXpop_buffer_state(yyscanner); * @endcode * then call this method to check if there are more files to include for * the most recent call to file_include(), if so, call * @code * PREFIXset_in(file, helper->scanner); * PREFIXpush_buffer_state(PREFIX_create_buffer(file, YY_BUF_SIZE, * helper->scanner), helper->scanner); * @endcode * * If there are no more files to process check * YY_CURRENT_BUFFER and if it is FALSE call yyterminate(). * * @return next file to process, or NULL (see comment) */ FILE *(*file_next)(parser_helper_t *this); /** * Start parsing a string, discards any currently stored data. */ void (*string_init)(parser_helper_t *this); /** * Append the given string. * * @param str string to append */ void (*string_add)(parser_helper_t *this, char *str); /** * Extract the current string buffer as null-terminated string. Can only * be called once per string. * * @return allocated string */ char *(*string_get)(parser_helper_t *this); /** * Destroy this instance. */ void (*destroy)(parser_helper_t *this); }; /** * Log the given message either as error or warning * * @param level log level * @param ctx current parser context * @param fmt error message format * @param ... additional arguments */ void parser_helper_log(int level, parser_helper_t *ctx, char *fmt, ...); #if DEBUG_LEVEL >= 1 # define PARSER_DBG1(ctx, fmt, ...) parser_helper_log(1, ctx, fmt, ##__VA_ARGS__) #endif #if DEBUG_LEVEL >= 2 # define PARSER_DBG2(ctx, fmt, ...) parser_helper_log(2, ctx, fmt, ##__VA_ARGS__) #endif #if DEBUG_LEVEL >= 3 # define PARSER_DBG3(ctx, fmt, ...) parser_helper_log(3, ctx, fmt, ##__VA_ARGS__) #endif #ifndef PARSER_DBG1 # define PARSER_DBG1(...) {} #endif #ifndef PARSER_DBG2 # define PARSER_DBG2(...) {} #endif #ifndef PARSER_DBG3 # define PARSER_DBG3(...) {} #endif /** * Create a parser helper object * * @param context user defined parser context * @return parser helper */ parser_helper_t *parser_helper_create(void *context); #endif /** PARSER_HELPER_H_ @}*/