nav_jan
nav_jan

Reputation: 2553

Difference between using a predefined token (%token) and using a single charecter in rule of YACC

I have a very big YACC file to debug but the part I am currently focusing on looks like this :

....

%token TOKEN_HASH 123 "#"

...

    RULE1 : TOKEN_XYZ TOKEN_HASH '(' ')' 
             {
              //DO something here
              //some C code
             }

I want to write RULE1 as follows :

RULE1 : TOKEN_XYZ '#' '(' ')' 
         {
          //DO something here
          //some C code
         }

Is this not allowed in yacc? Because I get the following error with second code :

parser.y: conflicts: 1 shift/reduce

parser.y: expected 0 shift/reduce conflicts

Any kind of help/comment is highly appreciated.

Thanks!

Upvotes: 1

Views: 272

Answers (2)

rici
rici

Reputation: 241931

bison does not let you both use a single-quoted terminal ('#') and define a named terminal (like TOKEN_HASH) whose numeric code is the equivalent of the quoted character (in this case, 35). It won't complain if you use '#' and you specify

%token TOKEN_HASH 123 "#"

because 123 is not the same as '#'; rather, it is the value of '{'. However, such a declaration is highly misleading: it tells the reader that a TOKEN_HASH is a hash character, but it is actually an open brace. (Of course, your lexer might return an open brace when it encounters a hash, but that would be even more confusing.)

The double-quoted string in the %token declaration (or the grammar) is only useful for documentation purposes. As such, you should try to make sure that the documentation is accurate. Neither bison nor flex will enforce or even take any notice of what is inside the double quotes, so you will receive no error or warning for a misleading label.

On the whole, you should not mix and match named single-character tokens and quoted single-character tokens, and you should never specify an integer code for a named token, even though bison allows you to. All you are doing in such cases is confusing people who read your code (and quite possibly yourself) and creating maintenance problems.

Now, the shift/reduce conflict will have to do with some other production in the grammar which includes the terminal '#'. Since TOKEN_HASH is a different terminal than '#',, the other production cannot conflict with RULE1 : TOKEN_XYZ TOKEN_HASH '(' ')'. But it certainly can conflict with RULE1 : TOKEN_XYZ '#' '(' ')'.

If you give bison the -v flag, it will produce a file with the extension .output which will provide useful information for tracking down the conflict.

Upvotes: 2

user207421
user207421

Reputation: 311050

You should economize on %token directives and use the actual character literals wherever you can in the grammar. That way you also economize on flex directives: you don't need one per special character, you only need this:

. return yytext[0];

as your last rule.

Upvotes: 0

Related Questions