CD Lab Manual - Updated
CD Lab Manual - Updated
Compiler Design
Name ……………………………………………..
To be the fountainhead of novel ideas & innovations in science & technology &
persist to be a foundation of pride for all Indians.
Attaining global recognition in computer science and engineering education, research and training to
meet the growing needs of the industry and society.
Provide quality undergraduate and postgraduate education, in both the theoretical and applied
foundations of computer science, and train students to effectively apply this education to solve real-
world problems, thus amplifying their potential for lifelong high-quality careers.
1. To prepare students for successful careers in software industry that meet the needs of Indian
and multinational companies.
2. To develop the skills among students to analyze real world problem & implement with
computer engineering solution and in multidisciplinary projects.
4. To develop the ability to work with the core competence of computer science & engineering
i.e. software engineering, hardware structure & networking concepts so that one can find
feasible solution to real world problems.
6. To motivate students perseverance for lifelong learning and to introduce them to professional
ethics and codes of professional practice.
PO5. Modern tool usage: Create, select, and apply appropriate techniques,
resources, and modern engineering and IT tools including prediction and modeling
to complex engineering activities with an understanding of the limitations.
PO6. The engineer and society: Apply reasoning informed by the contextual
knowledge to assess societal, health, safety, legal and cultural issues and the
consequent responsibilities relevant to the professional engineering practice.
PO8. Ethics: Apply ethical principles and commit to professional ethics and
responsibilities and norms of the engineering practice.
PO12. Life-long learning: Recognize the need for, and have the preparation and
ability to engage in independent and life-long learning in the broadest context of
technological change.
3. Apply type checking for semantic analysis and analyze Run time environment.
2. While entering into the LAB students should wear their ID cards.
5. Students should sign in the LOGIN REGISTER before entering into the
laboratory.
6. Students should come with observation and record note book to the
laboratory.
9. After completing the laboratory exercise, make sure to SHUTDOWN the system
properly.
INDEX
Experiment-1
Compiler is a computer program that changes source code written in a high-level language into low-
level machine language. It translates the code written in one programming language to some other
language without modifying the definition of the code. The compiler also produces the end code
efficient which is optimized for execution time and memory space.
There are various types of compilers which are as follows
Traditional Compilers(C, C++, and Pascal) These compilers transform a source program in an HLL into its simi
Interpreters (LISP, SNOBOL, and Java1.0) These Compilers first convert Source code into intermediate code, a
Cross-Compilers These are the compilers that run on one machine and make code for another machine. A cross
Incremental Compilers Incremental Compiler is a compiler, which executes the recompilation of only a changed
Converters (e.g. COBOL to C++) These programs will be compiling from one high-level language to another.
Just-In-Time (JIT) Compilers (Java, Micosoft.NET) These are the runtime compilers from intermediate languag
Single-Pass Compiler In a single-pass compiler, when a line source is processed it is scanned and the tokens are
Multi-Pass Compiler The compiler scans the input source once and makes the first modified structure, therefore
Ahead-of-Time (AOT) Compilers (e.g., .NET ngen) These are the pre-compilers to the native code for Java and
Binary Compilation These compilers will be compiling the object code of one platform into the object code of a
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-2
Compilation:-
Definition:
Compilation is a process that translates a program in one language (the source language) into an
equivalent program in another language (the object or target language).
An important part of any compiler is the detection and reporting of errors; this will be dis-cussed in
more detail later in the introduction. Commonly, the source language is a high-level programming
language (i.e. a problem-oriented language), and the target language is a ma-chine language or
assembly language (i.e. a machine-oriented language). Thus compilation is fundamental concept in
the production of software: it is the link between the (abstract) world of application development and
the low-level world of application execution on machines. The complete process of compilation is
illustrated as:
Phases of a Compiler:-
The process of compilation is split up into six phases, each of which interacts with a symbol table
manager and an error handler. This is called the analysis/synthesis model of compilation. There are
many variants on this model, but the essential elements are the same.
Lexical Analysis
A lexical analyzer or scanner is a program that groups sequences of characters into lexemes and
outputs (to the syntax analyzer) a sequence of tokens. Here:
(a) Tokens are symbolic names for the entities that make up the text of the program; e.g. if for the
keyword if, and id for any identifier. These make up the output of
the lexical analyzer.
(b) A pattern is a rule that specifies when a sequence of characters from the input constitutes a token;
e.g. the sequence i, f for the token if, and any sequence of alphanumeric starting with a letter for the
token id.
(c) A lexeme is a sequence of characters from the input that match a pattern (and hence constitute an
instance of a token); for example if matches the pattern for if, and foo123bar matches the pattern for
id.
Syntax Analysis
A syntax analyzer or parser is a program that groups sequences of tokens from the lexical analysis
phase into phrases each with an associated phrase type.
A phrase is a logical unit with respect to the rules of the source language. For example, consider:
a := x * y + z
After lexical analysis, this statement has the structure
id1 assign id2 binop1 id3 binop2 id4
Parse Trees and Syntax Trees. The structure of a phrase is best thought of as a parse tree or a syntax
tree. A parse tree is tree that illustrates the grouping of tokens into phrases.
A syntax tree is a compacted form of parse tree in which the operators appear as the interior nodes.
The construction of a parse tree is a basic activity in compiler-writing.
A parse tree for the example Pascal statement is:
Comment:
The distinction between lexical and syntactical analysis sometimes seems arbitrary. The main
criterion is whether the analyzer needs recursion or not:
• lexical analyzers hardly ever use recursion; they are sometimes called linear analysers since they
scan the input in a ‘straight line’ (from from left to right).
• syntax analyzers almost always use recursion; this is because phrase types are often defined in
terms of themselves (cf. the phrase type ‘expression’ above).
Semantic Analysis:
A semantic analyzer takes its input from the syntax analysis phase in the form of a parse tree and a
symbol table. Its purpose is to determine if the input has a well-defined meaning; in practice
semantic analyzers are mainly concerned with type checking and type coercion based on type rules.
Expression Type Rules. Let exp be an expression.
(a) If exp is a constant then exp is well-typed and its type is the type of the constant.
(b) If exp is a variable then exp is well-typed and its type is the type of the variable.
(c) If exp is an operator applied to further sub expressions such that:
(i) The operator is applied to the correct number of sub expressions,
(ii) Each sub expression is well-typed and
(iii) each sub expression is of an appropriate type, then exp is well-typed and its type is the
result type of the operator.
Code Optimization
An optimizer attempts to improve the time and space requirements of a program. There are Many
ways in which code can be optimized, but most are expensive in terms of time and space
to implement.
Common optimizations include:
• removing redundant identifiers,
• removing unreachable sections of code,
• identifying common sub expressions,
• Unfolding loops and
• eliminating procedures.
Code Generation:
The final phase of the compiler is to generate code for a specific machine. In this phase we consider:
• Memory management,
• register assignment and
• Machine-specific optimization.
The output from this phase is usually assembly language or reloadable machine code.
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-3
Program to recognize white spaces, count number of identifiers, characters, tabs and the length
of the input string.
#include <iostream>
using namespace std;
int main(){
string str;
int digitCounter = 0, spaceCounter = 0;
cout << "Enter any string: ";
getline(cin, str);
//'\0 represent end of string
for(int i = 0; str[i]!='\0'; i++) {
if(str[i]>='0' && str[i]<='9') {
digitCounter++;
}
else if(str[i]==' ') {
spaceCounter++;
}
}
cout << "Digits in String: " << digitCounter << endl;
cout << "White Spaces in String: " << spaceCounter << endl;
return 0;
}
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-4
#include <bits/stdc++.h>
using namespace std;
if (line[line.size() - 2] == '*'
&& line[line.size() - 1] == '/' && line[0] == '/' && line[1] == '*') {
// Driver Code
int main()
{
// Given string
string line = "/*GeeksForGeeks GeeksForGeeks*/";
return 0;
}
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-5
#include<stdio.h>
#include<string.h>
#define SIZE 10
int main () {
char non_terminal;
char beta,alpha;
int num;
char production[10][SIZE];
int index=3; /* starting of the string following "->" */
printf("Enter Number of Production : ");
scanf("%d",&num);
printf("Enter the grammar as E->E-A :\n");
for(int i=0;i<num;i++){
scanf("%s",production[i]);
}
for(int i=0;i<num;i++){
printf("\nGRAMMAR : : : %s",production[i]);
non_terminal=production[i][0];
if(non_terminal==production[i][index]) {
alpha=production[i][index+1];
printf(" is left recursive.\n");
while(production[i][index]!=0 && production[i][index]!='|')
index++;
if(production[i][index]!=0) {
beta=production[i][index+1];
printf("Grammar without left recursion:\n");
printf("%c->%c%c\'",non_terminal,beta,non_terminal);
printf("\n%c\'->%c%c\'|E\n",non_terminal,alpha,non_terminal);
}
else
printf(" can't be reduced\n");
}
else
printf(" is not left recursive.\n");
index=3; }
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-6
Program for left factoring
#include<iostream>
#include<string>
using namespace std;
int main()
{ string ip,op1,op2,temp;
int sizes[10] = {};
char c;
int n,j,l;
cout<<"Enter the Parent Non-Terminal : ";
cin>>c;
ip.push_back(c);
op1 += ip + "\'->";
op2 += ip + "\'\'->";;
ip += "->";
cout<<"Enter the number of productions : ";
cin>>n;
for(int i=0;i<n;i++)
{
cout<<"Enter Production "<<i+1<<" : ";
cin>>temp;
sizes[i] = temp.size();
ip+=temp;
if(i!=n-1)
ip += "|";
}
cout<<"Production Rule : "<<ip<<endl;
char x = ip[3];
for(int i=0,k=3;i<n;i++)
{
if(x == ip[k])
{
if(ip[k+1] == '|')
{
op1 += "#";
ip.insert(k+1,1,ip[0]);
ip.insert(k+2,1,'\'');
k+=4;
}
else
{
op1 += "|" + ip.substr(k+1,sizes[i]-1);
ip.erase(k-1,sizes[i]+1);
}
}
else
{
while(ip[k++]!='|');
}
}
char y = op1[6];
for(int i=0,k=6;i<n-1;i++)
{
if(y == op1[k])
{
if(op1[k+1] == '|')
{
op2 += "#";
op1.insert(k+1,1,op1[0]);
op1.insert(k+2,2,'\'');
k+=5;
}
else
{
temp.clear();
for(int s=k+1;s<op1.length();s++)
temp.push_back(op1[s]);
op2 += "|" + temp;
op1.erase(k-1,temp.length()+2);
} }}
op2.erase(op2.size()-1);
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-7
Program to find FIRST and FOLLOW of NON TERMINALS of the any given grammar.
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int count, n = 0;
strcpy(production[7], "F=i");
int kay;
char done[count];
int ptr = -1;
if (xxx == 1)
continue;
// Function call
findfirst(c, 0, 0);
ptr += 1;
if (first[i] == calc_first[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
printf("%c, ", first[i]);
calc_first[point1][point2++] = first[i];
}
}
printf("}\n");
jm = n;
point1++;
}
printf("\n");
printf("-----------------------------------------------\n\n");
char donee[count];
ptr = -1;
// Checking if Follow of ck
// has already been calculated
for(kay = 0; kay <= ptr; kay++)
if(ck == donee[kay])
xxx = 1;
if (xxx == 1)
continue;
land += 1;
// Function call
follow(ck);
ptr += 1;
calc_follow[point1][point2++] = ck;
void follow(char c)
{
int i, j;
{
// Calculate the follow of the Non-Terminal
// in the L.H.S. of the production
follow(production[i][0]);
}
}
}
}
}
}
}
}
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-8
#include<stdio.h>
#include<conio.h>
#include<string.h>
char s[20],stack[20];
void main()
char m[5][6][3]={"tb"," "," ","tb"," "," "," ","+tb"," "," ","n","n","fc"," "," ","fc"," "," "," ","n","*fc","
a ","n","n","i"," "," ","(e)"," "," "};
int size[5][6]={2,0,0,2,0,0,0,3,0,0,1,1,2,0,0,2,0,0,0,1,3,0,1,1,1,0,0,3,0,0};
int i,j,k,n,str1,str2;
clrscr();
scanf("%s",s);
strcat(s,"$");
n=strlen(s);
stack[0]='$';
stack[1]='e';
i=1;
j=0;
printf("\nStack Input\n");
printf("__________________\n");
while((stack[i]!='$')&&(s[j]!='$'))
if(stack[i]==s[j])
i--;
j++;
switch(stack[i])
break;
break;
break;
break;
break;
switch(s[j])
break;
break;
break;
break;
break;
break;
if(m[str1][str2][0]=='\0')
printf("\nERROR");
exit(0);
else if(m[str1][str2][0]=='n')
i--;
else if(m[str1][str2][0]=='i')
stack[i]='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",s[k]);
printf(" \n ");
printf("\n SUCCESS");
getch();
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-9
#include<stdio.h>
int regs[26];
int base;
%}
%start list
%union { int a; }
%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.a] = $3.a;
}
|
expr '*' expr
{
|
number
;
number: DIGIT
{
$$ = $1;
base = ($1.a==0) ? 8 : 10;
} |
number DIGIT
{
$$.a = base * $1.a + $2.a;
}
;
%%
main()
{
return(yyparse());
}
yyerror(s)
char *s;
{
fprintf(stderr, "%s\n",s);
}
yywrap()
{
return(1);
}
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-10
Program for LR Parser.
#include<stdio.h>
#include<conio.h>
char stack[30];
int top=-1;
void push(char c)
top++;
stack[top]=c;
char pop()
char c;
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;
char s1[20],s2[20],ch1,ch2,ch3;
clrscr();
printf("\n\n\t\t LR PARSING");
scanf("%s",s1);
l=strlen(s1);
j=0;
printf("\n\t\t $");
for(i=0;i<l;i++)
s1[i]=' ';
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");
exit();
else
push('E');
printstat();
ch2=ch1;
getch();
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-11
#include<iostream.h>
#include<string.h>
#include<conio.h>
int nt,t,top=0;
char s[50],NT[10],T[10],st[50],l[10][10],tr[50][50];
int searchnt(char a)
{
int count=-1,i;
for(i=0;i<nt;i++)
{
if(NT[i]==a)
return i;
}
return count;
}
int searchter(char a)
{
int count=-1,i;
for(i=0;i<t;i++)
{
if(T[i]==a)
return i;
}
return count;
}
void push(char a)
{
s[top]=a;
top++;
}
char pop()
{
top--;
return s[top];
}
void installl(int a,int b)
{
if(l[a][b]=='f')
{
l[a][b]='t';
push(T[b]);
push(NT[a]);
}
}
void main()
{
int i,s,k,j,n;
char pr[30][30],b,c;
clrscr();
cout<<"Enter the no of productions:";
cin>>n;
cout<<"Enter the productions one by one\n";
for(i=0;i<n;i++)
cin>>pr[i];
nt=0;
t=0;
for(i=0;i<n;i++)
{
if((searchnt(pr[i][0]))==-1)
NT[nt++]=pr[i][0];
}
for(i=0;i<n;i++)
{
for(j=3;j<strlen(pr[i]);j++)
{
if(searchnt(pr[i][j])==-1)
{
if(searchter(pr[i][j])==-1)
T[t++]=pr[i][j];
}
}
}
for(i=0;i<nt;i++)
{
for(j=0;j<t;j++)
l[i][j]='f';
}
for(i=0;i<nt;i++)
{
for(j=0;j<t;j++)
tr[i][j]='f';
}
for(i=0;i<nt;i++)
{
for(j=0;j<n;j++)
{
if(NT[(searchnt(pr[j][0]))]==NT[i])
{
if(searchter(pr[j][3])!=-1)
installl(searchnt(pr[j][0]),searchter(pr[j][3]));
else
{
for(k=3;k<strlen(pr[j]);k++)
{
if(searchnt(pr[j][k])==-1)
{
installl(searchnt(pr[j][0]),searchter(pr[j][k]));
break;
}
}
}
}
}
}
while(top!=0)
{
b=pop();
c=pop();
for(s=0;s<n;s++)
{
if(pr[s][3]==b)
installl(searchnt(pr[s][0]),searchter(c));
}
}
for(i=0;i<nt;i++)
{
cout<<"Leading["<<NT[i]<<"]"<<"\t{";
for(j=0;j<t;j++)
{
if(l[i][j]=='t')
cout<<T[j]<<",";
}
cout<<"}\n";
}
top=0;
for(i=0;i<nt;i++)
{
for(j=0;j<n;j++)
{
if(NT[searchnt(pr[j][0])]==NT[i])
{
if(searchter(pr[j][strlen(pr[j])-1])!=-1)
installt(searchnt(pr[j][0]),searchter(pr[j][strlen(pr[j])-1]));
else
{
for(k=(strlen(pr[j])-1);k>=3;k--)
{
if(searchnt(pr[j][k])==-1)
{
installt(searchnt(pr[j][0]),searchter(pr[j][k]));
break;
}
}
}
}
}
}
while(top!=0)
{
b=pop();
c=pop();
for(s=0;s<n;s++)
{
if(pr[s][3]==b)
installt(searchnt(pr[s][0]),searchter(c));
}
}
for(i=0;i<nt;i++)
{
cout<<"Trailing["<<NT[i]<<"]"<<"\t{";
for(j=0;j<t;j++)
{
if(tr[i][j]=='t')
cout<<T[j]<<",";
}
cout<<"}\n";
}
getch();
}
Viva Questions:
Q.1
Ans:
Q.2
Ans:
Experiment-12
Structure of a Lex file - The structure of a Lex file is intentionally similar to that of a yacc file; files
are divided into three sections, separated by lines that contain only two percent signs, as follows:
Definition section
%%
Rules section
%%
C code section
The definition section defines macros and imports header files written in C. It is also possible to
write any C code here, which will be copied verbatim into the generated source file.
The rules section associates regular expression patterns with C statements. When the lexer sees text
in the input matching a given pattern, it will execute the associated C code.
The C code section contains C statements and functions that are copied verbatim to the generated
source file. These statements presumably contain code called by the rules in the rules section. In
large programs it is more convenient to place this code in a separate file linked in at compile time.
The following represents a simple pattern, composed of a regular expression that scans for
identifiers. Lex will read this pattern and produce C code for a lexical analyzer that scans for
identifiers.
letter(letter|digit)*
This pattern matches a string of characters that begins with a single letter followed by zero or more
letters or digits. This example nicely illustrates operations allowed in regular expressions:
• repetition, expressed by the “*” operator
• alternation, expressed by the “|” operator
• concatenation
Any regular expression expressions may be expressed as a finite state automaton (FSA). We can
represent an FSA using states, and transitions between states. There is one start state and one or more
final or accepting states.
In Figure 3 state 0 is the start state and state 2 is the accepting state. As characters are read we make
a transition from one state to another. When the first letter is read we transition to state 1. We remain
in state 1 as more letters or digits are read. When we read a character other than a letter or digit we
transition to accepting state 2. Any FSA may be expressed as a computer program. For example, our
3-state machine is easily programmed:
start: goto state0
state0: read c if c = letter goto state1 goto state0
state1: read c if c = letter goto state1 if c = digit goto state1 goto state2
state2: accept string
Yacc: Yet Another Compiler-Compiler
Computer program input generally has some structure; in fact, every computer program that does
input can be thought of as defining an ``input language'' which it accepts. An input language may be
as complex as a programming language, or as simple as a sequence of numbers. Unfortunately, usual
input facilities are limited, difficult to use, and often are lax about checking their inputs for validity.
Yacc provides a general tool for describing the input to a computer program. The Yacc user specifies
the structures of his input, together with code to be invoked as each such structure is recognized.
Yacc turns such a specification into a subroutine that han- dles the input process; frequently, it is
convenient and appropriate to have most of the flow of control in the user's application handled by
this subroutine.
Grammars for yacc are described using a variant of Backus Naur Form (BNF). This technique,
pioneered by John Backus and Peter Naur, was used to describe ALGOL60. A
BNF grammar can be used to express context-free languages. Most constructs in modern
programming languages can be represented in BNF. For example, the grammar for an expression that
multiplies and adds numbers is
E -> E + E
E -> E * E
E-> id
Three productions have been specified. Terms that appear on the left-hand side (lhs) of a production,
such as E (expression) are nonterminals. Terms such as id (identifier) are terminals (tokens returned
by lex) and only appear on the right-hand side (rhs) of a production. This grammar specifies that an
expression may be the sum of two expressions, the product of two expressions, or an identifier. We
can use this grammar to generate expressions:
E -> E * E (r2)
-> E * z (r3)
-> E + E * z (r1)
-> E + y * z (r3)
-> x + y * z (r3)
At each step we expanded a term and replace the lhs of a production with the corresponding rhs. The
numbers on the right indicate which rule applied. To parse an expression we need to do the reverse
operation. Instead of starting with a single nonterminal (start symbol) and generating an expression
from a grammar we need to reduce an expression to a single nonterminal. This is known as bottom-
up or shift-reduce parsing and uses a stack for storing terms.
Yacc is officially known as a "parser".It's job is to analyse the structure of the input stream, and
operate of the "big picture".
In the course of it's normal work, the parser also verifies that the input is syntactically sound.
Consider again the example of a C-compiler. In the C-language, a word can be a function name or a
variable, depending on whether it is followed by a ( or a = There should be exactly one } for
each { in the program.
YACC stands for "Yet Another Compiler Compiler". This is because this kind of analysis of text
files is normally associated with writing compilers.
However, as we will see, it can be applied to almost any situation where text-based input is being
used.
For example, a C program may contain something like:
{
int int;
int = 33;
printf("int: %d\n",int);
}
In this case, the lexical analyser would have broken the input sream into a series of "tokens", like
this:
{
int
int
;
int
=
33
;
printf
(
"int: %d\n"
,
int
)
;
}
Note that the lexical analyser has already determined that where the keyword int appears within
quotes, it is really just part of a litteral string. It is up to the parser to decide if the token int is being
used as a keyword or variable. Or it may choose to reject the use of the name int as a variable name.
The parser also ensures that each statement ends with a ; and that the brackets balance.
E -> E + E
is ambiguous, for we may recurse on the left or the right. To remedy the situation, we could rewrite
the grammar or supply yacc with directives that indicate which operator has precedence. The latter
method is simpler and will be demonstrated in the practice section.
The following grammar has a reduce-reduce conflict. With an id on the stack we may reduce to T, or
E.
E -> T
E -> id
T -> id
Yacc takes a default action when there is a conflict. For shift-reduce conflicts yacc will shift. For
reduce-reduce conflicts it will use the first rule in the listing. It also issues a warning message
whenever a conflict exists. The warnings may be suppressed by making the grammar unambiguous.
Several methods for removing ambiguity will be presented in subsequent sections.
Viva Questions:
Q.1
Ans.
Q.2
Ans.
Experiment-13
// 13. Program for checking string is valid or invalid.
#include<string.h>
#include<stdio.h>
#include<conio.h>
void main()
{ clrscr();
char str[100],ch;
int i=0,l=0,len=0;
printf("\n Enter The String: \n ");
while((ch=getchar())!='\n')
{
str[i]=ch;
i++;
}
str[i]='\0';
len=strlen(str);
if((str[0]>='a'&&str[0]<='z'))
{ for(int j=1;j<len-1;j++)
{
if((str[j]>='a'&&str[j]<='z'))
{
j++;
if(str[j]=='\0')
goto result;
}
else
{
l=1;
goto result;
}
}
}
else
l=1;
result:
if(l==0)
printf("\n String is valid ");
else
printf("\n String is invalid ");
getch();
}
OUTPUT
Viva Questions:
Q.1:
Ans:
Q.2:
Ans:
Experiment-14
#include<stdio.h>
#include<conio.h>
void main()
{
int inp[10],stat[10],res[100],fs,st,l=0,chk[10],in,a,nxt,t,q=0;
clrscr();
for(int h=0;h<a;h++)
{
for(t=0;t<in;t++)
if(chk[h]==inp[t])
nxt=res[q*in+t];
for(t=0;t<st;t++)
if(nxt==stat[t])
q=t;
if(nxt==fs)
printf("String is accepted");
else
printf("String is rejected");
getch();
}
OUTPUT
Viva Questions:
Q.1:
Ans:
Q.2:
Ans:
Experiment -15
#include<stdio.h>
#include<conio.h>
#include<string.h>
#define MAX 50
char pop();
void push(char);
int getOperatorPriority(char);
int isOperator(char);
void toPostFix(char *, char *);
struct Stack
{
char exp[MAX];
int top ;
}s;
void main()
{
char infix[MAX] , postfix[MAX];
s.top = -1;
clrscr();
printf("\n Please Enter the Infix Notation:\n ");
gets(infix);
toPostFix(infix,postfix);
printf("\nThe postfix notation is :-\n ");
puts(postfix);
getch();
}
char pop()
{
char tmp;
if(s.top == -1)
printf("\nUnderflow");
else
{
tmp = s.exp[s.top];
s.exp[s.top--] = '\0';
return tmp;
}
{
if( !isOperator(in[i]) )
{
post[postdex++] = in[i];
}
else
{
push(in[i]);
}
}
while(postdex != index)
post[postdex++] = pop();
post[postdex] = '\0';
}
OUTPUT
Viva Questions:
Q.1:
Ans:
Q.2:
Ans:
IPS ACADEMY
Knowledge, Skills, Values
16 Collages,71 Courses,51 Acre Campus
ISO 9001: 2008 Certified
Knowledge Village
Rajendra Nagar
A.B.Road Indore
452012(M.P.) India
Ph: 0731-4014601-604 Mo: 07746000161
E Mail: [email protected]
Website: ies.ipsacademy.org & www.ipsacademy.org