160 PCD
160 PCD
Name:
Register No:
Register Number:
Certified that this is the Bonafide Record of work done by Mr. / Ms.
of III / VI (year/semester)
Register Number:
Submitted for the End Semester Practical Examination held on
VISION
To create computer professionals with a strong academic and technical background to achieve special
distinction at the national and international arena and also to serve and lead the society.
MISSION
➢ Providing excellent learning opportunities for students in Computer Science and Engineering to meet the
laboratory and work-based experiences to formulate and solve problems in Computer Science and
Engineering and other related domains and will develop proficiency in computer based engineering and
2. PEO2: Graduates will be prepared to communicate and work effectively on the multidisciplinary
engineering projects practicing the ethics of their profession with a sense of social responsibility.
3. PEO3: Graduates will recognize the importance of lifelong learning to become experts either as
PSO-1 Analyze, design, implement, test and evaluate computer programs in the areas related to
algorithms, networking, web design, cloud computing, IoT and data analytics of varying
complexity.
PSO-2 Develop innovative ideas to provide solutions for complex problems and apply advanced
knowledge of computer science domain to identify research challenges in Computer Science and
Engineering.
INDEX
10
21PD19-PRINCIPLES OF COMPILER DESIGN
Ex.No: 01
IMPLEMENTATION OF LEXICAL ANALYZER IN C
Date:
AIM:
Algorithm:
b) elsego to step 4
Step 4:Compare the array with the predefined set of keywords. if the characters are
alphabets and
Step 5: If the character is not an alphabet compare it with the set of operator and
Program:
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
void main()
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
FILE *fp;
int i,j;
char arr[100],k;
char kw[10][10]={"int","float","double","end","main","void","include","printf","scanf"};
char hf[2][10]={"stdio.h","conio.h"};
char op[5]={'+','-','*','/','%'};
char punc[6]={'(',')','{','}',','};
clrscr();
fp=fopen("input.c","r");
printf("InputProgram\n");
while(!feof(fp))
arr[0]=fgetc(fp);
printf("%c",arr[0]);
fclose(fp);
printf("\nSymboltable\n");
fp=fopen("input.c","r");
printf("\nKeywords");
while(!feof(fp))
arr[0]=fgetc(fp);
fscanf(fp,"%s",arr);
for(i=0;i<10;i++)
if(strcmp(arr,kw[i])==0)
printf("\t%s",arr);
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
}}}
fclose(fp);
fp=fopen("input.c","r");
printf("\nHeaderfiles");
while(!feof(fp))
arr[0]=fgetc(fp);
fscanf(fp,"%s",arr);
for(i=0;i<2;i++)
if(strcmp(arr,hf[i])==0)
printf("\t%s",arr);
}}}
fclose(fp);
fp=fopen("input.c","r");
printf("\nOperators");
while(!feof(fp))
arr[0]=fgetc(fp);
for(i=0;i<5;i++)
if(arr[0]==op[i])
printf("\t%c",arr[0]);
}}}
fclose(fp);
fp=fopen("input.c","r");
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
printf("\npunctuation");
while(!feof(fp))
arr[0]=fgetc(fp);
for(i=0;i<6;i++)
if(arr[0]==punc[i])
printf("\t%c",arr[0]);}}}
fclose(fp);
fp=fopen("input.c","r");
printf("\nConstants");
while(!feof(fp))
arr[0]=fgetc(fp);
if(isdigit(arr[0]))
printf(" %c ",arr[0]);}}
fclose(fp);
fp=fopen("input.c","r");
printf("\nidentifier ");
while(!feof(fp))
fscanf(fp,"%s",arr);
for(i=0;i<2;i++)
if(strcmp(arr,kw[i])==0)
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
fscanf(fp,"%s",arr);
j=0;
printf("%c",arr[j]);
j++;
}}}}
fclose(fp);
getch();
Input:
#include<stdio.h>
#include<conio.h>
void main()
int a,b,c;
a=10;
b=5;
c=a+b;
printf(“Thesumis %d”,c);
getch();
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Output:
RESULT:
Thus,the program for developing a lexical analyzer to recognize a few
patterns in C has been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Ex.No:02
IMPLEMENTATION OF LEXICAL ANALYSER USING LEX TOOL
Date:
Aim:
To write a C program for implementing the lexical analyzer using LEX Tool.
Algorithm:
Step 2: Create a Lex Specification file using the Echo,YYLEX, YYTEXT, YYWRAPAP, YYIN.
Step 5: The YYTEXT() function is used to store the Null Terminated string.
Step 6: The YYWRAP() function returns zero when the scanner continues scanning and returns 1
when the end of file is encountered.
Step 7: The YYIN() function is used to store the input source program.
Step 8: The main function first calls the yylex and yywrap() function and executes.
Step 9: Print the Pre-processor Directive, Keyword, function as in the source program.
Program:
%{
int COMMENT=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
int |
float |
char |
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
double |
while |
for |
struct |
typedef |
do |
if |
break|
continue |
void |
switch |
return |
else |
\)(\:)? {if(!COMMENT)printf("\n\t");ECHO;printf("\n");}
\( ECHO;
\<= |
\>= |
\< |
== |
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
%%
FILE *file;
file=fopen("var.c","r");
if(!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;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
b=2;
c=a+b;
printf("Sum:%d",c);
Output
RESULT:
Thus, the program for Implementation of a lexical analyzer using lex tool has been
executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Aim:
To write a C program to implement a recursive descent parser for an expression grammar that
generates arithmetic expression with digits + and *.
Algorithm:
E->TE‟
E‟->+TE‟|€
T->FT‟
T‟->*FT‟ |€
F->I | (E)
a) If the RHS has a non-terminal, then call the function corresponding to it.
b) If the RHS has a terminal, then check if it matches with the input, else print error.
Step 5: Repeat the previous step until the given input string is completely parsed or an error is
encountered.
Step 6: Stoptheprogram.
Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char input[100];
int i,l;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
void main()
clrscr();
printf("\nE->TE'\nE'->+TE'/@\nT->FT'\nT'->*FT'/@\nF->(E)/ID\n");
gets(input);
if(E())
if(input[i+1]=='\0')
printf("\nString is accepted");
else
else
getch()
E()
{ if(T())
{ if(EP()
return(1);
else
return(0);
else
return(0);
EP()
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
if(input[i]=='+')
{ i+
+;
if(T())
{ if(EP()
return(1);
else
return(0);
else
return(0);
Else
return(1);
T()
{ if(F())
{ if(TP()
return(1);
else
return(0);
else
return(0);
TP()
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
if(input[i]=='*')
{ i+
+;
if(F())
{ if(TP()
return(1);
else
return(0);
else
return(0);
else
return(1);
F()
if(input[i]=='(')
{ i+
+;
if(E())
if(input[i]==')')
{ i+
+;
return(1);
else
return(0);
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
else
return(0);
}
else if(input[i]>='a'&&input[i]<='z'||input[i]>='A'&&input[i]<='Z')
{ i+
+;
return(1);
else
return(0);
}
Output:
RESULT:
Thus, the decent parser for an expression grammer for arithmetic expression with digits has
been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Ex.No:04
IMPLEMENTATION OF A PARSER FOR THE SAME GRAMMAR AS USING
Date: YACC AND LEX
Aim:
Algorithm:
Step 1: In parser.l give the LEX specification.
a) In the declaration section given the regular expression for an identifier and number.
b) Identify the tokens as keywords or variables or numbers or data types or relational operators and
return them to y.tab.h.
c) Skip the white spaces.
a) Define tokens as specified in sample.l and the arithmetic operators as left associative.
b) Specify the productions i.e. the syntax for a program block, code, statement, condition. For example,
the syntax for program is PROGRAM: MAIN BLOCK; which means the program starts with main,
followed by a block.
c) Give the auxiliary code and initialize the parsing using yyparse().
d) Keep track of the error number to check if the program is error free or not. If error =0 then the
program is error free else it has errors.
Print the line number having the error and error no. is incremented for every error using yyerror().
Program:
%{
/* Definition section */
#include "y.tab.h"
%}
/* Rule Section */
%
[aA] {return A;}
[bB] {return B;}
\n {return NL;}
. {return yytext[0];}
%%
int yywrap()
{
return 1;
}
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
%{
/* Definition section */
#include<stdio.h>
#include<stdlib.h>
%}
%token A B NL
/* Rule Section */
%%
stmt: S NL { printf("valid string\n");
exit(0); }
;
S: A S B |
;
%%
int yyerror(char *msg)
{
printf("invalid string\n");
exit(0);
}
//driver code
main()
{
printf("enter the string\n");
yyparse();
}
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
OUTPUT:
RESULT:
Thus the program for developing a Implementation of a parser for the same grammar in
yaac and lex has been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Aim:
To write a Yacc program for performing calculator functions like addition and multiplication.
Algorithm:
Step 1: In the declaration section, include the header files stdio.h and ctype.h.
Step 4: In the rule section, give the productions for program, statement, expr.For example, expr may
be INTEGER, VARIABLE, EXPR ‟+ ”EXPR, EXPR ‟-” EXPR, EXPR ‟*” EXPR ‟/”
EXPR, (“EXPR‟).
Step 5: The evaluated value of the arithmetic expression is then stored in $$.
Program:
%{
/* Definition section */
#include<stdio.h>
#include "y.tab.h"
extern int yylval;
%}
/* Rule Section */
%%
[0-9]+ {
yylval=atoi(yytext);
return NUMBER;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
[\t] ;
[\n] return 0;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
Parser Source Code :
%{
/* Definition section */
#include<stdio.h>
int flag=0;
%}
%token NUMBER
/* Rule Section */
%%
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;}
;
%%
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
//driver code
void main()
{
printf("\nEnter Any Arithmetic Expression which
can have operations Addition,
Subtraction, Multiplication, Division,
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:
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
RESULT:
Thus the program for developing a semantic rules to the YAAC program and implement a
calculator that takes an expression with digits + and * has been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Aim:
To write a C program to implement the front end of a compiler that generates the three
addresses code for a simple language with one data type integer, arithmetic operators.
Algorithm:
Step 4: If it is invalid, return the error message, otherwise, for each computation
store the result in the three address statement. (store it in temporary variable
say t1,t2,t3 ,etc.,).
Step 5: Assign the final temporaryvalue to the variable in which the result has to be stored.
PROGRAM:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
INTEGER,
PLUS,
MINUS,
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
MULTIPLY,
DIVIDE,
END
} TokenType;
typedef struct {
TokenType type;
int value;
} Token;
{ Token token;
if (isdigit(expr[*index])) {
token.type = INTEGER;
token.value = atoi(&expr[*index]);
} else {
switch (expr[(*index)++])
{ case '+':
token.type = PLUS;
break;
case '-':
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
token.type = MINUS;
break;
case '*':
token.type = MULTIPLY;
break;
case '/':
token.type = DIVIDE;
break;
case '\0':
token.type =END;
break;
default:
exit(1);
return token;
{ int index = 0;
Token token;
switch (token.type)
{ case INTEGER:
break;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
case PLUS:
printf("ADD\n");
break;
case MINUS:
printf("SUBTRACT\n");
break;
case MULTIPLY:
printf("MULTIPLY\n");
break;
case DIVIDE:
printf("DIVIDE\n");
break;
default:
break;
int main() {
char expression[MAX_EXPR_LENGTH];
generateThreeAddressCode(expression);
return 0;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
OUTPUT:
RESULT:
Thus the program for developing arithmetic operators that generate three address
code for simple language in C has been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Aim:
To write a C program to implement the front end of a compiler that generates the three
addresses code for a simple language with relational operators, variable declaration statement.
Algorithm:
Step2:Define structures for tokens, symbol table entries, and Three Address Code (TAC).
Step6:Generate Three Address Code (TAC) for each expression encountered during
parsing.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
// Token types
#define IDENTIFIER 1
#define KEYWORD 2
#define OPERATOR 3
#define LITERAL 4
typedef struct {
} Token;
// Function prototypes
int main() {
charinput[MAX_CODE_LENGTH];
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
syntaxAnalysis(tokens);
free(tokens);
return 0;
char* token;
charcopy[MAX_CODE_LENGTH];
strcpy(copy, input);
int tokenCount = 0;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
// Determinetoken type
int tokenType;
if (strcmp(token, "int") == 0)
{ tokenType = KEYWORD;
tokenType = OPERATOR;
{ tokenType = LITERAL;
} else {
tokenType = IDENTIFIER;
// Store token
tokens[tokenCount].type =tokenType;
strcpy(tokens[tokenCount].lexeme, token);
tokenCount++;
tokens[tokenCount].type = 0;
strcpy(tokens[tokenCount].lexeme, "");
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
return tokens;
printf("Syntax Analysis:\n");
int i = 0;
while (tokens[i].type != 0) {
i++;
i++;
printf("\n");
generateThreeAddressCode(tokens);
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
printf("Three-Address Code:\n");
int i = 0;
while (tokens[i].type != 0) {
i++;
i += 2;
i++;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
OUTPUT:
RESULT:
Thus,the program for developing relational operators and variable declaration
statement that generate three address code for simple language in C has been executed
successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Aim:
To write a C program to implement the front end of a compiler that generates the three
addresses code for a simple language with one conditional construct,one iterative construct
statement.
Algorithm:
Step2: Lexical Analysis: Tokenize the input code to identify tokens such as identifiers,
keywords, operators, and literals.
Step3:Syntax Analysis: Implement a parser to ensure that the input code adheres to the
syntax rules of the simple language. This involves constructing a grammar for the language
and writing code to parse the input according to that grammar.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
// Token types
#define IDENTIFIER 1
#define KEYWORD 2
#define OPERATOR 3
#define LITERAL 4
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
strcpy(tokens[5].lexeme, ")");
tokens[5].type = OPERATOR;
strcpy(tokens[6].lexeme, "{");
tokens[6].type = OPERATOR;
strcpy(tokens[7].lexeme, "x");
tokens[7].type = IDENTIFIER;
strcpy(tokens[8].lexeme, "=");
tokens[8].type = OPERATOR;
strcpy(tokens[9].lexeme, "x");
tokens[9].type = IDENTIFIER;
strcpy(tokens[10].lexeme, "-");
tokens[10].type = OPERATOR;
strcpy(tokens[11].lexeme, "1");
tokens[11].type = LITERAL;
strcpy(tokens[12].lexeme, ";");
tokens[12].type = OPERATOR;
strcpy(tokens[13].lexeme, "}");
tokens[13].type = OPERATOR;
strcpy(tokens[14].lexeme,"else");
tokens[14].type = KEYWORD;
strcpy(tokens[15].lexeme, "{");
tokens[15].type = OPERATOR;
strcpy(tokens[16].lexeme, "x");
tokens[16].type = IDENTIFIER;
strcpy(tokens[17].lexeme, "=");
tokens[17].type = OPERATOR;
strcpy(tokens[18].lexeme, "x");
tokens[18].type = IDENTIFIER;
strcpy(tokens[19].lexeme, "+");
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
tokens[19].type = OPERATOR;
strcpy(tokens[20].lexeme, "1");
tokens[20].type = LITERAL;
strcpy(tokens[21].lexeme, ";");
tokens[21].type = OPERATOR;
strcpy(tokens[22].lexeme, "}");
tokens[22].type = OPERATOR;
return tokens;
}
int main() {
char input[100];
printf("Enter code: ");
fgets(input, sizeof(input), stdin);
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
free(tokens);
return 0;
}
OUTPUT:
RESULT:
Thus the program for developing conditional construct,one iterative construct and
assignment statement that generate three address code for simple language in C has
been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Ex. No:9
IMPLEMENTATION OF A BACK END COMPILER USING C
Date:
Aim:
To write a c program to implement the back end of a compiler (code generator) for
the three address code.
Algorithm:
Step4: If the given length is greater than 5,then return the error message as invalid
expression.
Program:
#include <stdio.h >
#include<conio.h>
void main() {
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
int i = 0;
//clrscr();
do
scanf("%s", icode[i]);
printf("\n************************");
i = 0;
do {
strcpy(str, icode[i]);
switch (str[3])
{ case '+':
break;
case '-':
strcpy(opr, "SUB");
break;
case '*':
break;
case '/':
break;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
getch();
OUTPUT:
RESULT:
Thus the program for developing back end of a compiler (code generator) that
generate three address code for simple language in C has been executed successfully.
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
Ex. No:10
STACK IMPLEMENTATION OF LR PARSER USING C
Date:
Aim:
Algorithm:
Step1: Get the input expression and store it in the input buffer.
Step 2: Read the data from the input buffer one at the time and convert into corresponding
Non Terminal using production rules available.
Step 3: Perform push & pop operation for LR parsing table construction.
Step 4: Display the result with conversion of corresponding input symbols to production
and production reduction to start symbol. No operation performed on the operator.
Program:
#include<stdio.h >
#include<stdio.h >
#include<conio.h>
char stack[30];
int top=-1;
void push(char c)
top++;
stack[top]=c;
char pop()
char c;
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
if(top!=-1)
c=stack[top];
top--;
return c;
return'x';
void printstat()
int i;
printf("\n\t\t\t $");
for(i=0;i<=top;i++)
printf("%c",stack[i]);
void main()
int i,j,k,l;
chars1[20],s2[20],ch1,ch2,ch3;
printf("\n\n\t\t LR PARSING");
scanf("%s",s1);
l=strlen(s1);
j=0;
printf("\n\t\t $");
for(i=0;i<sizeof(s1);i++)
s1[i]=' ';
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
s1[i+1]='E';
printstat(); printf("id");
push('E');
printstat();
push(s1[i]);
printstat();
printstat();
l=strlen(s2);
while(l)
ch1=pop();
if(ch1=='x')
printf("\n\t\t\t $");
break;
if(ch1=='+'||ch1=='/'||ch1=='*'||ch1=='-')
ch3=pop();
if(ch3!='E')
printf("errror");
else
717822P160
21PD19-PRINCIPLES OF COMPILER DESIGN
push('E');
printstat();
ch2=ch1;
getch();
OUTPUT:
RESULT:
Thus the program for developing stack implementation of LR parser that
generate three address code for simple language in C has been executed
successfully.
717822P160