mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
syntax: introducing %precr to add specific precedence relations
It is now possible to add specific precedence relations between two symbols,
or a symbol and a group, with the %precr keyword:
%gprec arith {
%left '+' '-'
%left '*' '/'
}
%gprec boolean {
%left OR
%left AND
}
%right '^'
%precr '^' > arith
%precr OR AND > '^'
Here, the symbol ^ is of higher priority than the the ones in arith, but of
lower priority than both OR and AND. OR and '+', for example, cannot be
compared.
* src/parse-gram.y, src/scan-gram.l: Lexer and grammar implementation of
%precr.
* src/symtab.c, src/symtab.h: implementation of the addition of single link
precedence relationships.
This commit is contained in:
@@ -131,6 +131,7 @@
|
|||||||
%token PERCENT_PREC "%prec"
|
%token PERCENT_PREC "%prec"
|
||||||
%token PERCENT_DPREC "%dprec"
|
%token PERCENT_DPREC "%dprec"
|
||||||
%token PERCENT_GPREC "%gprec"
|
%token PERCENT_GPREC "%gprec"
|
||||||
|
%token PERCENT_PRECR "%precr"
|
||||||
%token PERCENT_MERGE "%merge"
|
%token PERCENT_MERGE "%merge"
|
||||||
|
|
||||||
/*----------------------.
|
/*----------------------.
|
||||||
@@ -176,6 +177,7 @@
|
|||||||
%token PIPE "|"
|
%token PIPE "|"
|
||||||
%token PROLOGUE "%{...%}"
|
%token PROLOGUE "%{...%}"
|
||||||
%token SEMICOLON ";"
|
%token SEMICOLON ";"
|
||||||
|
%token GT ">"
|
||||||
%token TAG "<tag>"
|
%token TAG "<tag>"
|
||||||
%token TAG_ANY "<*>"
|
%token TAG_ANY "<*>"
|
||||||
%token TAG_NONE "<>"
|
%token TAG_NONE "<>"
|
||||||
@@ -217,7 +219,13 @@
|
|||||||
%union {named_ref *named_ref;}
|
%union {named_ref *named_ref;}
|
||||||
%type <named_ref> named_ref.opt
|
%type <named_ref> named_ref.opt
|
||||||
|
|
||||||
%type <uniqstr> prec_group_name.opt
|
%type <uniqstr> prec_group_name.opt string_or_id
|
||||||
|
|
||||||
|
%union {prec_rel_comparator prec_rel_comparator;}
|
||||||
|
%type <prec_rel_comparator> prec_rel_comparator
|
||||||
|
|
||||||
|
%type <list> precedence_relation_symbols precedence_symbol
|
||||||
|
|
||||||
/*---------.
|
/*---------.
|
||||||
| %param. |
|
| %param. |
|
||||||
`---------*/
|
`---------*/
|
||||||
@@ -370,6 +378,7 @@ params:
|
|||||||
grammar_declaration:
|
grammar_declaration:
|
||||||
precedence_declaration
|
precedence_declaration
|
||||||
| precedence_group_declaration
|
| precedence_group_declaration
|
||||||
|
| precedence_relation_declaration
|
||||||
| symbol_declaration
|
| symbol_declaration
|
||||||
| "%start" symbol
|
| "%start" symbol
|
||||||
{
|
{
|
||||||
@@ -513,6 +522,46 @@ tag.opt:
|
|||||||
| TAG { current_type = $1; tag_seen = true; }
|
| TAG { current_type = $1; tag_seen = true; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Declaration of a precedence relation between two (lists of) tokens */
|
||||||
|
precedence_relation_declaration:
|
||||||
|
"%precr" precedence_relation_symbols
|
||||||
|
{ prec_braces = default_braces_state; }
|
||||||
|
prec_rel_comparator
|
||||||
|
precedence_relation_symbols
|
||||||
|
{ declare_precedence_relation ($2, $5, $4, @4); }
|
||||||
|
;
|
||||||
|
|
||||||
|
precedence_relation_symbols:
|
||||||
|
precedence_symbol { $$ = $1; }
|
||||||
|
| precedence_relation_symbols precedence_symbol
|
||||||
|
{ $$ = symbol_list_append ($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
precedence_symbol:
|
||||||
|
string_or_id
|
||||||
|
{
|
||||||
|
if (is_prec_group ($1))
|
||||||
|
$$ = expand_symbol_group (symgroup_from_uniqstr($1, &@1), @1);
|
||||||
|
else
|
||||||
|
$$ = symbol_list_sym_new (symbol_from_uniqstr ($1, @1), @1);
|
||||||
|
}
|
||||||
|
| CHAR
|
||||||
|
{
|
||||||
|
$$ = symbol_list_sym_new (symbol_from_uniqstr (uniqstr_new (char_name ($1)), @1), @1);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
string_or_id:
|
||||||
|
STRING { $$ = uniqstr_new (quotearg_style (c_quoting_style, $1)); }
|
||||||
|
| ID { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
prec_rel_comparator:
|
||||||
|
">" { $$ = prec_superior; }
|
||||||
|
| "=" { $$ = prec_equal; }
|
||||||
|
| ">" ">" { $$ = prec_superior_strict; }
|
||||||
|
;
|
||||||
|
|
||||||
/* Just like symbols.1 but accept INT for the sake of POSIX. */
|
/* Just like symbols.1 but accept INT for the sake of POSIX. */
|
||||||
symbols.prec:
|
symbols.prec:
|
||||||
symbol.prec
|
symbol.prec
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ eqopt ([[:space:]]*=)?
|
|||||||
"%parse-param" RETURN_PERCENT_PARAM(parse);
|
"%parse-param" RETURN_PERCENT_PARAM(parse);
|
||||||
"%prec" return PERCENT_PREC;
|
"%prec" return PERCENT_PREC;
|
||||||
"%precedence" return PERCENT_PRECEDENCE;
|
"%precedence" return PERCENT_PRECEDENCE;
|
||||||
|
"%precr" return PERCENT_PRECR;
|
||||||
"%printer" return PERCENT_PRINTER;
|
"%printer" return PERCENT_PRINTER;
|
||||||
"%pure-parser" RETURN_PERCENT_FLAG("api.pure");
|
"%pure-parser" RETURN_PERCENT_FLAG("api.pure");
|
||||||
"%require" return PERCENT_REQUIRE;
|
"%require" return PERCENT_REQUIRE;
|
||||||
@@ -278,6 +279,7 @@ eqopt ([[:space:]]*=)?
|
|||||||
"|" return PIPE;
|
"|" return PIPE;
|
||||||
";" return SEMICOLON;
|
";" return SEMICOLON;
|
||||||
"}" return RBRACE;
|
"}" return RBRACE;
|
||||||
|
">" return GT;
|
||||||
|
|
||||||
{id} {
|
{id} {
|
||||||
val->uniqstr = uniqstr_new (yytext);
|
val->uniqstr = uniqstr_new (yytext);
|
||||||
|
|||||||
64
src/symtab.c
64
src/symtab.c
@@ -240,6 +240,55 @@ add_prec_equal_link (prec_node *s1, prec_node *s2, bool transitive,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The function to use to register \a c type relations. */
|
||||||
|
typedef void (*add_link_t) (prec_node *, prec_node *, bool, location);
|
||||||
|
static add_link_t
|
||||||
|
add_link_function (prec_rel_comparator c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case prec_superior_strict:
|
||||||
|
case prec_superior:
|
||||||
|
return &add_prec_link;
|
||||||
|
case prec_equal:
|
||||||
|
return &add_prec_equal_link;
|
||||||
|
}
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------.
|
||||||
|
| Handle the precedence declaration between the elements of S1 and S2. |
|
||||||
|
`---------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void
|
||||||
|
declare_precedence_relation (symbol_list *s1, symbol_list *s2,
|
||||||
|
prec_rel_comparator c, location loc)
|
||||||
|
{
|
||||||
|
void (*functionPtr) (prec_node *, prec_node *, bool, location)
|
||||||
|
= add_link_function (c);
|
||||||
|
bool transitive = c != prec_superior_strict;
|
||||||
|
for (symbol_list *l1 = s1; l1; l1 = l1->next)
|
||||||
|
for (symbol_list *l2 = s2; l2; l2 = l2->next)
|
||||||
|
(*functionPtr)(l1->content.sym->content->prec_node,
|
||||||
|
l2->content.sym->content->prec_node, transitive, loc);
|
||||||
|
symbol_list_free (s1);
|
||||||
|
symbol_list_free (s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------.
|
||||||
|
| Get the list of symbols contained in a group. |
|
||||||
|
`----------------------------------------------*/
|
||||||
|
|
||||||
|
symbol_list *
|
||||||
|
expand_symbol_group (symgroup *group, location loc)
|
||||||
|
{
|
||||||
|
symbol_list *l = NULL;
|
||||||
|
for (sym_content *s = group->symbol_list; s; s = s->group_next)
|
||||||
|
l = symbol_list_append (l, symbol_list_sym_new (s->symbol, loc));
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------.
|
/*------------------------------------------------------------------------.
|
||||||
| Add a symbol to the current declaration group, and declare the implicit |
|
| Add a symbol to the current declaration group, and declare the implicit |
|
||||||
| precedence links. SAME_LINE is true if the symbol was declared in the |
|
| precedence links. SAME_LINE is true if the symbol was declared in the |
|
||||||
@@ -358,6 +407,7 @@ symbol_new (uniqstr tag, location loc)
|
|||||||
|
|
||||||
res->tag = tag;
|
res->tag = tag;
|
||||||
res->location = loc;
|
res->location = loc;
|
||||||
|
|
||||||
res->alias = NULL;
|
res->alias = NULL;
|
||||||
res->content = sym_content_new (res);
|
res->content = sym_content_new (res);
|
||||||
res->is_alias = false;
|
res->is_alias = false;
|
||||||
@@ -1503,6 +1553,20 @@ symgroup_new (const uniqstr tag, location loc)
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------.
|
||||||
|
| Check if there is a group by that name. |
|
||||||
|
`----------------------------------------*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_prec_group (const uniqstr key)
|
||||||
|
{
|
||||||
|
symgroup probe;
|
||||||
|
symgroup *entry;
|
||||||
|
probe.tag = key;
|
||||||
|
entry = hash_lookup (group_table, &probe);
|
||||||
|
return entry != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------.
|
/*--------------------------------------------------------------------------.
|
||||||
| Get the symbol precedence group by that name. If not present, a new group |
|
| Get the symbol precedence group by that name. If not present, a new group |
|
||||||
| is created and inserted in the table, with the location information |
|
| is created and inserted in the table, with the location information |
|
||||||
|
|||||||
15
src/symtab.h
15
src/symtab.h
@@ -330,6 +330,11 @@ void set_current_group (const uniqstr name, location *loc);
|
|||||||
symgroup *
|
symgroup *
|
||||||
symgroup_from_uniqstr (const uniqstr key, location *loc);
|
symgroup_from_uniqstr (const uniqstr key, location *loc);
|
||||||
|
|
||||||
|
/** Check if there is a symbol precedence group by that name. */
|
||||||
|
bool
|
||||||
|
is_prec_group (const uniqstr key);
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------.
|
/*----------------------------------.
|
||||||
| Graph of precedence relationships |
|
| Graph of precedence relationships |
|
||||||
`----------------------------------*/
|
`----------------------------------*/
|
||||||
@@ -361,6 +366,16 @@ enum prec_rel_comparator
|
|||||||
prec_superior,
|
prec_superior,
|
||||||
prec_superior_strict,
|
prec_superior_strict,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Declare a precedence relationship between the symbols of the two lists,
|
||||||
|
* as defined by the operator. */
|
||||||
|
void
|
||||||
|
declare_precedence_relation (symbol_list *l1, symbol_list *l2,
|
||||||
|
prec_rel_comparator c, location loc);
|
||||||
|
/** Return the list of symbols contained in the group. */
|
||||||
|
symbol_list *
|
||||||
|
expand_symbol_group (symgroup * group, location loc);
|
||||||
|
|
||||||
/** Check if s1 and s2 have the same precedence level. */
|
/** Check if s1 and s2 have the same precedence level. */
|
||||||
bool is_prec_equal (prec_node * s1, prec_node * s2);
|
bool is_prec_equal (prec_node * s1, prec_node * s2);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user