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:
Carl Worth
2010-05-18 22:10:04 -07:00
parent d476db38fe
commit a807fb72c4
4 changed files with 343 additions and 271 deletions
+68 -9
View File
@@ -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