0
votes

So I'm writing a bison (without lex) parser and now I want to read the input code from file and to write the output to another file.

Searching the stackoverflow for some time I found that this way should be good. bison.y:

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    extern FILE *yyin;

    int yylex() { return getc(stdin); }
    void yyerror(char *s) {
      fprintf (stderr, "%s\n", s);
    }
    int counter = 1;
    char filename2[10] = "dest.ll";
    FILE *f2;
%}
%name parse

%%

//grammars

%%

int main(int argc, char *argv[]) {
    yyin = fopen(argv[1], "r");
    if (argc > 2)
      f2 = fopen(argv[2], "w");
    else
      f2 = fopen(filename2, "w");
    yyparse();

    return 0;
} 

Then i compile it this way:

bison bison.y
cc -ly bison.tab.c

And here the result of cc-compilation:

/tmp/ccNqiuhW.o: In function `main':
bison.tab.c:(.text+0x960): multiple definition of `main'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/liby.a(main.o):(.text.startup+0x0): first defined here
/tmp/ccNqiuhW.o: In function `main':
bison.tab.c:(.text+0x98c): undefined reference to `yyin'
collect2: error: ld returned 1 exit status

The output bison.tab.c file have only 1 main. Ofc int/void main doesn't matter. Can you teach me how to do it correctly?

P.S. By the way, I don't want to spam different posts, and have a little question here. How can I store the string (char *) in $$ in bison? For example, I want to generate a code string after I met the int grammar. I have this error and can't find the answer:

bison.y:94:8: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
 INTNUM: NUMBER | DIGIT INTNUM {$$ = "string"};

bison.y: In function ‘yyparse’:
bison.y:28:15: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
 PROGRAM: EXPRS { fprintf(f2, "%s: string here %d.\n", $$, counter++) };

will be extremely good if I find the help.

1
The order in which you add libraries with the -l option is relevant. Move the -ly option last after the source file, so you build like cc bison.tab.c -ly.Some programmer dude
So library liby contains a default main to be used when no main is provided by the user. That means main must be found first so no main will be extracted from the library.Paul Ogilvie

1 Answers

2
votes

You are linking library liby (linker option -ly). The Bison manual has this to say about it:

The Yacc library contains default implementations of the yyerror and main functions.

So that's why you have multiple definitions of main. You provide one, and there's one in liby.

Moreover, the docs go on to say that

These default implementations are normally not useful, but POSIX requires them.

(Emphasis added)

You do not need to link liby in order to build a program that includes a bison-generated parser, and normally you should not do so. Instead, provide your own main() and your own yyerror(), both of which you've already done.

Additionally, you are expected to provide a definition of yyin, not just a declaration, whether you link liby or not. To do so, remove the extern keyword from the declaration of yyin in your grammar file.

Your grammar is not complete (there are no rules at all) and the %name directive is not documented and is not recognized by my Bison, but if I add a dummy rule and comment out the %name, in conjunction with the other changes discussed, then bison generates a C source file for me that can be successfully compiled to an executable (without liby).