200490131008 Compiler Design
Practical: 1
Aim: Implementation of Finite Automata and String Validation.
Code:
#include<stdio.h>
#define max 100
int main()
{
char str[max], f='a';
int i;
printf("Enter a string: ");
scanf("%s",str);
for(i=0; str[i]!='\0'; i++)
{
switch(f)
{
case 'a':
if(str[i]=='0')
{
f='b';
}
else if(str[i]=='1')
{
f='a';
}
break;
case 'b':
if(str[i]=='0')
{
f='b';
}
else if(str[i]=='1')
{
f='c';
}
break;
case 'c':
if(str[i]=='0')
{
f='b';
}
else if(str[i]=='1')
{
f='a';
}
break;
}
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |1
200490131008 Compiler Design
}
if(f=='c')
{
printf("String Accepted..!");
}
else
{
printf("String Not Accepted..!");
}
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |2
200490131008 Compiler Design
Practical: 2
Aim: Introduction to Lex Tool.
Code:
%{
#include <stdio.h>
%}
K if|else|int|char|float
Letter [A-Za-z]
Digit [0-9]
Id ({Letter}|_)+({Letter}|{Digit})*
Op \+|\-|\<|\<=|\>=|\*|\=
%%
{K} {printf("%s is a Keyword\n", yytext); }
{Id} {printf("%s is an identifier\n", yytext); }
{Digit}+ {printf("%s is a number\n", yytext); }
{Op} {printf("%s is an operator\n", yytext); }
[\n\t ]+ {/*Ignore whitespace */}
. {printf("%s is an unrecognized token\n",
yytext);}
%%
int main()
{
printf("Enter the Input: \n");
yylex();
return 0;
}
int yywrap()
{
return 1;
}
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |3
200490131008 Compiler Design
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |4
200490131008 Compiler Design
Practical 3:
Aim: Implement following Program using Lex
a) Ceasor Cipher
Code:
%{
#include <stdio.h>
#include <ctype.h> // For isalpha, isupper, islower
// Define the shift value
#define SHIFT 3
%}
%%
[a-zA-Z] {
char ch = yytext[0];
if (isupper(ch)) {
putchar('A' + (ch - 'A' + SHIFT) % 26);
} else if (islower(ch)) {
putchar('a' + (ch - 'a' + SHIFT) % 26);
}
}
. {
// Print any other character as is (e.g., spaces,
punctuation, numbers)
putchar(yytext[0]);
}
%%
int main()
{
printf("Enter text to encrypt:\n");
yylex();
return 0;
}
int yywrap()
{
return 1;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |5
200490131008 Compiler Design
b) Extract single and multiline comments from C program.
Code:
%{
#include <stdio.h>
%}
%%
"/*"([^*]|\*+[^*/])*\*+"/" { printf("\nMulti-line
comment found:\n%s\n", yytext); }
"//".* { printf("\nSingle-
line comment found: \n%s\n", yytext);}
.|\n { }
%%
int main()
{
char fname[100];
printf("Enter the name of the C file: ");
scanf("%s", fname);
yyin = fopen(fname, "r");
if (yyin == NULL)
{
perror("Error opening file");
return 1;
}
printf("\n--- Extracting Comments from '%s'
---\n", fname);
yylex();
fclose(yyin);
printf("--- Comment extraction complete ---
\n");
return 0;
}
int yywrap()
{
return 1;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |6
200490131008 Compiler Design
Practical: 4
Aim: Implement following Programs Using Lex
a) Convert Roman to Decimal
Code:
%{
#include <stdio.h>
#include <stdlib.h> // For exit()
int total = 0;
%}
%%
"CM" { total += 900; } // 900
"CD" { total += 400; } // 400
"XC" { total += 90; } // 90
"XL" { total += 40; } // 40
"IX" { total += 9; } // 9
"IV" { total += 4; } // 4
"M" { total += 1000; } // 1000
"D" { total += 500; } // 500
"C" { total += 100; } // 100
"L" { total += 50; } // 50
"X" { total += 10; } // 10
"V" { total += 5; } // 5
"I" { total += 1; } // 1
\n { return total; }
. {
fprintf(stderr, "Error: Invalid Roman numeral
symbol'%s'\n", yytext);
exit(1);
}
%%
int main()
{
printf("Enter Roman numeral (use uppercase): ");
yylex();
printf("Decimal equivalent: %d\n", total);
return 0;
}
int yywrap()
{
return 1;
}
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |7
200490131008 Compiler Design
Output:
b) Extract html tags from .html file.
Code:
%{
#include <stdio.h>
%}
%%
\<[^>]*\> { printf("%s\n", yytext); }
.|\n { /* Do nothing - effectively ignores regular
content */ }
%%
int main()
{
char fname[100];
printf("Enter the name of file: ");
scanf("%s",fname);
yyin=fopen(fname,"r");
yylex();
return 0;
}
int yywrap()
{
return 1;
}
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |8
200490131008 Compiler Design
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 Page |9
200490131008 Compiler Design
Practical: 5
Aim: Write a FLEX program that accepts language of all strings of the form a nbn.
Code:
%{
#include <stdio.h>
int i, ca = 0, cb = 0;
%}
%%
[a]+[b]+ {
for(i=0;i<yyleng;i++)
if(yytext[i]=='a')
ca++;
else if(yytext[i]=='b')
cb++;
if(ca==cb)
printf("String accepted\n");
else
printf("String not accepted\n");
return 0;
}
.+ {
printf("String not accepted\n");
return 0;
}
%%
int main()
{
printf("Enter a string: ");
yylex();
return 0;
}
int yywrap()
{
return 1;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 10
200490131008 Compiler Design
Practical : 6
Aim: Write a FLEX program to take input from text file and count no of characters,
no. of spaces, no. of lines & no. of words.
Code:
/* FLEX program to read a file and count lines, words,
characters,
and spaces */
%{
#include <stdio.h>
int lines = 0;
int words = 0;
int characters = 0;
int spaces = 0;
int in_word = 0; // Flag to check if inside a word
int last_char = 0; // To detect if last char was newline
%}
%%
\n {
lines++;
characters++;
in_word = 0;
last_char = '\n';
}
[ \t] {
spaces++;
characters++;
in_word = 0;
last_char = yytext[0];
}
[A-Za-z0-9]+ {
characters += yyleng;
if (!in_word)
words++;
in_word = 1;
}
last_char = yytext[yyleng - 1];
}
. {
characters++;
in_word = 0;
last_char = yytext[0];
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 11
200490131008 Compiler Design
%%
int main()
{
char fname[100];
printf("Enter the name of file: ");
scanf("%s", fname);
yyin = fopen(fname, "r");
if (!yyin)
{
printf("Error: Cannot open file %s\n", fname);
return 1;
}
yylex();
//count last line if file doesn’t end with newline
if (characters > 0 && last_char != '\n')
{
lines++;
}
printf("\n--- File Analysis Results ---\n");
printf("Lines : %d\n", lines);
printf("Words : %d\n", words);
printf("Characters : %d\n", characters);
printf("Spaces : %d\n", spaces);
return 0;
}
int yywrap()
{
return 1;
}
Contents of input file ([Link])
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 12
200490131008 Compiler Design
Practical : 7
AIM: Introduction to YACC and generate calculator program.
What is YACC?
• YACC stands for Yet Another Compiler Compiler, a powerful tool designed to
generate parsers for programming languages and interpreters. It reads a formal
grammar, typically written in Context-Free Grammar (CFG), and produces a C
program that can parse input strings to check whether they followthat grammar.
• In compiler construction, YACC plays the role of the syntax analyzer (or parser). It
takes a stream of tokens — usually generated by a Lexical Analyzer (Lex/Flex) —
and applies grammar rules to analyze their structure.
Lex + YACC Integration Overview:
• The typical process in a compiler front-end involves:
1. Lex (Lexical Analyzer):
o Scans the input text.
o Breaks it into tokens (e.g., numbers, operators, keywords).
o Returns token types to the parser.
2. YACC (Syntax Analyzer):
o Receives tokens from Lex.
o Matches sequences of tokens to grammar rules.
o Executes C code blocks (actions) associated with those rules.
Structure of a YACC Program:
• A YACC file has three main sections:
1. Declarations Section
2. Grammar Rules Section
3. Auxiliary Functions Section
➢ Declarations Section (%{ ... %})
• This is similar to Lex’s declaration section.
• Used for including headers, defining variables, function prototypes, and declaring
tokens and precedence.
• Example:
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token NUM
%left '+' '-'
%left '*' '/'
• %token declares tokens (terminals).
• %left defines associativity and precedence of operators to resolve ambiguity.
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 13
200490131008 Compiler Design
➢ Grammar Rules Section (%% ... %%)
• This section defines how tokens (terminals) and non-terminals are combined.
• Each production rule follows this format:
non_terminal : production_body { action }
• The left-hand side (LHS) is a non-terminal.
• The right-hand side (RHS) can be a mix of terminals and non-terminals.
• The { action } block is C code executed when the rule is matched.
• YACC uses special variables:
o $1, $2, ... to access components of the RHS.
o $$ to represent the value of the LHS.
• Example:
expr : expr '+' expr { $$ = $1 + $3; }
• This rule defines addition of two expressions.
➢ Auxiliary Functions Section
• This section includes:
o main(): the program’s entry point.
o yyparse(): the parser function (automatically generated).
o yyerror(): to handle syntax errors.
• Example:
int main() {
yyparse(); // Starts the parser
return 0;
}
int yyerror(char *s) {
printf("Syntax Error: %s\n", s);
return 0;
}
Compilation and Execution Steps:
Step 1: Save Your Files
• filename.l for Lex code
• filename.y for YACC code
Step 2: Compile Using Terminal
• flex filename.l // generates [Link].c
• bison -d filename.y // generates [Link].c and [Link].h
• gcc [Link].c [Link].c // compile to executable
Step 3: Run the Program
• [Link] // run executable file
Example Program: YACC program for Simple Arithmetic Calculator
/* This example implements a calculator using Lex and
YACC that
can evaluate expressions like:
2 + 3 * 4
(5 - 2) * 6
*/
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 14
200490131008 Compiler Design
Code:
Lex File (prac7.l)
/* Lex file to implement simple arithmetic calculator */
%{
#include "[Link].h"
%}
%%
[0-9]+ { yylval = atoi(yytext); return NUM; }
[ \t] ; // Ignore whitespace
\n return 0; // End on newline
. return yytext[0];
%%
int yywrap()
{
return 1;
}
YACC File (pract7.y)
/* YACC file to implement simple desk calculator */
%{
#include <stdio.h>
#include <stdlib.h>
int yylex(void);
int yyerror(char *s);
%}
%token NUM
%left '+' '-'
%left '*' '/'
%%
start: expr { printf("Result: %d\n", $$);
return 0; };
expr : expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr {
if ($3 == 0) {
printf("Error: Division by zero\n");
$$ = 0;
} else {
$$ = $1 / $3;
}
}
| '('expr')' { $$ = $2; }
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 15
200490131008 Compiler Design
| NUM { $$ = $1; }
;
%%
int main()
{
printf("Enter an arithmetic expression: \n");
yyparse();
}
int yyerror(char *s)
{
fprintf(stderr, "Syntax Error: %s\n", s);
return 0;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 16
200490131008 Compiler Design
Practical: 8
Aim : Write a YACC program to check syntax of for loop.
Code:
Lex File (pract8.l)
%{
#include "[Link].h"
%}
%%
"for" return FOR;
"(" return OB;
")" return CB;
";" return SEMI;
"=" return EQ;
"++" return INC;
"--" return DEC;
"<=" return LE;
">=" return GE;
"<" return LT;
">" return GT;
"+" return PLUS;
"-" return MINUS;
[0-9]+ return NUM;
[a-zA-Z_][a-zA-Z0-9_]* return ID;
[ \t\r]+ ; // Ignore spaces/tabs
\n return NL;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
YACC File (pract8.y)
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token FOR OB CB SEMI EQ ID NUM LT GT LE GE INC DEC PLUS
MINUS NL
%%
program : stmt NL { printf("Valid 'for' loop syntax.\n");
exit(0); }
;
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 17
200490131008 Compiler Design
stmt : FOR OB init SEMI cond SEMI inc CB
;
init : ID EQ NUM
| /* empty */
;
cond : ID LT NUM
| ID GT NUM
| ID LE NUM
| ID GE NUM
| /* empty */
;
inc : ID INC
| ID DEC
| INC ID
| DEC ID
| /* empty */
;
%%
int main()
{
printf("Enter a 'for' loop header:\n");
yyparse();
return 0;
}
int yyerror(char *s)
{
fprintf(stderr, "Syntax Error: %s\n", s);
return 0;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 18
200490131008 Compiler Design
Practical: 9
Aim: Write a YACC program to validate syntax of function prototype.
Code:
Lex File (pract9.l)
%{
#include "[Link].h"
%}
%%
"int"|"float"|"double"|"void"|"char" { return BUILTIN; }
[a-zA-Z_][a-zA-Z0-9_]* { return ID; }
"," { return COMMA; }
";" { return SC; }
"(" { return LPAREN; }
")" { return RPAREN; }
[\t \n]+ ; // Ignore whitespace
. { return yytext[0]; }
%%
int yywrap()
{
return 1;
}
YACC File (pract9.y)
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token BUILTIN ID COMMA SC LPAREN RPAREN
%%
S : FUN { printf("Valid function prototype syntax\n");
exit(0); }
;
FUN : BUILTIN ID LPAREN PARAM RPAREN SC
;
PARAM : BUILTIN ID
| PARAM COMMA BUILTIN ID
| /* empty */ // Allows void or empty parameters
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 19
200490131008 Compiler Design
%%
int main()
{
printf("\nEnter function declaration statement:\n");
yyparse();
return 0;
}
int yyerror(char *s)
{
fprintf(stderr, "Syntax Error: %s\n", s);
return 0;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 20
200490131008 Compiler Design
Practical: 10
Aim: Write a YACC program to validate nested if control statements.
Code:
Lex File (pract10.l)
%{
#include "[Link].h"
%}
%%
"if" return IF;
"(" return LPAREN;
")" return RPAREN;
"{" return LBRACE;
"}" return RBRACE;
"<"|">"|"=="|"<="|">="|"!=" return RELOP;
[0-9]+ return NUMBER;
[a-z][a-zA-Z0-9_]* return ID;
[sS][0-9]* return STMT;
\n return NL;
[ \t]+ ;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
YACC File (pract10.y)
%{
#include <stdio.h>
#include <stdlib.h>
int count = 0;
%}
%token IF RELOP STMT NUMBER ID NL
%token LPAREN RPAREN LBRACE RBRACE
%%
input : stmt NL {
printf("Valid Declaration\nNo. of nested if
statements = %d\n", count);
exit(0);
}
;
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 21
200490131008 Compiler Design
stmt : if_stmt
;
if_stmt : IF LPAREN cond RPAREN LBRACE stmt RBRACE {
count++;
}
| STMT
;
cond : expr RELOP expr ;
expr : ID | NUMBER ;
%%
int main()
{
printf("Enter nested if statement:\n");
yyparse();
return 0;
}
int yyerror(char *s)
{
fprintf(stderr, "Syntax Error: %s\n", s);
return 0;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170710 P a g e | 22