0% found this document useful (0 votes)
1 views41 pages

CD PracticalFile

Uploaded by

Rajat Sharma
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)
1 views41 pages

CD PracticalFile

Uploaded by

Rajat Sharma
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

220490131078 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 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';
}

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.

The function of Lex:


 Firstly, lexical analyzer creates a program lex.l in the Lex language. Then Lex
compiler runs the lex.l program and produces a C program [Link].c.
 Finally, C compiler runs the [Link].c program and produces an object program [Link]
(in Windows it is [Link]).
 [Link] is lexical analyzer that transforms an input stream into a sequence of tokens.

The structure of Lex programs:


 A Lex program is separated into three sections by %% delimiters. A Lex program
consists of three sections: Declarations, Rules and Auxiliary functions.
 The format of Lex source is as follows:
DECLARATIONS
%%
RULES
%%
AUXILIARY FUNCTIONS

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 \+|\-|\<|\<=|\>=|\*|\=

%%

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

[a-z] {char ch=yytext[0];


ch+=3;
if(ch>'z')

ch-=('z'+1-'a');

printf("%c",ch);

[A-Z] {char ch=yytext[0];


ch+=3;
if(ch>'Z')

ch-=('Z'+1-'A');
printf("%c",ch);

%%

int main()

SNPITRC/CSE/2025-26/SEM-7/3170701 5|Page
220490131078 Compiler Design

printf("Plain Text Is:");


yylex();
}

int yywrap(void)

return 1;

}
Output :

SNPITRC/CSE/2025-26/SEM-7/3170701 6|Page
220490131078 Compiler Design

b. Extract single and multiline comments from C 4 Program.


Code :
Practical3(b).l
%{
#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("\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

b. Extract html tags from .html file.


Code :
Practical4(b).l
%{
#include<stdio.h>
%}

%%

\<[^>]*\> {printf("%s\n", yytext);}


.|\n {/* DO NOTHING - effectively ignoew regular context */}

%%

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

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;
}
Output :

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.

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.

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

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

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

SNPITRC/CSE/2025-26/SEM-7/3170701 20 | P a g e
220490131078 Compiler Design

YACC File (pract7.y)


/* YACC file to implement simple desk calculator */

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

%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/3170701 21 | P a g e
220490131078 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/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.

 Lex File (pract7.l) - The Lexical Analyzer (Scanner):


 Purpose: To break down the raw input expression (a stream of characters) into
meaningful tokens (like numbers, operators, etc.) that the YACC parser can
understand.

 %{ ... %} section: Includes [Link].h. This header file is automatically


generated by YACC and contains definitions for the tokens (like NUM) that Lex
needs to return to YACC.

 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

 YACC File (pract7.y) - The Parser:


 Purpose: To take the stream of tokens from Lex, apply grammatical rules, check
for valid syntax, and perform calculations.
 %{ ... %} section: Includes stdio.h for printing and stdlib.h for exit() (implicitly
used by return 0; in start rule) or atoi if not in Lex.
 Token Declarations (%token):
o %token NUM: Declares NUM as a terminal token. Its value (from yylval
in Lex) will be accessible as $1, $2, etc., in YACC actions.
o %left '+' '-' and %left '*' '/': These define the precedence and associativity
of operators.
 %left means they are left-associative (e.g., a - b - c is (a - b) - c).

 Operators on a higher %left line (like * and /) have higher


precedence than those on lower lines (+ and -). This ensures 1 + 2 *
3 is parsed as 1 + (2 * 3).

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

%%

"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

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

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


;

stmt : FOR OB init SEMI cond SEMI inc CB


;

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

int yyerror(char *s)


{

SNPITRC/CSE/2025-26/SEM-7/3170701 27 | P a g e
220490131078 Compiler Design

fprintf(stderr, "Syntax Error: %s\n", s);


return 0;
}
Output :

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

for loop header) followed by a NL (newline).


 Action: If successful, it prints "Valid 'for' loop syntax." and exits
the program.
o stmt : FOR OB init SEMI cond SEMI inc CB;
 This is the core rule defining the structure of the for loop header:
for keyword, ( token, init part, ;, cond part, ;, inc part, ) token.
o init : ID EQ NUM | /* empty */;
 Initialization Part: Can be an ID equals a NUM (e.g., i=0) OR it
can be empty (e.g., for( ; ; )).
o cond : ID LT NUM | ID GT NUM | ID LE NUM | ID GE NUM | /* empty
*/;
 Condition Part: Can be an ID followed by a relational operator (<,
>, <=, >=) and a NUM (e.g., i<10) OR it can be empty.
o inc : ID INC | ID DEC | INC ID | DEC ID | /* empty */;
 Increment/Decrement Part: Can be an ID followed by INC or
DEC (e.g., i++, i--) OR INC or DEC followed by an ID (e.g., ++i, -
-i) OR it can be empty.
 main():
o Prompts the user to "Enter a 'for' loop header:".
o Calls yyparse(), which starts the parsing process, requesting tokens from
yylex().
 yyerror(char *s):
o This function is called by YACC whenever a syntax error is detected (i.e.,
the input doesn't match any grammar rules). It prints an error message to
standard error.

 Grammar Rules (%% ... %%):


o start: expr { ... };: This is the start symbol of the grammar. It means a valid
input is a single expression.
 Action: If expr is successfully parsed, it prints the final Result
which is the value of the parsed expression ($$). return 0; exits
yyparse.
o expr : expr '+' expr { $$ = $1 + $3; }:
 Rule: An expr can be an expr followed by + followed by another
expr.
 Action: When this rule is applied (meaning an addition operation is
recognized), it calculates the sum of the value of the first expr ($1)
and the third expr ($3) and stores the result in $$ (which represents
the value of the current expr). Similar rules apply for subtraction

SNPITRC/CSE/2025-26/SEM-7/3170701 30 | P a g e
220490131078 Compiler Design

and multiplication.
o expr '/' expr { ... }:
 Rule: Division.

 Action: Includes a check for division by zero to prevent runtime


errors, printing an error message if expr $3 is 0.
o '(' expr ')' { $$ = $2; }:
 Rule: An expr can be an opening parenthesis ( followed by another
expr followed by a closing parenthesis ).
 Action: The value of this entire parenthesized construct $$ is
simply the value of the expr inside the parentheses ($2). This rule
allows expressions within parentheses to be evaluated first,
overriding default operator precedence as needed (e.g., (2 + 3) * 4
will correctly evaluate 2 + 3 first).
o expr : NUM { $$ = $1; };:
 Rule: The simplest expr is a single number (NUM).
 Action: The value of the NUM token ($1) is assigned as the value
of the expr ($$).
 main():
o Prompts the user to enter an expression.
o Calls yyparse(), which is the main parsing function generated by YACC.
yyparse() will repeatedly call yylex() (from the Lex file) to get tokens until
it successfully parses the input or encounters an error.
 yyerror(char *s):
o This is a standard YACC error-handling function that you must provide.
o It's called by the parser whenever a syntax error is detected (i.e., the tokens
don't match any grammar rules).
o It prints an error message to stderr.

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

SNPITRC/CSE/2025-26/SEM-7/3170701 32 | P a g e
220490131078 Compiler Design

/* YACC file to validate syntax of function prototype */


%{
#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
;

%%

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

int yyerror(char *s)


{
fprintf(stderr, "Syntax Error: %s\n", s);
return 0;
}
Output :

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.

 Lex File (pract9.l) - The Tokenizer:


 Purpose: To scan the input character stream and convert it into a sequence of
meaningful tokens that the YACC parser can process.
 Token Rules:
o "int"|"float"|"double"|"void"|"char": Recognizes common C built-in data
types and returns the BUILTIN token.
o [a-zA-Z_][a-zA-Z0-9_]*: Recognizes identifiers (e.g., function names,
variable names) and returns the ID token.
o ",": Recognizes a comma and returns the COMMA token.
o ";": Recognizes a semicolon and returns the SC token (Semicolon).
o "(": Recognizes an opening parenthesis and returns the LPAREN token.
o ")": Recognizes a closing parenthesis and returns the RPAREN token.
o [\t \n]+: Matches one or more whitespace characters (tabs, spaces,
newlines) and performs an empty action (i.e., ignores them).

o . { return yytext[0]; }: This is a catch-all rule. If any character is


encountered that doesn't match the preceding rules, it returns its ASCII
value as a token. This could indicate an unexpected character in the input.
 yywrap(): Standard Flex function, returns 1 to signal the end of the input.
 YACC File (pract9.y) - The Parser:
 Purpose: To take the tokens generated by Lex and apply grammar rules to
determine if they form a syntactically correct function prototype.
 Token Declarations (%token): Lists all the terminal symbols (tokens) that the
parser expects from the Lexer (e.g., BUILTIN, ID, COMMA, SC, LPAREN,
RPAREN).

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

%%

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

%%

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

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

stmt : if_stmt
;

SNPITRC/CSE/2025-26/SEM-7/3170701 38 | P a g e
220490131078 Compiler Design

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/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.

 Lex File (pract10.l) - The Tokenizer:


 Purpose: To scan the input character stream and convert it into a sequence of
meaningful tokens that the YACC parser can understand.
 Token Rules:
o "if": Recognizes the keyword if and returns the IF token.
o "(", ")", "{", "}": Recognize parentheses and curly braces, returning
LPAREN, RPAREN, LBRACE, RBRACE respectively.
o "<"|">"|"=="|"<="|">="|"!=": Recognizes common relational operators and
returns the RELOP token.
o [0-9]+: Matches one or more digits and returns NUMBER (for numeric
values in conditions).
o [a-z][a-zA-Z0-9_]*: Matches identifiers (starts with a lowercase letter,
followed by letters, digits, or underscores) and returns ID.
o [sS][0-9]*: Matches a simplified representation of a statement (e.g., s, S1,
s2). This is a placeholder for actual code statements and returns STMT.
o \n: Matches a newline character and returns NL.
o [ \t]+: Ignores one or more spaces or tabs.
o . { return yytext[0]; }: A catch-all rule for any other unmatched character,
returning its ASCII value. This would typically indicate a lexical error.
 yywrap(): Standard Flex function, returns 1 to signal the end of input.
 YACC File (pract10.y) - The Parser:
 Purpose: To take the tokens generated by Lex and apply grammar rules to verify
the syntax of nested if statements. It also counts the number of if statements
encountered.
 Global Variable: int count = 0;: This variable is used to keep track of how many if
statements have been successfully parsed.
 Token Declarations (%token): Lists all the terminal symbols (tokens) that the
parser expects from the Lexer.

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:

 IF LPAREN cond RPAREN LBRACE stmt RBRACE:


Matches the structure if (condition) { statement }.
 Action ({ count++; }): When this specific if structure is
successfully recognized (reduced), the count variable is
incremented. This is how the program counts nested if
statements.
 | STMT: An if_stmt can also simply be a placeholder STMT.
This allows for a base case within the if block.
o cond : expr RELOP expr;
 Condition Rule: A condition (within if(...)) consists of an
expression, followed by a RELOP (relational operator), followed by
another expression (e.g., x > 5).
o expr : ID | NUMBER;
 Expression Rule: A simple expression can be either an ID
(identifier) or a NUMBER.
 main():
o Prompts the user to "Enter nested if statement:".
o Calls yyparse(), which starts the parsing process, requesting tokens from
yylex().
 yyerror(char *s):
o This function is called by the YACC parser whenever a syntax error is
detected (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 41 | P a g e

You might also like