Compiler File
Compiler File
Practical File
Compiler Design
(CSE Department)
-1-
S.No. Name of Program Date Teacher’s
Remarks
1.
Study of LEX and YACC tools.
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.
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 /
17.
Write a program to recognize the grammar
(a^nb^n, n>=10)
-3-
PRACTICAL -1
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.
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
-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.
-5-
Practical – 2
%{
#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
%{
#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
%{
#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;
}
- 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;
}
- 17 -
Output:
- 18 -
Practical-8
%{
#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
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
stack[++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 0;
}
- 24 -
Output:
- 25 -
Practical- 11
%{
/* 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;
}
- 26 -
%}
%token NUMBER
/* 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
#include <stdio.h>
#include <string.h>
#define SUCCESS 1
#define FAILED 0
// Function prototypes
int E(), Edash(), T(), Tdash(), F();
int main() {
puts("Enter the string");
scanf("%s", string); // Read input from the user
cursor = string;
puts("");
puts("Input Action");
puts(" ");
- 30 -
}
- 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;
}
- 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
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
%}
%token NUMBER
%left PLUS MINUS
%left MULTIPLY DIVIDE
%%
%%
int yylex() {
int c = getchar();
if (isdigit(c)) {
yylval = c - '0';
return NUMBER;
}
return c;
}
- 35 -
}
int main() {
yyparse();
return 0;
}
- 36 -
Output:
- 37 -
Practical-14
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
%}
%token NUMBER
%left PLUS MINUS
%left MULTIPLY DIVIDE
%%
%%
int yylex() {
int c = getchar();
if (isdigit(c)) {
yylval = c - '0';
return NUMBER;
}
return c;
}
- 38 -
int main() {
yyparse();
return 0;
}
- 39 -
Output:
- 40 -
Practical- 15
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
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
%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