From 14bfd2e9d9e5a17dfc7cbba44872abccad0c1d65 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 4 Apr 2013 16:38:17 +0200 Subject: [PATCH] grammar: record the kind of %define variable values Provide a means to tell the difference between "keyword" values (e.g., %define api.pull both), "string" values (e.g., %define file.name "foo"), and "code" values (e.g., %define api.namespace {calc}). Suggested by Joel E. Denny. http://lists.gnu.org/archive/html/bison-patches/2013-03/msg00016.html * src/muscle-tab.h, src/muscle-tab.c (muscle_kind, muscle_kind_new) (muscle_kind_string): New. (muscle_percent_define_insert): Take the kind as new argument. Insert it in the muscle table. Adjust callers. * src/getargs.c: Adjust callers. * src/parse-gram.y: Ditto. (content.opt): Remove, replaced by... (value): this new non-terminal, whose semantics value is stored in the new "value" union member. Provide a printer. Support values in braces in additions to keyword and string values. fuse me --- src/getargs.c | 4 +++- src/muscle-tab.c | 34 ++++++++++++++++++++++++++++++++-- src/muscle-tab.h | 20 +++++++++++++++++++- src/parse-gram.y | 47 ++++++++++++++++++++++++++++++++++------------- 4 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/getargs.c b/src/getargs.c index 02548650..e6f9d766 100644 --- a/src/getargs.c +++ b/src/getargs.c @@ -582,6 +582,7 @@ getargs (int argc, char *argv[]) if (value) *value++ = 0; muscle_percent_define_insert (name, command_line_location (), + muscle_string, value ? value : "", c == 'D' ? MUSCLE_PERCENT_DEFINE_D : MUSCLE_PERCENT_DEFINE_F); @@ -666,7 +667,8 @@ getargs (int argc, char *argv[]) case 't': muscle_percent_define_insert ("parse.trace", - command_line_location (), "", + command_line_location (), + muscle_keyword, "", MUSCLE_PERCENT_DEFINE_D); break; diff --git a/src/muscle-tab.c b/src/muscle-tab.c index 4d5dd0ac..10a0a5cb 100644 --- a/src/muscle-tab.c +++ b/src/muscle-tab.c @@ -28,6 +28,31 @@ #include "muscle-tab.h" #include "quote.h" +muscle_kind +muscle_kind_new (char const *k) +{ + if (STREQ (k, "code")) + return muscle_code; + else if (STREQ (k, "keyword")) + return muscle_keyword; + else if (STREQ (k, "string")) + return muscle_string; + aver (0); +} + +char const * +muscle_kind_string (muscle_kind k) +{ + switch (k) + { + case muscle_code: return "code"; + case muscle_keyword: return "keyword"; + case muscle_string: return "string"; + } + aver (0); +} + + /* A key-value pair, along with storage that can be reclaimed when this pair is no longer needed. */ typedef struct @@ -35,6 +60,7 @@ typedef struct char const *key; char const *value; char *storage; + muscle_kind kind; } muscle_entry; /* An obstack used to create some entries. */ @@ -446,6 +472,7 @@ muscle_percent_variable_update (char const *variable, location variable_loc, void muscle_percent_define_insert (char const *var, location variable_loc, + muscle_kind kind, char const *value, muscle_percent_define_how how) { @@ -456,6 +483,8 @@ muscle_percent_define_insert (char const *var, location variable_loc, char const *syncline_name = UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")"); char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")"); + char const *kind_name = + UNIQSTR_CONCAT ("percent_define_kind(", variable, ")"); /* Command-line options are processed before the grammar file. */ if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE @@ -481,6 +510,7 @@ muscle_percent_define_insert (char const *var, location variable_loc, muscle_user_name_list_grow ("percent_define_user_variables", variable, variable_loc); MUSCLE_INSERT_INT (how_name, how); + MUSCLE_INSERT_STRING (kind_name, muscle_kind_string (kind)); end: free (variable); } @@ -497,10 +527,10 @@ muscle_percent_define_ensure (char const *variable, location loc, /* Don't complain is VARIABLE is already defined, but be sure to set its value to VAL. */ if (!muscle_find_const (name)) - muscle_percent_define_insert (variable, loc, val, + muscle_percent_define_insert (variable, loc, muscle_keyword, val, MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); if (muscle_percent_define_flag_if (variable) != value) - muscle_percent_define_insert (variable, loc, val, + muscle_percent_define_insert (variable, loc, muscle_keyword, val, MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } diff --git a/src/muscle-tab.h b/src/muscle-tab.h index 30a74523..af6b615c 100644 --- a/src/muscle-tab.h +++ b/src/muscle-tab.h @@ -24,12 +24,29 @@ # include "location.h" +/* The kind of value associated to this muscle, depending on the + syntax of the value: keyword (no delimiter, e.g., true), string + (double quotes, e.g., "foo.h"), or code (braces, e.g., {int}). */ +typedef enum +{ + muscle_code, + muscle_keyword, + muscle_string +} muscle_kind; + +/* Conversion from string. */ +muscle_kind muscle_kind_new (char const *k); + +/* Conversion to string. */ +char const *muscle_kind_string (muscle_kind k); + + /* Create the MUSCLE_TABLE, and initialize it with default values. Also set up the MUSCLE_OBSTACK. */ void muscle_init (void); /* Insert (KEY, VALUE). If KEY already existed, overwrite the - previous value. */ + previous value. Otherwise create as a muscle_string type. */ void muscle_insert (char const *key, char const *value); /* Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always @@ -124,6 +141,7 @@ typedef enum { this as a user occurrence of VARIABLE by invoking muscle_user_name_list_grow. */ void muscle_percent_define_insert (char const *variable, location variable_loc, + muscle_kind kind, char const *value, muscle_percent_define_how how); diff --git a/src/parse-gram.y b/src/parse-gram.y index f03069dc..b6338597 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -26,7 +26,6 @@ #include "files.h" #include "getargs.h" #include "gram.h" -#include "muscle-tab.h" #include "named-ref.h" #include "quotearg.h" #include "reader.h" @@ -179,12 +178,12 @@ static char const *char_name (char); char *code; char const *chars; }; -%type STRING "%{...%}" EPILOGUE braceless content.opt +%type STRING "%{...%}" EPILOGUE braceless %type "{...}" "%?{...}" %printer { fputs (quotearg_style (c_quoting_style, $$), yyo); } STRING %printer { fprintf (yyo, "{\n%s\n}", $$); } - braceless content.opt "{...}" "%{...%}" EPILOGUE + braceless "{...}" "%{...%}" EPILOGUE %union {uniqstr uniqstr;} %type BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG tag variable @@ -288,9 +287,9 @@ prologue_declaration: { muscle_percent_define_ensure ($1, @1, true); } -| "%define" variable content.opt +| "%define" variable value { - muscle_percent_define_insert ($2, @2, $3, + muscle_percent_define_insert ($2, @2, $3.kind, $3.chars, MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } | "%defines" { defines_flag = true; } @@ -301,7 +300,8 @@ prologue_declaration: } | "%error-verbose" { - muscle_percent_define_insert ("parse.error", @1, "verbose", + muscle_percent_define_insert ("parse.error", @1, muscle_keyword, + "verbose", MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } | "%expect" INT { expected_sr_conflicts = $2; } @@ -634,9 +634,9 @@ named_ref.opt: | BRACKETED_ID { $$ = named_ref_new($1, @1); } ; -/*---------------------------. -| variable and content.opt. | -`---------------------------*/ +/*---------------------. +| variable and value. | +`---------------------*/ /* The STRING form of variable is deprecated and is not M4-friendly. For example, M4 fails for '%define "[" "value"'. */ @@ -646,10 +646,31 @@ variable: ; /* Some content or empty by default. */ -content.opt: - %empty { $$ = ""; } -| ID { $$ = $1; } -| STRING { $$ = $1; } +%code requires {#include "muscle-tab.h"}; +%union +{ + struct + { + char const *chars; + muscle_kind kind; + } value; +}; +%type value; +%printer +{ + switch ($$.kind) + { + case muscle_code: fprintf (yyo, "{%s}", $$.chars); break; + case muscle_keyword: fprintf (yyo, "%s", $$.chars); break; + case muscle_string: fprintf (yyo, "\"%s\"", $$.chars); break; + } +} ; + +value: + %empty { $$.kind = muscle_keyword; $$.chars = ""; } +| ID { $$.kind = muscle_keyword; $$.chars = $1; } +| STRING { $$.kind = muscle_string; $$.chars = $1; } +| braceless { $$.kind = muscle_code; $$.chars = $1; } ; -- 2.47.2