0% found this document useful (0 votes)
26 views

Compiler File

Uploaded by

Harsh Nara
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)
26 views

Compiler File

Uploaded by

Harsh Nara
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/ 47

Vaish College of Engineering

Practical File
Compiler Design

Submitted By: - Submitted To: -


Sejal Jain Ms. Pooja Bansal

21/CSE/164 Asstt. Professor

(CSE Department)

-1-
S.No. Name of Program Date Teacher’s
Remarks
1.
Study of LEX and YACC tools.

2. Write a program for token separation, to


recognize a valid arithmetic expression and
identify the identifiers and operators present. Print
them separately.

3.
Write a program for token separation by counting
the number of characters, words, spaces, end of
lines in a given input file.

4.
Write a program for Lexical analysis using LEX
tools, to count the number of vowels and
consonants in a given string.

5. Write a program to identify whether a given line is


a comment or not, and count the number of
comment lines in a given C program. Also
eliminate them and copy that program into separate
file.
6. Write a program to check whether a given
identifier is valid or not and count the number of
identifiers in a given input file.

7. Write a program to count the number of ‘scanf’


and ‘printf’ statements in a C program. Replace
them with ‘readf’ and ‘writef’ statements
respectively.
8.
Write a program to recognize whether a
given sentence is simple or compound.

9.
Write a program to recognize strings ‘aaab’,
‘abbb’, ‘ab’ and ‘a’ using grammar (a^nb^n, n>=0)
.

-2-
10.
Write a program for implementation of Operator
Precedence Parser.

11.
Write a program for implementation of calculator
using YACC tool.

12.
Write a program for implementation of Recursive
Descent Parser using LEX tool.

13.
Write a program for implementation of LL(1)
Parser.

14.
Write a program for implementation of LALR
Parser.

15.
Write a program to check the syntax of a simple
expression involving operators +, -, * and /

16. Write a program to recognize a valid variable,


which starts with a letter, followed by any number
of letters or digits.

17.
Write a program to recognize the grammar
(a^nb^n, n>=10)

-3-
PRACTICAL -1

Aim: Study of LEX and YACC tools.

LEX:

During the first phase the compiler reads the input and converts strings in the
source to tokens. With regular expressions we can specify patterns to lex so it can
generate code that will allow it to scan and match strings in the input. Each pattern
specified in the input to lex has an associated action. Typically, an action returns a
token that represents the matched string for subsequent use by the parser. Initially
we will simply print the matched string rather than return a token value.

The following represents a simple pattern, composed of a regular expression, that


scans for identifiers. Lex will read this pattern and produce C code for a lexical
analyser that scans for identifiers.

letter(letter|digit)*

This pattern matches a string of characters that begins with a single letter followed
by zero or more letters or digits. This example nicely illustrates operations allowed
in regular expressions:
• repetition, expressed by the “*” operator
• alternation, expressed by the “|” operator
• concatenation

Any regular expression expressions may be expressed as a finite state automaton


(FSA). We can represent an FSA using states, and transitions between states. There
is one start state and one or more final or accepting states.

Steps to Execute Lex Program:

lex <pgm name>


cc lex.yy.c –ll
./a.out

-4-
YACC:

Grammars for YACC are described using a variant of Backus Naur Form (BNF).
This technique, pioneered by John Backus and Peter Naur, was used to describe
ALGOL60. A BNF grammar can be used to express context-free languages. Most
constructs in modern programming languages can be represented in BNF. For
example, the grammar for an expression that multiplies and adds numbers is
E -> E + E
E -> E * E
E -> id

Three productions have been specified. Terms that appear on the left-hand side
(lhs) of a production, such as E (expression) are nonterminal. Terms such as id
(identifier) are terminals (tokens returned by lex) and only appear on the right-
hand side (rhs) of a production. This grammar specifies that an expression may be
the sum of two expressions, the product of two expressions, or an identifier. We
can use this grammar to generate expressions:
E -> E * E (r2)
-> E * z (r3)
-> E + E * z (r1)
-> E + y * z (r3)
-> x + y * z (r3)

At each step we expanded a term and replace the lhs of a production with the
corresponding rhs. The numbers on the right indicate which rule applied. To parse
an expression, we need to do the reverse operation. Instead of starting with a single
nonterminal (start symbol) and generating an expression from a grammar we need
to reduce an expression to a single nonterminal. This is known as bottom-up or
shift- reduce parsing and uses a stack for storing terms.

Steps to execute YACC


program: yacc –d <yacc_pgm
name>
lex <lex_pgm_name>
cc y.tab.c lex.yy.c –ly –ll
./a.out

-5-
Practical – 2

Aim: Write a program for token separation, to recognize a valid arithmetic


expression and identify the identifiers and operators present. Print them
separately.

%{
#include<stdio.h> #include<string.h>
int noprt=0, nopnd=0, valid=1, top=-1, m, l=0, j=0; char opnd[10][10],
oprt[10][10], a[100];
%}
%%
“(“ { top++; a[top]=’(‘ ; }
“{“ { top++; a[top]=’{‘ ; }
“[“ { top++; a[top]=’[‘ ; }
“)” { if(a[top]!=’(‘)
{
valid=0; return;
}
else
top--;
}
“}” { if(a[top]!=’{‘)
{
valid=0; return;
}
else
top--;
}
“]” { if(a[top]!=’[‘)
{
valid=0; return;
}
else
top--;
}

-6-
“+”|”-“|”*”|”/” { noprt++;
strcpy(oprt[l], yytext);
l++;
}
[0-9]+|[a-zA-Z][a-zA-Z0-9_]* {nopnd++;
strcpy(opnd[j],yytext);
j++;
}
%%
int yywrap()
{ return 1;
}

main()
{
int k;
printf(“Enter the expression.. at end press ^d\n”);
yylex(); if(valid==1 && i==-1 && (nopnd-noprt)==1)
{
printf(“The expression is valid\n”);
printf(“The operators are\n”); for(k=0;k<l;k++)
Printf(“%s\n”,oprt[k]); for(k=0;k<l;k++)
Printf(“%s\n”,opnd[k]);
}
else
Printf(“The expression is invalid”);
}

-7-
Output:

-8-
Practical – 3

Aim: Write a program for token separation by counting the number of


characters, words, spaces, end of lines in a given input file.

%{
#include<stdio.h>
Int c=0, w=0, s=0, l=0;
%}
WORD [^ \t\n,\.:]+
EOL [\n]
BLANK [ ]
%%
{WORD} {w++; c=c+yyleng;}
{BLANK} {s++;}
{EOL} {l++;}
. {c++;}
%%
int yywrap()
{ return 1;
}
main(int argc, char *argv[])
{
If(argc!=2)
{
printf(“Usage: <./a.out> <sourcefile>\n”);
exit(0);
}
yyin=fopen(argv[1],”r”);
yylex();
printf(“No of characters=%d\nNo of words=%d\nNo of spaces=%d\n No of
lines=%d”,c,w,s,l);
}

-9-
Output:

- 10 -
Practical – 4

Aim: Write a program for Lexical analysis using LEX tools, to count the
number of vowels and consonants in a given string.

%{
#include<stdio.h> int
vowels=0; int cons=0;
%}
%%
[aeiouAEIOU] {vowels++;}
[a-zA-Z] {cons++;}
%%
int yywrap()
{ return 1;
} main() {
printf(“Enter the string.. at end press ^d\n”);
yylex();
printf(“No of vowels=%d\nNo of consonants=%d\n”,vowels,cons);
}

- 11 -
Output:

- 12 -
Practical – 5

Aim: Write a program to identify whether a given line is a comment or not,


and count the number of comment lines in a given C program. Also eliminate
them and copy that program into separate file.

%{
#include<stdio.h>
int com=0; %}
%s COMMENT
%%
“/*”[.]*”*/” {com++;}
“/*” {BEGIN COMMENT ;}
<COMMENT>”*/” {BEGIN 0; com++ ;}
<COMMENT>\n {com++ ;}
<COMMENT>. {;}
.|\n {fprintf(yyout,”%s”,yytext);
%%
int yywrap()
{ return 1;
}
main(int argc, char *argv[])
{
If(argc!=2)
{
printf(“Usage: <./a.out> <sourcefile> <destn file>\n”);
exit(0);
}
yyin=fopen(argv[1],”r”);
yyout=fopen(argv[2],”w”);
yylex();
printf(“No of comment lines=%d\n”,com);
}

- 13 -
Output:

- 14 -
Practical – 6

Aim: Write a program to check whether a given identifier is valid or not and
count the number of identifiers in a given input file.

%{
#include<stdio.h>
int id=0;
%}
%%
[a-zA-Z][a-zA-Z0-9_]* { id++ ; ECHO; printf(“\n”);}
.+ { ;}
\n { ;}
%%
int yywrap()
{ return 1;
}

main (int argc, char *argv[])


{
if(argc!=2)
{
printf(“Usage: <./a.out> <sourcefile>\n”);
exit(0);
}
yyin=fopen(argv[1],”r”);
printf(“Valid identifires are\
n”); yylex();
printf(“No of identifiers = %d\n”,id);
}

- 15 -
Output:

- 16 -
Practical-7

Aim: Write a program to count the number of ‘scanf’ and ‘printf’ statements
in a C program. Replace them with ‘readf’ and ‘writef’ statements
respectively.

%{
#include<stdio.h>
int pc=0, sc=0;
%}
%%
“printf” { fprintf(yyout,”writef”); pc++;}
“scanf” { fprintf(yyout,”readf”); sc++;}
%%
int yywrap()
{
return 1;
}

main(int argc, char *argv[])


{
if(argc!=2)
{
printf(“Usage: <./a.out> <sourcefile> <destn file>\n”);
exit(0);
}
yyin=fopen(argv[1],”r”);
yyout=fopen(argv[2],”w”);
yylex();
printf(“No of printf statements = %d\n No of scanf statements=%d\n”, pc, sc);
}

- 17 -
Output:

- 18 -
Practical-8

Aim: Write a program to recognize whether a given sentence is simple or


compound.

%{
#include<stdio.h>
Int is_simple=1;
%}
%%
[ \t\n]+[aA][nN][dD][ \t\n]+ {is_simple=0;}
[ \t\n]+[oO][rR][ \t\n]+ {is_simple=0;}
[ \t\n]+[bB][uU][tT][ \t\n]+ {is_simple=0;} . {;}
%%
int yywrap()
{ return 1;
}

main()
{
int k;
printf(“Enter the sentence.. at end press ^d”);
yylex();
if(is_simple==1)
{
Printf(“The given sentence is simple”);
}
else
{
Printf(“The given sentence is compound”);

- 19 -
Output:

- 20 -
Practical-9

Aim: Write a program to recognize strings ‘aaab’, ‘abbb’, ‘ab’ and ‘a’ using
grammar (anbn, n>=0) .

Yacc Part

%token A B NL
%%
stmt : s NL { printf(“Valid String\n”); exit(0) ;}
;
s:AsB
|
;
%%
int yyerror(char *msg)
{
printf(“Invalid String\n”);
exit(0);
} main ()
{
printf(“Enter the String\n”); yyparse();
}

Lex Part
%{
#include “y.tab.h”
%}
%%
[aA] { return A; }
[bB] { return B; }
\n { return NL ;}
. { return yytext[0]; }
%%

- 21 -
Output:

- 22 -
Practical-10

Aim: Write a program for implementation of Operator Precedence Parser.

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

const int precedence[128] = {


['+'] = 1, ['-'] = 1,
['*'] = 2, ['/'] = 2,
['^'] = 3
};

bool isOperator(char ch) {


return precedence[ch] > 0;
}

bool precedenceParser(char *input) {


char stack[100];
int top = -1;
char *ptr = input;

stack[++top] = '$';

while (*ptr != '\0') {


if (*ptr == '(') {
stack[++top] = '(';
ptr++;
} else if (*ptr == ')') {
while (stack[top] != '(') {
if (top == 0)
return false;
top--;
}
top--;

- 23 -
ptr++;
} else if (isOperator(*ptr)) {
while (precedence[stack[top]] >= precedence[*ptr]) {
if (top == 0)
return false;
top--;
}
stack[++top] = *ptr;
ptr++;
} else if (isdigit(*ptr)) {
while (isdigit(*ptr))
ptr++;
} else {
return false;
}
}

return stack[top] == '$' && top == 0;


}
int main() {
char input[100];

printf("Enter an expression: ");


fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0';
if (precedenceParser(input))
printf("The expression is valid.\n");
else
printf("The expression is invalid.\n");

return 0;
}

- 24 -
Output:

- 25 -
Practical- 11

Aim: Write a program for implementation of calculator using YACC tool.

%{
/* 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;
}

Parser Source Code:


%{
/* Definition section */ #include<stdio.h>
int flag=0;

- 26 -
%}

%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;}

%%

- 27 -
//driver code

void main()
{
printf("\nEnter Any Arithmetic Expression which can have operations Addition, Subtraction, Mu
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;
}

- 28 -
Output:

- 29 -
Practical -12

Aim: Write a program for implementation of Recursive Descent Parser using


LEX tool.

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

#define SUCCESS 1
#define FAILED 0

// Function prototypes
int E(), Edash(), T(), Tdash(), F();

const char *cursor;


char string[64];

int main() {
puts("Enter the string");
scanf("%s", string); // Read input from the user
cursor = string;
puts("");
puts("Input Action");
puts(" ");

// Call the starting non-terminal E


if (E() && *cursor == '\0') { // If parsing is successful and the cursor has
reached the end
puts(" ");
puts("String is successfully parsed");
return 0;
}
else {
puts(" ");
puts("Error in parsing String");
return 1;
}

- 30 -
}

// Grammar rule: E -> T E'


int E() {
printf("%-16s E -> T E'\n", cursor);
if (T()) { // Call non-terminal T
if (Edash()) // Call non-terminal E'
return SUCCESS;
else
return FAILED;
}
else
return FAILED;
}

// Grammar rule: E' -> + T E' | $


int Edash() {
if (*cursor == '+') {
printf("%-16s E' -> + T E'\n", cursor);
cursor++;
if (T()) { // Call non-terminal T
if (Edash()) // Call non-terminal E'
return SUCCESS;
else
return FAILED;
}
else
return FAILED;
}
else {
printf("%-16s E' -> $\n", cursor);
return SUCCESS;
}
}

// Grammar rule: T -> F T'


int T() {

- 31 -
printf("%-16s T -> F T'\n", cursor);
if (F()) { // Call non-terminal F
if (Tdash()) // Call non-terminal T'
return SUCCESS;
else
return FAILED;
}
else
return FAILED;
}

// Grammar rule: T' -> * F T' | $


int Tdash() {
if (*cursor == '*') {
printf("%-16s T' -> * F T'\n", cursor); cursor+
+;
if (F()) { // Call non-terminal F
if (Tdash()) // Call non-terminal T'
return SUCCESS;
else
return FAILED;
}
else
return FAILED;
}
else {
printf("%-16s T' -> $\n", cursor);
return SUCCESS;
}
}

// Grammar rule: F -> ( E ) | i


int F() {
if (*cursor == '(') {
printf("%-16s F -> ( E )\n", cursor);
cursor++;
if (E()) { // Call non-terminal E

- 32 -
if (*cursor == ')') {
cursor++;
return SUCCESS;
}
else
return FAILED;
}
else
return FAILED;
}
else if (*cursor == 'i') {
printf("%-16s F -> i\n", cursor);
cursor++;
return SUCCESS;
}
else
return FAILED;
}

- 33 -
Output:

- 34 -
Practical-13

Aim: Write a program for implementation of LL(1) Parser.

%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
%}

%token NUMBER
%left PLUS MINUS
%left MULTIPLY DIVIDE

%%

expr: expr PLUS expr


| expr MINUS expr
| expr MULTIPLY expr
| expr DIVIDE expr
| NUMBER
;

%%

int yylex() {
int c = getchar();
if (isdigit(c)) {
yylval = c - '0';
return NUMBER;
}
return c;
}

void yyerror(char *s) {


printf("Error: %s\n", s);

- 35 -
}

int main() {
yyparse();
return 0;
}

- 36 -
Output:

- 37 -
Practical-14

Aim: Write a program for implementation of LALR Parser.

%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
%}

%token NUMBER
%left PLUS MINUS
%left MULTIPLY DIVIDE

%%

expr: expr PLUS expr


| expr MINUS expr
| expr MULTIPLY expr
| expr DIVIDE expr
| NUMBER
;

%%

int yylex() {
int c = getchar();
if (isdigit(c)) {
yylval = c - '0';
return NUMBER;
}
return c;
}

void yyerror(char *s) {


printf("Error: %s\n", s);
}

- 38 -
int main() {
yyparse();
return 0;
}

- 39 -
Output:

- 40 -
Practical- 15

Aim: Write a program to check the syntax of a simple expression involving


operators +, -, * and /

Yacc Part

%token NUMBER ID NL
%left ‘+’ ‘-‘
%left ‘*’ ‘/’
%%
stmt : exp NL { printf(“Valid Expression”); exit(0);}
;
exp : exp ‘+’ exp
| exp ‘-‘ exp
| exp ‘*’ exp
| exp ‘/’ exp
| ‘(‘ exp ‘)’
| ID
| NUMBER
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
} main ()
{
printf(“Enter the expression\n”); yyparse();
}
[0-9]+ { return NUMBER; }
[a-zA-Z][a-zA-Z0-9_]* { return ID; }
\n { return NL ;} . { return yytext[0]; }
%%

- 41 -
Output:

- 42 -
Practical-16

Aim: Write a program to recognize a valid variable, which starts with a letter,
followed by any number of letters or digits.

Yacc Part

%token DIGIT LETTER NL UND


%%
stmt : variable NL { printf(“Valid Identifiers\n”); exit(0);}
;

variable : LETTER alphanumeric


;

alphanumeric: LETTER alphanumeric | DIGIT


alphanumeric
| UND alphanumeric
| LETTER
| DIGIT
| UND
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
} main ()
{
printf(“Enter the variable name\n”); yyparse();
}

Lex Part

%{
#include “y.tab.h”

- 43 -
%}
%%
[a-zA-Z] { return LETTER ;}
[0-9] { return DIGIT ; }
[\n] { return NL ;}
[_] { return UND; }
. { return yytext[0]; }
%%

- 44 -
Output:

- 45 -
Practical-17

Aim: Write a program to recognize the grammar (a^nb^n, n>=10)

%token A B NL
%%
stmt : A A A A A A A A A A s B NL
{
Printf(“Valid”); exit(0);
} ;
s:s
A
|
;
int yyerror(char *msg)
{
printf(“Invalid String\n”);
exit(0);
} main ()
{
printf(“Enter the String\n”); yyparse();
}

Lex Part

%{
#include “y.tab.h”
%}
%%
[aA] { return A; }
[bB] { return B; }
\n { return NL ;} . { return yytext[0]; }
%%

- 46
Output:

- 47

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy