example program for the lex and yacc programs

Upload: cserajiv8466

Post on 30-Oct-2015

44 views

Category:

Documents


0 download

DESCRIPTION

tr

TRANSCRIPT

Example program for the lex and yacc programs

This section contains example programs for thelexandyacccommands.

Together, these example programs create a simple, desk-calculator program that performs addition, subtraction, multiplication, and division operations. This calculator program also allows you to assign values to variables (each designated by a single, lowercase letter) and then use the variables in calculations. The files that contain the examplelexandyaccprograms are as follows:

FileContent

calc.lexSpecifies thelexcommand specification file that defines the lexical analysis rules.

calc.yaccSpecifies theyacccommand grammar file that defines the parsing rules, and calls theyylexsubroutine created by thelexcommand to provide input.

The following descriptions assume that thecalc.lexandcalc.yaccexample programs are located in your current directory.

Compiling the example programTo create the desk calculator example program, do the following:

1. Process theyaccgrammar file using the-doptional flag (which informs theyacccommand to create a file that defines the tokens used in addition to the C language source code):

yacc -d calc.yacc2. Use thelscommand to verify that the following files were created:

y.tab.c

The C language source file that theyacccommand created for the parser

y.tab.h

A header file containing define statements for the tokens used by the parser

3. Process thelexspecification file:

lex calc.lex4. Use thelscommand to verify that the following file was created:

lex.yy.c

The C language source file that thelexcommand created for the lexical analyzer

5. Compile and link the two C language source files:

cc y.tab.c lex.yy.c6. Use thelscommand to verify that the following files were created:

y.tab.o

The object file for they.tab.csource file

lex.yy.o

The object file for thelex.yy.csource file

a.out

The executable program file

To run the program directly from thea.outfile, type:

$ a.outOR

To move the program to a file with a more descriptive name, as in the following example, and run it, type:

$ mv a.out calculate

$ calculateIn either case, after you start the program, the cursor moves to the line below the$(command prompt). Then, enter numbers and operators as you would on a calculator. When you press the Enter key, the program displays the result of the operation. After you assign a value to a variable, as follows, the cursor moves to the next line.

m=4

_When you use the variable in subsequent calculations, it will have the assigned value:

m+5

9

_Parser source codeThe following example shows the contents of thecalc.yaccfile. This file has entries in all three sections of ayaccgrammar file: declarations, rules, and programs.

%{

#include

int regs[26];

int base;

%}

%start list

%union { int a; }

%type expr number

%token DIGIT LETTER

%left '|'

%left '&'

%left '+' '-'

%left '*' '/' '%'

%left UMINUS /*supplies precedence for unary minus */

%% /* beginning of rules section */

list: /*empty */

|

list stat'\n'

|

list error'\n'

{

yyerrok;

}

;

stat: expr

{

printf("%d\n",$1);

}

|

LETTER '=' expr

{

regs[$1] = $3;

}

;

expr: '(' expr ')'

{

$$ = $2;

}

|

expr '*' expr

{

$$ = $1 * $3;

}

|

expr '/' expr

{

$$ = $1 / $3;

}

|

expr '%' expr

{

$$ = $1 % $3;

}

|

expr '+' expr

{

$$ = $1 + $3;

}

|

expr '-' expr

{

$$ = $1 - $3;

}

|

expr '&' expr

{

$$ = $1 & $3;

}

|

expr '|' expr

{

$$ = $1 | $3;

}

|

'-' expr %prec UMINUS

{

$$ = -$2;

}

|

LETTER

{

$$ = regs[$1];

}

|

number

;

number: DIGIT

{

$$ = $1;

base = ($1==0) ? 8 : 10;

} |

number DIGIT

{

$$ = base * $1 + $2;

}

;

%%

main()

{

return(yyparse());

}

yyerror(s)

char *s;

{

fprintf(stderr,"%s\n",s);

}

yywrap()

{

return(1);

}The file contains the following sections:

Declarations section.This section contains entries that:

Include standard I/O header file

Define global variables

Define thelistrule as the place to start processing

Define the tokens used by the parser

Define the operators and their precedence

Rules section.The rules section defines the rules that parse the input stream.

%start- Specifies that the whole input should matchstat.

%union- By default, the values returned by actions and the lexical analyzer are integers.yacccan also support values of other types, including structures. In addition,yacckeeps track of the types, and inserts appropriate union member names so that the resulting parser will be strictly type checked. Theyaccvalue stack is declared to be a union of the various types of values desired. The user declares the union, and associates union member names to each token and nonterminal symbol having a value. When the value is referenced through a $$ or $n construction,yaccwill automatically insert the appropriate union name, so that no unwanted conversions will take place.

%type- Makes use of the members of the%uniondeclaration and gives an individual type for the values associated with each part of the grammar.

%toksn- Lists the tokens which come from lex tool with their type.

Programs section.The programs section contains the following subroutines. Because these subroutines are included in this file, you do not need to use theyacclibrary when processing this file.

SubroutineDescription

mainThe required main program that calls theyyparsesubroutine to start the program.

yyerror(s)This error-handling subroutine only prints a syntax error message.

yywrapThe wrap-up subroutine that returns a value of 1 when the end of input occurs.

Lexical analyzer source codeThis file contains include statements for standard input and output, as well as for they.tab.hfile. If you use the-dflag with theyacccommand, theyaccprogram generates that file from theyaccgrammar file information. They.tab.hfile contains definitions for the tokens that the parser program uses. In addition, thecalc.lexfile contains the rules to generate these tokens from the input stream. The following are the contents of thecalc.lexfile.

%{

#include

#include "y.tab.h"

int c;

extern int yylval;

%}

%%

" " ;

[a-z] {

c = yytext[0];

yylval = c - 'a';

return(LETTER);

}

[0-9] {

c = yytext[0];

yylval = c - '0';

return(DIGIT);

}

[^a-z0-9\b] {

c = yytext[0];

return(c);

}Lexical Analyzer Source Code

Following are the contents of thecalc.lexfile. This file contains include statements for standard input and output, as well as for they.tab.hfile. Theyaccprogram generates that file from theyaccgrammar file information if you use the-dflag with theyacccommand. They.tab.hfile contains definitions for the tokens that the parser program uses. In addition,calc.lexcontains the rules to generate these tokens from the input stream.

%{

#include

#include "y.tab.h"

int c;

extern int yylval;

%}

%%

" " ;

[a-z] {

c = yytext[0];

yylval = c - 'a';

return(LETTER);

}

[0-9] {

c = yytext[0];

yylval = c - '0';

return(DIGIT);

}

[^a-z0-9\b] {

c = yytext[0];

return(c);

}

Parser Source Code

The following example shows the contents of thecalc.yaccfile. This file has entries in all three sections of ayaccgrammar file: declarations, rules, and programs.

%{

#include

int regs[26];

int base;

%}

%start list

%token DIGIT LETTER

%left '|'

%left '&'

%left '+' '-'

%left '*' '/' '%'

%left UMINUS /*supplies precedence for unary minus */

%% /* beginning of rules section */

list: /*empty */

|

list stat'\n'

|

list error'\n'

{

yyerrok;

}

;

stat: expr

{

printf("%d\n",$1);

}

|

LETTER '=' expr

{

regs[$1] = $3;

}

;

expr: '(' expr ')'

{

$$ = $2;

}

|

expr '*' expr

{

$$ = $1 * $3;

}

|

expr '/' expr

{

$$ = $1 / $3;

}

|

expr '%' expr

{

$$ = $1 % $3;

}

|

expr '+' expr

{

$$ = $1 + $3;

}

|

expr '-' expr

{

$$ = $1 - $3;

}

|

expr '&' expr

{

$$ = $1 & $3;

}

|

expr '|' expr

{

$$ = $1 | $3;

}

|

'-' expr %prec UMINUS

{

$$ = -$2;

}

|

LETTER

{

$$ = regs[$1];

}

|

number

;

number: DIGIT

{

$$ = $1;

base = ($1==0) ? 8:10;

} |

number DIGIT

{

$$ = base * $1 + $2;

}

;

%%

main()

{

return(yyparse());

}

yyerror(s)

char *s;

{

fprintf(stderr,"%s\n",s);

}

yywrap()

{

return(1);

}

Declarations Section

This section contains entries that:

Include standard I/O header file.

Define global variables.

Define thelistrule as the place to start processing.

Define the tokens used by the parser.

Define the operators and their precedence.

Rules SectionThe rules section defines the rules that parse the input stream.

Programs SectionThe programs section contains the following subroutines. Because these subroutines are included in this file, you do not need to use theyacclibrary when processing this file.

mainThe required main program that calls theyyparsesubroutine to start the program.

yyerror(s)This error-handling subroutine only prints a syntax error message.

yywrapThe wrap-up subroutine that returns a value of 1 when the end of input occurs.

Lexical Analyzer Source Code

Following are the contents of thecalc.lexfile. This file contains include statements for standard input and output, as well as for they.tab.hfile. Theyaccprogram generates that file from theyaccgrammar file information if you use the-dflag with theyacccommand. They.tab.hfile contains definitions for the tokens that the parser program uses. In addition,calc.lexcontains the rules to generate these tokens from the input stream.

%{

#include

#include "y.tab.h"

int c;

extern int yylval;

%}

%%

" " ;

[a-z] {

c = yytext[0];

yylval = c - 'a';

return(LETTER);

}

[0-9] {

c = yytext[0];

yylval = c - '0';

return(DIGIT);

}

[^a-z0-9\b] {

c = yytext[0];

return(c);

}

Compiling the Example Program

Perform the following steps, in order, to create the desk calculator example program:

1. Process theyaccgrammar file using the-doptional flag (which tells theyacccommand to create a file that defines the tokens used in addition to the C language source code):

yacc -d calc.yacc

2. Use thelicommand to verify that the following files were created:

y.tab.cThe C language source file that theyacccommand created for the parser.

y.tab.hA header file containing define statements for the tokens used by the parser.

3. Process thelexspecification file:

lex calc.lex

4. Use thelicommand to verify that the following file was created:

lex.yy.cThe C language source file that thelexcommand created for the lexical analyzer.

5. Compile and link the two C language source files:

cc y.tab.c lex.yy.c

6. Use thelicommand to verify that the following files were created:

y.tab.oThe object file for they.tab.csource file

lex.yy.oThe object file for thelex.yy.csource file

a.outThe executable program file

7. To then run the program directly from thea.outfile, enter:

8. $ a.out

9. Or, to move the program to a file with a more descriptive name, as in the following example, and run it, enter:

10. $ mv a.out calculate

11. $ calculate

12. In either case, after you start the program, the cursor moves to the line below the$(command prompt). Then enter numbers and operators in calculator fashion. When you press the Enter key, the program displays the result of the operation. After you assign a value to a variable:

13. m=4

14. _

15. the cursor moves to the next line. When you use the variable in subsequent calculations, it will have the assigned value:

16. m+5

17. 9

18. _