Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Theory of automata and formal language lab manual
1. EXPERIMENT NO:1
TITLE: LEXICAL ANALYZER
To find out a given string is an identifier or not.
OUTLINE:
Identifier is an entity which starts from a letter and then it can contain both letters and digit,
any other special character is not allowed in the identifier. While checking for identifier we
normally use DFA as it is done in lexical analysis state which works with regular grammar.
DFA for identifier consists of three states first state is accepting only letters and then moving
to second state when it got a letter. Second state can accept both letters and digits and
comeback to itself when it got one. Second state can also accept terminating symbol
(delimiter) which lead it to third state which identifies it as an identifier.
ALGORITHM:
Step 1. Start
Step 2. Check if the first char is a letter goto step 3 with rest of the string else goto 5.
Step 3. Check if the first character of the given string is a letter or a digit repeat step
3 with rest of the string else goto step 5.
Step 4. Print “The given string is an identifier” and goto step 6.
Step 5. Print “The given string is not an identifier”.
Step 6. Exit
OUTPUT:
Enter the desired String: a123
The given string is an identifier
……………………………………………….
Enter the desired String: shailesh
The given string is an identifier
……………………………………………..
Enter the desired String: 1asd
The given string is not an identifier
……………………………………………..
Enter the desired String: as-*l
The given string is not an identifier
2. EXPERIMENT NO :2
TITLE: DFA SIMULATION
Write a program for acceptance of a string using a given DFA.
OUTLINE:
A DFA is an acceptor that, for any state and input character, has at most one transition
state that the acceptor changes to. A Deterministic Finite Automata M involves the
following components:
■ A list of states
■ A set of alphabet letters
■ A set of transition functions
■ A start state
■ A set of final states
The program reads the description (listed above) of the machine M. It then reads in a set of
input strings (interactively) and determines whether or not a particular string is acceptable
by the machine.
OUTPUT:
No. of states in DFA are:3
No. of final states in DFA are:1
Enter state number(s) of final states(s):2
No. of characters you are using in DFA are:2
Enter those characters one by one:
a b
Describe your DFA
If char ‘A’ is output from state i to state j then write j at combination of i & ‘A’
1) Enter the string to be tested: aab
Valid string
2) Enter the string to be tested: abab
Error!!! Invalid string
TITLE: LEXICAL ANALYZER
To write a program for dividing the given input program into lexemes.
OUTLINE:
lexical analysis is the process of converting a sequence of characters into a sequence
of tokens. A program or function which performs lexical analysis is called a lexical
analyzer, or lexer.
3. ALGORITHM:
Step 1: start
Step 2: Read the file and open the file as read mode.
Step 3: Read the string for tokens identifiers, variables.
Step 4: take parenthesis also a token.
Step 5: parse the string
Step 6: stop.
OUTPUT:
Enter the input:
void main()
{
}
^Z
Lexeme Token
……………………………………………………………
void Keyword
main Function
( parenthesis
) parenthesis
{ Braces
} Braces
4. EXPERIMENT NO :3
TITLE:
A program to check the string of a given grammar.
OUTLINE:
A grammar consists of a finite nonempty set of rules or productions which specify the syntax
of the language. In the context of lexical analysis the rules are known as lexical rules.
Otherwise, the rules are meant for production rules or syntactical rules.
For a given grammar, the program reads a string as input. In a simple derivation process
the given string is parsed on a top-down manner.
ALGORITHM:
Step 1: start
Step 2: Read the file and open the file as read mode.
Step 3: Read the string for tokens identifiers, variables.
Step 4: take parenthesis also a token.
Step 5: parse the string
Step 6: stop.
OUTPUT:
The given grammar is: S->aS, S->Sb, S->ab
Enter the string to be checked:
aaabb
The string accepted
Enter the string to be checked:
abaab
The string does not belong to the specified grammar
Enter the string to be checked:
baaa
The string does not belong to the specified grammar
TITLE: CFG
Program to eliminate left-recursion from a context-free grammar.
OUTLINE:
A grammar G is said to be left-recursive if it has a non-terminal A such that there is a
derivation A => Aa for some a. A left-recursive grammar can cause a top -down parser to go
into an infinite loop i.e. when try to expand A, you may eventually find yourself again trying
5. to expand A without having consumed any input.
Consider the grammar:
A–> Aa | b is a general form of immediate left-recursive grammar.
To eliminate left-recursion you have to replace the grammar by the following pair of
production rules:
A–> bA’
A’–> aA |
ALGORITHM:
1. Arrange the NTs into some order A1, A2, …, An
2. for i ¬ 1 to n do
begin
for j¬ 1 to i-1 do
replace each production Ai ® Aj g by the productions
Ai ® d1 g ½d2 g½¼½dk g, where Ai® d1 ½d2½¼½dk are
all the current productions for Aj
eliminate any immediate left recursion among the Ai -productions
end
OUTPUT:
Enter no. of production are:6
Enter production:
E->E+T
E->T
T->T*F
T->F
F->(E)
F->id
production after left recursion are:
E->TU
U->+TU
U->#
T->FV
V->*FV
V->#
F->(E)
F->id
6. EXPERIMENT NO :4
TITLE: TOP-DOWN PARSING
Recursive-descent parsing: To write a program on recursive descendent parsing.
OUTLINE:
A parser that uses a set of recursive procedures to recognize its input by performing syntax
analysis with no backtracking is called a recursive-descent parser. It works in a top-down
fashion.
Consider the following grammar that is suitable for non-backtracking recursive-descent
parsing:
E–> TE’
E’–> +TE’ |
T–> FT’
T’–> *FT’ |
F–> (E) | id
ALGORITHM:
Step 1: start.
Step 2: Declare the prototype functions E() , EP(),T(), TP(),F()
Step 3: Read the string to be parsed.
Step 4: Check the productions
Step 5: Compare the terminals and Non-terminals
Step 6: Read the parse string.
Step 7: stop the production
OUTPUT:
The given grammar is: E–> TE’, E’–> +TE’ |@, T–> FT’, T’–> *FT’ |@, F–> (E) | id
Enter the expression to be parsed:
id + id * id
The string is parsed.
The given grammar is: E–> TE’, E’–> +TE’ |@, T–> FT’, T’–> *FT’ |@, F–> (E) | id
Enter the expression to be parsed:
id + id *+ id
The string is not parsed
7. EXPERIMENT NO :5
TITLE: IMPLEMENTATION OF PREDICTIVE PARSING
Write a code to compute the FIRST, and FOLLOW for all non-terminals.
Write a code to build LL(1) Parsing table for the given grammar.
OUTLINE:
Consider the grammar, G
E -> T E’
E’ -> + T E’ | ε
T -> F T’
T’ -> * F T’ | ε
F -> ( E ) | id
The construction of a predictive parser is aided by two functions associated with a grammar
G. These functions, FIRST and FOLLOW, allow us to fill in the entries of a predictive
parsing table for G, whenever possible.
ALGORITHM:
Computing FIRST sets:
To compute FIRST(X) for all grammar symbols X, apply the following rules until no more
terminals or ε can be added to any FIRST set.
1. if X is terminal, then FIRST(X) is {X}.
2. if X is non-terminal and X-> aα is a production, then add a to FIRST(X). if X-> ε to
FIRST(X).
3. if -> Y1,Y2,…….Yk is a production, then for all i such that all of Y1,….Yi-1 are non-
terminals and FIRST(Yj) contains ε for j=1,2,…… i-1, add every non- ε symbol
in FIRST(Y1) to FIRST(x). if V is in FIRST(Yj) for j=1,2,………k, then add ε to FIRST(X).
Computing FOLLOW sets:
To compute FOLLOW(A) for all non-terminals A, apply the following rules until nothing can
be added to any
1. Place $ in FOLLOW(S), where S is the start symbol and $ is the input right end marker.
2. If there is a production A –> aBb , then everything in FIRST(b), except for ε, is placed in
FOLLOW(B).
8. 3. If there is a production A –> aB, or a production A –> aBb where FIRST(b)
contains ε (i.e., b =>* ε), then everything in FOLLOW(A) is in FOLLOW(B).
Constructing Parsing Table:
To construct a parsing table M[A, a] for a grammar G is very simple. Here M[A, a] is a 2-
dimensional array.
1. For each production A–> a of the grammar, do steps 2 and 3.
2. For each terminal a in FIRST(a), add A–> a to M[A, a].
3. If ε is in FIRST(a) and $ is in FOLLOW(A), add A–> a to M[A, $].
Make each undefined entry of M error.
OUTPUT:
Non Terminals :
NT1 E
NT2 T
NT3 F
NT4 E’
NT5 T’
Terminals :
T1 : +
T2 : *
T3: (
T4: )
T5: id
T6: ε
Productions :
Production No 1 E->T E’
Production No 2 E’->+ T E’
Production No 3 T->F T’
Production No 4 T’->* F T’
Production No 5 F->( E )
Production No 6 F->id
9. Production No 7 E’->ε
Production No 8 T’->ε
First of all Non Terminal
FIRST( E ) = { (, id }
FIRST( T ) = { (, id }
FIRST( F ) = { (, id }
FIRST( E’ ) = { +, ε }
FIRST( T’ ) = { *, ε }
Follow of all Non Terminal
FOLLOW( E ) = { $, ) }
FOLLOW( T ) = { +, $, ) } FOLLOW( F ) = { *, +, $, ) } FOLLOW( E’ ) = { $, ) }
FOLLOW( T’ ) = { +, $, ) }
10. EXPERIMENT NO :6
TITLE: BOTTOM-UP PARSING
Program to show the implementation of Shift-Reduce Parser.
OUTLINE:
Shift-reduce parsing attempts to construct a parse tree for an input string beginning at the
leaves (the bottom) and working up towards the root (the top). At each reduction step a
particular substring matching the right side of a production is replaced by the symbol on the
left of that production, and if the substring is chosen correctly at each step, a rightmost
derivation is traced out in reverse.
In general, this parsing strategy is non-deterministic. Non-determinism can arise if there are
two productions such that the RHS of one of them is a prefix of the RHS of the other, i.e., if
there are different productions A → α, B → αβ with α ∈ (VN ∪ VT )and β ∈ ∈ (VN ∪ VT )*.
Implementation:
To implement shift-reduce parser, use a stack to hold grammar symbols and an input
buffer to hold the string w to be parsed.
Use $ to mark the bottom of the stack and also the right end of the input.
Initially the stack is empty, and the string w is on the input, as follows:
Stack Input
$ w $
The parser operates by shifting zero or more input symbols onto the stack until a handle β
is on top of the stack.
The parser then reduces β to the left side of the appropriate production.
The parser repeats this cycle until it has detected an error or until the stack contains the
start symbol and the input is empty:
Stack Input
$S $
After entering this configuration, the parser halts and announces successful completion of
parsing.
There are four possible actions that a shift-reduce parser can make:1) shift 2) reduce 3)
accept 4) error.
1. In a shift action, the next symbol is shifted onto the top of the stack.
2. In a reduce action, the parser knows the right end of the handle is at the top of the
stack. It must then locate the left end of the handle within the stack and decide with what
non-terminal to replace the handle.
3. In an accept action, the parser announces successful completion of parsing.
11. 4. In an error action, the parser discovers that a syntax error has occurred and calls an
error recovery routine.
· Note: an important fact that justifies the use of a stack in shift-reduce parsing: the
handle will always appear on top of the stack, and never inside
OUTPUT:
SHIFT REDUCE PARSER
GRAMMAR
E–> E + E
E–> E / E
E–> E * E
E–> E | ε
E–> a | b
Enter the string: a + b
Stack Implementation table
——————————————————————————————
Stack Input symbol Action
——————————————————————————————-
$ a + b$ —–
$a +b$ shift a
$E +b$ E–> a
$E+ b$ shift +
$E + b $ shift b
$E + E $ E–> b
$E $ E–> E + E
$E $ ACCEPT
12. TITLE: INTERMEDIATE CODE GENERATION
Program to generate the intermediate code in the form of Polish notation.
OUTLINE:
Polish notation, also known as Polish prefix notation or simply prefix notation, is a form of
notation for logic, arithmetic, and algebra. Its distinguishing feature is that it
places operators to the left of their operands. When Polish notation is used as a syntax for
mathematical expressions by compiler of programming languages, it is readily parsed
into abstract syntax trees and can, in fact, define a one-to-one representation for the same.
ALGORITHM:
begin
Create OperandStack;
Create OperatorStack;
while( not an empty input expression ) read next token from the input expression
if ( token is an operand )
OperandStack.Push (token);
endif
else if ( token is ‘(‘ or OperatorStack.IsEmpty() or OperatorHierarchy(token) >_
OperatorHierarchy(OperatorStack.Top()) )
OperatorStack.Push ( token );
endif
else if( token is ‘)’ )
while( OperatorStack.Top()!='(‘ )
OperatorStack.Pop(operator);
OperandStack.Pop(RightOperand);
OperandStack.Pop(LeftOperand);
operand = operator + LeftOperand + RightOperand;
13. OperandStack.Push(operand);
endwhile
OperatorStack.Pop(operator);
endif
else if( operator hierarchy of token is less than or equal to hierarchy of top of the operator
stack )
while( !OperatorStack.IsEmpty() and_
OperatorHierarchy(token)<=OperatorHierarchy(OperatorStack.Top()) )
OperatorStack.Pop(operator);
OperandStack.Pop(RightOperand);
OperandStack.Pop(LeftOperand);
operand = operator + LeftOperand + RightOperand;
OperandStack.Push(operand);
endwhile
OperatorStack.Push(token);
endif
endwhile
while( !OperatorStack.IsEmpty() )
OperatorStack.Pop(operator);
OperandStack.Pop(RightOperand);
OperandStack.Pop(LeftOperand);
operand = operator + LeftOperand + RightOperand;
OperandStack.Push(operand) ;
endwhile
// Save the prefix expression at the top of the operand stack followed by popping // the
operand stack.
print OperandStack.Top();
OperandStack.Pop();
14. End
OUTPUT:
Enter an input in the form of expression:
(a+b)*(c-d)
The polish notation is: *+ab-cd
Enter an input in the form of expression:
(a–b)/c*(d + e – f / g)
15. EXPERIMENT NO :7
TITLE: ITERMEDIATE CODE GENERATION
Program for generating for various intermediate code form:
· Three address code
· Quadruple
OUTLINE:
Three address code is a sequence of statements of the form x = y op z . Since a statement
involves no more than three references, it is called a “three-address statement,” and a sequence
of such statements is referred to as three-address code. For example, the three-address code for
the expression a + b * c + d is:
Sometimes a statement might contain less than three references; but it is still called a three-
address statement.
Representing three-address statements:
Records with fields for the operators and operands can be used to represent three-address
statements. It is possible to use a record structure with four fields: the first holds the operator,
the next two hold the operand1 and operand2, respectively, and the last one holds the result. This
representation of a three-address statement is called a “quadruple representation”.
Using quadruple representation, the three-address statement x = y op z is represented by
placing op in the operator field, y in the operand1 field, z in the operand2 field, and x in the result
field.
OP ARG1 ARG2 RESULT
0 + a B T1
1 + c D T2
2 * T1 T2 T3
16. OUTPUT:
Enter The Expression: a=b+c*d/e; THREE ADDRESS CODE
B:= d / e
C:= c * B
D:= b + B
E:= a = B
QUADRUPLES
ID OP OPERAND 1 OPERAND2 RESULT
(0) / d e B
(1) * c B C
(2) + b B D
(3) = a B E
17. EXPERIMENT NO :8
This program is to find out whether a given string is a identifier or not.
#include<stdio.h>
#include<conio.h>
int isiden(char*);
int second(char*);
int third();
void main()
{
char *str;
int i = -1;
clrscr();
printf(“nnttEnter the desired String: “);
/*do
{
++i;
str[i] = getch();
if(str[i]!=10 && str[i]!=13)
printf(“%c”,str[i]);
if(str[i] == ‘b’)
{
–i;
printf(” b”);
}
}while(str[i] != 10 && str[i] != 13);
*/
gets(str);
18. if(isident(str))
printf(“nnttThe given strig is an identifier”);
else
printf(“nnttThe given string is not an identifier”);
getch();
}
//To Check whether the given string is identifier or not
//This function acts like first stage of dfa
int isident(char *str)
{
if((str[0]>=’a’ && str[0]<=’z’) || (str[0]>=’A’ && str[0]<=’Z’))
{
return(second(str+1));
}
else
return 0;
}
//This function acts as second stage of dfa
int second(char *str)
{
if((str[0]>=’0′ && str[0]<=’9′) || (str[0]>=’a’ && str[0]<=’z’) || (str[0]>=’A’ && str[0]<=’Z’))
{
return(second(str+1)); //Implementing the loop from second stage to second stage
}
else
{
if(str[0] == 10 || str[0] == 13)
{
return(third(str));
20. EXPERIMENT NO :10
Write a program to simulate a machine known as the Deterministic
Finite Automata (DFA).
PROGRAM:
#include<iostream.h>
#include<conio.h>
#include<process.h>
#include<string.h>
class p_dfa
{
int n,n1,n2,final[10],fa[10][10];
char ch[10],*str;
public:
void accept();
void dfa(char*);
};
void p_dfa::accept()
{
int i,j;
cout << endl << “No. of states in DFA are:”;
cin >> n;
cout << endl << “No. of final states in DFA are:”;
cin >> n1;
cout << endl << “Enter state number(s) of final states(s):”;
for(i=0;i<n1;i++)
cin >> final[i];
cout << endl << “No. of characters you are using in DFA are:”;
21. cin >> n2;
cout << endl << “Enter those characters one by one:” << endl;
for(i=0;i<n2;i++)
cin >> ch[i];
cout << endl << “Describe your DFA” << endl;
cout << endl << “If char ‘A’ is output from stayte i to state j”;
cout << endl << “then write j at combination of i & ‘A'” << endl;
for(i=0;i<n2;i++)
cout << “t” << ch[i];
cout << endl;
for(i=0;i<n;i++)
{
cout << i << “t”;
for(j=0;j<n2;j++)
cin >> fa[i][j];
}
cout << endl << “Enter the string to be tested:”;
cin >> str;
dfa(str);
}
void p_dfa::dfa(char *str)
{
int i,j,len,state=0,flag;
char c;
len = strlen(str);
for(i=0;i<len;i++)
{
c = str[i];
24. INDEX
S.no Practical Signature Remark
1
2
3
4
5-a
5-b
6
7
8
To find out a given string is an identifier or not.
Write a program for acceptance of a string
using a given DFA.
A program to check the string of a given
grammar.
Recursive-descent parsing: To write a program
on recursive descendent parsing.
• Write a code to compute the FIRST, and
FOLLOW for all non-terminals.
• Write a code to build LL(1) Parsing table
for the given grammar.
Program to show the implementation of Shift-
Reduce Parser.
Program for generating for various
intermediate code form:
• Three address code
• Quadruple
This program is to find out whether a given
string is a identifier or not.