0% found this document useful (0 votes)
61 views51 pages

3160715-System Software Lab-Manual

Uploaded by

vrajsolanki7687
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
61 views51 pages

3160715-System Software Lab-Manual

Uploaded by

vrajsolanki7687
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 51

A Laboratory Manual for

System Software
(3160715)

B.E. Semester 6
(Computer)

Directorate of Technical Education,


Gandhinagar, Gujarat
Government Engineering College, Patan
Certificate
This is to certify that Mr./Ms. RANA KRISHNA CHANDRAKANT
Enrollment No. 210220131037 of B.E. Semester 6th Computer Science
and Engineering of this Institute (GTU Code: 022) has satisfactorily
completed the Practical / Tutorial work for the subject System Software
(3160715) for the academic year 2023-24.

Place: __________
Date: __________

Name and Sign of Faculty member

Head of the Department


Preface

Main motto of any laboratory/practical/field work is for enhancing required skills as


well as creating ability amongst students to solve real time problem by developing
relevant competencies in psychomotor domain. By keeping in view, GTU has
designed competency focused outcome-based curriculum for engineering degree
programs where sufficient weightage is given to practical work. It shows
importance of enhancement of skills amongst the students and it pays attention to
utilize every second of time allotted for practical amongst students, instructors and
faculty members to achieve relevant outcomes by performing the experiments
rather than having merely study type experiments. It is must for effective
implementation of competency focused outcome-based curriculum that every
practical is keenly designed to serve as a tool to develop and enhance relevant
competency required by the various industry among every student. These
psychomotor skills are very difficult to develop through traditional chalk and board
content delivery method in the classroom. Accordingly, this lab manual is designed
to focus on the industry defined relevant outcomes, rather than old practice of
conducting practical to prove concept and theory.

By using this lab manual students can go through the relevant theory and
procedure in advance before the actual performance which creates an interest and
students can have basic idea prior to performance. This in turn enhances pre-
determined outcomes amongst students. Each experiment in this manual begins
with competency, industry relevant skills, course outcomes as well as practical
outcomes (objectives). The students will also achieve safety and necessary
precautions to be taken while performing practical.

This manual also provides guidelines to faculty members to facilitate student


centric lab activities through each experiment by arranging and managing
necessary resources in order that the students follow the procedures with required
safety and necessary precautions to achieve the outcomes. It also gives an idea that
how students will be assessed by providing rubrics.

Utmost care has been taken while preparing this lab manual however always there
is chances of improvement. Therefore, we welcome constructive suggestions for
improvement and removal of errors if any.
System Software (3160715)
Practical List
Course Outcomes (COs):

CO-1 Explain and classify different methodologies, concepts and approaches to System Software
Programming.
CO-2 Identify elements of language processors with various data structures used in development of
one-pass and multi-pass assemblers.
CO-3 Examine macro processor, its usage and compare various loading and linking schemes.
CO-4 Build various system programs using language processor development tools such as YACC and
Lex.
CO-5 Design code optimization based solution for the given system problems by applying various
techniques
of compiler, interpreter and debugger.

Platform
Sr.
Objective(s) of Experiment to be CO1 CO2 CO3 CO4 CO5
No.
used
Write a C program to implement the
1. lexical analyzer. √

Write a program in text file and generate


2. √
SYMTAB and LITTAB.
Demonstrate the Use of macro features
of C language. Also demonstrate different
3. types of macro in C language.(simple √
macro, nested macro, macro with
argument and macro as inline function)

Write a Lexical Analyzer (using Lex utility √


4. for UNIX).
Demonstrate the use of YACC with √
5.
example program.
Write a C program to left factor the given √
6.
grammar.
Write a C program to remove the Left √
7.
Recursion from a given grammar.
8. Write C program to Implement Recursive √
Descendent Parsing for the given
Grammar.
E -> T + E / T
T -> F * T / F
F -> ( E ) / i
Implement Predictive Parser for the
9 arithmetic expression grammar using √
YACC and Lex.
Write a C program which generates
10 Quadruple Table for the given postfix √
String.
Industry Relevant Skills

The following industry relevant competencies are expected to be developed in


the student by undertaking the practical work of this laboratory.
1. Write lexical analyzer.
2. Write Predictive Parser.

Guidelines for Faculty members


1. Teacher should provide the guideline with demonstration of practical to
the students with all features.
2. Teacher shall explain basic concepts/theory related to the experiment to the
students before starting of each practical
3. Involve all the students in performance of each experiment.
4. Teacher is expected to share the skills and competencies to be
developed in the students and ensure that the respective skills and
competencies are developed in the students after the completion of the
experimentation.
5. Teachers should give opportunity to students for hands-on experience
after the demonstration.
6. Teacher may provide additional knowledge and skills to the students
even though not covered in the manual but are expected from the
students by concerned industry.
7. Give practical assignment and assess the performance of students
based on task assigned to check whether it is as per the instructions or
not.
8. Teacher is expected to refer complete curriculum of the course and
follow the guidelines for implementation.

Instructions for Students


1. Students are expected to carefully listen to all the theory classes delivered
by the faculty members and understand the COs, content of the course,
teaching and examination scheme, skill set to be developed etc.
2. Students shall organize the work in the group and make record of all
observations.
3. Students shall develop maintenance skill as expected by industries.
4. Student shall attempt to develop related hand-on skills and build confidence.
5. Student shall develop the habits of evolving more ideas, innovations, skills
etc. apart from those included in scope of manual.
6. Student shall refer technical magazines and data books.
7. Student should develop a habit of submitting the experimentation work as
per the schedule and s/he should be well prepared for the same.
Index
(Progressive Assessment Sheet)
Sr. Objective(s) of Experiment Page Date of Date of Assessm Sign. of Remar
No. No. perfor submis ent Teacher ks
mance sion Marks with
date
Write a C program to implement the lexical
1. analyzer.

Write a program in text file and generate


2.
SYMTAB and LITTAB.
Demonstrate the Use of macro features of C
language. Also demonstrate different types of
3. macro in C language.(simple macro, nested
macro, macro with argument and macro as
inline function)

Write a Lexical Analyzer (using Lex utility for


4.
UNIX).
Demonstrate the use of YACC with example
5.
program.
Write a C program to left factor the given
6.
grammar.
Write a C program to remove the Left
7.
Recursion from a given grammar.
Write C program to Implement Recursive
Descendent Parsing for the given Grammar.
8. E -> T + E / T
T -> F * T / F
F -> ( E ) / i
Implement Predictive Parser for the arithmetic
9
expression grammar using YACC and Lex.
Write a C program which generates Quadruple
10
Table for the given postfix String.
Total
Experiment No: 1

AIM: Write a C program to implement the lexical analyzer.

Date:

Competency and Practical Skills: C programming, Knowledge about lexical


analyzer.

Relevant CO: CO1

Objectives:(a) to understand working of lexical analyzer


(b) to understand implantation of lexical analyzer.

Equipment/Instruments: Desktop/laptop, C compiler, Editor

Theory: Lexical analysis often referred to as the first phase of a compiler or


interpreter, plays a crucial role in the process of translating high-level
programming languages into machine-readable code. Its primary function is to
break down the source code into a stream of tokens or lexemes, which are the
smallest meaningful units in a programming language. These tokens can include
keywords (e.g., "if," "while"), identifiers (e.g., variable names), literals (e.g.,
numbers, strings), and symbols (e.g., operators, punctuation).

The lexical analysis phase typically involves a scanner, which reads the source code
character by character and groups them into tokens based on predefined rules and
regular expressions. The output of lexical analysis is a stream of tokens with class
the tokens belongs to.

Procedure:
1. Write a C program to work as a lexical analyzer.

Observations:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
char str[100] = "int ans = b + 10.5 ;";

bool isDelimiter(char ch)


{ if (ch == ' ' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ',' || ch == ';' || ch == '>' || ch == '<' || ch
== '=' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') return (true); return
(false);
}

bool isOperator(char ch)


{ if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' || ch == '>' || ch == '<' ) return
(true); return (false);
}

bool validIdentifier(char* str)


{
int i;
if( ! ( isalpha(str[0]) || str[0] == '_') )
return false; for( i=1 ; i<strlen(str) ;
i++ )
{
if( ! ( isalnum(str[i]) || str[i] == '_') )
return false;
}
return true;
}

bool isKeyword(char* str)


{
int i;

char *keywords[] = { "auto", "break", "case", "char", "const", "continue", "default", "do", "double",
"else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while" };

for (i = 0; i < 32 ; i++)


{ if (strcmp(str, keywords[i]) == 0)
{
return true;
} }
return false;
}

bool isInteger(char* str)


{
int i; int len =
strlen(str);

for (i = 0; i < len; i++)


{
if( ! (isdigit(str[i]) ) )
return (false);
}
return (true);
}

bool isRealNumber(char* str)


{ int i, len = strlen(str);
bool hasDecimal = false;

for (i = 0; i < len; i++)


{
if( ! (isdigit(str[i]) ) && str[i] != '.' )
return false;

if (str[i] == '.')
{ hasDecimal = true;
}
}
return (hasDecimal);
}

char* subString(int left, int right)


{
int i;
char* subStr = (char*) malloc(sizeof(char) * (right - left + 2));

for (i = left; i <= right; i++)


subStr[i - left] = str[i]; subStr[right -
left + 1] = '\0'; return (subStr);
}

void Identify_Tokens()
{ int left = 0, right = 0; int
len = strlen(str);

while (right <= len && left <= right)


{ if (isDelimiter(str[right]) == false)
right++;

if (isDelimiter(str[right]) == true && left == right)


{ if (isOperator(str[right])
== true)
{ printf("'%c' IS AN OPERATOR\n",
str[right]);
}
right++;
left = right;
} else if (isDelimiter(str[right]) == true && left != right || (right == len &&
left != right))
{
char* subStr = subString(left, right - 1);

if (isKeyword(subStr) == true)
printf("'%s' IS A KEYWORD\n", subStr);

else if (isInteger(subStr) == true)


printf("'%s' IS AN INTEGER\n", subStr);

else if (isRealNumber(subStr) == true)


printf("'%s' IS A REAL NUMBER\n", subStr);

else if (validIdentifier(subStr) == true )


printf("'%s' IS A VALID IDENTIFIER\n", subStr);

else if (validIdentifier(subStr) == false)


printf("'%s' IS NOT A VALID IDENTIFIER\n", subStr); left = right;
}
}
return;
}

int main()
{
Identify_Tokens();
return (0);
}
Output:

References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 2

AIM: Write a program in text file and generate SYMTAB and LITTAB.

Date:

Competency and Practical Skills: Any programming language, Symbol table,


literal table

Relevant CO: CO2

Objectives:(a) to understand process of creating SYMTAB and LITTAB.

Equipment/Instruments: Desktop/laptop, any language compiler, Editor

Theory:

A symbol table, often abbreviated as "SYMTAB," is a data structure used in


compilers, assemblers, and interpreters to store information about the symbols
(identifiers) used in a program. Symbols in this context can include variable names,
function names, labels, and other identifiers defined or referenced within the
source code. The symbol table serves as a crucial component in the compilation or
interpretation process, helping to manage and resolve references to these symbols.
Following image show suggested format of SYMTAB.

A literal table, “LITTAB” refers to a data structure or component used in compilers,


assemblers, and other language processing systems to manage and store literal
values found within the source code of a program. Literal values are constant
values that appear in the code, such as integers, floating-point numbers, strings, or
characters. These values need to be identified, recorded, and often assigned
memory locations during the compilation or assembly process. Following image
show suggested format of LITTAB.

Procedure:
1. Write a C program to work as a lexical analyzer.

Observations:
Input File: “START.txt”

START 100
MOVEM BREG, ONE
MOVER BREG, A
MOVER BREG, B
MOVER BREG, C
PRINT A
PRINT B
PRINT C
STOP
A DS 1
B DS 1
C DS 1
ONE DC "1"
D DS 1
HUNDRED DC "100"

Program:

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

char str[500];

char SYMTAB[100]="";
char LITTAB[100]="";
char temp[10]; int
SYMADDRESS[10];
int name_i = 0;
int address_i = 0;
int LC; char
prev[10];
int count=0;

bool isDelimiter(char ch)


{ if (ch == ' ' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ',' || ch == ';' || ch == '>' || ch == '<' ||
ch == '=' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') return (true);
return (false);
}
bool isOperator(char ch)
{ if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' || ch == '>' || ch == '<' ) return
(true);
return (false);
}
bool validIdentifier(char* str)
{
int i;

if( ! ( isalpha(str[0]) || str[0] == '_') )


return false;
for( i=1 ; i<strlen(str) ; i++ )
{
if( ! ( isalnum(str[i]) || str[i] == '_') )
return false;
}
return true;
}
bool validLiteral(char* str)
{
int i; int len;
len=strlen(str);

if( str[0] == '\"' && str[len-1] == '\"' )


{
return true;
}
else
{
return false;
}
}
bool isOPCODE(char* str)
{
int i;
char *opcode[] = { "STOP", "ADD", "SUB", "MUL", "MOVEM", "MOVER", "COMP", "BC",
"DIV", "READ", "PRINT" };

for (i = 0; i < 11 ; i++)


{
if (strcmp(str, opcode[i]) == 0)
{
return true;
}
}
return false;
}

bool isAD(char* str)


{
int i;
char *AD[] = { "START", "END", "EQU", "ORIGIN", "LTORG"};

for (i = 0; i < 5 ; i++)


{
if (strcmp(str, AD[i]) == 0)
{
return true;
}
}
return false;
}

int isSTART(char* str)


{
int i;
char *AD[] = { "START", "END", "EQU", "ORIGIN", "LTORG"};

for (i = 0; i < 5 ; i++)


{
if (strcmp(str, AD[i]) == 0)
{
return i+1;
}
}
}

int isDL(char* str)


{
int i;
char *AD[] = { "DS", "DC"};
for (i = 0; i < 2 ; i++)
{
if (strcmp(str, AD[i]) == 0)
{
return i+1;
}
}
return 0;
}
bool isInteger(char* str)
{ int
i;
int len = strlen(str);

for (i = 0; i < len; i++)


{
if( ! (isdigit(str[i]) ) )
return (false);
}
return (true);
}
bool isRealNumber(char* str)
{ int i, len = strlen(str);
bool hasDecimal = false;

for (i = 0; i < len; i++)


{
if( ! (isdigit(str[i]) ) && str[i] != '.' )
return false;

if (str[i] == '.')
{
hasDecimal = true;
}
}
return (hasDecimal);
}
char* subString(int left, int right)
{ int i;
char* subStr = (char*) malloc(sizeof(char) * (right - left + 2));

for (i = left; i <= right; i++)


subStr[i - left] = str[i]; subStr[right -
left + 1] = '\0'; return (subStr);
}
char* Extract_Line(int left, int right)
{ int i;
char* subStr = (char*) malloc(sizeof(char) * (right - left + 2));

for (i = left; i <= right; i++)


subStr[i - left] = str[i]; subStr[right -
left + 1] = '\0'; return (subStr);
}
void Identify_Tokens()
{ int left = 0, right = 0; int
start_flag=0; int
DL_flag=0;
int len = strlen(str);

while (right <= len && left <= right)


{
if (isDelimiter(str[right]) == false)
right++;

if (isDelimiter(str[right]) == true && left == right)


{
right++;
left = right;
} else if (isDelimiter(str[right]) == true && left != right || (right == len && left !
= right))
{
char* subStr = subString(left, right - 1);

if (isOPCODE(subStr) == true)
{
}
else if (isAD(subStr) == true)
{
if(isSTART(subStr) == 1)
{
start_flag=1;
}
}
else if (isDL(subStr) == 1 || isDL(subStr) == 2) {
DL_flag=1;

if(isDL(subStr) == 1)
{
strcat(SYMTAB, prev);
strcat(SYMTAB, "\t\t");
sprintf(temp, "%d", LC);
strcat(SYMTAB, temp);
strcat(SYMTAB, "\n");
}

if(isDL(subStr) == 2)
{
strcat(LITTAB, prev);
strcat(LITTAB, "\t\t");
sprintf(temp, "%d", LC);
strcat(LITTAB, temp);
strcat(LITTAB, "\n");
}

}
else if (isInteger(subStr) == true)
{
if (start_flag==1)
{
LC = atoi(subStr) - 1;
start_flag=0;
}
if(DL_flag==1)
{
DL_flag=0;
}
}
else if (isRealNumber(subStr) == true)
{
}
else if (validIdentifier(subStr) == true )
{
if( (strcmp(subStr,"BREG")) !=0 )
{
strcpy(prev,subStr);
}
}
else if (validLiteral(subStr) == true)
{
// printf("\n It is a literal \n");
}
left = right;
}
}
return;
}
int main()
{
FILE *fp; char c; int
i,j; char Line[20];
fp=fopen("START.txt","r");

while((c=fgetc(fp))!=EOF)
{
printf("%c",c);
}

fclose(fp);
printf("\n------------------------\n");
fp=fopen("START.txt","r");

do
{
i=0;
while((c=fgetc(fp))!='\n')
{
if(c!=EOF)
{
Line[i++]=c;
}
else
{
goto END;
}
}
Line[i]='\0';

strcpy(str,Line);
Identify_Tokens();
LC++;
}while(1);

END:

printf("\n SYMBOL TABLE \n");


printf("-----------------------\n"); printf("Symbol
Name | Address\n");
printf("-----------------------\n"); printf("%s",
SYMTAB); printf("\n");
printf("\n LITERAL TABLE \n");
printf("-----------------------\n"); printf("Literal
Name | Address\n");
printf("-----------------------\n"); printf("%s",
LITTAB);
return 0;
}

Output:
References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.

Experiment No: 3

AIM: Demonstrate the Use macro features of C language.

Date:
Competency and Practical Skills: C programming, macro writing and application

Relevant CO: CO3

Objectives: (a) To understand application of macro.


(b) To understand processing of macro by macro processor.

Equipment/Instruments: Desktop/laptop, C language compiler, Editor

Theory: In programming, a macro is a mechanism for performing text-based


substitutions or code generation within the source code of a program. Macros are
typically used to simplify repetitive or complex coding tasks, improve code
readability, and enable code reuse. Macros are supported in various programming
languages and environments, although their specific implementation and syntax
may vary.

In C programming language, Macros are typically defined using the #define


preprocessor directive and can be used for various purposes, including creating
constants, simplifying code, and enabling conditional compilation.

Here's a basic overview of macros in C:

1. Macro Definition: To define a macro, you use the #define directive followed by
the macro name and its replacement value. The replacement value can be an
expression, a constant, or any valid C code.

#define PI 3.14155926

Where ever PI will appear in program, will be replaced by value. Similarly


small functions can also be defined using macro.

Observations:

#include<stdio.h>

#define PI 3.14
#define COUNT 100
#define CAPITAL "Delhi"

#define SQUARE(x) (x)*(x)


#define CUBE(x) SQUARE(x)*(x)
#define MAX(a,b) (a)>(b)?(a):(b)
#define MIN(a,b) (a)<(b)?(a):(b)

void main()
{
int a=5,b=99;

printf("\n----------------- Simple Macro -----------------\n");

printf("PI = %f \n", PI);


printf("COUNT = %d \n", COUNT);
printf("I am in %s \n", CAPITAL);
printf("Area of Circle = %f \n", PI * 10 * 10 );

printf("\n-------------- Macro with Argument --------------\n");

printf("Square of a = %d \n", SQUARE(a));

printf("\n----------------- Nested Macro ------------------\n");

printf("Cube of a = %d \n", CUBE(a));

printf("\n------------ Macro as Inline Function -----------\n");

printf("Enter a and b : \n");

scanf("%d%d",&a,&b);

printf("Max = %d \n", MAX(a,b));

printf("Min = %d ", MIN(a,b));

Output:
References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.

Experiment No: 4
AIM: Write a Lexical Analyzer (using Lex utility for UNIX).

Date:

Competency and Practical Skills: Lex utility

Relevant CO: CO4

Objectives: (a) To acquire skill of writing program for Lex utility.


(b) To able to write lexical analyzer for different language.

Equipment/Instruments: Desktop/laptop, Lex Utility

Theory:

 Lex, originally written by Mike Lesk and Eric Schmidt[3] and described in 1975,
is the standard lexical analyzer generator on many Unix systems.
 Lex reads an input stream specifying the lexical analyzer and writes source
code which implements the lexical analyzer in the C programming language.

Lex accepts an input specification which consist of three components.


1. Definitions
2. Rules
3. User Code
This components are separated by %% symbol.

• Definition: It contains declaration of simple name definition to simplify


scanner specification or in simple words it contains the variables to hold
regular expressions.
• For example, if you want to define D as a numerical digit, you would write
the following: D [0-9]
• Rules Section: Once you have defined your terms, you can write the rules
section. It contains strings and expressions to be matched by
the yylexsubroutine, and C commands to execute when a match is made.
• This section is required, and it must be preceded by the delimiter %%(double
percent signs), whether or not you have a definitions section.
The lex command does not recognize your rules without this delimiter.

X :match the character ’x’


. : any character except newline.
[xyz] : a "character class"; in this case, the pattern matches either an ’x’,
a ’y’, or a ’z’.
r*: zero or more r's, where r is any regular expression
r+: one or more r's

• User Code Section: This section can contain any C/C++ program code that
user want to execute.
• Yylex() function is used to flex compiler , which is embedded in this section so
user need to include this function.

Sample Program

%{
#include <iostream>
%}

%%
[0-9]+\.[0-9]+ { cout<< "Found a floating-point number:" <<yytext<<endl; }
[0-9]+ { cout<< "Found an integer:" <<yytext<<endl; }
[a-zA-Z0-9]+ { cout<< "Found a string: " <<yytext<<endl; }
%%

main()
{
// lex through the input:
yylex();
}

How to Execute Lex Program

1. flex lexfin.l
2. gcclex.yy.c , will produce a.exe as output
3. a.exe tt.c

Observations:
%{
#include <stdio.h>
%}

%%

[ \t\n] ; // Ignore whitespace and newline


[0-9]+ { printf("Integer Number: %s\n", yytext); }
[0-9]+[.][[0-9]+ { printf("Fractional Number: %s\n", yytext); }
"int"|"float" { printf("Keyword: %s\n", yytext); }
[a-zA-Z_][a-zA-Z0-9_]* { printf("Identifier: %s\n", yytext); }
[+\-*/=] { printf("Operator: %s\n", yytext); }
[;] ;
. { printf("Invalid token: %s\n", yytext); }

%%

int yywrap(void)
{
}

int main(void)
{
printf("Enter a statement : ");
yylex();
return 0;
}

Output:

References used by the students:


Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 5

AIM: Demonstrate the use of YACC with example program.

Date:

Competency and Practical Skills: Lex and YACC utility

Relevant CO: CO4

Objectives: (a) to able to write parser using YACC.


(b)to able to use YACC utility for writing parser.

Equipment/Instruments: Desktop/laptop, Lex and YACC utility

Theory:

YACC stands for "Yet another Compiler Compiler." It is a tool used in the field of
computer science and software development to generate parsers and syntax
analyzers for programming languages or other formal languages. YACC is often used
in conjunction with Lex, another tool used for lexical analysis (scanning or
tokenization).

Here's how YACC typically works:

1. Input: You provide YACC with a formal grammar description of a language


using a specific syntax known as Backus-Naur Form (BNF) or Extended
Backus-Naur Form (EBNF). This grammar describes the syntax rules of the
language you want to process.
2. Parser Generation: YACC processes the grammar and generates a parser in a
programming language like C, C++, or others. This parser can take input in
the form of a stream of tokens (usually generated by Lex or some other
lexical analyzer) and parse it according to the grammar rules.
3. Parsing: When you run the generated parser with input code, it performs
syntax analysis and creates a parse tree or an abstract syntax tree (AST)
representing the structure of the input code based on the grammar rules.
4. Semantic Actions: YACC allows you to specify semantic actions in your
grammar rules. These actions can be programmed to build an abstract
representation of the code, perform symbol table management, or generate
code in another programming language.
5. Error Handling: YACC can also include error-handling routines to report and
handle syntax errors gracefully.
Installing Softwares:

1. Download Flex 2.5.4a


2. Download Bison 2.4.1
3. Download DevC++
4. Install Flex at “C:\GnuWin32“
5. Install Bison at “C:\GnuWin32“
6. Install DevC++ at “C:\Dev-Cpp“
7. Open Environment Variables.
8. Add “C:\GnuWin32\bin;C:\Dev-Cpp\bin;” to path.

Steps to install Bison

1. Download DEV-CPP from here and install it.


2. Download Bison setup program from here and change its path as shown
below and install it.

Observations:

//Put Program along with Output of the program.

test.l
%{
#include<stdio.h> #include
"test.tab.h"
extern int yylval;
%}

/* Rule Section */

%%

[0-9]+ { yylval=atoi(yytext);
return NUMBER; }
[\t] ;

[\n] return 0;

. return yytext[0];

%%

int yywrap()
{
return 1;
}
test.y

%{
#include<stdio.h>
int flag=0;
%}

%token NUMBER

%left '+' '-'

%left '*' '/' '%'

%left '(' ')'

/* Rule Section */

%%

ArithmeticExpression: E{ printf("\n Result=%d \n\n", $$);


return 0; };

E: E'+'E {$$=$1+$3;}
|E'-'E {$$=$1-$3;}
|E'*'E {$$=$1*$3;}
|E'/'E {$$=$1/$3;}
|E'%'E {$$=$1%$3;}
|'('E')' {$$=$2;}
| NUMBER {$$=$1;}
;

%%

//driver code
void main()
{
printf("\n Enter Any Arithmetic Expression : ");

yyparse();

if(flag==0)
{
printf(" Valid Arithmetic Expression...! \n");
}
}

yyerror()
{
printf(" Invalid Arithmetic Expression...! \n");
flag=1;
}
Output:

References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 6

AIM: Write a C program to left factor the given grammar.

Date:

Competency and Practical Skills: C programming, Left Factoring

Relevant CO: CO4

Objectives: (a) to understand left factoring

Equipment/Instruments: Desktop/laptop, C Compiler, Editor

Theory:

Left factoring is a process by which the grammar with common prefixes is


transformed to make it useful for Top-Down parsers.
In left factoring,

 Make one production for each common prefixes.


 The common prefix may be a terminal or a non-terminal or a combination of
both.
 Rest of the derivation is added by new productions.

Example:

Do left factoring in the following grammar-

S → iEtS / iEtSeS / a
E→b

The left factored grammar is-

S → iEtSS’ / a
S’ → eS / ∈
E→b

Observations:

#include<stdio.h> char
NT[5] = "A";
char new_NT[5];

char P[5][10] = {"abcd","abcw"};

char new_P[5][10];

int i,j,x,count=2,common=1;

void Leftfactor()
{
for(i=0;i<count;i++)
{
for(j=i+1;j<count;j++)
{
while(common-1 < strlen(P[i]))
{
if( ! (strncmp(P[i],P[j],common)))
{
common++;
}
else
{
printf("\nGrammar after removing left factoring : \n");
printf("%s -> ",NT);

for(x=0;x<common-1;x++)
{
printf("%c",P[i][x]);
}
printf("%s'",NT);
break;
}
}
}
}

// Code for New NT


strcpy(new_NT,NT);
strcat(new_NT,"'"); printf("\
n");
printf("%s -> ", new_NT);

x=0;

for(i=common-1 ; i<strlen(P[0]) ; i++)


{
while(P[0][i] != '\0')
{
new_P[0][x++]=P[0][i++];
}
new_P[0][x]='\0';
}

x=0;
for(i=common-1 ; i<strlen(P[1]) ; i++)
{
while(P[1][i] != '\0')
{
new_P[1][x++]=P[1][i++];
}
new_P[1][x]='\0';
}

printf("%s | %s ",new_P[0],new_P[1]);

} void
main()
{
printf("Grammar rule is as follows: \n");
printf("%s -> ", NT);
for(i=0;i<count;i++)
{
if(i!=count-1)
{
printf(" %s |",P[i]);
}
else
{
printf(" %s \n",P[i]);
}
}
Leftfactor();
}

Output:

References used by the students:


Rubric wise marks obtained:
Good (2) Satisfactory (1) Need Improvement
(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 7

AIM: Write a C program to remove the Left Recursion from a given grammar.

Date:

Competency and Practical Skills: C programming, Left Recursion

Relevant CO: CO4

Objectives:(a) to understand Left Recursion

Equipment/Instruments: Desktop/laptop, C Compiler, Editor

Theory:

Left recursion is a concept in formal grammar theory and parsing algorithms used in
computer science and natural language processing. It refers to a situation in which
a grammar rule directly or indirectly references itself from the left-hand side of the
production rule.

In the context of context-free grammars, a grammar rule is typically defined as:

A → α1 | α2 | ... | αn

Where "A" is a non-terminal symbol, and α1, α2, ..., αn are sequences of non-
terminal and terminal symbols. Left recursion occurs when one of the αi sequences
starts with the same non-terminal symbol "A" that is on the left-hand side:

A → Aα1 | Aα2 | ... | Aαn

Left recursion can lead to problems in parsing and can make it difficult to construct
efficient parsers using certain parsing techniques, such as recursive descent
parsing. To eliminate left recursion from a grammar, you can use a technique called
left recursion elimination, which involves rewriting the grammar rules to remove
the left recursion. The idea is to factor out the left recursion so that the grammar
becomes:

A → β1A' | β2A' | ... | βmA' A' → α1 | α2 | ... | αn


Here, A' is a new non-terminal symbol, and β1, β2, ..., βm are sequences of symbols
that do not start with A. This restructuring of the grammar allows for more
straightforward parsing.

Left recursion elimination is a fundamental step in the process of converting a


context-free grammar into other forms suitable for parsing, such as LL(1) or LR(1)
grammars, which can be more easily processed by parser generators or manual
parsing algorithms.

Observations:

#include<stdio.h>
#include<string.h>

char NT[5] = "A";


char new_NT[5];

char P[2][10] = {"Abc","xy"};

char new_P[5][10];

char R1[10],R2[10],New_R1[10],New_R2[10];

int i,j,x,count=2;
int flag1=0,flag2=0;

void PRINT()
{
printf("%s -> ",NT);
if(flag1==1)
printf("%s",R2);
else if(flag2==1)
printf("%s",R1);

strcpy(new_NT,NT);
strcat(new_NT,"\'");

printf("\n%s -> ",new_NT);

(flag1==1)? printf("%s",New_R1): printf("");


(flag2==1)? printf("%s",New_R2): printf("");

printf(" | %c",238);

}
void LeftRecursion()
{
for(i=0;i<2;i++)
{
if(NT[0]==P[i][0])
{
if(i==0)
flag1=1;
if(i==1)
flag2=1;
}
}

if(flag1==1)
{
for(i=0,j=1;i<strlen(P[0]);i++,j++)
{
New_R1[i] = P[0][j];
}
New_R1[i]='\0';
strcat(New_R1,NT);
strcat(New_R1,"\'");
}
else
{
strcpy(R1,P[0]);
}

if(flag2==1)
{
for(i=0,j=1;i<strlen(P[1]);i++,j++)
{
New_R2[i] = P[1][j];
}
New_R2[i]='\0';
strcat(New_R2,NT);
strcat(New_R2,"\'");
}
else
{
strcpy(R2,P[1]);
strcat(R2,"A\'");
}

PRINT();
}

void main()
{
printf("Grammar rule is as follows: \n");
printf("%s -> ", NT);
for(i=0;i<count;i++)
{
if(i!=count-1)
{
printf(" %s |",P[i]);
}
else
{
printf(" %s \n",P[i]);
}
}
printf("\n--------------------------\n");

LeftRecursion();
}

Output:

References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 8

AIM: Write C program to Implement Recursive Descendent Parsing for the given
Grammar.
E -> T + E / T
T -> F * T / F
F ->( E ) / i
Date:

Competency and Practical Skills: C Programming, Recursive Descendent


Parser

Relevant CO: CO4

Objectives: (a) to understand and implement Recursive Descendent Parser

Equipment/Instruments: Desktop//laptop, C Compiler, Editor

Theory:

It is a kind of Top-Down Parser. A top-down parser builds the parse tree from the
top to down, starting with the start non-terminal. A Predictive Parser is a special
case of Recursive Descent Parser, where no Back Tracking is required. By carefully
writing a grammar means eliminating left recursion and left factoring from it, the
resulting grammar will be a grammar that can be parsed by a recursive descent
parser.

It can be defined as a Parser that uses the various recursive procedures to process
the input string with no backtracking. It can be simply performed using a Recursive
language. The first symbol of the string of R.H.S of production will uniquely
determine the correct alternative to choose.

The major approach of recursive-descent parsing is to relate each non-terminal


with a procedure. The objective of each procedure is to read a sequence of input
characters that can be produced by the corresponding non-terminal, and return a
pointer to the root of the parse tree for the non-terminal. The structure of the
procedure is prescribed by the productions for the equivalent non-terminal.

The recursive procedures can be simply to write and adequately effective if written
in a language that executes the procedure call effectively. There is a procedure for
each non-terminal in the grammar. It can consider a global variable lookahead,
holding the current input token and a procedure match (Expected Token) is the
action of recognizing the next token in the parsing process and advancing the input
stream pointer, such that lookahead points to the next token to be parsed. Match ()
is effectively a call to the lexical analyzer to get the next token.

For example, input stream is a + b$.

lookahead == a

match()

lookahead == +

match ()

lookahead == b

……………………….

……………………….

In this manner, parsing can be done.

Observations:

#include<stdio.h>
#include<string.h>

char NT[5] = "A";


char new_NT[5];

char P[2][10] = {"Abc","xy"};

char new_P[5][10];

char R1[10],R2[10],New_R1[10],New_R2[10];

int i,j,x,count=2;
int flag1=0,flag2=0;

void PRINT()
{
printf("%s -> ",NT);
if(flag1==1)
printf("%s",R2);
else if(flag2==1)
printf("%s",R1);

strcpy(new_NT,NT);
strcat(new_NT,"\'");

printf("\n%s -> ",new_NT);


(flag1==1)? printf("%s",New_R1): printf("");
(flag2==1)? printf("%s",New_R2): printf("");

printf(" | %c",238);

}
void LeftRecursion()
{
for(i=0;i<2;i++)
{
if(NT[0]==P[i][0])
{
if(i==0)
flag1=1;
if(i==1)
flag2=1;
}
}

if(flag1==1)
{
for(i=0,j=1;i<strlen(P[0]);i++,j++)
{
New_R1[i] = P[0][j];
}
New_R1[i]='\0';
strcat(New_R1,NT);
strcat(New_R1,"\'");
}
else
{
strcpy(R1,P[0]);
}

if(flag2==1)
{
for(i=0,j=1;i<strlen(P[1]);i++,j++)
{
New_R2[i] = P[1][j];
}
New_R2[i]='\0';
strcat(New_R2,NT);
strcat(New_R2,"\'");
}
else
{
strcpy(R2,P[1]);
strcat(R2,"A\'");
}

PRINT();
}

void main()
{
printf("Grammar rule is as follows: \n");
printf("%s -> ", NT);
for(i=0;i<count;i++)
{
if(i!=count-1)
{
printf(" %s |",P[i]);
}
else
{
printf(" %s \n",P[i]);
}
}
printf("\n--------------------------\n");

LeftRecursion();
}

Output:

References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 9

AIM: Implement Predictive Parser for the arithmetic expression grammar


using YACC and Lex.

Date:

Competency and Practical Skills: C Programming, Predictive Parser

Relevant CO: CO5

Objectives: (a) to understand and implement Predictive Parser

Equipment/Instruments: Desktop//laptop, C Compiler, Editor

Theory:

Predictive parser is a recursive descent parser, which has the capability to


predict which production is to be used to replace the input string. The
predictive parser does not suffer from backtracking.

To accomplish its tasks, the predictive parser uses a look-ahead pointer,


which points to the next input symbols. To make the parser back-tracking
free, the predictive parser puts some constraints on the grammar and
accepts only a class of grammar known as LL(k) grammar.

Predictive parsing uses a stack and a parsing table to parse the input and
generate a parse tree. Both the stack and the input contains an end symbol
$ to denote that the stack is empty and the input is consumed. The parser
refers to the parsing table to take any decision on the input and stack
element combination.
Observations:

Lexical Analyzer Source Code:

input.l

%option noyywrap
%{
#include"y.tab.h"
extern yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext); return NUMBER;}
[a-zA-Z]+ {return ID;}
[\t]+ ;
\n {return 0;}
. {return yytext[0];}
%%

input.y

%{
#include<stdio.h>
int flag=0;
%}
%token NUMBER ID
%left '+' '-'
%left '*' '/'
%%
expr: expr '+' expr
|expr '-' expr
|expr '*' expr
|expr '/' expr
|'-'NUMBER
|'-'ID
|'('expr')'
|NUMBER
|ID
;
%%
void main()
{
printf("\n Enter the expression\n\n ");
yyparse();
if(flag==0)
{
printf("\n Expression is valid \n\n");
}
}
int yyerror(char *s)
{
printf("\n Expression is invalid \n\n");
flag=1;
}
Output: -

References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.
Experiment No: 10

AIM: Write a C program which generates Quadruple Table for the given postfix String.

Date:

Competency and Practical Skills: C Programming, Quadruple Table

Relevant CO: CO1

Objectives: (a) to understand and implement generation of Quadruple Table.

Equipment/Instruments: Desktop/laptop, C Compiler, Editor

Theory:

A Quadruple Table, also known as a Quad Table or Quadruple Table, is a


data structure used in compiler design and optimization to represent
intermediate code or three-address code. It is a tabular structure that stores
quadruples or "quads." Each quad typically represents a single operation or
instruction in a high-level programming language and is used to generate
target code (assembly or machine code) later in the compilation process.

A quad typically consists of four fields:

op, opr1, opr2, result

1. Operator (or Operation): This field specifies the operation to be


performed, such as addition, subtraction, multiplication, assignment,
etc. It is usually represented as a string or an integer code.
2. Operand 1: This field represents the first operand of the operation. It
can be a variable, a constant, or an intermediate result.
3. Operand 2: This field represents the second operand of the operation.
Like Operand 1, it can be a variable, a constant, or an intermediate
result.
4. Result: This field stores the result of the operation. It can be a
temporary variable that holds intermediate values.

Observations:
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct quad
{
char
op; char
op1; char
op2;
char r;
};
void
main(
)
{
struct quad a[20]; char
s[20],temp2[20],temp1[10];
int k=0,i=0,count,j,len;
clrscr();

printf("enter the string in postorder\n");


gets(s);
printf("operator | operand1 | operand2 | result\n");
printf("---------------------------------------\n");
len=strlen(s);
while(k<len)
{
if(s[k]=='+'||s[k]=='-'||s[k]=='*'||s[k]=='/'||s[k]=='^'||s[k]=='=')
{
a[i].op=s[k];
a[i].op1=s[k-2];
a[i].op2=s[k-1];
a[i].r=(char)i+49;
printf(" %c | %c | %c | %c\n",a[i].op,a[i].op1,a[i].op2,a[i].r);
s[k-2]=(char)i+49;
count = k+1;
j=-1;
strcpy(temp2,NULL);
while(count<=len)
{
temp2[++j]=s[count++];
}
temp2[j+1]='\0';
count=0;
j=-1;
strcpy(temp1,NULL);
while(count<=k-2)
{
temp1[++j]=s[count++];
}
temp1[j+1]='\0';

strcpy(s,temp1);
strcat(s,temp2);
len=strlen(s);
i++;
k=k-1;
}
else
k++;
}
printf("---------------------------------------\n");
getch();
}

Output:

References used by the students:

Rubric wise marks obtained:

Good (2) Satisfactory (1) Need Improvement


(0)
Regularity High (>70%) Moderate (40- Poor (0-40%)
70%)
Problem Analysis Apt & Full Limited Very Less
& Development of Identification of Identification of Identification of the
the Solution the Problem & the Problem / Problem / Very Less
Complete Incomplete Solution for the
Solution for the Solution for the Problem
Problem Problem
Testing of the Correct Solution Partially Correct Very less correct
Solution as required Solution for the solution for the
Problem problem
Documentation Documentation Not up to Proper format not
completed standard. followed,
neatly. incomplete.

You might also like