Rewrite macro handling to support function-like macro invocation in macro values
The rewrite her discards the functions that did direct, recursive expansion of macro values. Instead, the parser now pushes the macro definition string over to a stack of buffers for the lexer. This way, macro expansion gets access to all parsing machinery. This isn't a small change, but the result is simpler than before (I think). It passes the entire test suite, including the four tests added with the previous commit that were failing before.
This commit is contained in:
@@ -24,11 +24,13 @@
|
||||
#ifndef GLCPP_H
|
||||
#define GLCPP_H
|
||||
|
||||
#include <talloc.h>
|
||||
|
||||
#include "hash_table.h"
|
||||
|
||||
#define yyscan_t void*
|
||||
|
||||
/* Some data types used for parser value. */
|
||||
/* Some data types used for parser values. */
|
||||
|
||||
typedef struct string_node {
|
||||
const char *str;
|
||||
@@ -52,6 +54,56 @@ typedef struct argument_list {
|
||||
|
||||
typedef struct glcpp_parser glcpp_parser_t;
|
||||
|
||||
/* Support for temporarily lexing/parsing tokens from a string. */
|
||||
|
||||
typedef struct glcpp_lex_node {
|
||||
void *buffer;
|
||||
struct glcpp_lex_node *next;
|
||||
} glcpp_lex_node_t;
|
||||
|
||||
typedef struct {
|
||||
glcpp_parser_t *parser;
|
||||
glcpp_lex_node_t *head;
|
||||
} glcpp_lex_stack_t;
|
||||
|
||||
void
|
||||
glcpp_lex_stack_push (glcpp_lex_stack_t *stack, const char *string);
|
||||
|
||||
int
|
||||
glcpp_lex_stack_pop (glcpp_lex_stack_t *stack);
|
||||
|
||||
typedef enum {
|
||||
TOKEN_CLASS_ARGUMENT,
|
||||
TOKEN_CLASS_IDENTIFIER,
|
||||
TOKEN_CLASS_FUNC_MACRO,
|
||||
TOKEN_CLASS_OBJ_MACRO
|
||||
} token_class_t;
|
||||
|
||||
token_class_t
|
||||
glcpp_parser_classify_token (glcpp_parser_t *parser,
|
||||
const char *identifier,
|
||||
int *parameter_index);
|
||||
|
||||
typedef struct {
|
||||
int is_function;
|
||||
string_list_t *parameters;
|
||||
const char *identifier;
|
||||
const char *replacement;
|
||||
} macro_t;
|
||||
|
||||
typedef struct expansion_node {
|
||||
macro_t *macro;
|
||||
argument_list_t *arguments;
|
||||
struct expansion_node *next;
|
||||
} expansion_node_t;
|
||||
|
||||
struct glcpp_parser {
|
||||
yyscan_t scanner;
|
||||
struct hash_table *defines;
|
||||
expansion_node_t *expansions;
|
||||
glcpp_lex_stack_t *lex_stack;
|
||||
};
|
||||
|
||||
glcpp_parser_t *
|
||||
glcpp_parser_create (void);
|
||||
|
||||
@@ -61,15 +113,17 @@ glcpp_parser_parse (glcpp_parser_t *parser);
|
||||
void
|
||||
glcpp_parser_destroy (glcpp_parser_t *parser);
|
||||
|
||||
typedef enum {
|
||||
MACRO_TYPE_UNDEFINED,
|
||||
MACRO_TYPE_OBJECT,
|
||||
MACRO_TYPE_FUNCTION
|
||||
} macro_type_t;
|
||||
void
|
||||
glcpp_parser_push_expansion_macro (glcpp_parser_t *parser,
|
||||
macro_t *macro,
|
||||
argument_list_t *arguments);
|
||||
|
||||
macro_type_t
|
||||
glcpp_parser_macro_type (glcpp_parser_t *parser,
|
||||
const char *identifier);
|
||||
void
|
||||
glcpp_parser_push_expansion_argument (glcpp_parser_t *parser,
|
||||
int argument_index);
|
||||
|
||||
void
|
||||
glcpp_parser_pop_expansion (glcpp_parser_t *parser);
|
||||
|
||||
/* Generated by glcpp-lex.l to glcpp-lex.c */
|
||||
|
||||
@@ -91,10 +145,15 @@ yyparse (glcpp_parser_t *parser);
|
||||
|
||||
#define xtalloc(ctx, type) (type *)xtalloc_named_const(ctx, sizeof(type), #type)
|
||||
|
||||
#define xtalloc_size(ctx, size) xtalloc_named_const(ctx, size, __location__)
|
||||
|
||||
void *
|
||||
xtalloc_named_const (const void *context, size_t size, const char *name);
|
||||
|
||||
char *
|
||||
xtalloc_strdup (const void *t, const char *p);
|
||||
|
||||
char *
|
||||
xtalloc_strndup (const void *t, const char *p, size_t n);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user