You are on page 1of 18

Ex No:1 IMPLEMENTATION OF SYMBOL TABLE USING C

AIM:
To write a program for implementing Symbol Table using C.

ALGORITHM:

Step1: Start the program for performing insert, display, delete, search and modify option in symbol
table
Step2: Define the structure of the Symbol Table
Step3: Enter the choice for performing the operations in the symbol Table
Step4: If the entered choice is 1, search the symbol table for the symbol to be inserted. If the symbol
is
already present, it displays “Duplicate Symbol”. Else, insert the symbol and the corresponding
address in
the symbol table.
Step5: If the entered choice is 2, the symbols present in the symbol table are displayed.
Step6: If the entered choice is 3, the symbol to be deleted is searched in the symbol table.
Step7: If it is not found in the symbol table it displays “Label Not found”. Else, the symbol is deleted.
Step8: If the entered choice is 5, the symbol to be modified is searched in the symbol table.

PROGRAM CODE:
//Implementation of symbol table
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
void main()
{
int i=0,j=0,x=0,n;
void *p,*add[5];
char ch,srch,b[15],d[15],c;
printf("Expression terminated by $:");
while((c=getchar())!='$')
{
b[i]=c;
i++;
}
n=i-1;
printf("Given Expression:");
i=0;
while(i<=n)
{
printf("%c",b[i]);
i++;
}
printf("\n Symbol Table\n");
printf("Symbol \t addr \t type");
while(j<=n)
{
c=b[j];
if(isalpha(toascii(c)))
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf("\n%c \t %d \t identifier\n",c,p);
x++;
j++;
}
else
{
ch=c;
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
{
p=malloc(ch);
add[x]=p;
d[x]=ch;
printf("\n %c \t %d \t operator\n",ch,p);
x++;
j++;
}}}}

OUTPUT:

RESULT:
Thus to write a program for implementing Symbol Table using C was executed and verified
successfully.
Ex No: 2 IMPLEMENTATION OF A LEXICAL ANALYZER USING LEX

AIM:

To write a program for implementing a Lexical analyser using LEX tool in Linux platform.

ALGORITHM:

Step1: Lex program contains three sections: definitions, rules, and user subroutines. Each section
must be separated from the others by a line containing only the delimiter, %%. The format is as
follows: definitions %% rules %% user_subroutines

Step2: In definition section, the variables make up the left column, and their definitions make up the
right column. Any C statements should be enclosed in %{..}%. Identifier is defined such that the first
letter of an identifier is alphabet and remaining letters are alphanumeric.

Step3: In rules section, the left column contains the pattern to be recognized in an input file to
yylex(). The right column contains the C program fragment executed when that pattern is recognized.
The various patterns are keywords, operators, new line character, number, string, identifier,
beginning and end of block, comment statements, preprocessor directive statements etc.

Step4: Each pattern may have a corresponding action, that is, a fragment of C source code to
execute when the pattern is matched.

Step5: When yylex() matches a string in the input stream, it copies the matched text to an external
character array, yytext, before it executes any actions in the rules section.

Step6: In user subroutine section, main routine calls yylex(). yywrap() is used to get more input.

Step7: The lex command uses the rules and actions contained in file to generate a program, lex.yy.c,
which can be compiled with the cc command. That program can then receive input, break the input
into the logical pieces defined by the rules in file, and run program fragments contained in the
actions in file.

PROGRAM CODE:

//Implementation of Lexical Analyzer using Lex tool

%{
int COMMENT=0;

%}
identifier [a-zA-Z][a-zA-Z0-9]*

%%
#.* {printf("\n%s is a preprocessor directive",yytext);}
int |
float |

char |
double |
while |
for |
struct |
typedef |
do |
if |
break |
continue |
void |
switch |
return |
else |

goto {printf("\n\t%s is a keyword",yytext);}


"/*" {COMMENT=1;}{printf("\n\t %s is a COMMENT",yytext);}
{identifier}\( {if(!COMMENT)printf("\nFUNCTION \n\t%s",yytext);}
\{ {if(!COMMENT)printf("\n BLOCK BEGINS");}
\} {if(!COMMENT)printf("BLOCK ENDS ");}
{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s IDENTIFIER",yytext);}
\".*\" {if(!COMMENT)printf("\n\t %s is a STRING",yytext);}
[0-9]+ {if(!COMMENT) printf("\n %s is a NUMBER ",yytext);}
\)(\:)? {if(!COMMENT)printf("\n\t");ECHO;printf("\n");}
\( ECHO;

= {if(!COMMENT)printf("\n\t %s is an ASSIGNMENT OPERATOR",yytext);}

\<= |
\>= |
\< |
== |

\> {if(!COMMENT) printf("\n\t%s is a RELATIONAL OPERATOR",yytext);}

%%

int main(int argc, char **argv)

{
FILE *file;
file=fopen("var.c","r");
if(!file)
{

printf("could not open the file");


exit(0);
}
yyin=file;
yylex();
printf("\n");
return(0);
}

int yywrap()
{
return(1);
}

INPUT:
//var.c
#include<stdio.h>
#include<conio.h>

void main()
{
int a,b,c;

a=1;
b=2;
c=a+b;
printf("Sum:%d",c);
}

OUTPUT:

RESULT:
Thus to write a program for implementing a Lexical analyser using LEX tool in Linux platform was
executed and verified successfully.
3. Generate YACC specification for a few syntactic categories.

3a. Program to recognize a valid arithmetic expression that uses operator +, -, * and /.

AIM:

To write a Yacc program to valid arithmetic expression using Yacc .

ALGORITHM:

Step1: Start the program.

Step2: Reading an expression .

Step3: Checking the validating of the given expression according to the rule using yacc.

Step4: Using expression rule print the result of the given values

Step5: Stop the program.

Lex Program: (sample.l)

%{
#include<stdio.h>
#include "y.tab.h"
%}
%%
[a-zA-Z]+ return VARIABLE;
[0-9]+ return NUMBER;
[\t] ;
[\n] return 0;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
Yacc program: (sample.y)

%{
#include<stdio.h>
%}
%token NUMBER
%token VARIABLE
%left '+' '-'
%left '*' '/' '%'
%left '(' ')'
%%
S: VARIABLE'='E {
printf("\nEntered arithmetic expression is Valid\n\n");
return 0;
}
E:E'+'E
|E'-'E
|E'*'E
|E'/'E
|E'%'E
|'('E')'
| NUMBER
| VARIABLE
;
%%
void main()
{
printf("\nEnter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:\n");
yyparse();
}
void yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");

Output:

Result:
Thus the Program to recognize a valid arithmetic expression that uses operator +, -, * and / was
executed and verified successfully.
3b. Program to recognize a valid variable which starts with a letter followed by any number of letters
or digits

AIM :

To write a yacc program to check valid variable followed by letter or digits

ALGORITHM:

Step1: Start the program

Step2: Reading an expression

Step3: Checking the validating of the given expression according to the rule using yacc.

Step4: Using expression rule print the result of the given values

Step5: Stop the program

%{

#include<stdio.h>

%}

%%

int|char|float|return { printf("%s=> Keywords",yytext);}\

#.* { printf("\n%s=>Preprocessor Directive",yytext);}

printf|scanf|main { printf("\n%s=>functions",yytext);}

[a-zA-Z]+ { printf("\n%s=>Identifiers",yytext);}

["][a-z]["] { printf("\n%s=>Keywords",yytext);}

[0-9] { printf("\n%s=>Keywords",yytext);}

"+"|"-"|"*"|"/"|"%" { printf("\n%s=>Operators",yytext);}

","|";"|"&"|"("|")"|["]|"{"|"}" { printf("\n%s=>Special Characters",yytext);}

%%

int main()

FILE *fp;

fp=fopen("input.txt","r");

yyin=fp;

yylex();
return 0;

int yywrap()

return 1;

input.txt

Output:

Result:
Thus the Program to recognize a valid variable which starts with a letter followed by any
number of letters or digits was executed and verified successfully.
c. Program to recognize a valid control structures syntax of C language (For loop,

while loop, if-else, if-else-if, switch-case, etc.).

AIM :

To write a yacc program to check valid control structures syntax of C language (For loop,

while loop, if-else, if-else-if, switch-case, etc.).

ALGORITHM:

Step1: Start the program

Step2: Reading an Program

Step3: Checking the validating of the given program according to the rule using yacc.

Step4: Using control structures rule print the result of the given values

Step5: Stop the program

%{

#include<stdio.h>

%}

%%

int|char|float|return { printf("%s=> Keywords",yytext);}\

#.* { printf("\n%s=>Preprocessor Directive",yytext);}

printf|scanf|main { printf("\n%s=>functions",yytext);}

printf|for|do|while|if|if-else|if-else-if |switch-case{ printf("\n%s=>control Structures",yytext);}

[a-zA-Z]+ { printf("\n%s=>Identifiers",yytext);}

["][a-z]["] { printf("\n%s=>Keywords",yytext);}

[0-9] { printf("\n%s=>Keywords",yytext);}

"+"|"-"|"*"|"/"|"%" { printf("\n%s=>Operators",yytext);}

","|";"|"&"|"("|")"|["]|"{"|"}" { printf("\n%s=>Special Characters",yytext);}

%%

int main()

FILE *fp;
fp=fopen("input.txt","r");

yyin=fp;

yylex();

return 0;

int yywrap()

return 1;

input.txt

Output:

Result:
Thus the program to recognize a valid control structures syntax of C language (For loop,
while loop, if-else, if-else-if, switch-case, etc.) was executed and verified successfully.
3d. IMPLEMENTATION OF CALCULATOR USING LEX & YACC

AIM:

To write a program for implementing a calculator for computing the given expression using
semantic rules of the YACC tool and LEX.

ALGORITHM:

Step1: A Yacc source program has three parts as follows:

Declarations %% translation rules %% supporting C routines

Step2: Declarations Section: This section contains entries that:

i. Include standard I/O header file.

ii. Define global variables.

iii. Define the list rule as the place to start processing.

iv. Define the tokens used by the parser. v. Define the operators and their precedence.

Step3: Rules Section: The rules section defines the rules that parse the input stream. Each rule of a
grammar production and the associated semantic action.

Step4: Programs Section: The programs section contains the following subroutines. Because these
subroutines are included in this file, it is not necessary to use the yacc library when processing this
file.

Step5: Main- The required main program that calls the yyparse subroutine to start the program.

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

Step7: yywrap -The wrap-up subroutine that returns a value of 1 when the end of input occurs. The
calc.lex file contains include statements for standard input and output, as programmar file
information if we use the -d flag with the yacc command. The y.tab.h file contains definitions for the
tokens that the parser program uses.

Step8: calc.lex contains the rules to generate these tokens from the input stream.

PROGRAM CODE:

//Implementation of calculator using LEX and YACC

LEX PART:

%{

#include<stdio.h>

#include "y.tab.h"

extern int yylval;


%}

%%

[0-9]+ {

yylval=atoi(yytext);

return NUMBER;

[\t] ;

[\n] return 0;

. return yytext[0];

%%

int yywrap()

return 1;

YACC PART:

%{

#include<stdio.h>

int flag=0;

%}

%token NUMBER

%left '+' '-'

%left '*' '/' '%'

%left '(' ')'

%%

ArithmeticExpression: E{

printf("\nResult=%d\n",$$);

return 0;

};

E:E'+'E {$$=$1+$3;}

|E'-'E {$$=$1-$3;}

|E'*'E {$$=$1*$3;}
|E'/'E {$$=$1/$3;}

|E'%'E {$$=$1%$3;}

|'('E')' {$$=$2;}

| NUMBER {$$=$1;}

%%

void main()

printf("\nEnter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:\n");

yyparse();

if(flag==0)

printf("\nEntered arithmetic expression is Valid\n\n");

void yyerror()

printf("\nEntered arithmetic expression is Invalid\n\n");

flag=1;

OUTPUT:

Result:
Thus the implementation of calculator using lex & yacC was executed and verified successfully.

4. Generate three address code for a simple program using LEX and YACC.

Aim:
To write a program to generate three address code for a simple program using LEX and YACC.
Algorithm:
1.Use Lex to create a lexer that tokenizes the input source code. Define regular expressions for
keywords, identifiers, constants (e.g., integers, floats), and operators.

2.Use Yacc (or Bison) to create a parser that generates a syntax tree from the tokenized input. Define
grammar rules for the programming language, including expressions, statements, and
control structures.
3.Create a symbol table to keep track of variables and their types. Update the symbol table durin!g
parsing whenever a variable is declared.

4. Attach semantic actions to the Yacc grammar rules to generate three-address code during
the parsing process. These actions should handle expressions, assignments, and control
structures.
5.As you parse the input source code, use semantic actions to generate three-address code
instructions. These instructions should represent the operations performed in the program.Maintain
a list of three-address code instructions, and update it as you encounter different statements and
expressions.

6.Introduce temporary variables to hold intermediate results in expressions.Ensure that variables are
correctly looked up in the symbol table and that their types are compatible in expressions.

7.Once the parsing is complete, output the generated three-address code. You can print it to a file or
directly to the console.

8.Perform optimization passes on the generated code to improve its efficiency. Common
optimizations include constant folding, common subexpression elimination, and dead code
elimination.

9.If your goal is to compile the program, you can further translate the three-address code into
assembly code for the target architecture.

10. Thoroughly test your three-address code generator with various input programs to
ensure correctness and efficiency.Debug any issues in the code generation process by
examining the generated three-address code and the syntax tree.

Program:

Lex Part

%{

#include"y.tab.h"

extern char yyval;

%}

%%

[0-9]+ {yylval.symbol=(char)(yytext[0]);return NUMBER;}

[a-z] {yylval.symbol= (char)(yytext[0]);return LETTER;}


. {return yytext[0];}

\n {return 0;}

%%

Yacc Part

%{

#include"y.tab.h"

#include<stdio.h>

char addtotable(char,char,char);

int index1=0;

char temp = 'A'-1;

struct expr{

char operand1;

char operand2;

char operator;

char result;

};

%}

%union{

char symbol;

%left '+' '-'

%left '/' '*'

%token <symbol> LETTER NUMBER

%type <symbol> exp

%%

statement: LETTER '=' exp ';' {addtotable((char)$1,(char)$3,'=');};

exp: exp '+' exp {$$ = addtotable((char)$1,(char)$3,'+');}

|exp '-' exp {$$ = addtotable((char)$1,(char)$3,'-');}

|exp '/' exp {$$ = addtotable((char)$1,(char)$3,'/');}

|exp '*' exp {$$ = addtotable((char)$1,(char)$3,'*');}

|'(' exp ')' {$$= (char)$2;}


|NUMBER {$$ = (char)$1;}

|LETTER {(char)$1;};

%%

struct expr arr[20];

void yyerror(char *s){

printf("Errror %s",s);

char addtotable(char a, char b, char o){

temp++;

arr[index1].operand1 =a;

arr[index1].operand2 = b;

arr[index1].operator = o;

arr[index1].result=temp;

index1++;

return temp;

void threeAdd(){

int i=0;

char temp='A';

while(i<index1){

printf("%c:=\t",arr[i].result);

printf("%c\t",arr[i].operand1);

printf("%c\t",arr[i].operator);

printf("%c\t",arr[i].operand2);

i++;

temp++;

printf("\n");

int find(char l){


int i;

for(i=0;i<index1;i++)

if(arr[i].result==l) break;

return i;

int yywrap(){

return 1;

int main(){

printf("Enter the expression: ");

yyparse();

threeAdd();

printf("\n");

return 0;

Output:

Result:
Thus to generate three address code for a simple program using LEX and YACC was executed
and verified successfully.

You might also like