0% found this document useful (0 votes)
17 views28 pages

Ex: 1.a Program To Recognize A Few Patterns in C Aim

The document describes multiple C programs aimed at recognizing patterns, implementing a symbol table, and creating a lexical analyzer using LEX and YACC. Each section outlines the aim, algorithm, source code, and results of the programs, including a lexical analyzer for C, a symbol table implementation, and validation of arithmetic expressions and variable names. The programs successfully execute their intended functionalities, demonstrating the application of lexical analysis and parsing techniques.

Uploaded by

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

Ex: 1.a Program To Recognize A Few Patterns in C Aim

The document describes multiple C programs aimed at recognizing patterns, implementing a symbol table, and creating a lexical analyzer using LEX and YACC. Each section outlines the aim, algorithm, source code, and results of the programs, including a lexical analyzer for C, a symbol table implementation, and validation of arithmetic expressions and variable names. The programs successfully execute their intended functionalities, demonstrating the application of lexical analysis and parsing techniques.

Uploaded by

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

Ex: 1.

Program to Recognize a Few Patterns in C

Aim

To write a C program to develop a lexical analyzer to recognize a few patterns in C.

Algorithm

Step1: Start the program.

Step2: Read a simple C language program as input string.

Step3: Display the input string.

Step4: Separate the tokens of the string.

Step5: Display each token with its type.

Step6: Also display whether the token is valid or invalid.

Step7: Stop the program.

Source Code

//Develop a lexical analyzer to recognize a few patterns in C.

#include <stdbool.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

// Returns 'true' if the character is a DELIMITER.

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);

// Returns 'true' if the character is an OPERATOR.

bool isOperator(char ch)

if (ch == '+' || ch == '-' || ch == '*' ||

ch == '/' || ch == '>' || ch == '<' ||

ch == '=')

return (true);

return (false);

// Returns 'true' if the string is a VALID IDENTIFIER.

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);

// Returns 'true' if the string is a KEYWORD.

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"))

return (true);

return (false);

// Returns 'true' if the string is an INTEGER.

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);

// Returns 'true' if the string is a REAL NUMBER.

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);

}
// Extracts the SUBSTRING.

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);

// Parsing the input STRING.

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]);


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);

left = right;

return;

}
OUTPUT

RESULT

Thus the program for developing a lexical analyzer to recognize a few patterns in C
has been executed successfully.

Ex: 1.b

Implementation of Symbol Table using C

Aim

To write a program for implementing symbol table using C.

Algorithm

Step 1: Start the program.

Step 2: Read an expression in C.

Step 3: Create an entry in the symbol table for each valid identifier.

Step 4: Display each identifier with its type.


Step 5: Stop the program.

Source Code

//Implementation of symbol table

#include<stdio.h>

#include<conio.h>

#include<ctype.h>

#include<stdlib.h>

#include<string.h>

#include<math.h>

void main()

int i=0,j=0,x=0,n;

void *p,*add[5];

char ch,srch,b[15],d[15],c;

printf("Expression terminated by $:");

while((c=getchar())!='$')

b[i]=c;

i++;

n=i-1;

printf("Given Expression:");

i=0;

while(i<=n)

printf("%c",b[i]);
i++;

printf("\n Symbol Table\n");

printf("Symbol \t addr \t type");

while(j<=n)

c=b[j];

if(isalpha(toascii(c)))

p=malloc(c);

add[x]=p;

d[x]=c;

printf("\n%c \t %d \t identifier\n",c,p);

x++;

j++;

else

ch=c;

if(ch=='+'||ch=='-'||ch=='*'||ch=='=')

p=malloc(ch);

add[x]=p;

d[x]=ch;

printf("\n %c \t %d \t operator\n",ch,p);

x++;

j++;
}}}

getch();

OUTPUT

RESULT

Thus the program for symbol table has been executed successfully.
Ex: 2

Implementation of a Lexical Analyzer using LEX

Aim

To write a program for implementing a Lexical Analyzer using LEX tool.

Procedure

1. A LEX program contains three sections: definitions, rules, and user subroutines. Each
section must be separated from the others by a line containing only the delimiter, %
%. The format is as follows: definitions %% rules %% user_subroutines
2. In definition section, the variables make up the left column, and their definitions make
up the right column. Any C statements should be enclosed in %{..}%. An identifier is
defined such that the first letter of an identifier is alphabet and the remaining letters
are alphanumeric.
3. In rules section, the left column contains the pattern to be recognized in an input file
named yylex(). The right column contains the C program fragment executed when
that pattern is recognized. The various patterns are keywords, operators, new line
character, number, string, identifier, beginning and end of block, comment statements,
preprocessor directive statements etc.
4. Each pattern may have a corresponding action, that is, a fragment of C source code to
execute when the pattern is matched.
5. When yylex() matches a string in the input stream, it copies the matched text to an
external character array, yytext, before it executes any actions in the rules section.
6. In user subroutine section, main routine calls yylex(). yywrap() is used to get more
input.
7. The LEX command uses the rules and actions contained in file to generate a program,
lex.yy.c, which can be compiled with the gcc command. That program can then
receive input, break the input into the logical pieces defined by the rules in file, and
run program fragments contained in the actions in file.
8. This LEX program reads a C file as input and displays the tokens of the input file as
output.

Source Code

/*Implementation of Lexical Analyzer using LEX tool – lexical.l */

%{

int COMMENT=0;

%}
identifier [a-zA-Z][a-zA-Z0-9]*

%%

#.* {printf("\n%s is a preprocessor directive",yytext);}

int |

float |

char |

double |

while |

for |

struct |

typedef |

do |

if |

break |

continue |

void |

switch |

return |

else |

goto {printf("\n\t%s is a keyword",yytext);}

"/*" {COMMENT=1;}{printf("\n\t %s is a COMMENT",yytext);}

{identifier}\( {if(!COMMENT)printf("\nFUNCTION \n\t%s",yytext);}

\{ {if(!COMMENT)printf("\n BLOCK BEGINS");}

\} {if(!COMMENT)printf("BLOCK ENDS ");}

{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s IDENTIFIER",yytext);}

\".*\" {if(!COMMENT)printf("\n\t %s is a STRING",yytext);}


[0-9]+ {if(!COMMENT) printf("\n %s is a NUMBER ",yytext);}

\)(\:)? {if(!COMMENT)printf("\n\t");ECHO;printf("\n");}

\( ECHO;

= {if(!COMMENT)printf("\n\t %s is an ASSIGNMENT OPERATOR",yytext);}

\<= |

\>= |

\< |

== |

\> {if(!COMMENT) printf("\n\t%s is a RELATIONAL OPERATOR",yytext);}

%%

int main(int argc, char **argv)

FILE *file;

file=fopen("input.txt","r");

if(!file)

printf("could not open the file");

exit(0);

yyin=file;

yylex();

printf("\n");

return(0);

int yywrap()

{
return(1);

INPUT

//input.txt

#include<stdio.h>

#include<conio.h>

void main()

int a,b,c;

a=1;

b=2;

c=a+b;

printf("Sum:%d",c);

OUTPUT
RESULT

Thus the program for implementation of a Lexical Analyzer using LEX tool has been
executed successfully.
Ex: 3.a

Program to Recognize a Valid Arithmetic Expression using YACC

Aim

To write a C program to recognize a valid arithmetic expression that uses operator +,


-, * and /.

Algorithm

Step1: Start the program.

Step2: Read an expression.

Step3: Check the validity of the given expression according to the rule using yacc.

Step4: Using expression rule print the result of the given values.

Step5: Stop the program.

Source Code

/* LEX Code arith.l */

%{

#include "y.tab.h"

%}

%%

[a-zA-Z_][a-zA-Z_0-9]* return id;

[0-9]+(\.[0-9]*)? return num;

[+/*] return op;

. return yytext[0];

\n return 0;

%%

int yywrap()

return 1;
}

/* YACC Code arith.y */

%{

#include<stdio.h>

int valid=1;

%}

%token num id op

%%

start : id '=' s ';'

s: id x

| num x

| '-' num x

| '(' s ')' x

x: op s

| '-' s

%%

int yyerror()

valid=0;

printf("\nInvalid expression!\n");

return 0;

int main()

{
printf("\nEnter the expression:\n");

yyparse();

if(valid)

{ printf("\nValid expression!\n"); }

Output

RESULT

Thus the program to recognize a valid arithmetic expression using YACC has been
executed successfully.
Ex: 3.b

Program to Recognize a Valid Variable using YACC

Aim

To write a C program to recognize a valid variable which starts with a letter followed
by any number of letters or digits.

Algorithm

Step1: Start the program.

Step2: Read the name of a variable.

Step3: Check the validity of the given variable according to the rule using YACC.

Step4: Display the result.

Step5: Stop the program.

Source Code

/*Lex part: vartest.l */

%{

#include "y.tab.h"

%}

%%
[a-zA-Z_][a-zA-Z_0-9]* return letter;

[0-9] return digit;

. return yytext[0];

\n return 0;

%%

int yywrap()

return 1;

/* yacc part: vartest.y*/

%{

#include<stdio.h>

int valid=1;

%}

%token digit letter

%%

start : letter s

s: letter s

| digit s

%%

int yyerror()

printf("\n Its not an identifier!\n");

valid=0;

return 0;
}

int main()

printf("\n Enter a name to test for identifier ");

yyparse();

if(valid)

printf("\nIt is an identifier!\n");

Output

RESULT

Thus the program to recognize a valid variable using YACC has been executed
successfully.
Ex: 3.c

Program to Recognize a Valid Control Structure Syntax of C Language using YACC

Aim

To write a C program to recognize avalid control structure syntax of C language


using YACC.

Algorithm

Step1: Start the program.

Step2: Read a valid control structure.

Step3: Checking the validity of the given control structure according to the rule using YACC.

Step4: Display the result.

Step5: Stop the program.

Source Code

/* YACC PART: iff.y*/

%{

#include<stdio.h>

#include<stdlib.h>

int count=0;

%}

%token IF RELOP S NUMBER ID NL

%%

stmt: if_stmt NL {printf("No. of nested if statements=%d\n",count);exit(0);}

if_stmt : IF'('cond')''{'if_stmt'}' {count++;}

|S

cond: x RELOP x
;

x:ID | NUMBER

%%

int yyerror(char *msg)

printf("the statement is invalid\n");

exit(0);

main()

printf("enter the statement\n");

yyparse();

/*LEX PART: iff.l*/

%option noyywrap

%{

#include "y.tab.h"

%}

%%

"if" {return IF;}

[sS][0-9]* {return S;}

"<"|">"|"=="|"<="|">="|"!=" {return RELOP;}

[0-9]+ {return NUMBER;}

[a-z][a-zA-Z0-9_]* {return ID;}

\n {return NL;}

. {return yytext[0];}
%%

Output

RESULT

Thus the program to recognize a valid control structure syntax of C Language using
YACC has been executed successfully.
Ex: 3.d

Implementation of a Calculator using LEX and YACC

Aim

To write a program for implementing a calculator using LEX and YACC.

Algorithm

Step1: A Yacc source program has three part: Declarations %% translation rules %% C
routines

Step2: Declarations Section: This section contains entries that:

i. Include standard I/O header file.

ii. Define global variables.

iii. Define the list rule as the place to start processing.

iv. Define the tokens used by the parser.

v. Define the operators and their precedence.

Step3: Rules Section: The rules section defines the rules that parse the input stream. Each
rule of

a grammar production and the associated semantic action.

Step4: Programs Section: The programs section contains the following subroutines. Because,

these subroutines are included in this file, it is not necessary to use the yacc library
when

process this file.

Step5: Main- The required main program that calls the yyparse subroutine to start the
program.

Step6: yyerror(s) -This error-handling subroutine only prints a syntax error message.

Step7: yywrap -The wrap-up subroutine that returns a value of 1 when the end of input
occurs.

The calc.l file contains include statements for standard input and output, as
programmer

file information if we use the -d flag with the yacc command. The y.tab.h file contains

definitions for the tokens that the parser program uses.


Step8: calci.l contains the rules to generate these tokens from the input stream.

Source Code

/* lex code calci.l */

%{

/* Definition section */

#include<stdio.h>

#include "y.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;

/* Yacc code : calci.y */


%{

/* Definition section */

#include<stdio.h>

int flag=0;

%}

%token NUMBER

%left '+' '-'

%left '*' '/' '%'

%left '(' ')'

/* Rule Section */

%%

ArithmeticExpression:

E{

printf("\nResult=%d\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("\nEnter Any Arithmetic Expression which can have operations Add, Sub, Mul, Div, Modulus
and Round brackets:\n");

yyparse();

if(flag==0)

printf("\nEntered arithmetic expression is Valid\n\n");

void yyerror()

printf("\nEntered arithmetic expression is Invalid\n\n");

flag=1;

Output

RESULT

Thus the program to implement a calculator using LEX and YACC has been
executed.

You might also like