• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 376
  • Last Modified:

C program with YACC and LEX.

Platform: Digital Unix
Compiler: cc

How can I write a program with this three files?
1.- myProgram.c: Contains the source code and the parser call: yyparse()

2.- myProgram.y: Contains the parser rules in YACC. Use the third module.

3.- myProgram.l: This is the lexer for the parser.

How do I write the include's in each file?

How do I compile this programs?

What makefile must I write?
0
carlos0007
Asked:
carlos0007
  • 5
  • 5
  • 2
1 Solution
 
curriCommented:
You may want to take a look at this free notes
http://members.xoom.com/thomasn/y_man.htm 
(or go to your library and get a good book on that, like using lex & yacc from o'reilly, or get the manuals from your system; there are good manuals for GNU flex & bison).

Now, the simple answer to your question (not that it would be useful if you don't know HOW to make the files :):

you type
   yacc myprogram.y
this would produce 2 files, y.tab.c and y.tab.h
    lex myprogram.l
this would produce a  file, lex.yy.c

In your program, you may want to #include y.tab.h (I'm not sure about this); And you may need to put declarations for yyparse and yylex.

Your final compilation would be something like:
cc myprogram.c y.tab.c lex.yy.c

Of course, you may want to put all of this into a makefile. (and then you need to know about makefiles)

The way I always go about that (I've used flex/bison several times, but don't use them often, so I always forget :) is to download an example (see the URL above) and modify the makefile :).


Orlando


What
 

0
 
carlos0007Author Commented:
Dear Curri:

Thank you for your comments.

I have already worked with yacc and lex and I know basically the way it works.

I would like to get as is follows:
I would like to have a module .c in which I could include mine main program and the call to the parser through the function yyparse().
In another module with extension .y I will write the gramatic rules to analyze.
The third module I will have the lexer that will give you back the tokens to the parser.

I DONT'T WANT writing all my code into the .y module but to have the three modules separated.

I DON'T WANT EITHER including the principal part of my code in the .y file.

I want to have clearlly divided these three parts:
1.- The C program.
2.- The Parser.
3.- The Lexer.

Can I do that?

Thanks a lot.

Carlos Urtasun
0
 
curriCommented:
Sure you can !! That is what I tried to explain.

You have a .l file, and when you pass it trough lex, you get a .c file.

You have a .y file, and when you pass it trough yacc, you get a .h file and a .c file.

You make your own .c file. there you include the .h file that yacc generated.

You compile all three programs, and link them all together.

You have three separate files (in fact 7 :)

Orlando
0
Easily manage email signatures in Office 365

Managing email signatures in Office 365 can be a challenging task if you don't have the right tool. CodeTwo Email Signatures for Office 365 will help you implement a unified email signature look, no matter what email client is used by users. Test it for free!

 
GleasonGuyCommented:
With the files you mentioned, you would do the following (depending on your versions of lex & yacc)

yacc -l -o myGrammar.c -D tokens.h myProgram.y
lex -a -l -o myScanner.c myProgram.l
cc myProgram.c
link myProgram myScanner myGrammar

Where main.c includes:

int
main(int argc, char *argv[])
{
    HandleCommandlineArgs(argc, argv);

    yyout = stderr;
    if( (yyin = fopen("inputfile", "r")) == NULL) {
        return 1;
    }

    InitHelperFunctions();

    return yyparse();
}
0
 
carlos0007Author Commented:
Remembering:
Platform: Digital Unix
Compiler: cc

Dear Curri:
I've done "lex lexer.l" and I get: lex.yy.c

I've done "yacc parser.y" and I get: y.tab.c
But I don't get a .h file!

Dear Guy:
My lex and yacc are standards.
The yacc flags -o -D don't exists.
The lex flags -a -l -o either.

man yacc returns the flags:
-b -d -l -N -p -P -s -t -v

man lex returns the flags:
-c -n -r -t -v -V -Q
0
 
GleasonGuyCommented:
Sorry about those flags. I was trained in the Unix world, but now work in the "other" world. Thos flags that I used were for MKS lex & yacc. They are defined as follows:
-a = allows 8-bit ASCII (don't need)
-l = disables #line directives (don't need)
-o filename = specifies output filename (don't need)
-D filename = same as -d except that filename is specified (don't need). Tokens should default to y.tab.h

So with that out of the way you would get:
yacc -d myProgram.y
lex myProgram.l
cc myProgram.c
cc lex.yy.c
cc y.tab.c
link myProgram lex.yy y.tab
0
 
carlos0007Author Commented:
Dear Guy:
I've done "yacc -d parser.y" and I get: y.tab.c
and
y.tab.h

I've done "lex -d lexer.l" and I get: lex.yy.c

I've done "cc myProgram.c" and I get:
ld:
Unresolved:
yyparse

Why?
I have in myProgram.c:
#include "y.tab.h"
....
main(int argc, char *argv[])
{
   ...
   yyparse();
   ...
}

Thanks a lot.
0
 
GleasonGuyCommented:
Sorry about that. You need some externs in myProgram.c

extern int yyparse(void);

and probably,

extern FILE *yyin;
extern FILE *yyout;
0
 
carlos0007Author Commented:
I have in myProgram.c now:
#include "y.tab.h"
#include <ctype.h>
#include <stdio.h>
extern int yyparse(void);
extern FILE *yyin;
extern FILE *yyout;

And I get again after "cc myProgram.c":
ld:
Unresolved:
yyparse

In lexer.l I have:
%{
#undef input
#undef unput
int input(void);
void unput();
extern char *params; /*GLOBAL VAR FROM myProgram.c*/
%}

....

%%
....

%%
static int iLex =0;

int input (void)
{
   ...
}

void unput(int ch)
{
   ...
}

In parser.y I have:
%{
#include <ctype.h>
#include <stdio.h>
%}

....

%%

#include "lex.yy.c"

void yyerror(char *s)
{
   ...
}

Thanks a lot.

Carlos Urtasun
0
 
GleasonGuyCommented:
I think another apology is due on my part. It's been a while since I've used a make file (or command line), especially in Unix. Most of my program is done in a GUI, so my brain has gotten soft.

cc does both compiling and linking, so try just the following...

yacc -d myProgram.y
lex myProgram.l
cc myProgram.c lex.yy.c y.tab.c

Barring any more brain malfunctions on my end, that will do it.

0
 
carlos0007Author Commented:
I have in myProgram.c now:
#include "y.tab.h"
#include <ctype.h>
#include <stdio.h>
extern int yyparse(void);
extern FILE *yyin;
extern FILE *yyout;
....

In lexer.l I have:
%{
#include "y.tab.h"
#undef input
#undef unput
int input(void);
void unput();
void yyerror(char *s);
extern char *params; /*GLOBAL VAR FROM myProgram.c*/
%}
....

%%
....

%%
static int iLex =0;

int input (void)
{
   ...
}

void unput(int ch)
{
   ...
}

void yyerror(char *s)
{
        printf("ERROR: %s String: '%s'\n",s,yytext);
}

In parser.y I have:
%{
#include <ctype.h>
#include <stdio.h>
%}

....

%%

I've done:
yacc -d myProgram.y
lex myProgram.l
cc myProgram.c lex.yy.c y.tab.c

and I get:
myProgram.c:
lex.yy.c:
y.tab.c:
ld:
Unresolved:
yywrap

Why?

Thanks a lot.

Carlos Urtasun
0
 
GleasonGuyCommented:
Whenever you get an "Unresolved" error, it means that there is a function or variable that the linker cannot find.

In your case, the linker can't find yywrap. I think you need to add
extern int yywrap();
to your code (I'm pretty sure it goes in the public are of parse.y).

Good luck.
0

Featured Post

Evaluating UTMs? Here's what you need to know!

Evaluating a UTM appliance and vendor can prove to be an overwhelming exercise.  How can you make sure that you're getting the security that your organization needs without breaking the bank? Check out our UTM Buyer's Guide for more information on what you should be looking for!

  • 5
  • 5
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now