mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-11 05:13:04 +00:00
Allow specification of semantic predicates.
These changes allow users to prefix an action with %? to indicate that it
is a semantic predicate---an expression that is evaluated immediately (not
deferred, even in GLR nondeterministic mode) and causes a syntax error if
false. In GLR parsers, this has the effect of killing one of a set of
split-off parses, just as would an ordinary syntax error.
Changelog:
* NEWS: Describe new semantic-predicate feature.
* data/c.m4 (b4_predicate_case): New definition.
* data/java.m4 (b4_predicate_case): New definition.
* data/glr.c (yyimmediate): Add definition.
(yydoAction): Remove comment, now obsolete.
Do YY_REDUCE_PRINT here.
(yyglrReduce): Alter comment to indicate that semantic values
need not be deferred.
Remove YY_REDUCE_PRINT from here; done in yydoAction.
(yyprocessOneStack): Pass immediate flag.
Delete stacks rejected by predicates in newly split-off parsers.
Change handling of yyerr so that only current stack gets deleted
when semantic predicate fails.
(yyfillin): Don't crash if a semantic value is unresolved (as may
happen in predicate rules).
Copy lr state as well in debugging mode.
Update comment on setting of yysval to include yyloc as well.
(yy_reduce_print): Add yynormal argument. Perform fillin properly.
Report unresolved RHS values.
(yyimmediate): New table.
* src/gram.h (struct rule): Add is_predicate field.
* src/output.c (user_actions_output): Use b4_predicate_case for
predicates.
(prepare_symbols): Output yyimmediate.
* src/scan-gram.l: Add %? token, SC_PREDICATE state.
* src/scan-code.l (code_props_rule_action_init): Add is_predicate
argument.
* src/scan-code.h (struct code_props): Add is_predicate field.
(code_props_rule_action_init): New interface.
* src/parse-gram.y (%?{...}): New token.
(rhs): Add %?{...} rule.
* src/parse-gram.c: Regenerate.
* src/parse-gram.h: Regenerate.
* src/reader.c (grammar_current_rule_action_append): Add
immediate argument.
(grammar_midrule_action): Use new interface for
code_props_rule_action_init.
(grammar_current_rule_action_append): Ditto.
(packgram): Transfer is_predicate value.
* src/reader.h (grammar_current_rule_action_append): New interface.
* doc/bison.texinfo: Document semantic predicates (%?).
* data/glr.c (yylhsNonterm, yyisDefaultedState,yyDefaultAction)
(yygetLRActions,yynewGLRStackItem,yyaddDeferredAction,yyinitStateSet)
(yyinitGLRStack,yyexpandGLRStack,yyupdateSplit,yymarkStackDeleted)
(yyundeleteLastStack,yyglrShift,yyglrShiftDefer,yydoAction,yyglrReduce)
(yyidenticalOptions,yymergeOptionSets,yyresolveStates,yyresolveAction)
(yyresolveLocations,yyresolveValue,yyreducePrint): Update parameter
names in comments and mention all parameters.
(struct yyGLRState): Fix description of yyposn field.
(yyresolveLocations): Correct comment so as not to imply action when
yyn1==0.
This commit is contained in:
@@ -194,6 +194,7 @@ typedef struct
|
||||
|
||||
location location;
|
||||
bool useful;
|
||||
bool is_predicate;
|
||||
|
||||
const char *action;
|
||||
location action_location;
|
||||
|
||||
11
src/output.c
11
src/output.c
@@ -204,7 +204,7 @@ prepare_symbols (void)
|
||||
|
||||
/*----------------------------------------------------------------.
|
||||
| Prepare the muscles related to the rules: r1, r2, rline, dprec, |
|
||||
| merger. |
|
||||
| merger, immediate. |
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
@@ -215,6 +215,7 @@ prepare_rules (void)
|
||||
unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
|
||||
int *dprec = xnmalloc (nrules, sizeof *dprec);
|
||||
int *merger = xnmalloc (nrules, sizeof *merger);
|
||||
int *immediate = xnmalloc (nrules, sizeof *immediate);
|
||||
|
||||
rule_number r;
|
||||
for (r = 0; r < nrules; ++r)
|
||||
@@ -229,6 +230,8 @@ prepare_rules (void)
|
||||
dprec[r] = rules[r].dprec;
|
||||
/* Merger-function index (GLR). */
|
||||
merger[r] = rules[r].merger;
|
||||
/* Immediate reduction flags (GLR). */
|
||||
immediate[r] = rules[r].is_predicate;
|
||||
}
|
||||
|
||||
muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules);
|
||||
@@ -236,6 +239,7 @@ prepare_rules (void)
|
||||
muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules);
|
||||
muscle_insert_int_table ("dprec", dprec, 0, 0, nrules);
|
||||
muscle_insert_int_table ("merger", merger, 0, 0, nrules);
|
||||
muscle_insert_int_table ("immediate", immediate, 0, 0, nrules);
|
||||
|
||||
MUSCLE_INSERT_INT ("rules_number", nrules);
|
||||
MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
|
||||
@@ -349,8 +353,9 @@ user_actions_output (FILE *out)
|
||||
for (r = 0; r < nrules; ++r)
|
||||
if (rules[r].action)
|
||||
{
|
||||
fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1,
|
||||
rules[r].action_location.start.line);
|
||||
fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ",
|
||||
rules[r].is_predicate ? "predicate_" : "",
|
||||
r + 1, rules[r].action_location.start.line);
|
||||
escaped_output (out, rules[r].action_location.start.file);
|
||||
fprintf (out, ")\n[ %s]])\n\n", rules[r].action);
|
||||
}
|
||||
|
||||
939
src/parse-gram.c
939
src/parse-gram.c
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.483-4ad39-dirty. */
|
||||
/* A Bison parser, made by GNU Bison 2.4.516-804e. */
|
||||
|
||||
/* Interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||
2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
@@ -31,7 +32,7 @@
|
||||
version 2.2 of Bison. */
|
||||
/* "%code requires" blocks. */
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 201 "src/parse-gram.y"
|
||||
#line 202 "src/parse-gram.y"
|
||||
|
||||
# ifndef PARAM_TYPE
|
||||
# define PARAM_TYPE
|
||||
@@ -46,7 +47,7 @@
|
||||
|
||||
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 50 "src/parse-gram.h"
|
||||
#line 51 "src/parse-gram.h"
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
@@ -93,21 +94,22 @@
|
||||
PERCENT_VERBOSE = 293,
|
||||
PERCENT_YACC = 294,
|
||||
BRACED_CODE = 295,
|
||||
BRACKETED_ID = 296,
|
||||
CHAR = 297,
|
||||
EPILOGUE = 298,
|
||||
EQUAL = 299,
|
||||
ID = 300,
|
||||
ID_COLON = 301,
|
||||
PERCENT_PERCENT = 302,
|
||||
PIPE = 303,
|
||||
PROLOGUE = 304,
|
||||
SEMICOLON = 305,
|
||||
TAG = 306,
|
||||
TAG_ANY = 307,
|
||||
TAG_NONE = 308,
|
||||
PERCENT_PARAM = 309,
|
||||
PERCENT_UNION = 310
|
||||
BRACED_PREDICATE = 296,
|
||||
BRACKETED_ID = 297,
|
||||
CHAR = 298,
|
||||
EPILOGUE = 299,
|
||||
EQUAL = 300,
|
||||
ID = 301,
|
||||
ID_COLON = 302,
|
||||
PERCENT_PERCENT = 303,
|
||||
PIPE = 304,
|
||||
PROLOGUE = 305,
|
||||
SEMICOLON = 306,
|
||||
TAG = 307,
|
||||
TAG_ANY = 308,
|
||||
TAG_NONE = 309,
|
||||
PERCENT_PARAM = 310,
|
||||
PERCENT_UNION = 311
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@@ -150,21 +152,22 @@
|
||||
#define PERCENT_VERBOSE 293
|
||||
#define PERCENT_YACC 294
|
||||
#define BRACED_CODE 295
|
||||
#define BRACKETED_ID 296
|
||||
#define CHAR 297
|
||||
#define EPILOGUE 298
|
||||
#define EQUAL 299
|
||||
#define ID 300
|
||||
#define ID_COLON 301
|
||||
#define PERCENT_PERCENT 302
|
||||
#define PIPE 303
|
||||
#define PROLOGUE 304
|
||||
#define SEMICOLON 305
|
||||
#define TAG 306
|
||||
#define TAG_ANY 307
|
||||
#define TAG_NONE 308
|
||||
#define PERCENT_PARAM 309
|
||||
#define PERCENT_UNION 310
|
||||
#define BRACED_PREDICATE 296
|
||||
#define BRACKETED_ID 297
|
||||
#define CHAR 298
|
||||
#define EPILOGUE 299
|
||||
#define EQUAL 300
|
||||
#define ID 301
|
||||
#define ID_COLON 302
|
||||
#define PERCENT_PERCENT 303
|
||||
#define PIPE 304
|
||||
#define PROLOGUE 305
|
||||
#define SEMICOLON 306
|
||||
#define TAG 307
|
||||
#define TAG_ANY 308
|
||||
#define TAG_NONE 309
|
||||
#define PERCENT_PARAM 310
|
||||
#define PERCENT_UNION 311
|
||||
|
||||
|
||||
|
||||
@@ -173,7 +176,7 @@
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 87 "src/parse-gram.y"
|
||||
#line 88 "src/parse-gram.y"
|
||||
|
||||
assoc assoc;
|
||||
char *code;
|
||||
@@ -186,13 +189,13 @@ typedef union YYSTYPE
|
||||
unsigned char character;
|
||||
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 225 "src/parse-gram.y"
|
||||
#line 226 "src/parse-gram.y"
|
||||
|
||||
param_type param;
|
||||
|
||||
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 196 "src/parse-gram.h"
|
||||
#line 199 "src/parse-gram.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
|
||||
@@ -118,7 +118,6 @@ static char const *char_name (char);
|
||||
%token PERCENT_DPREC "%dprec"
|
||||
%token PERCENT_MERGE "%merge"
|
||||
|
||||
|
||||
/*----------------------.
|
||||
| Global Declarations. |
|
||||
`----------------------*/
|
||||
@@ -151,6 +150,7 @@ static char const *char_name (char);
|
||||
;
|
||||
|
||||
%token BRACED_CODE "{...}"
|
||||
%token BRACED_PREDICATE "%?{...}"
|
||||
%token BRACKETED_ID "[identifier]"
|
||||
%token CHAR "char"
|
||||
%token EPILOGUE "epilogue"
|
||||
@@ -171,7 +171,7 @@ static char const *char_name (char);
|
||||
/* braceless is not to be used for rule or symbol actions, as it
|
||||
calls code_props_plain_init. */
|
||||
%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
|
||||
%type <code> "{...}"
|
||||
%type <code> "{...}" "%?{...}"
|
||||
%printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
|
||||
STRING
|
||||
%printer { fprintf (stderr, "{\n%s\n}", $$); }
|
||||
@@ -586,7 +586,9 @@ rhs:
|
||||
| rhs symbol named_ref.opt
|
||||
{ grammar_current_rule_symbol_append ($2, @2, $3); }
|
||||
| rhs "{...}" named_ref.opt
|
||||
{ grammar_current_rule_action_append ($2, @2, $3); }
|
||||
{ grammar_current_rule_action_append ($2, @2, $3, false); }
|
||||
| rhs "%?{...}"
|
||||
{ grammar_current_rule_action_append ($2, @2, NULL, true); }
|
||||
| rhs "%prec" symbol
|
||||
{ grammar_current_rule_prec_set ($3, @3); }
|
||||
| rhs "%dprec" INT
|
||||
@@ -601,7 +603,6 @@ named_ref.opt:
|
||||
BRACKETED_ID { $$ = named_ref_new($1, @1); }
|
||||
;
|
||||
|
||||
|
||||
/*---------------------------.
|
||||
| variable and content.opt. |
|
||||
`---------------------------*/
|
||||
|
||||
@@ -377,7 +377,8 @@ grammar_midrule_action (void)
|
||||
code_props_rule_action_init (&midrule->action_props,
|
||||
current_rule->action_props.code,
|
||||
current_rule->action_props.location,
|
||||
midrule, 0);
|
||||
midrule, 0,
|
||||
current_rule->action_props.is_predicate);
|
||||
code_props_none_init (¤t_rule->action_props);
|
||||
|
||||
if (previous_rule_end)
|
||||
@@ -468,14 +469,14 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
|
||||
|
||||
void
|
||||
grammar_current_rule_action_append (const char *action, location loc,
|
||||
named_ref *name)
|
||||
named_ref *name, bool is_predicate)
|
||||
{
|
||||
if (current_rule->action_props.code)
|
||||
grammar_midrule_action ();
|
||||
/* After all symbol declarations have been parsed, packgram invokes
|
||||
code_props_translate_code. */
|
||||
code_props_rule_action_init (¤t_rule->action_props, action, loc,
|
||||
current_rule, name);
|
||||
current_rule, name, is_predicate);
|
||||
}
|
||||
|
||||
|
||||
@@ -516,6 +517,7 @@ packgram (void)
|
||||
rules[ruleno].useful = true;
|
||||
rules[ruleno].action = p->action_props.code;
|
||||
rules[ruleno].action_location = p->action_props.location;
|
||||
rules[ruleno].is_predicate = p->action_props.is_predicate;
|
||||
|
||||
/* If the midrule's $$ is set or its $n is used, remove the `$' from the
|
||||
symbol name so that it's a user-defined symbol so that the default
|
||||
|
||||
@@ -53,7 +53,7 @@ void grammar_current_rule_merge_set (uniqstr name, location loc);
|
||||
void grammar_current_rule_symbol_append (symbol *sym, location loc,
|
||||
named_ref *named_ref);
|
||||
void grammar_current_rule_action_append (const char *action, location loc,
|
||||
named_ref *named_ref);
|
||||
named_ref *named_ref, bool);
|
||||
void reader (void);
|
||||
void free_merger_functions (void);
|
||||
|
||||
|
||||
@@ -63,6 +63,13 @@ typedef struct code_props {
|
||||
*/
|
||||
bool is_value_used;
|
||||
|
||||
/**
|
||||
* \c true iff this code is an action that is not to be deferred in
|
||||
* a non-deterministic parser.
|
||||
*/
|
||||
bool is_predicate;
|
||||
|
||||
|
||||
/** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION. */
|
||||
struct symbol_list *rule;
|
||||
|
||||
@@ -80,7 +87,7 @@ void code_props_none_init (code_props *self);
|
||||
|
||||
/** Equivalent to \c code_props_none_init. */
|
||||
#define CODE_PROPS_NONE_INIT \
|
||||
{CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, NULL, NULL}
|
||||
{CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, false, NULL, NULL}
|
||||
|
||||
/** Initialized by \c CODE_PROPS_NONE_INIT with no further modification. */
|
||||
extern code_props const code_props_none;
|
||||
@@ -134,7 +141,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
|
||||
*/
|
||||
void code_props_rule_action_init (code_props *self, char const *code,
|
||||
location code_loc, struct symbol_list *rule,
|
||||
named_ref *name);
|
||||
named_ref *name, bool is_predicate);
|
||||
|
||||
/**
|
||||
* \pre
|
||||
|
||||
@@ -902,7 +902,7 @@ code_props_symbol_action_init (code_props *self, char const *code,
|
||||
void
|
||||
code_props_rule_action_init (code_props *self, char const *code,
|
||||
location code_loc, symbol_list *rule,
|
||||
named_ref *name)
|
||||
named_ref *name, bool is_predicate)
|
||||
{
|
||||
self->kind = CODE_PROPS_RULE_ACTION;
|
||||
self->code = code;
|
||||
@@ -910,6 +910,7 @@ code_props_rule_action_init (code_props *self, char const *code,
|
||||
self->is_value_used = false;
|
||||
self->rule = rule;
|
||||
self->named_ref = name;
|
||||
self->is_predicate = is_predicate;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -106,11 +106,12 @@ static void unexpected_newline (boundary, char const *);
|
||||
/* A complex tag, with nested angles brackets. */
|
||||
%x SC_TAG
|
||||
|
||||
/* Three types of user code:
|
||||
/* Four types of user code:
|
||||
- prologue (code between `%{' `%}' in the first section, before %%);
|
||||
- actions, printers, union, etc, (between braced in the middle section);
|
||||
- epilogue (everything after the second %%). */
|
||||
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
|
||||
- epilogue (everything after the second %%).
|
||||
- predicate (code between `%?{' and `{' in middle section); */
|
||||
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
|
||||
/* C and C++ comments in code. */
|
||||
%x SC_COMMENT SC_LINE_COMMENT
|
||||
/* Strings and characters in code. */
|
||||
@@ -285,6 +286,13 @@ splice (\\[ \f\t\v]*\n)*
|
||||
BEGIN SC_BRACED_CODE;
|
||||
}
|
||||
|
||||
/* Semantic predicate. */
|
||||
"%?"[ \f\n\t\v]*"{" {
|
||||
nesting = 0;
|
||||
code_start = loc->start;
|
||||
BEGIN SC_PREDICATE;
|
||||
}
|
||||
|
||||
/* A type. */
|
||||
"<*>" return TAG_ANY;
|
||||
"<>" return TAG_NONE;
|
||||
@@ -661,7 +669,7 @@ splice (\\[ \f\t\v]*\n)*
|
||||
| Strings, comments etc. can be found in user code. |
|
||||
`---------------------------------------------------*/
|
||||
|
||||
<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
|
||||
<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_PREDICATE>
|
||||
{
|
||||
"'" {
|
||||
STRING_GROW;
|
||||
@@ -691,14 +699,32 @@ splice (\\[ \f\t\v]*\n)*
|
||||
|
||||
|
||||
/*-----------------------------------------------------------.
|
||||
| Scanning some code in braces (actions). The initial "{" is |
|
||||
| already eaten. |
|
||||
| Scanning some code in braces (actions, predicates). The |
|
||||
| initial "{" is already eaten. |
|
||||
`-----------------------------------------------------------*/
|
||||
|
||||
<SC_BRACED_CODE>
|
||||
<SC_BRACED_CODE,SC_PREDICATE>
|
||||
{
|
||||
"{"|"<"{splice}"%" STRING_GROW; nesting++;
|
||||
"%"{splice}">" STRING_GROW; nesting--;
|
||||
|
||||
/* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
|
||||
(as `<' `<%'). */
|
||||
"<"{splice}"<" STRING_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
int token = (YY_START == SC_BRACED_CODE) ? BRACED_CODE : BRACED_PREDICATE;
|
||||
unexpected_eof (code_start, "}");
|
||||
STRING_FINISH;
|
||||
loc->start = code_start;
|
||||
val->code = last_string;
|
||||
BEGIN INITIAL;
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
<SC_BRACED_CODE>
|
||||
{
|
||||
"}" {
|
||||
obstack_1grow (&obstack_for_string, '}');
|
||||
|
||||
@@ -712,21 +738,24 @@ splice (\\[ \f\t\v]*\n)*
|
||||
return BRACED_CODE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
|
||||
(as `<' `<%'). */
|
||||
"<"{splice}"<" STRING_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
unexpected_eof (code_start, "}");
|
||||
STRING_FINISH;
|
||||
loc->start = code_start;
|
||||
val->code = last_string;
|
||||
BEGIN INITIAL;
|
||||
return BRACED_CODE;
|
||||
}
|
||||
}
|
||||
|
||||
<SC_PREDICATE>
|
||||
{
|
||||
"}" {
|
||||
--nesting;
|
||||
if (nesting < 0)
|
||||
{
|
||||
STRING_FINISH;
|
||||
loc->start = code_start;
|
||||
val->code = last_string;
|
||||
BEGIN INITIAL;
|
||||
return BRACED_PREDICATE;
|
||||
}
|
||||
else
|
||||
obstack_1grow (&obstack_for_string, '}');
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------.
|
||||
| Scanning some prologue: from "%{" (already scanned) to "%}". |
|
||||
@@ -774,8 +803,8 @@ splice (\\[ \f\t\v]*\n)*
|
||||
| By default, grow the string obstack with the input. |
|
||||
`-----------------------------------------------------*/
|
||||
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;
|
||||
|
||||
%%
|
||||
|
||||
|
||||
Reference in New Issue
Block a user