CC Record
CC Record
iopasdfghjklzxcvbnmqwertyuiopasdfg
hjklzxcvbnmqwertyuiopasdfghjklzxcv
bnmqwertyuiopasdfghjklzxcvbnmqwe
rtyuiopasdfghjklzxcvbnmqwertyuiopa
Compiler Construction
sdfghjklzxcvbnmqwertyuiopasdfghjklz
Lab Manual
2019-20
xcvbnmqwertyuiopasdfghjklzxcvbnmq
wertyuiopasdfghjklzxcvbnmqwertyuio
pasdfghjklzxcvbnmqwertyuiopasdfghj
klzxcvbnmqwertyuiopasdfghjklzxcvbn
mq
Table of Contents
wertyuiopasdfghjklzxcvbnmqwertyuio
4. lex program for reverse of a string 18
LL(1) Parser 43
5.SLR parser 47
6.Parser programs using YACC 55
a. Program to evaluate an arithmetic expression involving operating +, -, * and /. 57
e.write a program for the LALR parser for the following grammar 64
A translator is a program that takes as input a program written in one language and produces as output a
program in another language. Beside program translation, the translator performs another very important
role, the error-detection. Any violation of d HLL specification would be detected and reported to the
programmers. Important role of translator are:
INTERPRETOR
COMPILER
PREPROSSESSOR
COMPILER :-
Compiler is a translator program that translates a program written in (HLL) the source program and
translate it into an equivalent program in (MLL) the target program. As an important part of a compiler is
error showing to the programmer.
Error message
Executing a program written n HLL programming language is basically of two parts. the source program
must first be compiled translated into a object program. Then the results object program is loaded into a
memory executed.
Source program object program
compiler
Syntax Analyzer
token
parse tree
improved IMC
Lexical Analysis:-
LA or Scanners reads the source program one character at a time, carving the
source program into a sequence of automic units called tokens.
Syntax Analysis:-
The second stage of translation is called Syntax analysis or parsing. In this phase
expressions, statements, declarations etc… are identified by using the results of lexical analysis. Syntax
analysis is aided by using techniques based on formal grammar of the programming language.
Intermediate Code Generations:-
An intermediate representation of the final machine language code is produced.
This phase bridges the analysis and synthesis phases of translation.
Code Optimization :-
This is optional phase described to improve the intermediate code so that the
output runs faster and takes less space.
Code Generation:-
The last phase of translation is code generation. A number of optimizations to
reduce the length of machine language program are carried out during this phase. The output of the
code generator is the machine language program of the specified computer.
Table Management (or) Book-keeping:-
This is the portion to keep the names used by the program and records essential
information about each. The data structure used to record this information called a ‘Symbol Table’.
Error Handlers:-
It is invoked when a flaw error in the source program is detected.
Passes:-
One (or) more phases one combined into a module called a pass.
Single-pass Compiler:-
All the phases are combined into a single
Multi-pass Compiler:-
More than one phase are combined into a number of groups called multi-pass.
(Multi pass compiler can be made to use less space than single pass compiler.).
LEXICAL ANALYSER:
Lexical analyser is the first phase of compiler. Which takes the source program as input and
produces the stream of tokens as output.
Week1
Viva Questions
Program: 1
Aim: To develop a lexical analyzer to recognize a few patterns
Algorithm for lexical analyzer:
function lexan: integer ; [ Returns an integer encoding of token]
var lexbuf : array[ 0 .. 100 ] of char ;
c: char ;
begin
loop begin
read a character into c ;
if c is a blank or a tab then
do nothing
else if c is a newline then
lineno : = lineno + 1
else if c is a digit then begin
set tokenval to the value of this and following digits ;
return NUM
end
else if c is a letter then begin
place c and successive letters and digits into lexbuf ;
p : = lookup ( lexbuf ) ;
if p = 0 then
p : = insert ( lexbf, ID) ;
tokenval : = p
return the token field of table entry p
end
else
set tokenval to NONE ; / * there is no attribute * /
return integer encoding of character c
end
end
Program:
1.
Standalone lexical analyzer program for identifying identifiers, keywords, operators, digits;
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main()
{
FILE *input,*output;
int l=1;
int t=0;
int j=0;
int i,flag;
char ch,str[20];
char keyword[30][30]={"int","main","if","else","do","while","struct","goto"};
input=fopen("input.txt","r");
output=fopen("output.txt","w");
fprintf(output,"Line no. \t Token no.\t Token\t Lexeme\n\n");
while(!feof(input))
{
i=0;
flag=0;
ch=fgetc(input);
if( ch=='+' || ch== '-' || ch=='*' || ch=='/' || ch=='<' || ch=='>')
{
fprintf(output,"%6d\t\t %6d\t\t Operator\t %6c\n",l,t,ch);
t++;
}
else if( ch==';' || ch=='{' || ch=='}' || ch=='(' || ch==')' || ch=='?' || ch=='@' ||
ch=='!' || ch=='%')
{
fprintf(output,"%6d\t\t %6d\t\t Special symbol\t %6c\n",l,t,ch);
t++;
}
else if(isdigit(ch))
{
fprintf(output,"%d6\t\t %6d\t\t Digit\t\t %6c\n",l,t,ch);
t++;
}
else if(isalpha(ch))
{
str[i]=ch;
i++;
ch=fgetc(input);
while(isalnum(ch)&& ch!=' ')
{
str[i]=ch;
i++;
ch=fgetc(input);
}
str[i]='\0';
for(j=0;j<=30;j++)
{
if(strcmp(str,keyword[j])==0)
{
flag=1;
break;
}
}
if(flag==1)
{
fprintf(output,"%6d\t\t %6d\t\t Keyword\t %6s\n",l,t,str);
t++;
}
else
{
fprintf(output,"%6d\t\t %6d\t\t Identifier\t %6s\n",l,t,str);
t++;
}
}
else if(ch=='\n')
{
l++;
}
}
fclose(input);
fclose(output);
output=fopen("output.txt","r");
while(!feof(output))
{
ch=fgetc(output);
printf("%c",ch);
}
fclose(output);
return 0;
}
INPUT.TXT
#include < stdio.h >
void main ()
{
int a,b,c ;
c = a + 9 ;
}
OUTPUT.TXT
Line no. Token no. Token Lexeme
1 0 Identifier include
1 1 Operator <
1 2 Identifier stdio
1 3 Identifier h
1 4 Operator >
2 5 Identifier void
2 6 Keyword main
2 7 Special symbol (
2 8 Special symbol )
3 9 Special symbol {
4 10 Keyword int
4 11 Identifier a
4 12 Identifier b
4 13 Identifier c
4 14 Special symbol ;
5 15 Identifier c
5 16 Special symbol =
5 17 Identifier a
5 18 Operator +
5 19 Digit 9
5 20 Special symbol ;
6 21 Special symbol }
2.Scanner programs using LEX
LEX: LEX is one of the compiler construction tools. Through this we can generate stream of
tokens from the given input stream. Compilation process of it is shown bellow.
Viva Questions
2) Differentiate token,lexeme,pattern?
%{
int v=0,c=0;
%}
%%
[aeiouAEIOU] v++;
[a-zA-Z] c++;
%%
main()
{
yylex();
printf("VOWELS=%d\nCONSONANTS=%d\n",v,c);
int c=0,w=0,l=0,s=0;
%}
%%
[\n] l++;
%%
{
if(argc==2)
yyin=fopen(argv[1],"r");
yylex();
printf("\nCHARACTER=%d",c);
printf("\nLINES=%d",l);
printf("\nWORD=%d\n",w);
else
printf("ERROR");
}
%{
#include<stdio.h>
#include<ctype.h>
%}
let [a-z]|[A-Z]
str {let}+
%%
{str} { int i;
for(i=0;i<yyleng;i++)
yytext[i]=tolower(yytext[i]);
printf("lower case\t %s",yytext);
}
%%
main()
{
printf("enter input");
yylex();
}
4. lex program for reverse of a string
%{
#include<stdio.h>
#include<ctype.h>
%}
let [a-z]|[A-Z]
str {let}+
%%
{str} { int i=0,j=yyleng-1;
char rev[50];
for(i=0;i<=yyleng;i++)
{
rev[i]=yytext[j];
j--;
}
puts(rev);
//printf("reverse string%s",rev);
}
%%
main()
{
printf("enter input");
yylex();
%{
/*Program to identify a real/float precision*/
%}
integer ([0-9]+)
float ([0-9]+\.[0-9]+)|([+|-]?[0-9]+\.[0-9]*[e|E][+|-][0-9]*)
%%
{integer}
printf("\n %s is an integer.\n",yytext);
{float} printf("\n %s is a floating number.\n",yytext);
%%
main()
{
yylex();
}
int yywrap()
{
return 1;
}
%{
int pi=0,ni=0,pf=0,nf=0;
%}
%%
\+?[0-9]+ pi++;
\+?[0-9]*\.[0-9]+ pf++;
\-[0-9]+ ni++;
\-[0-9]*\.[0-9]+ nf++;
%%
main()
{
printf("ENTER INPUT : ");
yylex();
ALGORITHM:
2. Open a file file.c in read and include the yylex() tool for input scanning.
5. Print the relational, assignment and all the operator using yytext() tool.
6. Also scan and print where the loop ends and begins.
Program
/*program name is lexp.l*/
%{
int COMMENT=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
int |
float |
char |
double |
while |
for |
do |
if |
break |
continue |
void |
switch |
case |
long |
struct |
const |
typedef |
return |
else |
"*/" {COMMET=1;}
/*{printf("\n\n\t%s is a COMMENT\n",yytext);}*/
{identifier}\( {if(!COMMENT)printf("\n\nFUNCTION\n\t%s",yytext);}
{identifier}(\[[0-9]*\])?{if(!COMMENT)
\( ECHO;
\<= |
\>= |
\< |
== |
|\n ;
%%
int main(int argc,char **argv) /* MAIN FUNCTION */
if(argc > 1)
FILE *file;
File = fopen(argv[1],”r”);
if(!file)
exit(0);
yyin=file;
yylex();
printf(“\n\n”);
return 0;
int yywrap()
return 0;
/*-------------------End of lexp.l----------------------*/
/*Program named as area.c*/
#include<stdio.h>
#include<stdlib.h>
int main()
printf("usage: %s radius\n",argv[0]);
exit(1);
else
double radius=atof(argv[1]);
double area=area_of_circle(radius);
return 0; /*returning 0 */
OUTPUT:
[localhost@sireesha]#lex lexp.l
[localhost@sireesha]#cc lex.yy.c
[localhost@sireesha]#./a.out area.c
double is a KEYWORD
Function
area_of_circle(
double is KEYWORD
r is an IDENTIFIER
);
int is a KEYWORD
Function
main
int is a KEYWORD
argc IDENTIFIER
char is a KEYWORD
argv[] IDENTIFIER
BLOCK BEGINS
if is a KEYWORD
argc IDENTIFIER
2 is a NUMBER
BLOCK BEGINS
FUNCTION
printf(
argv[0] IDENTIFIER
);
FUNCTION
exit(
1 is a NUMBER
);
BLOCK ENDS
else is Akeyword
BLOCK BEGINS
double is KEYWORD
radius IDENTIFIER
= is an ASSIGNMENT OPERATOR
FUNCTION
atof(
argv[1] IDENTIFIER
);
double is a KEYWORD
area IDENTIFIER
FUNCTION
printf(
radius IDENTIFIER
area IDENTIFIER
);
BLOCK ENDS
return is a KEYWORD
0 is a NUMBER
//Returning 0 is a COMMENT
BLOCK ENDS
//calculate FIRST
for(i=0;i<n;i++)
{
ch=prod[i][4];
j=i;
x=first1(ch);
// printf("%c\t",x);
first[i][0]=x;
}
printf("\n");
//Calculate FOLLOW
for(id=0;id<n;id++)
{
follow1(prod[id][0]);
if(id==0)
strcat(follow[0],"$");
}
//if NULL then change FOLLOW A-->xBT then follow(B)=first(T) if first(T) contains null
then follow(B)=follow(A)
for(id=0;id<n;id++)
{
x=prod[id][strlen(prod[id])-1];
if(isupper(x)&&x!=px)
{
px=x;
null(x);
}
}
//copying FOLLOW of Non terminals
for(c=0;c<n;c++)
{
if(prod[c][0]==prod[c-1][strlen(prod[c-1])-1])
strcpy(follow[c],follow[c-1]);
}
//printing FIRST after clubbing and removing duplicates
for(j=0;j<n-1;j++)
{
if(prod[j][0]==prod[j+1][0])
{
strcat(first[j],first[j+1]);
strcpy(first[j+1],first[j]);
}
}
for(j=n-1;j>0;j--)
{
for(c=j-1;c>=0;c--)
if(first[j][0]==first[c][0])
strcpy(first[c],first[j]);
}
for(c=0;c<n;c++)
{
if(prod[c][0]==prod[c+1][0])
{
printf("FIRST(%c)= { %s }\n",prod[c][0],first[c]);
c++;
}
else
{
printf("FIRST(%c)= { %s }\n",prod[c][0],first[c]);
}
}
//Similar printing of FOLLOW
for(c=0;c<n;c++)
{
if(prod[c][0]==prod[c+1][0])
{
printf("FOLLOW(%c)= { %s }\n",prod[c][0],follow[c]);
c++;
}
else
{
printf("FOLLOW(%c)= { %s }\n",prod[c][0],follow[c]);
}
}
}
char first1(char ch)
{
if(isupper(ch)&&j<n)
{
for(c=j+1;c<n;c++)
{
if(prod[c][0]==ch)
{
first1(prod[c][4]);
break;
}
}
}
else
return ch;
}
void follow1(char ch)
{
for(i=0;i<n;i++)
{
for(j=4;j<strlen(prod[i]);j++)
{
if(ch==prod[i][j])
{
if(prod[i][j+1]!='\0')
{
if(isupper(prod[i][j+1]))
{
for(c=0;c<n;c++)
if(prod[c][0]==prod[i][j+1])
{
strcpy(follow[id],first[c]);
break;
}
}
else
follow[id][0]=prod[i][j+1];
}
else
{
strcpy(follow[id],follow[i]);
}
}
}
}
}
void null(char ch)
{
int q=id,k;
q++;
while(q<n)
{
if(prod[q][4]=='#'&&prod[q][0]==ch)
{
for(k=0;k<n;k++)
{
if(prod[k][0]==prod[id][strlen(prod[id])-2])
{
strcat(follow[k],follow[id]);
break;
}
}
}
q++;
}
}
OUTPUT:
enter production1
E-->TA
enter production2
A-->+TA
enter production3
A-->#
enter production4
T-->FB
enter production5
B-->*FB
enter production6
B-->#
enter production7
F-->(E)
enter production8
F-->i
FIRST(E)= { (i }
FIRST(A)= { +# }
FIRST(T)= { (i }
FIRST(B)= { *# }
FIRST(F)= { (i }
FOLLOW(E)= { )$ }
FOLLOW(A)= { )$ }
FOLLOW(T)= { +)$ }
FOLLOW(B)= { +)$ }
FOLLOW(F)= { *+)$ }
Press any key to continue . . .
4.Recursive Decent Parser
1. Implementation of Recursive Descent Parser for the following grammar
1. S->cAd
2. A->ab/a
2. Implementation of Recursive Descent Parser for the following grammar
E->numT
T->*numT/€
Viva Questions
4. Define CFG?
5. Define ambiguity?
1.Implementation of Recursive Descent Parser for the following grammar
S->cAd
A->ab/a
Program:
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
char str[50];
int i;
void S(void);
void A(void);
main()
{
printf("enter a string");
gets(str);
i=0;
S();
}
void S(void)
{
if (str[i]=='c')
{
i++;
A();
if(str[i]=='d')
i++;
}
if(str[i]=='$')
{
printf("success");
}
else
printf("error");
}
void A(void)
{
if(str[i]=='a')
{
i++;
if(str[i]=='b')
{
i++;
}
else
i++;
}
}
OUTPUT:
[root@localhost ~]# ./a.out
enter a stringcabd$
success[root@localhost ~]# ./a.out
enter a stringbcd$
error[root@localhost ~]
PROGRAM
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
char str[50];
int i;
void E(void);
void T(void);
main()
{
printf("enter a string");
gets(str);
i=0;
E();
}
void E(void)
{
if (isdigit(str[i]))
{
i++;
T();
}
if(str[i]=='$')
{
printf("success");
}
else
printf("error");
}
void T(void)
{
if(str[i]=='*')
{
i++;
if(isdigit(str[i]))
{
i++;
T();
}
else
i++;
}
OUTPUT:
[root@localhost ~]# ./a.out
enter a string3*4$
success[root@localhost ~]# ./a.out
enter a string2+3$
error[root@localhost ~]
LL(1) Parser
Implementation of LL(1) parsing table
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<ctype.h>
void main()
{
int i,j,h,k,r,m,n,t,nt;
char prod[15][10], first[15][30], follow[15][30],terminals[10],nonterminals[10];
static char table[10][10][10]={" "};
*table[0][0]='X';
//clrscr();
printf("total no of productions\t no of terminals and \t nonterminals");
scanf("%d%d%d",&n,&t,&nt);
printf("\n\nenter production in this format LEFT-->RIGHT\n");
for(i=0;i<n;i++)
{
printf("\nenter production%d \n", i+1);
scanf("%s",&prod[i]);
}
printf("\nenter the values of non terminals\n");
scanf("%s",nonterminals);
scanf("%s",terminals);
*table[i][0]=nonterminals[i-1];
*table[0][j]=terminals[j-1];
}
h=t;
*table[0][h+1]='$';
for(i=0;i<=n;i++)
{
//check=prod[i][0];
for(j=1;j<=nt;j++)
{
if(prod[i][0]==(*table[j][0]))
r=j;
}
for(k=0;k<=strlen(first[i]);k++)
{
if(prod[i][4]!='#')
{
for(j=1;j<=t+1;j++)
{
if(isupper(prod[i][4]))
{
if(first[i][k]==*table[0][j])
strcpy(table[r][j],prod[i]);
}
else
{
if(first[i][k]==*table[0][j] && prod[i][4]==first[i][k])
strcpy(table[r][j],prod[i]);
}
}
}
else
{
for(m=0;m<=strlen(follow[i]);m++)
{
for(j=1;j<=t+1;j++)
{ if(follow[i][m]==*table[0][j])
strcpy(table[r][j],prod[i]);
}
}
}
}
printf("-----------------------------------------------------------");
for( i=0;i<=nt;i++)
{
printf("\n\n");
for(j=0;j<=t+1;j++)
{
printf("%s\t",table[i][j]);
printf("\n----------------------------------------------------------");
Output:
5.SLR parser
DESCRIPTION:
Program:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define S4 1
#define S5 2
#define S6 3
#define S7 4
#define R1 5
#define R2 6
#define R3 7
#define R4 8
#define R5 9
#define R6 10
#define S11 11
#define AC 11 /* ACCEPT */
#define ER -1 /* ERROR */
char string[STRING_SIZE];
int i=0;
int save;
#define STACK_SIZE 40
typedef struct {
int list[STACK_SIZE];
int top;
}Stack;
#define ID 0
#define ADD 1
#define MULT 2
#define OPBR 3
#define CLBR 4
#define DOLLAR 5
#define E 6
#define T 7
#define F 8
}
else if(string[i]=='+') {
save=i;
i++;
return ADD;
}
else if(string[i]=='*') {
save=i;
i++;
return MULT;
}
else if(string[i]=='(') {
save=i;
i++;
return OPBR;
}
else if(string[i]==')') {
save=i;
i++;
return CLBR;
}
else if(string[i]==0) {
return DOLLAR;
}
}
error() {
printf("Bad Bad error.\n");
exit(0);
}
int parse() {
int token;
Stack stack;
int state;
int j;
int action;
int previous;
initialize(&stack);
push(0,&stack);
token=0;
while(1) {
token=gettoken();
action=table[peek(&stack)][token];
switch(action) {
case S4:
push(token,&stack);
push(4,&stack);
break;
case S5:
push(token,&stack);
push(5,&stack);
break;
case S6:
push(token,&stack);
push(6,&stack);
break;
case S7:
push(token,&stack);
push(7,&stack);
break;
case AC:
return 1;
case ER:
error();
}
if(action>=5 && action <=10) {
while(action>=5 && action <=10) {
action=table[peek(&stack)][token];
switch(action) {
case R1:
for(j=0;j<6;j++)
pop(&stack);
state=table[peek(&stack)][E];
if(state!=ER) {
push(E,&stack);
push(state,&stack);
}
else
error();
break;
case R2:
pop(&stack);
pop(&stack);
state=table[peek(&stack)][E];
if(state!=ER) {
push(E,&stack);
push(state,&stack);
}
else
error();
break;
case R3:
for(j=0;j<6;j++)
pop(&stack);
state=table[peek(&stack)][T];
if(state!=ER) {
push(T,&stack);
push(state,&stack);
}
else
error();
break;
case R4:
pop(&stack);
pop(&stack);
state=table[peek(&stack)][T];
if(state!=ER) {
push(T,&stack);
push(state,&stack);
}
else
error();
break;
case R5:
for(j=0;j<6;j++)
pop(&stack);
state=table[peek(&stack)][F];
if(state!=ER) {
push(F,&stack);
push(state,&stack);
}
else
error();
break;
case R6:
pop(&stack);
pop(&stack);
state=table[peek(&stack)][F];
if(state!=ER) {
push(F,&stack);
push(state,&stack);
}
else
error();
break;
case AC:
return 1;
case ER:
error();
}
}
i=save;
}
}
return 0;
}
int main() {
printf("Enter the string: ");
scanf("%s",string);
if(parse()) {
printf("Success in parsing.\n");
}
else
error();
}
Output:
[localhost@sireesha]#cc slr.c
[localhost@sireesha]# ./a.out
Enter the strinh to be par sed.Press Ctrl Z at the end
A+B
Success in parsing
Prasuna
Success in parsing
Ctrl Z
[localhost@sireesha]#
4. Write a program for the basic calculator using lex and yacc
5. This Yacc specification and lex specification program’s are for testing balanced
parentheses.
YACC tool:
YACC is one of the compiler construction Tools which will produce a parser for a given grammar.
Yacc (Yet Another Compiler-Compiler) is a parser-generator for LALR-languages. The Yacc
specification is compiled to a C program and the execution of that program acts as the parser. The
specification contains the three parts:
declarations
%%
translation rules
%%
supporting C routines
The declaration part has two sections, the first one contains ordinary C declarations delimited by
%{ and %}.
The second section contains declaration of grammar tokens, which can be used in the later parts.
If Lex is used with Yacc then these tokens will be available also in Lex.
MOTIVATION
The LALR ( Look Ahead-LR ) parsing method is between SLR and Canonical LR both in terms
of power of parsing grammars and ease of implementation. This method is often used in practice
because the tables obtained by it are considerably smaller than the Canonical LR tables, yet most
common syntactic constructs of programming languages can be expressed conveniently by an LALR
grammar. The same is almost true for SLR grammars, but there are a few constructs that can not be
handled by SLR techniques
YACC PROGRAMS
%{
#include “y.tab.h”
extern int yylval;
%}
%%
[0-9]+ { yylval=atoi(yytext); return NUMBER; }
\n { return NL ;}
. { return yytext[0]; }
%%
Yacc Part
%token NUMBER ID
%left ‘+’ ‘-‘
%left ‘*’ ‘/’
%%
stmt : exp NL { printf(“Value = %d\n”,$1); exit(0);}
;
exp : exp ‘+’ exp { $$=$1+$3; }
| exp ‘-‘ exp { $$=$1-$3; }
| exp ‘*’ exp { $$=$1*$3; }
| exp ‘/’ exp { if($3==0)
{
printf(“Cannot divide by 0”);
exit(0);
}
else
$$=$1/$3;
}
| ‘(‘ exp ‘)’ { $$=$2; }
| ID { $$=$1; }
| NUMBER { $$=$1; }
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
}
main ()
{
printf(“Enter the expression\n”);
yyparse();
}
b. Program to recognize nested IF control statements and display the
levels of nesting.
Lex Part
%{
#include “y.tab.h”
%}
%%
“if” { return IF; }
[sS][0-9]* {return S;}
“<”|”>”|”==”|”!=”|”<=”|”>=” { return RELOP; }
[0-9]+ { return NUMBER; }
[a-zA-Z][a-zA-Z0-9_]* { return ID; }
\n { ; }
. { return yytext[0]; }
%%
Yacc Part
%token IF RELOP S NUMBER ID
%{
int count=0;
%}
%%
stmt : if_stmt { printf(“No of nested if statements=%d\n”,count); exit(0);}
;
if_stmt : IF ‘(‘ cond ‘)’ if_stmt {count++;}
| S;
;
cond : x RELOP x
;
x : ID
| NUMBER
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
}
main ()
{
printf(“Enter the statement”);
yyparse();
}
c. Program to recognize strings using grammar (anbn, n>=0)
Lex Part
%{
#include “y.tab.h”
%}
%%
[aA] { return A; }
[bB] { return B; }
\n { return NL ;}
. { return yytext[0]; }
Yacc Part
%token A B NL
%%
stmt : s NL { printf(“Valid String\n”); exit(0) ;}
;
s:AsB
|
;
%%
int yyerror(char *msg)
{
printf(“Invalid String\n”);
exit(0);
}
main ()
{printf(“Enter the String\n”);
yyparse();
}
Lex Part
%{
#include “y.tab.h”
%}
%%
[aA] { return A; }
[bB] { return B; }
\n { return NL ;}
. { return yytext[0]; }
%%
Yacc Part
%token A B NL
%%
stmt : A A A A A A A A A A s B NL
{
Printf(“Valid”); exit(0);
}
;
s:sA
|
;
int yyerror(char *msg)
{
printf(“Invalid String\n”);
exit(0);
}
main ()
{
printf(“Enter the String\n”); yyparse();}
e.write a program for the LALR parser for the following grammar
;
%%
int main()
{
yyparse();
}
yyerror(char *s)
{
printf("%s",s);
}
Output:
[localhost@sireesha]#lex LALAR.l
[localhost@sireesha]# yacc –d LALR.y
[localhost@sireesha]#cc lex.yy.c y.tab.c
[localhost@sireesha]# ./a.out
2+3
5.0000
5*4
20
f.Write a program for the basic calculator using lex and yacc
%{
#include <stdio.h>
int regs[26];
int base;
%}
%start list
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /*supplies precedence for unary minus */
list: /*empty */
|
list stat '\n'
|
list error '\n'
{
yyerrok;
}
;
stat: expr
{
printf("%d\n",$1);
}
|
LETTER '=' expr
{
regs[$1] = $3;
}
;
$$=$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;
}
|
%%
main()
{
return(yyparse());
}
yyerror(s)
char *s;
{
fprintf(stderr, "%s\n",s);
}
yywrap()
{
return(1);
}
%{
#include <ctype.h>
#include <stdio.h>
#include "y.tab.h"
extern int yydebug;
%}
%token OPEN CLOSE
%%
lines : s '\n' {printf("OK\n"); }
;
s:
| OPEN s CLOSE s
;
%%
void yyerror(char * s)
{
fprintf (stderr, "%s\n", s);
}
int yywrap(){return 1; }
int main(void) {
yydebug=1;
return yyparse();}
%{
#include"y.tab.h"
%}
%%
[ \t] { /* skip blanks and tabs */ }
"(" return OPEN;
")" return CLOSE;
\n|. { return yytext[0]; }
%{
#include "y.tab.h"
%}
NUMBER [0-9]+
LETTER [a-zA-Z]+
%%
{NUMBER} {yylval.sym=(char)yytext[0];
return NUMBER;}
\n {return 0;}
. {return yytext[0];}
//inter.y
%{
#include<stdio.h>
#include<string.h>
int nIndex=0;
struct InterCode
char operand1;
char operand2;
char opera;
};
%}
%union
char sym;
%%
|expr ';'
|'('expr')' {$$=(char)$2;}
|NUMBER {$$=(char)$1;}
|LETTER {$$=(char)$1;}
%%
yyerror(char *s)
printf("%s",s);
exit(0);
char temp='A';
Code[nIndex].operand1=operand1;
Code[nIndex].operand1=operand2;
Code[nIndex].opera=opera;
nIndex++;
temp++;
return temp;
ThreeAddressCode()
int nCnt=0;
char temp='A';
temp++;
while(nCnt<nIndex)
printf("%c:=\t",temp);
if(isalpha(Code[nCnt].operand1))
printf("%c\t",Code[nCnt].operand1);
else
printf("%c\t",temp);
printf("%c\t",Code[nCnt].opera);
if(isalpha(Code[nCnt].operand2))
printf("%c\t",Code[nCnt].operand2);
else
printf("%c\t",temp);
printf("\n");
nCnt++;
temp++;
void Quadruples()
int nCnt=0;
char temp='A';
temp++;
printf("\n\n\tQuadruples\n");
while(nCnt<nIndex)
printf("\n(%d) \t %c\t",nCnt,Code[nCnt].opera);
if(isalpha(Code[nCnt].operand1))
printf("%c\t",Code[nCnt].operand1);
else
printf("%c\t",temp);
if(isalpha(Code[nCnt].operand2))
printf("%c\t",Code[nCnt].operand2);
else
printf("%c\t",temp);
printf("%c\t",temp);
printf("\n");
nCnt++;
temp++;
main()
yyparse();
ThreeAddressCode();
Quadruples();
yywrap()
return 1;
8.Code Optimization:
If the compiler is an optimizing compiler, one of these stages "optimizes" the machine language code so
that it either takes less time to run or occupies less memory or sometimes both. Of course, whatever
optimizations the compiler does, it must not affect the logic of the program i.e. the optimization must
preserve the meaning of the program. One might wonder what type of optimizations the compiler uses to
produce efficient machine code? Since in no case the meaning of the program being compiled should be
changed, the compiler must inspect the program very thoroughly and find out the suitable optimizations
that can be applied. As we may wonder, such a thorough analysis of the program and then finding and
applying suitable optimizations is a complex and time consuming process.
A few type of code optimizations that the GNU C Compiler uses so that we can understand how the code
is optimized and appreciate the complexity of the optimization process. The GNU C Compiler is a
sophisticated optimizing C compiler that uses a large array of optimization techniques to produce
efficient code. It may not be possible to describe all of them, so I have chosen some that are interesting
and also easy to understand.
Constant Folding
Common Subexpression Elimination
Dead Code Elimination
Strength Reduction using Induction Variable
The GNU C Compiler is a sophisticated optimizing C compiler that uses a large array of
optimization techniques to produce efficient code.
The GNU C Compiler (called GCC henceforth) reads a C program source file, however,
it can also produce assembly language source code for the program instead of the object
code, so that we can read it and understand how the assembly language program looks.
We will be generating such assembly language files to see the optimizations being used
by the compiler, so it would be beneficial if we see how the assembly language code for a
simple C program looks like.
This is optional phase described to improve the intermediate code so that the
output runs faster and takes less space. Its output is another intermediate code program that does the
some job as the original, but in a way that saves time and / or spaces.
1, Local Optimization:-
There are local transformations that can be applied to a program to make an improvement. For example,
If A > B goto L2
Goto L3
L2 :
This can be replaced by a single statement
If A < B goto L3
Another important local optimization is the elimination of common sub-expressions
A := B + C + D
E := B + C + F
Might be evaluated as
T1 := B + C
A := T1 + D
E := T1 + F
Take this advantage of the common sub-expressions B + C.
2, Loop Optimization:-
Another important source of optimization concerns about increasing the speed of loops. A typical loop
improvement is to move a computation that produces the same result each time around the loop to a
point, in the program just before the loop is entered.
In this we use gcc compiler for compiling the program. Why because in cc compiler it is not
possible to create assembly code file. To create assembly file we use –S option , through this we
generate assembly file named as filename.s. To optimize this assembly code we use -O2 option.
int main()
{
int a, b;
int x, y, z;
scanf("%d %d", &a, &b);
x = a * b;
if(b >= 4)
{
y = a * b;
z = 0;
}
else
{
z = a * b * 4;
y = 0;
}
.file "test3.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d %d"
.LC1:
.string "x = %d, y = %d, z = %d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ebx
xorl %ebx, %ebx
pushl %ecx
subl $32, %esp
leal -16(%ebp), %eax
movl %eax, 8(%esp)
leal -12(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call scanf
movl -16(%ebp), %eax
movl %eax, %edx
imull -12(%ebp), %edx
cmpl $3, %eax
movl %edx, %ecx
jg .L4
leal 0(,%edx,4), %ebx
xorl %ecx, %ecx
.L4:
movl %ebx, 12(%esp)
movl %ecx, 8(%esp)
movl %edx, 4(%esp)
movl $.LC1, (%esp)
call printf
addl $32, %esp
xorl %eax, %eax
popl %ecx
popl %ebx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section .note.GNU-stack,"",@progbits
/* test4.c */
/* demonstration of dead code elimination */
#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
return 0;
}
/* end of test4.c */
/* --------------------------------------------------------------- */
OUTPUT:
[sireesha@linuxserver ~]$ gcc -c –S test4.c
[sireesha@linuxserver ~]$ gcc -c –S -O2 test4.c
[sireesha@linuxserver ~]$vi test4.s
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
leal -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call scanf
addl $36, %esp
xorl %eax, %eax
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section .note.GNU-stack,"",@progbits