Download as pdf or txt
Download as pdf or txt
You are on page 1of 31

Experiment 1

AIM: Write a program to implement the separation of


tokens from a source program.
Implementation:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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 == '>' ||
ch == '<' || ch == '=' || ch == '(' || ch == ')' ||
ch == '[' || ch == ']' || ch == '{' || ch == '}')
return (true);
return (false);
}

char* subString(char* str, 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 parse(char* str)


{
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\n", str[right]);

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

left = right;
}
}
return;
}

int main()
{
char str[100] = "while(1){int a = 4};";
parse(str);
return (0);
}

Output:
Experiment 2
AIM: Write a program to implement lexical analysis phase
of a compiler.
Implementation:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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)


{
if (str[0] == '0' || str[0] == '1' || str[0] == '2' ||
str[0] == '3' || str[0] == '4' || str[0] == '5' ||
str[0] == '6' || str[0] == '7' || str[0] == '8' ||
str[0] == '9' || isDelimiter(str[0]) == true)
return (false);
return (true);
}

bool isKeyword(char* str)


{
if (!strcmp(str, "if") || !strcmp(str, "else") ||
!strcmp(str, "while") || !strcmp(str, "do") ||
!strcmp(str, "break") ||
!strcmp(str, "continue") || !strcmp(str, "int")
|| !strcmp(str, "double") || !strcmp(str, "float")
|| !strcmp(str, "return") || !strcmp(str, "char")
|| !strcmp(str, "case") || !strcmp(str, "char")
|| !strcmp(str, "sizeof") || !strcmp(str, "long")
|| !strcmp(str, "short") || !strcmp(str, "typedef")
|| !strcmp(str, "switch") || !strcmp(str, "unsigned")
|| !strcmp(str, "void") || !strcmp(str, "static")
|| !strcmp(str, "struct") || !strcmp(str, "goto")|| !strcmp(str, "string"))
return (true);
return (false);
}

bool isInteger(char* str)


{
int i, len = strlen(str);

if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' || (str[i] == '-' && i > 0))
return (false);
}
return (true);
}

bool isRealNumber(char* str)


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

if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' && str[i] != '.' ||
(str[i] == '-' && i > 0))
return (false);
if (str[i] == '.')
hasDecimal = true;
}
return (hasDecimal);
}

char* subString(char* str, 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 parse(char* str)


{
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]);
else
printf("'%c' IS A DELIMITER\n", str[right]);

right++;
left = right;

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


|| (right == len && left != right)) {
char* subStr = subString(str, 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


&& isDelimiter(str[right - 1]) == false)
printf("'%s' IS A VALID IDENTIFIER\n", subStr);
else if (validIdentifier(subStr) == false
&& isDelimiter(str[right - 1]) == false)
printf("'%s' IS NOT A VALID IDENTIFIER\n", subStr);
else
printf("'%s' IS A DELIMITER\n", subStr);

left = right;
}
}
return;
}

int main()
{
char str[100] = "while(1){int a = 4.6};";
parse(str);
return (0);
}

Output:
Experiment 3

AIM: Develop simple language processors like desk calculator


and assembler.
Implementation

Desk calculator
#include <iostream>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

// Define a function to evaluate a given expression


double evaluateExpression(const std::string& expression) {
std::istringstream iss(expression);
std::stack<double> operandStack;
std::stack<char> operatorStack;

while (!iss.eof()) {
std::string token;
iss >> token;

if (token == "+" || token == "-" || token == "*" || token == "/") {


while (!operatorStack.empty() && operatorStack.top() != '(' && ((token == "*" || token == "/") ?
(operatorStack.top() == '*' || operatorStack.top() == '/') : true)) {
double b = operandStack.top();
operandStack.pop();
double a = operandStack.top();
operandStack.pop();
char op = operatorStack.top();
operatorStack.pop();

if (op == '+') operandStack.push(a + b);


else if (op == '-') operandStack.push(a - b);
else if (op == '*') operandStack.push(a * b);
else if (op == '/') operandStack.push(a / b);
}
operatorStack.push(token[0]);
} else if (token == "(") {
operatorStack.push('(');
} else if (token == ")") {
while (!operatorStack.empty() && operatorStack.top() != '(') {
double b = operandStack.top();
operandStack.pop();
double a = operandStack.top();
operandStack.pop();
char op = operatorStack.top();
operatorStack.pop();
2
if (op == '+') operandStack.push(a + b);
else if (op == '-') operandStack.push(a - b);
else if (op == '*') operandStack.push(a * b);
else if (op == '/') operandStack.push(a / b);
}
operatorStack.pop(); // Pop the remaining '('
} else {
double operand = stod(token);
operandStack.push(operand);
}
}

while (!operatorStack.empty()) {
double b = operandStack.top();
operandStack.pop();
double a = operandStack.top();
operandStack.pop();
char op = operatorStack.top();
operatorStack.pop();

if (op == '+') operandStack.push(a + b);


else if (op == '-') operandStack.push(a - b);
else if (op == '*') operandStack.push(a * b);
else if (op == '/') operandStack.push(a / b);
}

return operandStack.top();
}

int main() {
std::string expression;
std::cout << "Enter an arithmetic expression: ";
std::getline(std::cin, expression);

double result = evaluateExpression(expression);


std::cout << "Result: " << result << std::endl;

return 0;
}

2. ASSEMBLER
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 100


#define MAX_SYMBOLS 100

// Data structures to store symbols and their addresses


typedef struct {
char label[10];
int address;
} SymbolTableEntry;

3
SymbolTableEntry symbolTable[MAX_SYMBOLS];
int symbolCount = 0;

// Functions
int searchSymbolTable(char label[10]) {
for (int i = 0; i < symbolCount; i++) {
if (strcmp(symbolTable[i].label, label) == 0) {
return symbolTable[i].address;
}
}
return -1;
}

void addToSymbolTable(char label[10], int address) {


strcpy(symbolTable[symbolCount].label, label);
symbolTable[symbolCount].address = address;
symbolCount++;
}

int main() {
char line[MAX_LINE_LENGTH];
char mnemonic[10];
char label[10];
char operand[10];
int address = 0;
int machineCode = 0;

FILE *inputFile = fopen("assembly_code.txt", "r");


FILE *outputFile = fopen("machine_code.txt", "w");

if (!inputFile) {
printf("Error: Unable to open input file.\n");
return 1;
}

if (!outputFile) {
printf("Error: Unable to open output file.\n");
return 1;
}

while (fgets(line, MAX_LINE_LENGTH, inputFile)) {


sscanf(line, "%s %s %s", label, mnemonic, operand);

// First pass: Build the symbol table


if (label[0] != '\0') {
addToSymbolTable(label, address);
}

// Second pass: Translate instructions to machine code


if (strcmp(mnemonic, "ADD") == 0) {
machineCode = 0x1000;
} else if (strcmp(mnemonic, "SUB") == 0) {
machineCode = 0x2000;
} else if (strcmp(mnemonic, "LD") == 0) {
machineCode = 0x3000;
} else if (strcmp(mnemonic, "ST") == 0) {
machineCode = 0x4000;
} else if (strcmp(mnemonic, "HLT") == 0) {

4
machineCode = 0xF000;
} else {
printf("Error: Invalid mnemonic '%s'.\n", mnemonic);
return 1;
}

if (operand[0] != '\0') {
int operandValue = searchSymbolTable(operand);
if (operandValue == -1) {
printf("Error: Undefined label '%s'.\n", operand);
return 1;
}
machineCode += operandValue;
}

fprintf(outputFile, "%04X\n", machineCode);


address++;
}

fclose(inputFile);
fclose(outputFile);
printf("Assembly completed successfully.\n");

return 0;
}

RESULTS

Output:
a. Desk Calculator

5
ASSEMBLER O/P:

6
Experiment 4

AIM: Design a small high-level language.


Implementation:

Name of the Language: "MiniLang"

Features and Components:

1. Data Types:
• Integer (int): Represents whole numbers.
• Float (float): Represents numbers with decimal points.
• String (str): Represents text.

2. Variables:
• Variables are defined with the var keyword.
• Variables are dynamically typed (no need to specify data types explicitly).

3. Operators:
• Arithmetic operators: +, -, *, /, % (modulo)
• Comparison operators: ==, !=, <, >, <=, >=
• Logical operators: and, or, not

4. Control Flow:
• Conditional statements: if, else if, else
• Looping: for and while loops

5. Functions:
• Functions are defined with the func keyword.
• Support for parameters and return values.

6. Comments:
• Single-line comments using #

7
Source Code:

#include <iostream>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>

using namespace std;

// Function to evaluate arithmetic expressions


int evaluateExpression(const string& expression) {
stack<int> values;
stack<char> operators;

for (size_t i = 0; i < expression.length(); ++i) {


if (isspace(expression[i])) {
continue; // Skip whitespace
} else if (isdigit(expression[i])) {
int value = 0;
while (i < expression.length() && isdigit(expression[i])) {
value = value * 10 + (expression[i] - '0');
++i;
}
values.push(value);
--i; // Backtrack one character
} else if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/') {
while (!operators.empty() && (expression[i] != '+' && expression[i] != '-') && (operators.top() == '*' ||
operators.top() == '/')) {
char op = operators.top();
operators.pop();
int right = values.top();
values.pop();
int left = values.top();
values.pop();
if (op == '+') {
values.push(left + right);
} else if (op == '-') {
values.push(left - right);
} else if (op == '*') {
values.push(left * right);
} else if (op == '/') {
values.push(left / right);
}
}
operators.push(expression[i]);
} else {
cerr << "Error: Invalid character in the expression." << endl;
exit(1);
}
}

while (!operators.empty()) {
char op = operators.top();
operators.pop();

8
int right = values.top();
values.pop();
int left = values.top();
values.pop();
if (op == '+') {
values.push(left + right);
} else if (op == '-') {
values.push(left - right);
} else if (op == '*') {
values.push(left * right);
} else if (op == '/') {
values.push(left / right);
}
}

return values.top();
}

int main() {
string input;
while (true) {
cout << "Enter an arithmetic expression (or 'quit' to exit): ";
getline(cin, input);
if (input == "quit") {
break;
}

int result = evaluateExpression(input);


cout << "Result: " << result << endl;
}

return 0;
}

EXAMPLE

9
Output:

10
Experiment 5

AIM
Develop a lexical analyzer and a syntax analyzer for the same using the LEX and
YACC tools. Also implement the bookkeeper module.

Implementation
1. Lexical Analyzer(lex):

11
2 Syntax Analyzer(Yacc/bison)
%{

#include <stdio.h>

int yylex(void);

%}

%token NUMBER

%left '+' '-'

%left '*' '/'

%%

calc: expr '\n' { printf("Result: %d\n", $1);

expr: NUMBER { $$ = $1; }

| expr '+' expr { $$ = $1 + $3; }

| expr '-' expr { $$ = $1 - $3; }

| expr '*' expr { $$ = $1 * $3; }

| expr '/' expr {

if ($3 != 0) {

$$ = $1 / $3;

} else {

fprintf(stderr, "Error: Division by zero\n");

$$ = 0;

%%

int main() {

yyparse();

return 0;

}
12
Bookkeeper Module

You can create a file named bookkeeper.c with the following content:

#include <stdio.h>

void bookkeeper_module() {

printf("Bookkeeper module is working!\n");


}

Results
Compile

Input

Output

13
Experiment 6
AIM
Develop a simple calculator using LEX and YACC tools.

Implementation

Lexical Analyser for Calculator


%{
#include <stdio.h>
#include "y.tab.h"
extern int yylval;
%}
%% [ ] ;
“end” {return 0;}
[a-z] {
c = yytext[0]; yylval = c - 'a'; return(LETTER);
}
[0-9] {
c = yytext[0]; yylval = c - '0'; return(DIGIT);
}
[^a-z0-9\b] { c = yytext[0]; return(c);
}
%% 7
Parser for Calculator
%{
#include<stdio.h> int regs[26];
int base;
%}
%start list
/* %union { int a; } */
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /*supplies precedence for unary minus */
%% /* beginning of rules section */ list: /*empty */
|
list stat '\n'
|
list error '\n'
{
yyerrok;
}
;
14
stat: expr
{
printf("Value of expression is %d\n",$1);
}
|
LETTER '=' expr
{
regs[$1] = $3;
}
;
expr: '(' expr ')' {
$$ = $2; }
|expr '*' expr { $$ = $1 * $3; }
|expr '/' expr { $$ = $1 / $3; }
|expr '%' expr { $$ = $1 % $3; }
|expr '+' expr { $$ = $1 + $3; }
|expr '-' expr { $$ = $1 - $3; }
|expr '&' expr { $$ = $1 & $3; }
|expr '|' expr { $$ = $1 | $3; }
|'-' expr %prec UMINUS { $$ = -$2; }
|LETTER { $$ = regs[$1]; }
|number ; number: DIGIT { $$ = $1; base = ($1==0) ? 8 : 10; }
| number DIGIT { $$ = base * $1 + $2; };
%%
main() {
printf("Enter arithmetic expressions for evaluation\nEnter end to stop.\n"); return(yyparse()); }
yyerror(s)
char *s; { fprintf(stderr, "%s\n",s); }
yywrap() {
return(1);
}

RESULTS

15
Experiment 7

AIM

Implement a program for symbol table using hashing.

Implementation
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 11
char l[10];
struct symb
{
int add;
char label[10];
}sy[11];
void search();
void main()
{
int a[MAX],num,key,i,ch;
char ans;
int create(int);
void lprob(int [],int,int);
void display(int []);
system("cls");
for(i=0;i<MAX;i++)
a[i]=0;
do
{
printf("\nEnter your choice:");
printf("\n1 - Create entry in the symbol table\n2 - Search in the symbol table\n");
scanf("%d",&ch);
switch(ch)
{
case 1:
do
{
printf("\nEnter the address:");
scanf("%d",&num);
key=create(num);
printf("Enter the label:");
scanf("%s",l);
lprob(a,key,num);
16
printf("\nContinue?\n0 for no\n1 for yes\n");
scanf("%s",ans);
}
while(ans==1);
display(a);
break;
case 2:
search();
break;
}
}while(ch<=2);
getch();
}

int create(int num)


{
int key;
key=num%11;
return key;
}

void lprob(int a[MAX],int key,int num)


{
int flag,i,count=0;
void display(int a[]);
flag=0;
if(a[key]==0)
{
a[key]=num;
sy[key].add=num;
strcpy(sy[key].label,l);
}
else
{
i=0;
while(i<MAX)
{
if(a[i]!=0)
count++;
i++;
}
if(count==MAX)
{
printf("\nHash table is full");
display(a);
getch();
exit(1);
}
for(i=key+1;i<MAX;i++)
if(a[i]==0)
{
17
a[i]=num;
flag=1;
sy[key].add=num;
strcpy(sy[key].label,l);
break;
}
for(i=0;i<key && flag==0;i++)
if(a[i]==0)
{
a[i]=num;
flag=1;
sy[key].add=num;
strcpy(sy[key].label,l);
break;
}
}
}
void display(int a[MAX])
{
FILE *fp;
int i;
fp=fopen("symbol.txt","w");
printf("\nSymbol Table:");
printf("\nHash values Address Label");
for(i=0;i<MAX;i++)
{
printf("\n%d\t %d\t %s",i,sy[i].add,sy[i].label);
fprintf(fp,"\n%d %d %s",i,sy[i].add,sy[i].label);
}
fclose(fp);
}

void search()
{
FILE *fp1;
char la[10];
int set=0,s;
int j,i;
printf("Enter the label: ");
scanf("%s",la);
fp1=fopen("symbol.txt","r");
for(i=0;i<MAX;i++)
{
fscanf(fp1,"%d%d",&j,&sy[i].add);
if(sy[i].add!=0)
fscanf(fp1,"%s",sy[i].label);
}
for(i=0;i<MAX;i++)
{
if(sy[i].add!=0)
{
18
if(strcmp(sy[i].label,la)==0)
{
set=1;
s=sy[i].add;
}
}
}
if(set==1)
printf("\nThe label '%s' is present in the symbol table at address:%d\n",la,s);
else
printf("\nThe label is not present in the symbol table\n");
}

RESULTS

19
20
21
EXPERIMENT-8

AIM
Implement a bottom-up parser using YACC tool.

Implementation

LEX file:

%{
#include<stdio.h>
#include "y.tab.h"
%}

%%
[0-9]+ {yylval.dval=atof(yytext);
return DIGIT;
}
\n|. return yytext[0];
%%

YACC file:
%{
/*This YACC specification file generates the LALR parser for the program
considered in experiment 4.*/
#include<stdio.h>
%}
%union
{
double dval;
}
%token <dval> DIGIT
%type <dval> expr
%type <dval> term
%type <dval> factor
%%
line: expr '\n' {
printf("%g\n",$1);
}
;
expr: expr '+' term {$$=$1 + $3 ;}
| term
;
term: term '*' factor {$$=$1 * $3 ;}
| factor
22
;
factor: '(' expr ')' {$$=$2 ;}
| DIGIT
;
%%
int main()
{
yyparse();
}
yyerror(char *s)
{
printf("%s",s);
}

RESULT:
$lex parser.l
$yacc –d parser.y
$cc lex.yy.c y.tab.c –ll –lm
$./a.out

9+4

15.0000

23
EXPERIMENT-9
AIM
Represent ‘C’ language using Context Free Grammar

IMPLEMENTATION
program -> declaration-list

declaration-list -> declaration


| declaration-list declaration
declaration -> var-declaration
| fun-declaration

var-declaration -> type-specifier ID ;


type-specifier -> int
| float

fun-declaration -> type-specifier ID ( params ) compound-stmt

params -> param-list


| VOID
param-list -> param
| param-list , param

param -> type-specifier ID

compound-stmt -> { local-declarations statement-list }


local-declarations -> local-declaration
| local-declarations local-declaration
local-declaration -> type-specifier ID ;
statement-list -> statement
| statement-list statement
statement -> expression-stmt
| compound-stmt
| selection-stmt
| iteration-stmt
| return-stmt

expression-stmt -> expression ;


expression -> var = expression
| simple-expression

var -> ID
simple-expression -> additive-expression relop additive-expression
| additive-expression

relop -> < | <= | > | >= | == | !=

additive-expression -> additive-expression addop term


| term

addop -> + | -

24
term -> term mulop factor
| factor

mulop -> * | /
factor -> ( expression )
| var
| call
| NUM

call -> ID ( args )


args -> arg-list

arg-list -> expression
| arg-list , expression

selection-stmt -> if ( expression ) statement


| if ( expression ) statement else statement

iteration-stmt -> while ( expression ) statement

return-stmt -> return ;


| return expression

25
EXPERIMENT-10
AIM
Add assignment statement, If then else statement and while loop to the calculator and generate the three address code for
the same

IMPLEMENTATION
import ply.yacc as yacc
# Tokens
tokens = (
'NUMBER',
'ID',
'ASSIGN',
'IF',
'THEN',
'ELSE',
'WHILE',
'PLUS',
'MINUS',
'TIMES',
'DIVIDE',
'LPAREN',
'RPAREN',
'SEMICOLON',
)
# Grammar
def p_program(p):
'''
program : statements
'''
p[0] = p[1]
def p_statements_empty(p):
'''
statements :
'''
p[0] = []
def p_statements_statement(p):
'''
statements : statements statement SEMICOLON
'''
p[0] = p[1] + [p[2]]
def p_statement_assign(p):
'''
statement : ID ASSIGN expression
'''
p[0] = ("=", p[1], p[3])
def p_statement_if(p):
'''
statement : IF expression THEN statements ELSE statements
'''
p[0] = ("if-else", p[2], p[4], p[6])
def p_statement_while(p):
'''
statement : WHILE expression statements
'''
p[0] = ("while", p[2], p[3])
26

You might also like