CD PracticalFile
CD PracticalFile
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;
case 'b':
if (str[i] == '0') {
f = 'b';
} else if (str[i] == '1') {
f = 'c';
}
SNPITRC/CSE/2025-26/SEM-7/3170701 1|Page
220490131078 Compiler Design
break;
case 'c':
if (str[i] == '0') {
f = 'b';
} else if (str[i] == '1') {
f = 'a';
}
break;
}
}
if (f == 'c') {
printf("String Accepted..!\n");
} else {
printf("String Not Accepted..!\n");
}
return 0;
}
Output :
SNPITRC/CSE/2025-26/SEM-7/3170701 2|Page
220490131078 Compiler Design
Practical: 2
Aim : Introduction to Lex Tool.
Lex:
Lex is a program that generates lexical analyzer. It is used with YACC parser
generator.
The lexical analyzer is a program that transforms an input stream into a sequence of
tokens.
It reads the input stream and produces the source code as output through
implementing the lexical analyzer in the C program.
SNPITRC/CSE/2025-26/SEM-7/3170701 3|Page
220490131078 Compiler Design
Code:
%{
#include <stdio.h>
%}
K if|else|int|char|float
Letter [A-Za-z]
Digit [0-9]
Id ({Letter}|_)+({Letter}|{Digit})*
Op \+|\-|\<|\<=|\>=|\*|\=
%%
%%
int main()
{ printf("Enter the Input: \n");
yylex();
return 0;
}
int yywrap()
{
return 1;
}
Output:
SNPITRC/CSE/2025-26/SEM-7/3170701 4|Page
220490131078 Compiler Design
Practical: 3
Aim : Implement following Programs Using Lex.
a. Ceasor Cipher
Code :
%%
ch-=('z'+1-'a');
printf("%c",ch);
ch-=('Z'+1-'A');
printf("%c",ch);
%%
int main()
SNPITRC/CSE/2025-26/SEM-7/3170701 5|Page
220490131078 Compiler Design
int yywrap(void)
return 1;
}
Output :
SNPITRC/CSE/2025-26/SEM-7/3170701 6|Page
220490131078 Compiler Design
%%
"/*"([^*]|\*+[^*/])*\*+"/" { 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("\n--- Comment extraction complete ---\n");
return 0;
SNPITRC/CSE/2025-26/SEM-7/3170701 7|Page
220490131078 Compiler Design
}
int yywrap()
{
return 1;
}
[Link]
//This is Practical done by Mitesh Rathod
/* This is Multiline comment
cd Practical-3(b)
done by 220490131078 */
#include<stdio.h>
int main(){
int x = 7;
return 0;
}
Output :
SNPITRC/CSE/2025-26/SEM-7/3170701 8|Page
220490131078 Compiler Design
Practical: 4
Aim : Implement following Programs Using Lex.
a. Convert Roman to Decimal
%{
#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); // Terminate the program on an invalid input
}
%%
int main()
SNPITRC/CSE/2025-26/SEM-7/3170701 9|Page
220490131078 Compiler Design
{
printf("Enter Roman numeral (use uppercase): ");
yylex();
printf("Decimal equivalent: %d\n", total);
return 0;
}
int yywrap()
{
return 1;
}
Output :
SNPITRC/CSE/2025-26/SEM-7/3170701 10 | P a g e
220490131078 Compiler Design
%%
%%
int main() {
char fname[100];
printf("enter the name of the file: ");
scanf("%s", fname);
yyin = fopen(fname, "r");
yylex();
return 0;
}
int yywrap(){
return 1;
}
SNPITRC/CSE/2025-26/SEM-7/3170701 11 | P a g e
220490131078 Compiler Design
[Link]
<!DOCTYPE html>
<html>
<head>
<title>CD Practical4(b)</title>
</head>
<body>
<h1 class="Title">220490131078</h1>
<p id="currentTime">New Para</p>
</body>
</html>
Output :
SNPITRC/CSE/2025-26/SEM-7/3170701 12 | P a g e
220490131078 Compiler Design
Practical: 5
Aim : Write a FLEX program that accepts language of all strings of the form anbn.
Code :
%{
#include <stdio.h>
int ca = 0, cb = 0; // Counters for 'a' and 'b'
%}
%%
[a|b]+ {
ca = 0;
cb = 0;
for (int 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");
}
[^ab\n]+ {
printf("Invalid string! Only 'a' and 'b' allowed.\n");
SNPITRC/CSE/2025-26/SEM-7/3170701 13 | P a g e
220490131078 Compiler Design
\n { /* Ignore newline */ }
%%
int main() {
printf("Enter a string: ");
yylex();
return 0;
}
int yywrap() {
return 1;
}
Output :
SNPITRC/CSE/2025-26/SEM-7/3170701 14 | P a g e
220490131078 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++;
SNPITRC/CSE/2025-26/SEM-7/3170701 15 | P a g e
220490131078 Compiler Design
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];
}
%%
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);
SNPITRC/CSE/2025-26/SEM-7/3170701 16 | P a g e
220490131078 Compiler Design
return 1;
}
yylex();
//count last line if file doesn’t end with newline
if (characters > 0 && last_char != '\n') {
lines++;
}
SNPITRC/CSE/2025-26/SEM-7/3170701 17 | P a g e
220490131078 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 follow that 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.
SNPITRC/CSE/2025-26/SEM-7/3170701 18 | P a g e
220490131078 Compiler Design
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.
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;
}
SNPITRC/CSE/2025-26/SEM-7/3170701 19 | P a g e
220490131078 Compiler Design
%{
#include "[Link].h"
%}
%%
%%
int yywrap()
{
return 1;
}
SNPITRC/CSE/2025-26/SEM-7/3170701 20 | P a g e
220490131078 Compiler Design
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token NUM
%left '+' '-'
%left '*' '/'
%%
SNPITRC/CSE/2025-26/SEM-7/3170701 21 | P a g e
220490131078 Compiler Design
| NUM { $$ = $1; }
;
%%
int main()
{
printf("Enter an arithmetic expression: \n");
yyparse();
}
SNPITRC/CSE/2025-26/SEM-7/3170701 22 | P a g e
220490131078 Compiler Design
Explanation:
This is a classic example of how Lex (Flex) and YACC (Bison) work together to
create a simple arithmetic calculator.
The combined program allows the user to input an arithmetic expression (like "10
+ 5 * 2") and calculates its result.
Rules:
o [0-9]+ { yylval = atoi(yytext); return NUM; }:
Pattern: Matches one or more digits (e.g., "123", "7").
Action: Converts the matched text (yytext, which is a string) into an
integer using atoi() and stores it in yylval (a special Flex/YACC
variable used to pass the value of the token). It then returns the
token type NUM to YACC.
o [ \t] ;:
Pattern: Matches one or more spaces or tabs.
Action: The semicolon ; indicates an empty action, meaning it
simply ignores whitespace.
o \n return 0;:
Pattern: Matches a newline character.
Action: Returns 0. In YACC's yyparse(), a 0 returned by yylex()
signifies the end of the input stream for parsing.
o . return yytext[0];:
Pattern: Matches any single character not covered by the previous
rules (this would include operators like '+', '-', '*', '/').
Action: Returns the ASCII value of that character itself as the
token type. So, for '+', it returns the ASCII value of '+'. YACC uses
these ASCII values to identify the operators.
yywrap(): Standard Flex function, returns 1 to signal the end of the input file (or
stream, in this case, standard input).
SNPITRC/CSE/2025-26/SEM-7/3170701 23 | P a g e
220490131078 Compiler Design
SNPITRC/CSE/2025-26/SEM-7/3170701 24 | P a g e
220490131078 Compiler Design
Practical: 8
Aim : Write a YACC program to check syntax of for loop.
Code :
P8.l
/* Lex file for recognizing tokens in 'for' loop */
%{
#include "[Link].h"
%}
%%
SNPITRC/CSE/2025-26/SEM-7/3170701 25 | P a g e
220490131078 Compiler Design
\n return NL;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
P8.y
/* YACC file to check syntax of a 'for' loop */
%{
#include <stdio.h>
#include <stdlib.h>
%}
%%
SNPITRC/CSE/2025-26/SEM-7/3170701 26 | P a g e
220490131078 Compiler Design
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;
}
SNPITRC/CSE/2025-26/SEM-7/3170701 27 | P a g e
220490131078 Compiler Design
SNPITRC/CSE/2025-26/SEM-7/3170701 28 | P a g e
220490131078 Compiler Design
Explanation:
This Lex and YACC program work together to check the syntax of the header (the
part within parentheses) of a for loop in C language.
The user enters a single line representing the for loop header (e.g.,
for(i=0;i<10;i++)). Lex breaks this input into tokens, and YACC then uses
grammar rules to determine if the sequence of these tokens forms a valid for loop
header.
Lex File (pract8.l) - The Tokenizer:
Purpose: Reads the input character by character and groups them into predefined
tokens (like keywords, operators, identifiers, numbers).
Token Rules:
o "for": Recognizes the keyword for and returns the token FOR.
o "(", ")", ";", "=": Recognize specific characters and return OB (Open
Brace/Parenthesis), CB (Close Brace/Parenthesis), SEMI (Semicolon), EQ
(Equals).
o "++", "--": Recognize increment/decrement operators and return INC, DEC.
o "<=", ">=", "<", ">": Recognize relational operators and return LE (Less or
Equal), GE (Greater or Equal), LT (Less Than), GT (Greater Than).
o "+", "-": Recognize arithmetic operators and return PLUS, MINUS.
o [0-9]+: Matches one or more digits and returns NUM (Number).
o [a-zA-Z_][a-zA-Z0-9_]*: Matches C identifiers (starts with
letter/underscore, followed by letters/digits/underscores) and returns ID
(Identifier).
o [ \t\r]+: Ignores one or more spaces, tabs, or carriage returns.
o \n: Matches a newline character and returns NL (Newline). This NL token is
specifically used by YACC to signify the end of the input line for the for
loop header.
o .: A catch-all rule that matches any single character not covered by previous
rules and returns its ASCII value. This would typically indicate an
unexpected character.
yywrap(): Standard Flex function, signals the end of input by returning 1.
YACC File (pract8.y) - The Parser:
Purpose: Takes the tokens generated by Lex and checks if their sequence adheres
to the defined grammatical rules for a for loop header.
Token Declarations (%token): Lists all the tokens that Lex will return (e.g., FOR,
OB, CB, SEMI, ID, NUM, etc.).
Grammar Rules:
o program : stmt NL { printf("Valid 'for' loop syntax.\n"); exit(0); };
Start Rule: The entire input (program) must consist of a stmt (the
SNPITRC/CSE/2025-26/SEM-7/3170701 29 | P a g e
220490131078 Compiler Design
SNPITRC/CSE/2025-26/SEM-7/3170701 30 | P a g e
220490131078 Compiler Design
and multiplication.
o expr '/' expr { ... }:
Rule: Division.
SNPITRC/CSE/2025-26/SEM-7/3170701 31 | P a g e
220490131078 Compiler Design
Practical: 9
Aim : Write a YACC program to validate syntax of function prototype.
Code:
/* Lex file for recognizing tokens in function prototype */
%{
#include "[Link].h"
%}
%%
%%
int yywrap()
{
return 1;
}
YACC File (pract9.y)
SNPITRC/CSE/2025-26/SEM-7/3170701 32 | P a g e
220490131078 Compiler Design
%%
PARAM : BUILTIN ID
| PARAM COMMA BUILTIN ID
| /* empty */ // Allows void or empty parameters
;
%%
int main()
{
printf("\nEnter function declaration statement:\n");
yyparse();
return 0;
}
SNPITRC/CSE/2025-26/SEM-7/3170701 33 | P a g e
220490131078 Compiler Design
SNPITRC/CSE/2025-26/SEM-7/3170701 34 | P a g e
220490131078 Compiler Design
Explanation:
This Lex and YACC program is designed to check the syntax of a basic C function
prototype (or declaration).
The user enters a C function prototype (e.g., int add(int x, float y);). The Lexer
breaks this into tokens, and the YACC parser then verifies if the sequence of these
tokens matches the grammatical rules for a valid function prototype.
SNPITRC/CSE/2025-26/SEM-7/3170701 35 | P a g e
220490131078 Compiler Design
Grammar Rules:
o S : FUN { printf("Valid function prototype syntax\n"); exit(0); };
Start Rule: The entire input (S) must consist of a FUN (function
prototype).
Action: If a valid function prototype is parsed, it prints "Valid
function prototype syntax" and then exits the program.
o FUN : BUILTIN ID LPAREN PARAM RPAREN SC;
This rule defines the basic structure of a function prototype: a
BUILTIN type (return type), followed by an ID (function name), an
opening LPAREN, the PARAMeters list, a closing RPAREN, and
finally a SC (semicolon).
o PARAM : BUILTIN ID | PARAM COMMA BUILTIN ID | /* empty */;
This rule defines how the parameter list (PARAM) can be structured:
BUILTIN ID: A single parameter (e.g., int x).
PARAM COMMA BUILTIN ID: Multiple parameters,
recursively defined (e.g., int x, float y).
/* empty */: Allows for functions that take no parameters
(e.g., void func()).
main():
o Prompts the user to "Enter function declaration statement:".
o Calls yyparse(), the main parsing function generated by YACC, which
interacts with yylex() to get tokens and parse the input.
yyerror(char *s):
o This function is called by the YACC parser whenever it encounters a syntax
error (i.e., the input tokens do not conform to any of the defined grammar
rules). It prints an error message to stderr.
SNPITRC/CSE/2025-26/SEM-7/3170701 36 | P a g e
220490131078 Compiler Design
Practical: 10
Aim : Write a YACC program to validate nested if control statements.
Code :
P10.l
/* Lex file for recognizing tokens in validation of nested IF control statements */
%{
#include "[Link].h"
%}
%%
%%
SNPITRC/CSE/2025-26/SEM-7/3170701 37 | P a g e
220490131078 Compiler Design
int yywrap()
{
return 1;
}
P10.y
/* YACC file to validate nested IF control statements */
%{
#include <stdio.h>
#include <stdlib.h>
int count = 0;
%}
%%
input : stmt NL {
printf("Valid Declaration\nNo. of nested if
statements = %d\n", count);
exit(0);
}
;
stmt : if_stmt
;
SNPITRC/CSE/2025-26/SEM-7/3170701 38 | P a g e
220490131078 Compiler Design
SNPITRC/CSE/2025-26/SEM-7/3170701 39 | P a g e
220490131078 Compiler Design
Explanation:
This Lex and YACC program is designed to validate the syntax of nested if control
statements in a simplified C-like language and count the number of if statements.
The user enters a block of code containing if statements (potentially nested). The
Lexer breaks this input into tokens, and the YACC parser then checks if the
structure of these if statements is syntactically correct according to its defined
grammar.
SNPITRC/CSE/2025-26/SEM-7/3170701 40 | P a g e
220490131078 Compiler Design
Grammar Rules:
o input : stmt NL { ... };
Start Rule: The entire input (input) must consist of a stmt (a
statement, which can be an if statement) followed by a NL
(newline).
Action: If parsing is successful, it prints "Valid Declaration"
(though it's checking if statements, not declarations) and the total
number of nested if statements found (count), then exits.
o stmt : if_stmt;
A stmt (statement) can simply be an if_stmt. (This grammar is
simplified and only allows if statements or simple STMTs at the top
level).
o if_stmt : IF LPAREN cond RPAREN LBRACE stmt RBRACE { count++;
} | STMT;
This is the core rule for an if statement:
SNPITRC/CSE/2025-26/SEM-7/3170701 41 | P a g e