Compiler - Design - Lab Final 2024
Compiler - Design - Lab Final 2024
Compiler - Design - Lab Final 2024
TABLE OF CONTENTS
4. Generate three address code for a simple program using LEX and
CO3
YACC.
%{
/* program to recognize a C program */
int COMMENT = 0;
int cnt = 0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
#.* {
printf("\n%s is a PREPROCESSOR DIRECTIVE", yytext);
}
int |
float |
char |
double |
while |
for |
do |
if |
break |
continue |
void |
switch |
case |
long |
struct |
const |
typedef |
return |
else |
goto {
printf("\n\t%s is a KEYWORD", yytext);
}
"/*" {
COMMENT = 1;
}
"*/" {
COMMENT = 0;
cnt++;
}
{identifier}\( {
if (!COMMENT)
printf("\n\nFUNCTION\n\t%s", yytext);
}
\{ {
if (!COMMENT)
printf("\n BLOCK BEGINS");
}
\} {
if (!COMMENT)
printf("\n BLOCK ENDS");
}
{identifier}(\[[0-9]*\])? {
if (!COMMENT)
printf("\n %s IDENTIFIER", yytext);
}
\".*\" {
if (!COMMENT)
printf("\n\t%s is a STRING", yytext);
}
[0-9]+ {
if (!COMMENT)
printf("\n\t%s is a NUMBER", yytext);
}
\)(\;)? {
if (!COMMENT)
printf("\n\t");
ECHO;
printf("\n");
}
\( ECHO;
={
if (!COMMENT)
printf("\n\t%s is an ASSIGNMENT OPERATOR", yytext);
}
\<= |
\>= |
\< |
== |
\> {
if (!COMMENT)
printf("\n\t%s is a RELATIONAL OPERATOR", yytext);
}
%%
int yywrap() {
return 1;
}
How to Run:
$ lex c_lexical_analyzer.l
$ gcc -o c_lexical_analyzerlex.yy.c -ll
Input File
$ ./c_lexical_analyzerinput_file.c
#include <stdio.h>
int main() {
// This is a sample C program
int x = 10;
float y = 3.14;
char str[] = "Hello, World!";
return 0;
}
Output
#include <stdio.h> is a PREPROCESSOR DIRECTIVE
int is a KEYWORD
main is a KEYWORD
(
) is a RELATIONAL OPERATOR
{ is a RELATIONAL OPERATOR
This is a sample C program is a PREPROCESSOR DIRECTIVE
int is a KEYWORD
x is an IDENTIFIER
= is an ASSIGNMENT OPERATOR
10 is a NUMBER
; is a RELATIONAL OPERATOR
float is a KEYWORD
y is an IDENTIFIER
= is an ASSIGNMENT OPERATOR
3.14 is a NUMBER
; is a RELATIONAL OPERATOR
char is a KEYWORD
str is an IDENTIFIER
[ is a RELATIONAL OPERATOR] is a RELATIONAL OPERATOR
= is an ASSIGNMENT OPERATOR
"Hello, World!" is a STRING
; is a RELATIONAL OPERATOR
return is a KEYWORD
0 is a NUMBER
; is a RELATIONAL OPERATOR
} is a RELATIONAL OPERATOR
Program:
%{
#include <stdio.h>
%}
%option noyywrap
%%
"auto"|"break"|"case"|"char"|"const"|"continue"|"default"|"do"|"double"|"else"|"enum"|"ext
ern"|"float"|"for"|"goto"|"if"|"int"|"long"|"register"|"return"|"short"|"signed"|"sizeof"|"static"|"
struct"|"switch"|"typedef"|"union"|"unsigned"|"void"|"volatile"|"while" {
printf("Keyword: %s\n", yytext);
}
return 0;
}
Output:
$ flex token_recognizer.l
$ gcc -o token_recognizer lex.yy.c -ll
$ ./token_recognizer
#include <stdio.h>
int main() {
int x = 10;
float y = 3.14;
char str[] = "Hello, World!";
return 0;
}
Keyword: #include
Keyword: <stdio.h>
Keyword: int
Keyword: main( )
Keyword: int
Identifier: x= 10
Keyword: float
Identifier: y= 3.14
Keyword: char
Identifier: str= "Hello, World!"
Keyword: return 0
Ex:02 Lexical Analyzer Using Lex Tool
Program:
//Implementation of Lexical Analyzer using Lex tool
%{
int COMMENT=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
#.* {printf("\n%s is a preprocessor directive",yytext);}
int |
float |
char |
double |
while |
for |
struct |
typedef |
do |
if |
break |
continue |
void |
switch |
return |
else |
goto {printf("\n\t%s is a keyword",yytext);}
"/*" {COMMENT=1;}{printf("\n\t %s is a COMMENT",yytext);}
{identifier}\( {if(!COMMENT)printf("\nFUNCTION \n\t%s",yytext);}
\{ {if(!COMMENT)printf("\n BLOCK BEGINS");}
\} {if(!COMMENT)printf("BLOCK ENDS ");}
{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s IDENTIFIER",yytext);}
\".*\" {if(!COMMENT)printf("\n\t %s is a STRING",yytext);}
[0-9]+ {if(!COMMENT) printf("\n %s is a NUMBER ",yytext);}
\)(\:)? {if(!COMMENT)printf("\n\t");ECHO;printf("\n");}
\( ECHO;
= {if(!COMMENT)printf("\n\t %s is an ASSIGNMENT OPERATOR",yytext);}
\<= |
\>= |
\< |
== |
\> {if(!COMMENT) printf("\n\t%s is a RELATIONAL OPERATOR",yytext);}
%%
int main(int argc, char **argv)
{
FILE *file;
file=fopen("var.c","r");
if(!file)
{
printf("could not open the file");
exit(0);
}
yyin=file;
yylex();
printf("\n");
return(0);
}
int yywrap()
{
return(1);
}
Input:
#include <stdio.h>
int main() {
int x = 42;
char name[] = "John";
printf("Hello, %s!\n", name);
return 0;
}
Output:
Program: LEX
%{
#include "y.tab.h"
%}
%%
%%
int yywrap()
{
return 1;
}
YACC :
%{
#include<stdio.h>
int valid=1;
%}
%token num id op
%%
start : id '=' s ';'
s : id x
| num x
| '-' num x
| '(' s ')' x
;
x : op s
| '-' s
|
;
%%
int yyerror()
{
valid=0;
printf("\nInvalidexpression!\n");
return 0;
}
int main()
{
printf("\nEnter the expression:\n");
yyparse();
if(valid)
{
printf("\nValidexpression!\n");
}
}
Output:
$yacc –d arithmetic.y
$lex arithmetic.l
$gcc lex.yy.c y.tab.c -w
$./a.out
Enter the Expression: a=b*c+d
Valid Expression
Enter the Expression: b?a*c
Invalid Expression
Enter the Expresson: c=2*a+b
Valid Expression
Ex:03(b) YACC Program to Recognize valid Variable
Program: LEX
%{
#include "y.tab.h"
%}
%%
[a-zA-Z_][a-zA-Z_0-9]* return letter;
int yywrap()
{
return 1;
}
YACC:
%{
#include<stdio.h>
int valid=1;
%}
%%
start : letter s
s: letter s
| digit s
|
;
%%
int yyerror()
{
printf("\nIts not aidentifier!\n");
valid=0;
return 0;
}
int main()
{
printf("\nEnter a name to tested for identifier: ");
yyparse();
if(valid)
{
printf("\nIt is aidentifier!\n");
}
}
Output:
$yacc –d Variable.y
$lex Variable.l
$gcc lex.yy.c y.tab.c -w
$./a.out
Enter a name to tested for identifier: Counter01
Its a identifier!
$./a.out
Enter a name to tested for identifier: 1sequence
Its not identifier!
Ex:03(c) YACC Program to Validate Control Structures in C
Program: Lex:
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
"for" { return FOR; }
"while" { return WHILE; }
"if" { return IF; }
"else" { return ELSE; }
"switch" { return SWITCH; }
"case" { return CASE; }
"break" { return BREAK; }
"{" { return OPEN_BRACE; }
"}" { return CLOSE_BRACE; }
"(" { return OPEN_PAREN; }
")" { return CLOSE_PAREN; }
";" { return SEMICOLON; }
"" ; // Ignore whitespace
. ;
%%
YACC:
%{
#include <stdio.h>
int yylex(void);
void yyerror(const char *s);
%}
%%
program:
control_structure
;
control_structure:
for_loop { printf("Valid control structure\n"); }
| while_loop { printf("Valid control structure\n"); }
| if_else { printf("Valid control structure\n"); }
| switch_case { printf("Valid control structure\n"); }
;
for_loop:
FOR OPEN_PAREN SEMICOLON SEMICOLON CLOSE_PAREN OPEN_BRACE
control_structure CLOSE_BRACE
;
while_loop:
WHILE OPEN_PAREN CLOSE_PAREN OPEN_BRACE control_structure
CLOSE_BRACE
;
if_else:
IF OPEN_PAREN CLOSE_PAREN OPEN_BRACE control_structure
CLOSE_BRACE
| IF OPEN_PAREN CLOSE_PAREN OPEN_BRACE control_structure
CLOSE_BRACE ELSE OPEN_BRACE control_structure CLOSE_BRACE
;
switch_case:
SWITCH OPEN_PAREN CLOSE_PAREN OPEN_BRACE case_statements
CLOSE_BRACE
;
case_statements:
CASE constant COLON control_structure
| CASE constant COLON control_structure case_statements
;
constant:
/* Your implementation of constant here */
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Syntax error: %s\n");
}
int main(void) {
yyparse();
return 0;
}
Output:
$yacc –d Control.y
$lex Control.l
$gcc lex.yy.c y.tab.c -w
$./a.out
For Loop:
for(i = 0; i < 10; i++) {
printf("%d", i);
}
Valid control structure
While Loop:
while (i< 10) {
printf("%d", i);
i++;
}
Valid control structure
Switch-Case:
switch (choice) {
case 1:
printf("Choice is 1");
break;
case 2:
printf("Choice is 2");
default:
printf("Choice is not 1 or 2");
}
Program: LEX:
//yaccalc.y
%{
double memvar;
%}
%union
{
double dval;
}
%token <dval> NUMBER
%token <dval> MEM
%token LOG SINE nLOG COS TAN
%left '-' '+'
%left '*' '/'
%right '^'
%left LOG SINE nLOG COS TAN
%nonassoc UMINUS
%type <dval>expr
%%
start : statement '\n'
| start statement '\n'
;
statement : MEM '=' expr { memvar = $3; }
| expr { printf("Answer = %g\n",$1); }
;
expr: expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr
{
if($3==0)
printf("Divide by zero");
else
$$ = $1 / $3;
}
| expr '^' expr { $$ = pow($1,$3); }
;
expr : '-' expr %prec UMINUS { $$ = -$2; }
| '(' expr ')' { $$ = $2; }
| LOG expr { $$ = log($2)/log(10); }
| nLOG expr { $$ = log($2); }
| SINE expr { $$ = sin($2 * 3.1415/180); }
| COS expr { $$ = cos($2*3.1415/180); }
| TAN expr { $$ = tan($2*3.1415/180); }
| NUMBER { $$ = $1; }
| MEM { $$ = memvar; }
;
%%
main()
{
printf("Enter the Expression\n");
yyparse();
}
SAMPLE INPUT & OUTPUT
Input:
Enter the Expression
log100
Output:
Answer = 2
Input:
Enter the Expression
tan45
Output:
Answer = 0.999954
Ex:04 Three Address Code Generation
Program: Lex:
%{
#include "y.tab.h"
%}
%%
[0-9]+? {yylval.sym=(char)yytext[0]; return NUMBER;}
[a-zA-Z]+? {yylval.sym=(char)yytext[0];return LETTER;}
\n {return 0;}
. {return yytext[0];}
%%
yywrap()
{
return 1;
}
YACC:
%{
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void ThreeAddressCode();
void triple();
void qudraple();
char AddToTable(char ,char, char);
%union
{
char sym;
}
%token <sym> LETTER NUMBER
%type <sym> expr
%left '+'
%left '*''/'
%left '-'
%%
yyerror(char *s)
{
printf("%s",s);
exit(0);
}
void ThreeAddressCode()
{
int cnt = 0;
char temp = '1';
printf("\n\n\t THREE ADDRESS CODE\n\n");
while(cnt<ind)
{
if(code[cnt].opr != '=')
printf("t%c : = \t",temp++);
if(isalpha(code[cnt].opd1))
printf(" %c\t",code[cnt].opd1);
else if(code[cnt].opd1 >='1' && code[cnt].opd1 <='9')
printf("t%c\t",code[cnt].opd1);
printf(" %c\t",code[cnt].opr);
if(isalpha(code[cnt].opd2))
printf(" %c\n",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("t%c\n",code[cnt].opd2);
cnt++;
}
}
void quadruple()
{
int cnt = 0;
char temp = '1';
printf("\n\n\t QUADRAPLE CODE\n\n");
while(cnt<ind)
{
printf(" %c\t",code[cnt].opr);
if(code[cnt].opr == '=')
{
if(isalpha(code[cnt].opd2))
printf(" %c\t \t",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("t%c\t \t",code[cnt].opd2);
printf(" %c\n",code[cnt].opd1);
cnt++;
continue;
}
if(isalpha(code[cnt].opd1))
printf(" %c\t",code[cnt].opd1);
else if(code[cnt].opd1 >='1' && code[cnt].opd1 <='9')
printf("t%c\t",code[cnt].opd1);
if(isalpha(code[cnt].opd2))
printf(" %c\t",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("t%c\t",code[cnt].opd2);
else printf(" %c",code[cnt].opd2);
printf("t%c\n",temp++);
cnt++;
}
}
void triple()
{
int cnt=0;
char temp='1';
printf("\n\n\t TRIPLE CODE\n\n");
while(cnt<ind)
{
printf("(%c) \t",temp);
printf(" %c\t",code[cnt].opr);
if(code[cnt].opr == '=')
{
if(isalpha(code[cnt].opd2))
printf(" %c \t \t",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("(%c)\n",code[cnt].opd2);
cnt++;
temp++;
continue;
}
if(isalpha(code[cnt].opd1))
printf(" %c \t",code[cnt].opd1);
else if(code[cnt].opd1 >='1' && code[cnt].opd1 <='9')
printf("(%c)\t",code[cnt].opd1);
if(isalpha(code[cnt].opd2))
printf(" %c \n",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("(%c)\n",code[cnt].opd2);
else printf(" %c\n",code[cnt].opd2);
cnt++;
temp++;
}
}
main()
{
printf("\n Enter the Expression : ");
yyparse();
ThreeAddressCode();
quadruple();
triple();
}
Output:
$ lex calculator.l
$ yacc -d calculator.y
$ gcc lex.yy.c y.tab.c -o calculator -ll
$ ./calculator
t1 := 5
t2 := 3
t3 := t1 + t2
t4 := 4
t5 := t3 * t4
QUADRUPLE CODE
+ 5 3
+ t1 t2
* t3 4
* t5 t4
TRIPLE CODE
(1) + 5 3
(2) + t1 t2
(3) * t3 4
(4) * t5 t4
Ex: 05 Type Checking Using LEX and YACC
Program: LEX:
%{
#include "y.tab.h"
%}
%%
int {
yylval.type = "int";
return INT;
}
float {
yylval.type = "float";
return FLOAT;
}
[0-9]+ {
yylval.type = "int";
return INT_LITERAL;
}
[0-9]+"."[0-9]+ {
yylval.type = "float";
return FLOAT_LITERAL;
}
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
%union {
char* type;
}
%%
program: expression {
if (strcmp($1, "int") == 0 || strcmp($1, "float") == 0) {
printf("Type checked successfully: %s\n", $1);
} else {
printf("Type error: Incompatible type %s\n", $1);
}
}
%%
int main() {
yyparse();
return 0;
}
Output:
$ lex type_checker.l
$ yacc -d type_checker.y
$ gcc lex.yy.c y.tab.c -o type_checker
./type_checker
Program:
#include <stdio.h>
#include <string.h>
#include <stdbool>
#include <math.h>
struct op {
char l;
char r[20];
};
void main() {
int a, i, k, j, n, z = 0, m, q;
char *p, *l;
char temp, t;
char *tem;
struct op op[10], pr[10];
if (p) {
t = pr[j].l;
pr[j].l = pr[m].l;
for (i = 0; i< z; i++) {
l = strchr(pr[i].r, t);
if (l) {
a = l - pr[i].r;
pr[i].r[a] = pr[m].l;
}
}
}
}
}
if (!optimized) {
// Perform constant folding
double value = 0;
char op;
if (sscanf(result, "%lf %c %lf", &value, &op, &value) == 3) {
double result = 0;
if (op == '+') result = value + value;
if (op == '-') result = value - value;
if (op == '*') result = value * value;
if (op == '/') result = value / value;
printf("%c\t=", pr[i].l);
printf("%.2lf\n", result);
} else {
printf("%c\t=", pr[i].l);
printf("%s\n", pr[i].r);
}
}
}
}
Output:
Enter the Number of Values: 4
left: x
right: a ** b
left: y
right: a + a
left: z
right: x * x
left: w
right: b - b
Intermediate Code
x=a**b
y=a+a
z=x*x
w=b-b
Program:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int n, rlen = 0;
char icode[25][25], reg[25][25];
int isopr(char c) {
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '\0')
return 1;
return 0;
}
int main() {
int i, j, k, rno1, rno2;
char tmp[25];
if (icode[i][j + 1] == '-') {
strcpy(tmp, "00");
j++;
} else {
for (k = 0, j = j + 1; isopr(icode[i][j]) == 0; k++, j++)
tmp[k] = icode[i][j];
tmp[k] = '\0';
}
rno1 = getregno(tmp);
if (rno1 == -1) {
rno1 = addtoreg(tmp);
if (isdigit(tmp[0]))
printf("\nMOV #%s,R%d", tmp, rno1);
else
printf("\nMOV %s,R%d", tmp, rno1);
} else if (tmp[0] == 't') {
rno2 = addtoreg(tmp);
printf("\nMOV R%d,R%d", rno1, rno2);
}
genopr(icode[i][j]);
if (rno2 == -1) {
if (isdigit(tmp[0]))
printf("#%s,R%d", tmp, rno1);
else
printf("%s,R%d", tmp, rno1);
} else {
printf("R%d,R%d", rno2, rno1);
}
return 0;
}
Output:
Enter the number of Intermediate code Entries: 5
Enter the Intermediate code
t1 = 5
t2 = t1 + 3
t3 = t2 - 2
t4 = t3 * 4
t5 = t4 / 2
struct ProductionRule
{
char left[10];
char right[10];
};
int main()
{
char input[20], stack[50], temp[50], ch[2], *token1, *token2, *substring;
int i, j, stack_length, substring_length, stack_top, rule_count = 0;
struct ProductionRule rules[10];
stack[0] = '\0';
i = 0;
while (1)
{
// If there are more characters in the input string, add the next character to the
stack
if (i < strlen(input))
{
ch[0] = input[i];
ch[1] = '\0';
i++;
strcat(stack, ch);
printf("%s\t", stack);
for (int k = i; k < strlen(input); k++)
{
printf("%c", input[k]);
}
printf("\tShift %s\n", ch);
}
// Check if the stack contains only the start symbol and if the entire input string has
been processed
if (strcmp(stack, rules[0].left) == 0 && i == strlen(input))
{
printf("\nAccepted");
break;
}
// Check if the entire input string has been processed but the stack doesn't match
the start symbol
if (i == strlen(input))
{
printf("\nNot Accepted");
break;
}
}
return 0;
}
Output:
input String: id*id+id