SS Lab Manual
SS Lab Manual
1st Step: Using gedit create a file with extension l. For example: prg1.l
2nd Step: lex prg1.l
3rd Step: cc lex.yy.c –ll
4th Step: ./a.out
{definitions}
%%
{rules}
%%
{user subroutines/code section}
%% is a delimiter to the mark the beginning of the Rule section. The second %% is optional,
but the first is required to mark the beginning of the rules. The definitions and the code
/subroutines are often omitted.
Lex variables
yyin Of the type FILE*. This points to the current file being parsed by the lexer.
yyout Of the type FILE*. This points to the location where the output of the lexer
will be written. By default, both yyin and yyout point to standard input and
output.
yytext The text of the matched pattern is stored in this variable (char*).
yyleng Gives the length of the matched pattern.
yylineno Provides current line number information. (May or may not be supported by
the lexer.)
Lex functions
yylex() The function that starts the analysis. It is automatically generated by Lex.
yywrap() This function is called when end of file (or input) is encountered. If this
function returns 1, the parsing stops. So, this can be used to parse multiple
files. Code can be written in the third section, which will allow multiple files
to be parsed. The strategy is to make yyin file pointer (see the
preceding table) point to a different file until all the files are parsed. At the
end, yywrap() can return 1 to indicate end of parsing.
yyless(int n) This function can be used to push back all but first „n‟ characters of the read
token.
yymore() This function tells the lexer to append the next token to the current token.
Regular Expressions
It is used to describe the pattern. It is widely used to in lex. It uses meta language. The
character used in this meta language are part of the standard ASCII character set. An
expression is made up of symbols. Normal symbols are characters and numbers, but there are
other symbols that have special meaning in Lex. The following two tables define some of the
symbols used in Lex and give a few typical examples.
Character Meaning
A-Z, 0-9, a-z Characters and numbers that form part of the pattern.
. Matches any character except \n.
Used to denote range. Example: A-Z implies all characters from A
- to Z.
A character class. Matches any character in the brackets. If the first
[] character is ^ then it indicates a negation pattern. Example: [abC]
matches either of a, b, and C.
* Match zero or more occurrences of the preceding pattern.
Matches one or more occurrences of the preceding pattern.(no
empty string).
+ Ex: [0-9]+ matches “1”,”111” or “123456” but not an empty string.
Matches zero or one occurrences of the preceding pattern. Ex:
-?[0-9]+ matches a signed number including an optional
? leading minus.
$ Matches end of line as the last character of the pattern.
1) Indicates how many times a pattern can be present. Example:
A{1,3} implies one to three occurrences of A may be present.
2) If they contain name, they refer to a substitution by that name.
{} Ex: {digit}
Used to escape meta characters. Also used to remove the special
\ meaning of characters as defined in this table.
Ex: \n is a newline character, while “\*” is a literal asterisk.
^ Negation.
Matches either the preceding regular expression or the following
regular expression.
| Ex: cow|sheep|pig matches any of the three words.
"< symbols>" Literal meanings of characters. Meta characters hold.
Look ahead. Matches the preceding pattern only if followed by the
succeeding expression. Example: A0/1 matches A0 only if A01 is
/ the input.
Groups a series of regular expressions together into a new regular
expression.
Ex: (01) represents the character sequence 01. Parentheses are
() useful when building up complex patterns with *,+ and |
The name is an acronym for “Yet Another Compiler Compiler”. YACC generates the
code for the parser in the C programming language. YACC was developed at AT& T for the
Unix operating system. YACC has also been rewritten for other languages, including Java,
Ada.
The function parser calls the lexical analyzer to pick up the tokens from the input
stream. These tokens are organized according to the input structure rules .The input structure
rule is called as grammar. When one of the rule is recognized, then user code supplied for this
rule ( user code is action) is invoked. Actions have the ability to return values and makes use
of the values of other actions.
When we run YACC, it generates a parser in file y.tab.c and also creates an include
file y.tab.h. To obtain tokens, YACC calls yylex. Function yylex has a return type of int, and
returns the token. Values associated with the token are returned by lex in variable yylval.
Structure of YACC source program:
Basic Specification:
Every YACC specification file consists of three sections. The declarations, Rules
(of grammars), programs. The sections are separated by double percent “%%” marks. The
% is generally used in YACC specification as an escape character.
The general format for the YACC file is very similar to that of the Lex file.
{definitions}
%%
{rules}
%%
{user subroutines}
%% is a delimiter to the mark the beginning of the Rule section.
Definition Section
%union It defines the Stack type for the Parser. It is a union of various datas/structures/
Objects
%token These are the terminals returned by the yylex function to the YACC. A token can
also have type associated with it for good type checking and syntax directed
translation. A type of a token can be specified as %token <stack
member>tokenName.
Ex: %token NAME NUMBER
%type The type of a non-terminal symbol in the Grammar rule can be specified with
this.The format is %type <stack member>non-terminal.
%start Specifies the L.H.S non-terminal symbol of a production rule which should be
taken as the starting point of the grammar rules.
%prec Changes the precedence level associated with a particular rule to that of the
following token name or literal
Rules Section
The rules section simply consists of a list of grammar rules. A grammar rule has the form:
A: BODY
A represents a nonterminal name, the colon and the semicolon are YACC punctuation and
BODY represents names and literals. The names used in the body of a grammar rule may represent
tokens or nonterminal symbols. The literal consists of a character enclosed in single quotes.
Apart from the program code, it includes the current activity represented by
➢
Program Counter,
➢
Contents of Processor registers,
➢ Process Stack which contains temporary data like function parameters, return addresses
and local variables
➢
Data section which contains global variables
➢ Heap for dynamic memory allocation
Scheduling Algorithms
CPU Scheduler can select processes from ready queue based on various scheduling
algorithms. Different scheduling algorithms have different properties, and the choice of a
particular algorithm may favor one class of processes over another. The scheduling criteria
include
➢ CPU utilization:
➢ Throughput: The number of processes that are completed per unit time.
Deadlocks
A process requests resources; and if the resource is not available at that time, the
process enters a waiting state. Sometimes, a waiting process is never able to change state,
because the resource is has requested is held by another process which is also waiting. This
situation is called Deadlock. Deadlock is characterized by four necessary conditions
➢ Mutual Exclusion
➢
➢ Hold and Wait ➢ No Preemption Circular Wait
Shortest remaining time, also known as shortest remaining time first (SRTF), is
aschedulingmethod that is apreemptiveversion ofshortest job nextscheduling. In this
scheduling algorithm, theprocesswith the smallest amount of time remaining until completion
is selected to execute. Since the currently executing process is the one with the shortest amount
of time remaining by definition, and since that time should only reduce as execution
progresses, processes will always run until they complete or a new process is added that
requires a smaller amount of time.
Shortest remaining time is advantageous because short processes are handled very
quickly. The system also requires very little overhead since it only makes a decision when a
process completes or a new process is added, and when a new process is added the algorithm
only needs to compare the currently executing process with the new process, ignoring all other
processes currently waiting to execute.
Like shortest job first, it has the potential forprocess starvation; long processes may be
held off indefinitely if short processes are continually added.
The name of the algorithm comes from the round-robin principle known from other
fields, where each person takes an equal share of something in turn.
Banker’s algorithm:
The Banker's algorithm, sometimes referred to as the detection algorithm, is a
resourceallocation and deadlock avoidance algorithm developed by Edsger Dijkstra that tests
for safety by simulating the allocation of predetermined maximum possible amounts of all
resources, and then makes an "s-state" check to test for possible deadlock conditions for all
other pending activities, before deciding whether allocation should be allowed to continue.
The algorithm was developed in the design process for the operating system and
originally described (in Dutch) in EWD108. When a new process enters a system, it must
declare the maximum number of instances of each resource type that it may ever claim;
clearly, that number may not exceed the total number of resources in the system. Also, when
a process gets all its requested resources it must return them in a finite amount of time.
Page replacement algorithms LRU and FIFO:
In a computer operating system that uses paging for virtual memory management,
pagereplacement algorithms decide which memory pages to page out, sometimes called
swap out, or writeto disk, when a page of memory needs to be allocated. Page replacement
happens when a requested page is not in memory (page fault) and a free page cannot be used
to satisfy the allocation, either because there are none, or because the number of free pages is
lower than some threshold.
When the page that was selected for replacement and paged out is referenced again it
has to be paged in (read in from disk), and this involves waiting for I/O completion. This
determines the quality of the page replacement algorithm: the less time waiting for page- ins,
the better the algorithm. A page replacement algorithm looks at the limited information about
accesses to the pages provided by hardware, and tries to guess which pages should be replaced
to minimize the total number of page misses, while balancing this with the costs (primary
storage and processor time) of the algorithm itself. The page replacing problem is a typical
online problem from the competitive analysis perspective in the sense that the optimal
deterministic algorithm is known.
INTRODUCTION TO COMPILER DESIGN
A program for a computer must be built by combining these very simple commands into a
program in what is called machine language. Since this is a tedious and error prone process most
programming is, instead, done using a high-level programming language. This language can be very
different from the machine language that the computer can execute, so some means of bridging the
gap is required. This is where the compiler comes in. A compiler translates (or compiles) a program
written in a high-level programming language that is suitable for human programmers into the lowlevel
machine language that is required by computers.
Parsing:
A parser is a compiler or interpreter component that breaks data into smaller elements
for easy translation into another language. A parser takes input in the form of a sequence of
tokens or program instructions and usually builds a data structure in the form of a parse tree
or an abstract syntax tree.
A parser's main purpose is to determine if input data may be derived from the start
symbol of the grammar.
Top-Down Parsing:
When the parser starts constructing the parse tree from the start symbol and then tries
to transform the start symbol to the input, it is called top-down parsing.
Example: One solution to the quadratic equation using three address code is as
below. x = (-b + sqrt(b^2 - 4*a*c)) / (2*a) t1 = b * b t2 = 4 * a t3 = t2 * c t4 = t1 - t3
t5 = sqrt(t4) t6 = 0 - b t7 = t5 + t6 t9 = t7 / t8 x = t9 t8 = 2 * a
Procedure for Program Execution
➢ For Lex Program
Step 1: Create the lex file in unix envirnonment
vi filename.l
Step 2: Save and quit
Press Esc : wq if vi is used
Step 3: Compile the program using command
lex filename.l and
cc lex.yy.c -ll
Step 4:Execute the program using command:
./a.out
➢ For Yacc Program
Step 1: Create the lex file and yacc file both in unix envirnonment
vi filename.l
vi filename.y
Step 2: Save and quit
Press Esc : wq if vi is used
Step 3: Compile the both program using command
lex filename.l
yacc –d filename.y
cc lex.yy.c y.tab.c –ll –ly
Step 4:Execute the program using command:
./a.out
➢ For C/C++ Program
Step 1: Create the C/C++ file in unix envirnonment
vi filename.c
vi filename.cpp
Step 2: Save and quit
Press Esc : wq if vi is used
Step 3: Compile the both program using command
cc filename.c
g++ filename.cpp
Step 4: Execute the program using command:
./a.out
Program: 1A
Write a LEX program to recognize valid arithmetic expression. Identifiers in the expression could
be only integers and operators could be + and *. Count the identifiers & operators present and print
them separately.
PREREQUISITES
1. Define Regular Expression.
2. List and explain RE with examples.
3. Phases of Compiler.
4. Structure of Lex.
SOURCE CODE
%{
#include<stdio.h>
#include<string.h>
int c1=0,c2=0,c3=0,brackets=0,flag=0,l=0,i,k=0;
char opnd[20][20],oprt[20][20];
%}
%%
"+"|"*" {c1++; c2++; strcpy(oprt[k],yytext); k++;}
[0-9]+ {c2++; c3++;strcpy(opnd[l],yytext); l++;}
[(] brackets++;
[)] {if(brackets>0)
{ brackets--;}
else
flag=1;}
[\n] return;
%%
main()
{
printf("enter the expression\n");
yylex();
printf("the number of operators=%d\n",c1);
printf("the operators are\n");
for(i=0;i<k;i++)
{
printf("%s\n",oprt[i]);
}
printf("the number of identifiers=%d\n",c3);
printf("the identifiers are\n");
for(i=0;i<l;i++)
{
printf("%s\n",opnd[i]);
}
printf("the input expression is ");
if(c2%2==0||brackets!=0||c2==0||flag==1||c1>=c3)
printf("invalid expression\n");
else
printf("valid expression\n");
}
Dept. of CSE, 1
SJCIT
OUTPUT/ RESULTS
Dept. of CSE, 2
SJCIT
Program: 1B
Write YACC program to evaluate arithmetic expression involving operators: +, -, *, and /.
PREREQUISITES
1. Definition of Parser.
2. Define CFG.
3. Structure of YACC.
SOURCE CODE
LEX FILE:
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext); return dig;}
[ \t] ;
\n return 0;
. return yytext[0];
%%
YACC FILE:
%{
#include<stdio.h>
%}
%token dig
%left '+','-'
%left '*','/'
%%
S:E {printf("value=%d\n",$1);exit(0);}
| error'\n' {printf("invalid expression\n");exit(0);}
;
E:E'+'E {$$=$1+$3;}
|E'-'E {$$=$1-$3;}
|E'*'E {$$=$1*$3;}
|E'/'E {if($3==0)
{
printf("\nerror division by zero\n");
exit(0);
}
else
{ $$=$1/$3;}
}
|'('E')' {$$=$2;}
|dig {$$=$1;}
;
%%
int main()
{
Dept. of CSE, 3
SJCIT
yyparse();
return 0;
}
int yyerror()
{
printf("error");
return 1;
}
OUTPUT/ RESULTS
Dept. of CSE, 4
SJCIT
Program: 2
Develop, Implement and Execute a program using YACC tool to recognize all strings
ending with b preceded by n a’s using the grammar a n b (note: input n value)
PREREQUISITES
1. Write Grammar for a n b
2. Write Grammar for a nbbbn
SOURCE CODE
LEX FILE:
%{
#include "y.tab.h"
%}
%%
a {return A;}
b {return B;}
\n {return 0;}
. {return yytext[0];}
%%
YACC FILE:
%{
#include <stdio.h>
int count=0,n;
%}
%token A
%token B
%%
S : T B {
if (count<n || count>n) {
yyerror();
}
}
Aa : A {count++;}
T : Aa| T Aa;
%%
int main()
{ printf("Enter the value of n \n");
scanf("%d",&n);
printf("Enter the string\n");
yyparse();
printf("Valid string");
}
int yyerror()
{
printf("Invalid string\n");
exit(0);
}
Dept. of CSE, 5
SJCIT
OUTPUT/ RESULTS
Dept. of CSE, 6
SJCIT
Program: 3
Design, develop and implement YACC/C program to construct Predictive / LL(1) Parsing Table
for the grammar rules: A →aBa , B →bB | ε. Use this table to parse the sentence: abba$
PREREQUISITES
1. Rules for FIRST and FOLLOW sets.
2. Algorithm for predictive parsing table.
SOURCE CODE
#include<stdio.h>
#include<string.h>
predictiveparser()
{
char fin[10][20],st[10][20],ft[20][20],fol[20][20];
int a=0,e,i,t,b,c,n,k,l=0,j,s,m,p;
printf("Enter the no. of Nonterminals\n");
scanf("%d",&n);
printf("Enter the productions in a grammar\n");
for(i=0;i<n;i++)
scanf("%s",st[i]);
for(i=0;i<n;i++)
fol[i][0]='\0';
for(s=0;s<n;s++)
{
for(i=0;i<n;i++)
{
j=3;
l=0;
a=0;
l1: if(!((st[i][j]>64)&&(st[i][j]<91)))
{
for(m=0;m<l;m++)
{
if(ft[i][m]==st[i][j])
goto s1;
}
ft[i][l]=st[i][j];
l=l+1;
s1: j=j+1;
}
else
{
if(s>0)
{
while(st[i][j]!=st[a][0])
{
a++;
}
b=0;
while(ft[a][b]!='\0')
{
Dept. of CSE, 7
SJCIT
for(m=0;m<l;m++)
{
if(ft[i][m]==ft[a][b])
goto s2;
}
ft[i][l]=ft[a][b];
l=l+1;
s2: b=b+1;
}
}
}
while(st[i][j]!='\0')
{
if(st[i][j]=='|')
{
j=j+1;
goto l1;
}
j=j+1;
}
ft[i][l]='\0';
}
}
printf("\n FIRST SET :\n");
for(i=0;i<n;i++)
printf("FIRS[%c]= %s\t\n",st[i][0],ft[i]);
fol[0][0]='$';
for(i=0;i<n;i++)
{
k=0;
j=3;
if(i==0)
l=1;
else
l=0;
k1:while((st[i][0]!=st[k][j])&&(k<n))
{
if(st[k][j]=='\0')
{
k++;
j=2;
}
j++;
}
j=j+1;
if(st[i][0]==st[k][j-1])
{
if((st[k][j]!='|')&&(st[k][j]!='\0'))
{
a=0;
if(!((st[k][j]>64)&&(st[k][j]<91)))
{
for(m=0;m<l;m++)
Dept. of CSE, 8
SJCIT
{
if(fol[i][m]==st[k][j])
goto q3;
}
q3: fol[i][l]=st[k][j];
l++;
}
else
{
while(st[k][j]!=st[a][0])
{
a++;
}
p=0;
while(ft[a][p]!='\0')
{
if(ft[a][p]!='@')
{
for(m=0;m<l;m++)
{
if(fol[i][m]==ft[a][p])
goto q2;
}
fol[i][l]=ft[a][p];
l=l+1;
}
else
e=1;
q2: p++;
}
if(e==1)
{
e=0;
goto a1;
}
}
}
else
{
Dept. of CSE, 10
SJCIT
q1:c++;
}
}
goto k1;
}
fol[i][l]='\0';
}
printf("\n FOLLOW SET :\n");
for(i=0;i<n;i++)
printf("FOLLOW[%c] = %s \n",st[i][0],fol[i]);
printf("\n");
s=0;
for(i=0;i<n;i++)
{
j=3;
while(st[i][j]!='\0')
{
if((st[i][j-1]=='|')||(j==3))
{
for(p=0;p<=2;p++)
{
fin[s][p]=st[i][p];
}
t=j;
for(p=3;((st[i][j]!='|')&&(st[i][j]!='\0'));p++)
{
fin[s][p]=st[i][j];
j++;
}
fin[s][p]='\0';
if(st[i][t]=='@')
{
b=0; a=0;
while(st[a][0]!=st[i][0])
{
a++;
}
while(fol[a][b]!='\0')
{
printf("M[ %c , %c ] = %s
n",st[i][0],fol[a][b],fin[s]);
b++;
}
}
else if(!((st[i][t]>64)&&(st[i][t]<91)))
{
printf("M[ %c , %c ] = %s
n",st[i][0],st[i][t],fin[s]);
}
else
{
b=0;
Dept. of CSE, 11
SJCIT
a=0;
Dept. of CSE, 12
SJCIT
while(st[a][0]!=st[i][3])
a++;
while(ft[a][b]!='\0')
{
printf("M[ %c , %c ] = %s
n",st[i][0],ft[a][b],fin[s]);
b++;
}
}
s++;
}
if(st[i][j]=='|')
j++;
}
}
}
parseinputstring()
{
char input[20],stack[20];
char m[2][3][3]={"aBa"," "," ","@","bB"," "};
int size[2][3]={3,20,0,1,2,0};
int i,j,k,n,str1,str2;
printf("\n Enter the input string: ");
scanf("%s",input);
strcat(input,"$");
n=strlen(input);
stack[0]='$';
stack[1]='A';
stack[2] ='\0';
i=1;
j=0;
printf("\nStack Input\n");
printf("- -\n");
printf("%s %s\n", stack, input);
while((stack[i]!='$')&&(input[j]!='$'))
{
if(stack[i]==input[j] && ( stack[i] && input[j] != '$'))
{
i--;
j++;
for(k=0;k<=i;k++)
printf("%c",stack[k]);
printf(" ");
for(k=j;k<n;k++)
printf("%c",input[k]);
printf(" \n ");
}
switch(stack[i])
{
case 'A': str1=0;
break;
case 'B': str1=1;
Dept. of CSE, 13
SJCIT
break;
Dept. of CSE, 14
SJCIT
}
switch(input[j])
{
case 'a': str2=0;
break;
case 'b': str2=1;
break;
case '$': str2=2;
break;
}
if(m[str1][str2][0]=='\0')
printf("\nERROR");
else if(m[str1][str2][0]=='@')
i--;
else
{
for(k=size[str1][str2]-1;k>=0;k--)
{
stack[i]=m[str1][str2][k];
i++;
}
i--;
}
for(k=0;k<=i;k++)
printf("%c",stack[k]);
printf(" ");
for(k=j;k<=n;k++)
printf("%c",input[k]);
printf(" \n ");
}
printf("SUCCESS\n");
}
void main()
{
printf("\n1. Construction of Predictive Parsing Table LL(1)
or the grammar\n");
printf(" A -> aBa \n B -> bB | @ \n\n\n");
predictiveparser();
printf("\n\n");
printf("The predictive parsing table is:\n");
printf("- -
--\n");
printf("|\tNT\t\t| a\t\t| b\t| $\t|\n");
printf("- -
--\n");
printf("|\tA\t\t| A->aBa\t|\t|\t|\n");
printf("- -
--\n");
printf("|\tB\t\t| B->@\t\t|B->bB\t|\t|\n");
printf("- -
--\n\n\n");
printf( "2. Parsing the given input string using the above
table\n\n");
Dept. of CSE, 15
SJCIT
parseinputstring();
}
OUTPUT/RESULTS
Dept. of CSE, 16
SJCIT
Program: 4
Design, develop and implement YACC/C program to demonstrate Shift Reduce Parsing technique
for the grammar rules: E →E+T | T, T →T*F | F, F →(E) | id and parse the sentence: id + id *
id.
PREREQUISITES
1. Explanation of Bottom up parser
2. Shift/Reduce conflicts and Reduce/Reduce conflicts
3. Precedence orders and associativity.
SOURCE CODE
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int len,top=-1,i,j;
char str[20],stk[20];
void errfcn();
void stkfcn();
void chk();
void smch();
void main()
{
puts("Note: Do Not give spaces in between the operator in the
input\n");
puts("The given GRAMMAR is \nE->E+T|T\nT->T*F|F\nF->(E)|id\n");
puts("enter the input srting");
gets(str);
len=strlen(str);
puts("stack\t\tinput\t\taction\n");
printf("$%s\t\t%s$\n",stk,str);
for(i=0;i<len;i++)
{
if(str[i]=='i' && str[i+1]=='d')
{
str[i]=str[i+1]=' ';
top=top+1;
printf("$%sid\t\t%s$\t\tSHIFT->id\n",stk,str);
stk[top]='F';
printf("$%s\t\t%s$\t\tREDUCE to F->id\n",stk,str);
stkfcn();
smch();
i=i+1;
}
else if(str[i]=='+' || str[i]=='*')
{
top=top+1;
stk[top]=str[i];
str[i]=' ';
if(stk[top]=='+')
printf("$%s\t\t%s$\t\tSHIFT->+\n",stk,str);
else
Dept. of CSE, 17
SJCIT
printf("$%s\t\t%s$\t\tSHIFT->*\n",stk,str);
if((stk[0]=='+'|| stk[0]=='*')||((stk[top]=='+'||
stk[top]=='*')&&(stk[top-1]=='+'|| stk[top-1]=='*')))
errfcn();
}
else
errfcn();
}
if(stk[top]=='+'||stk[top]=='*')
errfcn();
chk();
if(top==0)
{
if(stk[top]=='F')
{
stk[top]='T';
printf("$%s\t\t%s$\t\tREDUCE to T->F\n",stk,str);
}
if(stk[top]=='T')
{
stk[top]='E';
printf("$%s\t\t%s$\t\tREDUCE to E->T\n",stk,str);
}
}
printf("$%s\t\t%s$\t\tSUCCESS\n",stk,str);
}
void stkfcn()
{
if((top==0)&&((str[i+2]=='+')||(str[i+2]==' ')))
{
stk[top]='T';
printf("$%s\t\t%s$\t\tREDUCE to T->F\n",stk,str);
stk[top]='E';
printf("$%s\t\t%s$\t\tREDUCE to E->T\n",stk,str);
return;
}
else if((top==0)&&(str[i+2]=='*'))
{
stk[top]='T';
printf("$%s\t\t%s$\t\tREDUCE to T->F\n",stk,str);
return;
}
if(stk[top-1]=='+')
{
stk[top]='T';
printf("$%s\t\t%s$\t\tREDUCE to T->F\n",stk,str);
chk();
}
else if(stk[top-1]=='*')
chk();
}
Dept. of CSE, 18
SJCIT
void chk()
{
if(stk[top-1]=='*')
{
stk[top-1]=stk[top]=' ';
top=top-2;
printf("$%s\t\t%s$\t\tREDUCE to T->T*F\n",stk,str);
if((str[i+2]=='+')&&(top==0))
{
stk[top]='E';
printf("$%s\t\t%s$\t\tREDUCE to E->T\n",stk,str);
}
}
else if((stk[top-1]=='+' && str[i+2]=='+')||(stk[top-1]=='+' &&
str[i+2]!='*'))
{
if(top-2==0)
{
stk[top-2]='E';
}
else
{
stk[0]='E';
for(j=3;j<=top;j++)
{
stk[j]=stk[j-2];
}
}
stk[top-1]=stk[top]=' ';
top=top-2;
printf("$%s\t\t%s$\t\tREDUCE to E->E+T\n",stk,str);
}
}
void smch()
{
if(stk[top-1]=='+' && str[i+2]=='+')
{
if(top-2==0)
{
stk[top-2]='E';
}
else
{
stk[0]='E';
for(j=3;j<=top;j++)
{
stk[j]=stk[j-2];
}
}
stk[top-1]=stk[top]=' ';
top=top-2;
printf("$%s\t\t%s$\t\tREDUCE to E->T\n",stk,str);
}
Dept. of CSE, 19
SJCIT
}
void errfcn()
{
printf("ERROR:invalid argument\n");
exit(0);
}
OUTPUT/RESULTS
Dept. of CSE, 20
SJCIT
Program: 5
Design, develop and implement a C/Java program to generate the machine code using
Triples for the statement A = -B * (C +D) whose intermediate code in three-address form:
T1 = -B
T2 = C + D
T3 = T1 + T2
A = T3
PREREQUISITES
1. Different forms of ICG
2. DAG Representation with example.
SOURCE CODE
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
char op[2],arg1[5],arg2[5],result[5];
void main()
{
FILE *fp1,*fp2;
fp1=fopen("input.txt","r");
fp2=fopen("output.txt","w");
while(!feof(fp1))
{
fscanf(fp1,"%s%s%s%s",result,arg1,op,arg2);
if(strcmp(op,"+")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nADD R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"*")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMUL R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"-")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nSUB R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"/")==0)
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nDIV R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"=")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
Dept. of CSE, 21
SJCIT
fprintf(fp2,"\nMOV %s,R0",result);
}
}
fclose(fp1);
fclose(fp2);
}
OUTPUT/RESULTS
Dept. of CSE, 22
SJCIT
Program:6A
Write a LEX program to eliminate comment lines in a C program and copy the resulting
program into a separate file.
PREREQUISITES
SOURCE CODE
%{
#include<stdio.h>
int slc=0,mlc=0;
%}
%x CMNTSL CMNTML
%%
"/*" {BEGIN CMNTML; mlc++;}
<CMNTML>. ;
<CMNTML>\n ;
<CMNTML>"*/" {BEGIN 0;}
"//" {BEGIN CMNTSL; slc++;}
<CMNTSL>. ;
<CMNTSL>\n {BEGIN 0;}
%%
main(int argc, char *argv[])
{
if(argc!=3)
{
printf("usage:%s <src file> <dst file>\n",argv[0]);
return;
}
yyin=fopen(argv[1],"r");
yyout=fopen(argv[2],"w");
yylex();
printf("Number of single comment lines=%d\n",slc);
printf("Number of multi comment lines=%d\n",mlc);
}
Dept. of CSE, 23
SJCIT
OUTPUT/RESULTS
Dept. of CSE, 24
SJCIT
Program: 6B
Write YACC program to recognize valid identifier, operators and keywords in the given text (C
program) file.
PREREUISITES
1. Built-in function of YACC.
2. Lexer- parser communication.
SOURCE CODE
LEX FILE:
%{
#include <stdio.h>
#include "y.tab.h"
extern int yylval;
%}
%%
[ \t] ;
YACC FILE:
{
#include<stdio.h>
#include<stdlib.h>
int id=0, dig=0, key=0, op=0;
extern FILE *yyin;
%}
%token DIGIT ID KEY OP
%%
input:
DIGIT input { dig++; }
| ID input { id++; }
| KEY input { key++; }
| OP input {op++;}
| DIGIT { dig++; }
| ID { id++; }
| KEY { key++; }
| OP { op++;}
;
%%
int main(int argc, char *argv[])
{
if(argc!=2)
{
printf("Usage: %s <source file>",argv[0]);
Dept. of CSE, 25
SJCIT
return;
Dept. of CSE, 26
SJCIT
}
yyin=fopen(argv[1],"r");
yyparse();
printf("numbers = %d\nKeywords = %d\nIdentifiers = %d\noperators =
%d\n",dig, key,id, op);
}
void yyerror()
{
printf("EEK, parse error! Message: ");
return;
}
OUTPUT/RESULTS
INPUT:
OUTPUT:
Dept. of CSE, 27
SJCIT
Program: 7
Design, develop and implement a C/C++/Java program to simulate the working of Shortest
remaining time and Round Robin (RR) scheduling algorithms. Experiment with different
quantum sizes for RR algorithm.
ALGORITHM / PROCEDURE
1. Write algorithm for SRT
2. Write algorithm for RR
SOURCE CODE
#include<stdio.h>
#include<stdlib.h>
int no;
void roundrobin(int,int,int[],int[]);
void srtf();
main()
{
int n,tq,choice;
int bt[10], st[10], i,j,k;
for(;;)
{
printf("Enter choice\n");
printf("1.Round Robin \n2.str \n3.Exit\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Round robin scheduling algorithm\n");
printf("Enter the number of process\n");
scanf("%d",&n);
printf("Enter burst time for sequences\n");
for(i=0;i<n;i++)
{
scanf("%d",&bt[i]);
st[i]=bt[i];
}
printf("Enter time quantum\n");
scanf("%d",&tq);
roundrobin(n,tq,st,bt);
break;
case 2: printf("\n\n-------------------Shortest remaining
time ----- ");
srtf();
break;
case 3: exit(0);
break;
}
}
}
void srtf()
{
int
n,j=0,st[10],bt[10],rt[10],remain=0,smallest,time=0,i,endtime,swt=0,stat=0
;
printf("Enter the no. of process:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter the arrivaltime for p[%d]:",i+1);
Dept. of CSE, 29
SJCIT
scanf("%d",&st[i]);
printf("Enter the burst time for p[%d]:",i+1);
scanf("%d",&bt[i]);
rt[i]=bt[i];
}
rt[100]=999;
printf("Process\t|writing time\t|turnarround time\n");
for(time=0;remain!=n;time++)
{
smallest=100;
for(i=0;i<n;i++)
{
if(st[i]<=time && rt[i]<rt[smallest] && rt[i]>0)
{
smallest=i;
}
}
rt[smallest]--;
if(rt[smallest]==0)
{
remain++;
endtime=time+1;
j=smallest;
printf("p[%d]\t|\t%d\t|\t%d\n",smallest+1,endtime-bt[j]-
st[j],endtime-st[j]);
swt +=endtime-bt[j]-st[j];
stat +=endtime-st[j];
}
}
float awt=0.0,atat=0.0;
awt=(float)swt/n;
atat=(float)stat/n;
printf("Average waiting time:%f\n",awt);
printf("Average turnarround time:%f\n",atat);
}
OUTPUT/RESULT
Enter choice
1.Round Robin
2.str
3.Exit
1
Round robin scheduling algorithm
Enter the number of process
4
Enter burst time for sequences
4252
Enter time quantum
Dept. of CSE, 30
SJCIT
15
process no burst time waiting time turnaround time
1 4 0 4
2 2 4 6
3 5 6 11
4 2 11 13
Average waiting time is5.250000
Average turnaround time is 8.500000
Enter choice
1.Round Robin
2.str
3.Exit
2
Dept. of CSE, 31
SJCIT
Program: 8
Design, develop and implement a C/C++/Java program to implement Banker’s algorithm.
Assume suitable input required to demonstrate the results.
ALGORITHM/PROCEDURE
1. Algorithm for Banker’s
SOURCE CODE
#include<stdio.h>
struct process
{
int all[6],max[6],need[6],finished,request[6];
}p[10];
int avail[6],sseq[10],ss=0,check1=0,check2=0,n,pid,nor,nori,work[6];
int main()
{
int safeseq(void);
int ch,k,i=0,j=0,pid,ch1;
int violationcheck=0,waitcheck=0;
do
{
printf("\n1.Input\n2.New Request\n3.Safe State or
Not\n4.Print\n5.Exit\nEnter your choice:");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("\nEnter the number of processes:");
scanf("%d",&n);
printf("\nEnter the number of resources:");
scanf("%d",&nor);
printf("\nEnter the available resources:");
for(j=0;j<n;j++)
{
for(k=0;k<nor;k++)
{
if(j==0)
{
printf("\nFor Resource Type %d:",k);
scanf("%d",&avail[k]);
}
p[j].max[k]=0;
p[j].all[k]=0;
p[j].need[k]=0;
p[j].finished=0;
p[j].request[k]=0;
}
}
for(i=0;i<n;i++)
{
printf("\nEnter Max and Allocated Resources for P %d
:",i);
Dept. of CSE, 32
SJCIT
for(j=0;j<nor;j++)
{
printf("\nEnter the Max of Resources %d:",j);
scanf("%d",&p[i].max[j]);
printf("\nAllocation of Resources %d:",j);
scanf("%d",&p[i].all[j]);
if(p[i].all[j]>p[i].max[j])
{
printf("\nAllocation should be less than or equal
to Max\n");
j--;
}
else
p[i].need[j]=p[i].max[j]-p[i].all[j];
}
}
break;
case 2:
violationcheck=0;
waitcheck=0;
printf("\nRequesting Process ID:\n");
scanf("%d",&pid);
for(j=0;j<nor;j++)
{
printf("\nNumber of Request for Resource %d:",j);
scanf("%d",&p[pid].request[j]);
if(p[pid].request[j]>p[pid].need[j])
violationcheck=1;
if(p[pid].request[j]>avail[j])
waitcheck=1;
}
if(violationcheck==1)
printf("\nThe Process Exceeds its Max needs:
Terminated\n");
else if(waitcheck==1)
printf("\nLack of Resources: Process State - Wait\n");
else
{
for(j=0;j<nor;j++)
{
avail[j]=avail[j]-p[pid].request[j];
p[pid].all[j]=p[pid].all[j]+p[pid].request[j];
p[pid].need[j]=p[pid].need[j]-p[pid].request[j];
}
ch1=safeseq();
if(ch1==0)
{
for(j=0;j<nor;j++)
{
avail[j]=avail[j]+p[pid].request[j];
p[pid].all[j]=p[pid].all[j]-p[pid].request[j];
Dept. of CSE, 33
SJCIT
p[pid].need[j]=p[pid].need[j]+p[pid].request[j];
Dept. of CSE, 34
SJCIT
}
}
else if(ch1==1)
printf("\nRequest committed.\n");
}
break;
case 3:
if(safeseq()==1)
printf("\nThe System is in Safe State\n");
else
printf("\nThe System is not in Safe State\n");
break;
case 4:
printf("\nNumber of Process:%d\n",n);
printf("\nNumber of Resources:%d\n",nor);
printf("\nPid\tMax\tAllocated\tNeed\n");
for(i=0;i<n;i++)
{
printf(" P%d :",i);
for(j=0;j<nor;j++)
printf(" %d ",p[i].max[j]);
printf("\t");
for(j=0;j<nor;j++)
printf(" %d ",p[i].all[j]);
printf("\t");
for(j=0;j<nor;j++)
printf(" %d ",p[i].need[j]);
printf("\n");
}
printf("\nAvailable:\n");
for(i=0;i<nor;i++)
printf(" %d ",avail[i]);
break;
case 5: break;
}
}while(ch!=5);
return 0;
}
int safeseq()
{
int tj,tk,i,j,k;
ss=0;
for(j=0;j<nor;j++)
work[j]=avail[j];
for(j=0;j<n;j++)
p[j].finished=0;
for(tk=0;tk<nor;tk++)
{
for(j=0;j<n;j++)
{
if(p[j].finished==0)
Dept. of CSE, 35
SJCIT
{
check1=0;
for(k=0;k<nor;k++)
if(p[j].need[k]<=work[k])
check1++;
if(check1==nor)
{
for(k=0;k<nor;k++)
{
work[k]=work[k]+p[j].all[k];
p[j].finished=1;
}
sseq[ss]=j;
ss++;
}
}
}
}
check2=0;
for(i=0;i<n;i++)
if(p[i].finished==1)
check2++;
printf("\n");
if(check2>=n)
{
for(tj=0;tj<n;tj++)
printf("p%d",sseq[tj]);
return 1;
}
else
printf("\nThe System is not in Safe State\n");
return 0;
}
OUTPUT/RESULTS
$ ./a.out
1.Input
2.New Request
3.Safe State or Not
4.Print
5.Exit
Enter your choice:1
Dept. of CSE, 36
SJCIT
For Resource Type 0:3
For Resource Type 1:3
For Resource Type 2:2
Dept. of CSE, 37
SJCIT
Enter the Max of Resources 0:4
Allocation of Resources 0:0
1. Input
2. New Request
3.Safe State or Not
4.Print
5.Exit
Enter your choice:3
p1p3p4p0p2
The System is in Safe State
1. Input
2. New Request
3.Safe State or Not
4.Print
5.Exit
Available:
332
1. Input
2. New Request
3.Safe State or Not
4.Print
5.Exit
Enter your choice:2
Dept. of CSE, 38
SJCIT
Requesting Process ID:
1
Number of Request for Resource 0:1
Number of Request for Resource 1:0
Number of Request for Resource 2:2
p1p3p4p0p2
Request committed.
1.Input
2.New Request
3.Safe State or Not
4.Print
5.Exit
Available:
230
1. Input
2. New Request
3.Safe State or Not
4.Print
5.Exit
1.Input
2. New Request
3. Safe State or Not
4.Print
5.Exit
Enter your choice:2
Dept. of CSE, 39
SJCIT
4
1.Input
2.New Request
3.Safe State or Not
4.Print
5.Exit
Enter your choice:2
1.Input
2.New Request
3.Safe State or Not
4.Print
5.Exit
Available:
230
1. Input
2. New Request
Dept. of CSE, 40
SJCIT
3. Safe State or Not
4.Print
5.Exit
Enter your choice:5
Dept. of CSE, 41
SJCIT
Program: 9
Design, develop and implement a C/C++/Java program to implement page replacement
algorithms LRU and FIFO. Assume suitable input required to demonstrate the results.
ALGORITHM/PROCEDURE
1. Algorithm for LRU.
2. Algorithm for FIFO
SOURCE CODE
#include<stdio.h>
#include<stdlib.h>
Dept. of CSE, 42
SJCIT
PRESS 0 : ");
Dept. of CSE, 43
SJCIT
scanf("%d",&YN);
}
while(YN==1);return(0);
}
//FIFO
void FIFO(char s[],char F[],int l,int f)
{
int i,j=0,k,flag=0,cnt=0;
printf("\n\tPAGE\t FRAMES\t FAULTS");
for(i=0;i<l;i++)
{
for(k=0;k<f;k++)
{
I f(F[k]==s[i])
flag=1;
}
if(flag==0)
{
printf("\n\t%c\t",s[i]);
F[j]=s[i];
j++;
for(k=0;k<f;k++)
{
printf(" %c",F[k]);
}
printf("\tPage-fault%d",cnt);
cnt++;
}
else
{
flag=0;
printf("\n\t%c\t",s[i]);
for(k=0;k<f;k++)
{
printf(" %c",F[k]);
}
printf("\tNo page-fault");
}
if(j==f)
j=0;
}
}
//LRU
Dept. of CSE, 45
SJCIT
OUTPUT/RESULTS
Enter the no of empty frames: 3
Enter the length of the string: 20
Enter the string: 70120304230321201701
*********** MENU ***********
1:FIFO
2:LRU
4:EXIT
IF NO PRESS 0 : 1
1:FIFO
2:LRU
4:EXIT
Dept. of CSE, 46
SJCIT
Enter your choice: 2
IF NO PRESS 0 :
Dept. of CSE, 47
SJCIT
VIVA QUESTIONS
2. What is an Assembler?
Assembler for an assembly language, a computer program to translate between lower-level
representations of computer programs.
4. Explain yyleng?
Yyleng-contains the length of the string our lexer recognizes.
5. What is a Parser?
A Parser for a Grammar is a program which takes in the Language string as it's input and produces
either a corresponding Parse tree or an Error.
Dept. of CSE, 48
SJCIT
12. Are Lexical Analysis and Parsing two different Passes?
These two can form two different passes of a Parser. The Lexical analysis can store all the recognized
tokens in an intermediate file and give it to the Parser as an input. However it is more convenient to
have the lexical Analyzer as a co routine or a subroutine which the Parser calls whenever it requires a
token.
| OR (alternation)
() Group of
Subexpression
* 0 or more
Occurrences
? 0 or 1 Occurrence
+ 1 or more
Occurrences
{n,m} n-m Occurrences
15. If Context-free grammars can represent every regular expression, why do one needs
R.E at all?
Regular Expression are Simpler than Context-free grammars.
It is easier to construct a recognizer for R.E than Context-Free grammar.
Breaking the Syntactic structure into Lexical & non-Lexical parts provide better front end for the
Parser.
R.E are most powerful in describing the lexical constructs like identifiers, keywords etc while
Context-free grammars in representing the nested or block structures of the Language.
Dept. of CSE, 49
SJCIT
The Parsing method is which the Parse tree is constructed from the input language string beginning
from the leaves and going up to the root node.
Bottom-Up parsing is also called shift-reduce parsing due to its implementation. The YACC supports
shift-reduce parsing.
Dept. of CSE, 50
SJCIT