[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Weird problem
From: |
Akim Demaille |
Subject: |
Re: Weird problem |
Date: |
Thu, 27 Jun 2013 12:06:00 +0200 |
Le 24 juin 2013 à 20:56, Valentin Tolmer <address@hidden> a écrit :
> Hello everyone,
Hi!
> I'm working on an addition to bison, and I have a small grammar problem...
> I added something to the bison grammar, to understand statements such as
> %prec OR '+' > '*' (for example)
>
> However when parsing a statement with several tokens as char, I have a
> problem. The example I'm currently testing with is this:
>
> %prec '^' > OR '*' '/' '-' '+'
>
> which is read to me, for some reason, as
> %prec '+' > OR '+' '+' '+' '+'
This kind of symptom is probably the sign that you are keeping
a pointer to a semantic value, instead of keeping the semantic
value itself (which might require allocation, depending on its
type). Be sure to read
http://www.gnu.org/software/bison/manual/bison.html#Strings-are-Destroyed
> What I mean is that every char is correctly read, the symbols are the right
> ones, but somehow when creating the list, it screws up and replaces every
> char with the last one read (not just +, the last one read). I test the lists
> at the beginning of declare_precedence_relation, so none of my outside code
> affects it.
>
> Here's the code, in parse-gram.y (the printf displays the right characters):
>
>
> precedence_relation_declaration:
> "%prec" precedence_relation_symbols precedence_relation_comparator
> precedence_relation_symbols
> { declare_precedence_relation ($2, $4, $3); }
> ;
>
> 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); //not
> called in this example
> else
> $$ = symbol_list_sym_new (symbol_from_uniqstr ($1, @1), @1);
> }
> | CHAR
> {
> printf ("char seen : %s\n", symbol_from_uniqstr(char_name ($1), @1)->tag);
char is working on a private buffer:
static char const *
char_name (char c)
{
if (c == '\'')
return "'\\''";
else
{
char buf[4];
buf[0] = '\''; buf[1] = c; buf[2] = '\''; buf[3] = '\0';
return quotearg_style (escape_quoting_style, buf);
}
}
which results obviously in always the same address. You are calling
symbol_from_uniqstr on something which is _not_ a uniqstr. uniqstr
is the same type as char*, however, these strings are "internalized",
i.e., a single copy of them is kept, which allows us to compare/hash
strings by working on addresses instead of the characters. So here,
since everything works on *addresses* and you have only one, of course
latter symbol override former ones.
Admittedly you should add a "uniqstr_assert" in symbol_from_uniqstr.
Once it properly blows at your face, fix your code and use
uniqstr_new from your char_name.
> $$ = symbol_list_sym_new (symbol_from_uniqstr (char_name ($1), @1), @1);
> }
> ;
>
> string_or_id:
> STRING { $$ = uniqstr_new (quotearg_style (c_quoting_style, $1)); } //not
> called, I believe, in that example
> | ID { $$ = $1; }
> ;
>
> precedence_relation_comparator:
> ">" { $$ = prec_superior; }
> | "=" { $$ = prec_equal; }
> | ">" ">" { $$ = prec_superior_strict; }
> ;
>
> _______________________________________________
> address@hidden https://lists.gnu.org/mailman/listinfo/help-bison