Aim: Design a Lexical Analyzer which removes redundant spaces, tabs and new lines.
It should
also ignore comments. Although the syntax specification states that identifiers can be arbitrarily
long, you may restrict the length to some reasonable value. Simulate the same in C language.
Program:
#include <ctype.h>
//#include <stdbool.h>
typedef int bool;
#define true 1
#define false 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<conio.h>
#define MAX_LENGTH 100
bool isDelimiter(char chr)
{
return (chr == ' ' || chr == '+' || chr == '-'
|| chr == '*' || chr == '/' || chr == ','
|| chr == ';' || chr == '%' || chr == '>'
|| chr == '<' || chr == '=' || chr == '('
|| chr == ')' || chr == '[' || chr == ']'
|| chr == '{' || chr == '}');
}
bool isOperator(char chr)
{
return (chr == '+' || chr == '-' || chr == '*'
|| chr == '/' || chr == '>' || chr == '<'
|| chr == '=' || chr==',');
}
bool isValidIdentifier(char* str)
{
return (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]));
}
bool isKeyword(char* str)
{
int i;
const 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 < sizeof(keywords) / sizeof(keywords[0]); i++) {
if (strcmp(str, keywords[i]) == 0) {
return true;
}
}
return false;
}
// check for an integer value
bool isInteger(char* str)
{
if (str == NULL || *str == '\0') {
return false;
}
int i = 0;
while (isdigit(str[i])) {
i++;
}
return str[i] == '\0';
}
// trims a substring from a given string's start and end
// position
char* getSubstring(char* str, int start, int end)
{
int length = strlen(str);
int subLength = end - start + 1;
char* subStr
= (char*)malloc((subLength + 1) * sizeof(char));
strncpy(subStr, str + start, subLength);
subStr[subLength] = '\0';
return subStr;
}
// this function parse the input
int lexicalAnalyzer(char* input)
{
int left = 0, right = 0;
int len = strlen(input);
while (right <= len && left <= right) {
if (!isDelimiter(input[right]))
right++;
if (isDelimiter(input[right]) && left == right) {
if (isOperator(input[right]))
printf("Token: Operator, Value: %c\n",
input[right]);
right++;
left = right;
}
else if (isDelimiter(input[right]) && left != right
|| (right == len && left != right)) {
char* subStr
= getSubstring(input, left, right - 1);
if (isKeyword(subStr))
printf("Token: Keyword, Value: %s\n",
subStr);
else if (isInteger(subStr))
printf("Token: Integer, Value: %s\n",
subStr);
else if (isValidIdentifier(subStr)
&& !isDelimiter(input[right - 1]))
printf("Token: Identifier, Value: %s\n",
subStr);
else if (!isValidIdentifier(subStr)
&& !isDelimiter(input[right - 1]))
printf("Token: Unidentified, Value: %s\n",
subStr);
left = right;
}
}
return 0;
}
// main function
void main()
{
// Input 01
char lex_input01[MAX_LENGTH] = "\nint abc = xy +\t 1mn";
printf("For Expression \"%s\":\n", lex_input01);
lexicalAnalyzer(lex_input01);
printf(" \n");
// Input 02
char lex_input02[MAX_LENGTH]
= "int x=ab+bc+30+switch+ 0y ";
printf("For Expression \"%s\":\n", lex_input02);
lexicalAnalyzer(lex_input02);
//iNPUT 03
char lex_input03[MAX_LENGTH]
= "int main(){ int a,b,c}";
printf("For Expression \"%s\":\n", lex_input03);
lexicalAnalyzer(lex_input03);
getch();
}
Aim: Check the given input string is accepted or not for Regular Expression
#include<stdio.h>
Program:
#include<stdlib.h>
#include<string.h>
void main()
char s[20],c;
int state=0,i=0;
clrscr();
printf("n Enter a string:");
gets(s);
while(s[i]!='')
switch(state)
case 0: c=s[i++];
if(c=='a')
state=1;
else if(c=='b')
state=2;
else
state=6;
break;
case 1: c=s[i++];
if(c=='a')
state=3;
else if(c=='b')
state=4;
else
state=6;
break;
case 2: c=s[i++];
if(c=='a')
state=6;
else if(c=='b')
state=2;
else
state=6;
break;
case 3: c=s[i++];
if(c=='a')
state=3;
else if(c=='b')
state=2;
else
state=6;
break;
case 4: c=s[i++];
if(c=='a')
state=6;
else if(c=='b')
state=5;
else
state=6;
break;
case 5: c=s[i++];
if(c=='a')
state=6;
else if(c=='b')
state=2;
else
state=6;
break;
case 6: printf("n %s is not recognised.",s);
exit(0);
if(state==1)
printf("n %s is accepted under rule 'a'",s);
else if((state==2)||(state==4))
printf("n %s is accepted under rule 'a*b+'",s);
else if(state==5)
printf("n %s is accepted under rule 'abb'",s);
getch();
}
Aim: Write a C program to simulate lexical analyzer for validating operators.
#include<stdio.h>
#include<conio.h>
void main()
char s[5];
clrsr();
printf("\n Enter any operator:");
gets(s);
switch(s[0])
case'>': if(s[1]=='=')
printf("\n Greater than or equal");
else
printf("\n Greater than");
break;
case'<':
if(s[1]=='=')
printf("\n Less than or equal");
else
printf("\nLess than"); break;
case'=':
if(s[1]=='=')
printf("\nEqual to");
else
printf("\nAssignment"); break;
case'!':
if(s[1]=='=')
printf("\nNot Equal");
else
printf("\n Bit Not");
break;
case'&':
if(s[1]=='&')
printf("\nLogical AND");
else
printf("\n Bitwise AND"); b
break;
case'|':
if(s[1]=='|')
printf("\nLogical OR");
else
printf("\nBitwise OR");
break;
case'+':
printf("\n Addition");
break;
case'-':
printf("\nSubstraction");
break;
case'*':
printf("\nMultiplication");
break;
case'/':
printf("\nDivision");
break;
case'%':
printf("Modulus");
break;
default:
printf("\n Not a operator");
gtch();
Aim: Write a C program for implementing the functionalities of predictive parser for the mini
language.
#include <stdio.h>
#include <string.h>
char prol[7][10] = { "S", "A", "A", "B", "B", "C", "C" };
char pror[7][10] = { "A", "Bb", "Cd", "aB", "@", "Cc", "@" };
char prod[7][10] = { "S->A", "A->Bb", "A->Cd", "B->aB", "B->@", "C->Cc", "C->@" };
char first[7][10] = { "abcd", "ab", "cd", "a@", "@", "c@", "@" };
char follow[7][10] = { "$", "$", "$", "a$", "b$", "c$", "d$" };
char table[5][6][10];
int numr(char c)
switch (c)
case 'S':
return 0;
case 'A':
return 1;
case 'B':
return 2;
case 'C':
return 3;
case 'a':
return 0;
case 'b':
return 1;
case 'c':
return 2;
case 'd':
return 3;
case '$':
return 4;
return (2);
int main()
int i, j, k;
for (i = 0; i < 5; i++)
for (j = 0; j < 6; j++)
strcpy(table[i][j], " ");
printf("The following grammar is used for Parsing Table:\n");
for (i = 0; i < 7; i++)
printf("%s\n", prod[i]);
printf("\nPredictive parsing table:\n");
fflush(stdin);
for (i = 0; i < 7; i++)
k = strlen(first[i]);
for (j = 0; j < 10; j++)
if (first[i][j] != '@')
strcpy(table[numr(prol[i][0]) + 1][numr(first[i][j]) + 1], prod[i]);
for (i = 0; i < 7; i++)
if (strlen(pror[i]) == 1)
if (pror[i][0] == '@')
k = strlen(follow[i]);
for (j = 0; j < k; j++)
strcpy(table[numr(prol[i][0]) + 1][numr(follow[i][j]) + 1], prod[i]);
strcpy(table[0][0], " ");
strcpy(table[0][1], "a");
strcpy(table[0][2], "b");
strcpy(table[0][3], "c");
strcpy(table[0][4], "d");
strcpy(table[0][5], "$");
strcpy(table[1][0], "S");
strcpy(table[2][0], "A");
strcpy(table[3][0], "B");
strcpy(table[4][0], "C");
printf("\n--------------------------------------------------------\n");
for (i = 0; i < 5; i++)
for (j = 0; j < 6; j++)
printf("%-10s", table[i][j]);
if (j == 5)
printf("\n--------------------------------------------------------\n");
Aim: Write a C program for constructing of LL (1) parsing or non recursive parsing.
Program:
#include<stdio.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();
printf("\n Enter the input string: ");
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])
case 'e':
str1=0;
break;
case 'b':
str1=1;
break;
case 't':
str1=2;
break;
case 'c':
str1=3;
break;
case 'f':
str1=4;
break;
switch(s[j])
case 'i':
str2=0;
break;
case '+':
str2=1;
break;
case '*':
str2=2;
break;
case '(':
str2=3;
break;
case ')':
str2=4;
break;
case '$':
str2=5;
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();
Input:
Enter the input string: i + i * i
EXPERIMENT-9
OBJECTIVE:
Construction of recursive descent parsing for the following grammar
E->TE'
E'->+TE/@ "@ represents null character"
T->FT'
T`->*FT'/@
F->(E)/ID
RESOURCE:
Turbo C++
PROGRAM LOGIC:
Read the input string.
Write procedures for the non terminals
Verify the next token equals to non terminals if it satisfies match the non terminal.
If the input string does not match print error.
PROCEDURE:
Go to debug -> run or press CTRL + F9 to run the program.
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char input[100];
int i,l;
void main()
{
clrscr();
printf("\nRecursive descent parsing for the following grammar\n");
printf("\nE->TE'\nE'->+TE'/@\nT->FT'\nT'->*FT'/@\nF->(E)/ID\n");
printf("\nEnter the string to be checked:");
gets(input);
if(E())
{
if(input[i+1]=='\0')
printf("\nString is accepted");
else
printf("\nString is not accepted");
}
else
printf("\nString not accepted");
22
getch();
}
E()
{
if(T())
{
if(EP())
return(1);
else
return(0);
}
else
return(0);
}
EP()
{
if(input[i]=='+')
{
i++;
if(T())
{
if(EP())
return(1);
else
return(0);
}
else
return(0);
}
else
return(1);
}
T()
{
if(F())
{
if(TP())
return(1);
else
return(0);
}
else
23
return(0);
}
TP()
{
if(input[i]=='*')
{
i++;
if(F())
{
if(TP())
return(1);
else
return(0);
}
else
return(0);
}
else
return(1);
}
F()
{
if(input[i]=='(')
{
i++;
if(E())
{
if(input[i]==')')
{
i++;
return(1);
}
else
return(0);
}
else
return(0);
}
else if(input[i]>='a'&&input[i]<='z'||input[i]>='A'&&input[i]<='Z')
{
i++;
return(1);
24
}
else
return(0);
}
INPUT & OUTPUT:
Recursive descent parsing for the following grammar
E->TE'
E'->+TE'/@
T->FT'
T'->*FT'/@
F->(E)/ID
Enter the string to be checked:(a+b)*c
String is accepted
Recursive descent parsing for the following grammar
E->TE'
E'->+TE'/@
T->FT'
T'->*FT'/@
F->(E)/ID
Enter the string to be checked: a/c+d
String is not accepted
25