CC_Lab3

Exercise 1

1. project.l

%option yylineno


%{

#include<stdio.h>

#include"y.tab.h"

#include<math.h>

#include<string.h>

extern char unmatched_token[];

%}


%%

"#include<stdio.h>" {return HEADER;}

"int" {return INT;}

"main" {return MAIN;}

"(" {return LB;}

")" {return RB;}

"{" {return LCB;}

"}" {return RCB;}

[\n\t ]+ {/*new line or space*/}

. {strcpy(unmatched_token,yytext);}

%%



int yywrap(void)

{

return 1;

}


2. project.y

%{

#include<stdio.h>

int yylex(void);

int yyerror(const char *s);

int success = 1;

char unmatched_token[40];

extern char*yytext;

%}


%token SC COMA VAR EQ OP HEADER INT MAIN LB RB LCB RCB

%start prm


%%

prm : HEADER INT MAIN LB RB LCB RCB

%%


int main()

{

yyparse();

if(success)

printf("Parsing Successful\n");

return 0;

}


int yyerror(const char *msg)

{

extern int yylineno;

printf("Parsing Failed\nLine Number: %d %s unmatched token %s\n",yylineno,msg,unmatched_token);

success = 0;

return 0;

}


Execution Steps:-

  1. lex project.l

  2. yacc -dv project.y

  3. cc -c lex.yy.c

  4. cc -c y.tab.c

  5. cc lex.yy.o y.tab.o -ll -o mini

  6. mini <input1.c

input1.c

#include<stdio.h>

int main()

{


}

input2.c

#include<stdio.h>int main()

{}

input3.c

#include<stdio.h>

int mine()

{

}

input4.c

#include<stdio.h>

int mine[]

(

}


Exercise 2

project.l

%option yylineno


%{

#include<stdio.h>

#include"y.tab.h"

#include<math.h>

extern int yyerror(const char *msg);


%}


%%

"#include<stdio.h>" {return HEADER;}

"int" {return INT;}

"main" {return MAIN;}

"(" {return LB;}

")" {return RB;}

"{" {return LCB;}

"}" {return RCB;}

"," {return COMA;}

";" {return SC;}

[a-z]+ {return VAR;}

[\n\t ]+ {/*new line or space characters*/}

. {printf("unexpected character sequence %s",yytext); exit(0);}

%%


int yywrap(void)

{

return 1;

}


project.y

%{

#include<stdio.h>

int yylex(void);

int yyerror(const char *s);

int success = 1;

%}


%token HEADER INT MAIN LB RB LCB RCB SC COMA VAR EQ OP

%start prm


%%

prm : HEADER INT MAIN LB RB LCB BODY RCB {printf("Parsing successful..");}

BODY : DECLARATION_STATEMENTS

DECLARATION_STATEMENTS : DECLARATION_STATEMENT DECLARATION_STATEMENTS

| DECLARATION_STATEMENT

DECLARATION_STATEMENT:INT VAR_LIST SC {}

VAR_LIST : VAR COMA VAR_LIST {/*This grammar confirms whether the variable names are seperated by commas or not*/}

| VAR

%%


int main()

{

yyparse();

/* if(success)

printf("Parsing Successful\n"); */

return 0;

}


int yyerror(const char *msg)

{

extern int yylineno;

printf("Parsing Failed\nLine Number: %d %s\n",yylineno,msg);

success = 0;

return 0;

}

input1.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

}


input2.c

#include<stdio.h>

int main()

{

int var1,var2,var3;

}


input3.c

#include<stdio.h>

int main()

{

int var,varone,two;

int teeone,teetwo,;

}


Execution Steps:-

  1. lex project.l

  2. yacc -dv project.y

  3. cc -c lex.yy.c

  4. cc -c y.tab.c

  5. cc lex.yy.o y.tab.o -ll -o

  6. mini <input1.c

  7. mini<input2.c

  8. mini<input3.c


Exercise 3

project.l

%option yylineno


%{

#include<stdio.h>

#include"y.tab.h"

#include<math.h>

%}


%%

"#include<stdio.h>" {return HEADER;}

"int" {return INT;}

"main" {return MAIN;}

"(" {return LB;}

")" {return RB;}

"{" {return LCB;}

"}" {return RCB;}

"," {return COMA;}

";" {return SC;}

[\+\-\*\/] {return OP;}

"=" {return EQ;}

[a-z]+ {return VAR;}

[\n\t ]+ {/*new line or space*/}

. {printf("invalid character sequence %s\n",yytext); exit(0);}

%%



int yywrap(void)

{

return 1;

}


project.y

%{

#include<stdio.h>

int yylex(void);

int yyerror(const char *s);

int success = 1;

%}


%token HEADER INT MAIN LB RB LCB RCB SC COMA VAR EQ OP

%start prm


%%

prm : HEADER INT MAIN LB RB LCB BODY RCB {printf("\n parsing successful\n");}

BODY : DECLARATION_STATEMENTS PROGRAM_STATEMENTS

DECLARATION_STATEMENTS : DECLARATION_STATEMENT DECLARATION_STATEMENTS {printf("\n Declaration section successfully parsed\n");}

| DECLARATION_STATEMENT

PROGRAM_STATEMENTS : PROGRAM_STATEMENT PROGRAM_STATEMENTS {printf("\n program statements successfully parsed\n");}

| PROGRAM_STATEMENT

DECLARATION_STATEMENT:INT VAR_LIST SC

VAR_LIST : VAR COMA VAR_LIST {printf("\n variable list successfully parsed\n");}

| VAR {}

PROGRAM_STATEMENT : VAR EQ A_EXPN SC

A_EXPN : A_EXPN OP A_EXPN

| LB A_EXPN RB

| VAR

%%


int main()

{

yyparse();

/* if(success)

printf("Parsing Successful\n");*/

return 0;

}


int yyerror(const char *msg)

{

extern int yylineno;

printf("Parsing Failed\nLine Number: %d %s\n",yylineno,msg);

success = 0;

return 0;

}



input1.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

int testone, testtwo;

testone=(vartwo+varthree/(varone*vartwo);

testtwo=testone*varone+vartwo;

}


input2.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

int testone, testtwo;

testone=(vartwo++varthree/(varone*vartwo);

testtwo=testone*varone+vartwo;

}


input3.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

int testone, testtwo;

testone=(vartwo+varthree/(varone*vartwo);

testtwo=testone*varone+vartwo

}

Execution Steps:-

  1. lex project.l

  2. yacc -dv project.y

  3. cc -c lex.yy.c

  4. cc -c y.tab.c

  5. cc lex.yy.o y.tab.o -ll -o mini

  6. mini <input1.c

Problem

project.l

%option yylineno


%{

#include<stdio.h>

#include<string.h>

#include"y.tab.h"

#include<math.h>

extern int var_count;


%}


%%

"#include<stdio.h>" {return HEADER;}

"if" {printf("usage of keyword \"%s\" is prohibited\n",yytext);exit(0);}

"int" {yylval.data_type=0;return INT;}

"char" {yylval.data_type=1; return CHAR;}

"main" {return MAIN;}

"(" {return LB;}

")" {return RB;}

"{" {return LCB;}

"}" {return RCB;}

"," {return COMA;}

";" {return SC;}

[\+\-\*\/] {return OP;}

"=" {return EQ;}

[a-z]+ {strcpy(yylval.var_name,yytext);return VAR;}

[\n\t ]+ {/*new line or space*/}

. {printf("invalid character sequence %s\n",yytext); exit(0);}

%%



int yywrap(void)

{

return 1;

}


project.y

%{

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

int yylex(void);

int yyerror(const char *s);

int success = 1;

int current_data_type;

int expn_type=-1;

int temp;

struct symbol_table{char var_name[30]; int type;}var_list[20];

int var_count=-1;

extern int lookup_in_table(char var[30]);

extern void insert_to_table(char var[30], int type);

%}


%union{

int data_type;

char var_name[30];

}

%token HEADER MAIN LB RB LCB RCB SC COMA VAR EQ OP


%token<data_type>INT

%token<data_type>CHAR

%token<data_type>FLOAT

%token<data_type>DOUBLE


%type<data_type>DATA_TYPE

%type<var_name>VAR

%start prm


%%

prm : HEADER MAIN_TYPE MAIN LB RB LCB BODY RCB {

printf("\n parsing successful\n");

}

BODY : DECLARATION_STATEMENTS PROGRAM_STATEMENTS

DECLARATION_STATEMENTS : DECLARATION_STATEMENT DECLARATION_STATEMENTS

{

printf("\n Declaration section successfully parsed\n");

}

| DECLARATION_STATEMENT

PROGRAM_STATEMENTS : PROGRAM_STATEMENT PROGRAM_STATEMENTS

{

printf("\n program statements successfully parsed\n");

}

| PROGRAM_STATEMENT

DECLARATION_STATEMENT: DATA_TYPE VAR_LIST SC {}

VAR_LIST : VAR COMA VAR_LIST {

insert_to_table($1,current_data_type);

}

| VAR {

insert_to_table($1,current_data_type);

}

PROGRAM_STATEMENT : VAR EQ A_EXPN SC { expn_type=-1; }

A_EXPN : A_EXPN OP A_EXPN

| LB A_EXPN RB

| VAR {

if((temp=lookup_in_table($1))!=-1)

{

if(expn_type==-1)

{

expn_type=temp;

}else if(expn_type!=temp)

{

printf("\ntype mismatch in the expression\n");

exit(0);

}

}else

{

printf("\n variable \"%s\" undeclared\n",$1);exit(0);

}

}

MAIN_TYPE : INT

DATA_TYPE : INT {

$$=$1;

current_data_type=$1;

}

| CHAR {

$$=$1;

current_data_type=$1;

}

| FLOAT

| DOUBLE

%%


int lookup_in_table(char var[30])

{

return -1;

}

void insert_to_table(char var[30], int type)

{

}



int main()

{

yyparse();

/* if(success)

printf("Parsing Successful\n");*/

return 0;

}


int yyerror(const char *msg)

{

extern int yylineno;

printf("Parsing Failed\nLine Number: %d %s\n",yylineno,msg);

success = 0;

return 0;

}



input1.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

char testone, testtwo,testthree;

testone=testtwo+testthree/(testone*testtwo);

vartwo=varone*varone+varthree;

}


input2.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

char testone, testtwo,testthree,vartwo;

testone=testtwo+testthree/(testone*testtwo);

vartwo=varone*varone+varfive;

}


input3.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

char testone, testtwo,testthree;

testone=vartwo+testthree/(testone*testtwo);

vartwo=varone*varone+varfive;

}


input4.c

#include<stdio.h>

int main()

{

int varone,vartwo,varthree;

char testone, testtwo,testthree;

testone=testtwo+testthree/(testone*testtwo);

vartwo=varone*varfour+varfive;

}

Designing a Lexical Analyser for a mini-compiler

You are given 3 mini-compilers (in 3 different folders) each with a set of 3-4 sample input C

files. Compile the input files using each of those given corresponding mini-compilers, note the

outputs in your lab journal with proper reasoning. Run the following sequence of commands in

order to run the programs.

1. Run ls command to begin with. You should see two files project.l (lex file) and project.y

(yacc file) along with the input files.

2. Run flex project.l. This should generate the C program for the lexical analyser lex.yy.c

(run ls command and verify whether the file being generated or not).

3. Run yacc −dv project.y. This should generate the C program for the syntax analyser y.tab.c

along with supplementary files y.tab.h and y.output(run ls command and verify whether the

files being generated or not).

4. Run gcc −o mini-compiler lex.yy.c y.tab.c −lfl to generate the executable.

5. Feed in the C file to your mini-compiler by running ./mini-compiler < input.c.

Read through the programs project.l and project.y and justify your output with concise proper

reasoning.

1.1 Modify your lex program to incorporate the following changes

In this part, you are supposed to modify the third exercise to incorporate the following changes.

1. As per the current set up, the programmer is supposed to use only those lower case alphabets

in variable names in their C program. Modify your lex program so as to let the programmer

have uppercase letters A to F together with digits 0 to 9 in variable names.

2. Add provision to declare variables of type float, double and char.

3. Terminate your program with an error message if in case the programmer uses keywords

“if”, “while”, “do”, and “for” as variable names. Note that its permitted to have variable

names beginning with keywords (ifvar, donut etc.) (hint: rely on conflict resolution rules).

1.2 Type checking in program statements

In this problem, you are supposed to incorporate two functions insert to table() and lookup in table()

to your yacc program (prototype of the functions and symbol table data structure are given.

You just have to write the body of both functions) so that in each of those program statements,

the parser would confirm the following.

1. Whether all variables in an expression are of the same type. If not, would show up a type

mismatch error message (as in file input3.c the error message should be: ‘type mismatch in

the expression’).

2. Is there a variable declared multiple times (show a multiple declaration error message and

terminate) (input2.c, the error message should be: ‘multiple declaration of variable vartwo’).

3. Is there an undeclared variable (show an undeclared error message and exit) (in input4.c

the error message should be: ‘variable “varfour” undeclared’).