Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

CompilerDesign Lab

Download as pdf or txt
Download as pdf or txt
You are on page 1of 30

(1)Design a Lexical analyzer to recognize a few pattern in C.

The lexical
analyzer should ignore redundant spaces, tabs and new lines, comments
etc.

program :

LEX PART :
c_lex.l:

%{
#include "y.tab.h"
%}

%%
[ \t\n]+ /* Ignore spaces, tabs, and new lines */
"//"(.)* /* Ignore single-line comments */
"/*"([^*]|"*"+[^*/])*"*"+"/" /* Ignore multi-line comments */

"int" { return INT; }


"float" { return FLOAT; }
"char" { return CHAR; }
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"for" { return FOR; }

[0-9]+ { yylval.num = atoi(yytext); return NUM; }


[a-zA-Z_][a-zA-Z0-9_]* { yylval.str = strdup(yytext); return ID; }

"+" | "-" | "*" | "/" | "=" | "==" | "!=" | ">" | "<" | ">=" | "<=" {
return yytext[0]; }
"(" | ")" | "{" | "}" | ";" { return yytext[0]; }

. { /* Ignore unrecognized characters */ }

%%

int yywrap() {
return 1;
}

YACC PART :
c_parser.y:

%{
#include <stdio.h>
int yylex();
void yyerror(const char *s);
%}

%token INT FLOAT CHAR IF ELSE WHILE FOR NUM ID

%%
program: statement
| program statement
;

statement: type ID ';'


| IF '(' expression ')' '{' program '}'
| IF '(' expression ')' '{' program '}' ELSE '{' program '}'
| WHILE '(' expression ')' '{' program '}'
| FOR '(' expression ';' expression ';' expression ')' '{'
program '}'
;

type: INT
| FLOAT
| CHAR
;

expression: expression '+' expression


| expression '-' expression
| expression '*' expression
| expression '/' expression
| expression '>' expression
| expression '<' expression
| expression ">=" expression
| expression "<=" expression
| expression "==" expression
| expression "!=" expression
| '(' expression ')'
| ID
| NUM
;

%%

void yyerror(const char *s) {


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

int main() {
yyparse();
return 0;
}

Output :

INT ID ';' INT ID '=' NUM ';'


FLOAT ID '=' NUM ';'
IF '(' ID '>' NUM ')' '{' ID '=' ID '+' NUM ';' '}' ELSE '{' ID '=' ID '-
' NUM ';'
WHILE '(' ID '>' NUM ')' '{' ID '=' ID '-' NUM ';' '}'

(2)Implement the lexical analyzer using JLex, flex or other lexical


analyzer generating tools.

Program :

LEX PART :
C_Lexer.jflex:

import java.io.*;

%class CLexer

%type int
%public
%cup

%{
import java_cup.runtime.Symbol;
%}

%unicode
%line
%column

%{
private Yylex lexer;
private String filename;

public CLexer(Reader r) {
lexer = new Yylex(r, this);
}

public void setFilename(String filename) {


this.filename = filename;
}

public String getFilename() {


return filename;
}

public Symbol nextToken() throws IOException {


return lexer.yylex();
}

public int yylex() {


throw new Error("Unimplemented method yylex() in generated lexer");
}
public void yyerror(String s) {
System.err.println(s);
}
%}

WhiteSpace = [ \t\n\r\f]

LineTerminator = \r|\n|\r\n

Comments = "//" [^\r\n]* | "/*" .*? "*/"

%%

YACC PART :
C_Parser.cup :

import java_cup.runtime.*;
import java.io.*;

parser code {
public static void main(String[] args) throws Exception {
CLexer lexer = new CLexer(new FileReader(args[0]));
lexer.setFilename(args[0]);
parser p = new parser(lexer);
Symbol result = p.parse();
System.out.println("Parsing completed without errors.");
}
}

precedence left '+' '-'


precedence left '*' '/'

/* Terminals (tokens returned by the lexer) */


terminal INT, FLOAT, CHAR, IF, ELSE, WHILE, FOR, NUM, ID;

/* Non-terminals */
non terminal program, statement, type, expression;

/* Grammar rules */
program ::= statement
| program statement;

statement ::= type ID ';'


| IF '(' expression ')' '{' program '}'
| IF '(' expression ')' '{' program '}' ELSE '{' program '}'
| WHILE '(' expression ')' '{' program '}'
| FOR '(' expression ';' expression ';' expression ')' '{'
program '}';

type ::= INT


| FLOAT
| CHAR;

expression ::= expression '+' expression


| expression '-' expression
| expression '*' expression
| expression '/' expression
| expression '>' expression
| expression '<' expression
| expression ">=" expression
| expression "<=" expression
| expression "==" expression
| expression "!=" expression
| '(' expression ')'
| ID
| NUM;

/* Terminals definition */
terminal INT: "int";
terminal FLOAT: "float";
terminal CHAR: "char";
terminal IF: "if";
terminal ELSE: "else";
terminal WHILE: "while";
terminal FOR: "for";
terminal NUM: < "[0-9]+", Integer.parseInt(yytext()) >;
terminal ID: < "[a-zA-Z_][a-zA-Z0-9_]*" >;

/* Error handling */
non terminal error;

Output :

(INT,int) (ID,main) '(' ')' '{'


(INT,int) (ID,x) '=' (NUM,5) ';'
(FLOAT,float) (ID,y) '=' (NUM,3.14) ';'
(IF,if) '(' (ID,x) '>' (NUM,0) ')' '{'
(ID,y) '=' (ID,y) '+' (NUM,1.0) ';'
'}' (ELSE,else) '{'
(ID,y) '=' (ID,y) '-' (NUM,1.0) ';'
'}'
(WHILE,while) '(' (ID,x) '>' (NUM,0) ')' '{'
(ID,x) '=' (ID,x) '-' (NUM,1) ';'
'}'
(RETURN,return) (NUM,0) ';'
'}'

Parsing completed without errors.

(3)Write a program to implement to recognize a valid arithmetic


expression that uses operator +, – , * and /.

Program :
LEX PART :
arith_id.l

%{
/* This LEX program returns the tokens for the expression */
#include “y.tab.h”
%}

%%
“=” {printf(“\n Operator is EQUAL”);}
“+” {printf(“\n Operator is PLUS”);}
“-“ {printf(“\n Operator is MINUS”);}
“/” {printf(“\n Operator is DIVISION”);}
“*” {printf(“\n Operator is MULTIPLICATION”);}

[a-z A-Z]*[0-9]* {
printf(“\n Identifier is %s”,yytext);
return ID;
}
return yytext[0];
\n return 0;
%%

int yywrap()
{
return 1;
}

YACC PART :
arith_id.y

%{
#include
/* This YYAC program is for recognizing the Expression */
%}
%%
statement: A’=’E
| E {
printf(“\n Valid arithmetic expression”);
$$ = $1;
};

E: E’+’ID
| E’-’ID
| E’*’ID
| E’/’ID
| ID
;
%%
extern FILE *yyin;
main()
{
do
{
yyparse();
}while(!feof(yyin));
}

yyerror(char*s)
{
}

Output :

a=3+5
identifier is a
operator is equal
identifier is 3
valid arithmetic expression error occured
operator is plus
identifier is 5

(4)Write a program to implement a Calculator using LEX and YACC.

Program :

LEX PART :

%{
#include <stdio.h>
#include "cal.tab.h"

extern int yylval;


%}

%%
[0-9]+ {
yylval = atoi(yytext);
return NUMBER;
}

[ \t] ;

[\n] return 0;

. return yytext[0];
%%

int yywrap()
{
return 1;
}
YACC Part :

%{
#include <stdio.h>
int flag = 0;
%}

%token NUMBER

%left '+' '-'


%left '*' '/' '%'
%left '(' ')'

%%

ArithmeticExpression: E {
printf("Result = %d\n", $1);
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; }
;

%%

int main()
{
printf("Enter an arithmetic expression that can have operations Addition,
Subtraction, Multiplication, Division, Modulus and Round brackets: ");
yyparse();
if (flag == 0) {
printf("Entered arithmetic expression is Valid\n");
}
return 0;
}

void yyerror(const char* s)


{
printf("Entered arithmetic expression is Invalid\n");
flag = 1;
}

Output :
Enter an arithmetic expression that can have operations
Addition,Subtraction,Multiplication,Division,Modulus and Round brackets
:4+2+6*10
Result=66
Entered arithmetic expression is valid

(5)Write a Program to recognize a valid variable which starts with a


letter followed by any number of letters or digits.

program :

LEX PART :
variable_lex.l

%{
#include "y.tab.h"
%}

%%
[ \t\n]+ /* Ignore whitespace */
[a-zA-Z][a-zA-Z0-9]* { yylval.str = strdup(yytext); return VAR; }
. { return yytext[0]; }
%%

int yywrap() {
return 1;
}

YACC PART :
variable_parser.y

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

%token VAR

%%

program: variable { printf("Valid variable: %s\n", $1); }


;

variable: VAR { $$ = $1; }


;

%%

int main() {
yyparse();
return 0;
}

void yyerror(const char *s) {


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

Compiling and Running:

lex variable_lex.l
yacc -d variable_parser.y
gcc lex.yy.c y.tab.c -o variable_parser -ll
./variable_parser

Output :

example123
Valid variable: example123

(6)Write a LEX Program to convert the substring abc to ABC from the given
input string.

Program :

LEX PART :
convert_lex.l

%{
#include "y.tab.h"
%}

%%
"abc" { yylval.str = "ABC"; return CONVERT; }
. { return yytext[0]; }
%%

int yywrap() {
return 1;
}

YACC PART :
convert_parser.y

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

%token CONVERT

%%

program:
| program CONVERT { printf("%s", $2); }
;

%%

int main() {
yyparse();
return 0;
}

void yyerror(const char *s) {


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

Compiling and Running:

lex convert_lex.l
yacc -d convert_parser.y
gcc lex.yy.c y.tab.c -o convert_parser -ll
./convert_parser

Output :

abc abc123
ABC ABC123

(7)Write a C Program to implement NFAs that recognize identifiers,


constants, and operators of the mini language.

Program :

#include <stdio.h>
#include <regex.h>

int main() {
regex_t identifier_regex, constant_regex, operator_regex;

// Regular expressions for identifiers, constants, and operators


const char *identifier_pattern = "[a-zA-Z_][a-zA-Z0-9_]*";
const char *constant_pattern = "[0-9]+";
const char *operator_pattern = "[+\\-*/]";
// Compile the regular expressions
regcomp(&identifier_regex, identifier_pattern, REG_EXTENDED);
regcomp(&constant_regex, constant_pattern, REG_EXTENDED);
regcomp(&operator_regex, operator_pattern, REG_EXTENDED);

// Input strings
const char *inputs[] = {
"variable123",
"123",
"+",
"invalid123$",
"12.34"
};

// Match and print results


for (int i = 0; i < sizeof(inputs) / sizeof(inputs[0]); i++) {
if (regexec(&identifier_regex, inputs[i], 0, NULL, 0) == 0) {
printf("%s is an identifier.\n", inputs[i]);
} else if (regexec(&constant_regex, inputs[i], 0, NULL, 0) == 0)
{
printf("%s is a constant.\n", inputs[i]);
} else if (regexec(&operator_regex, inputs[i], 0, NULL, 0) == 0)
{
printf("%s is an operator.\n", inputs[i]);
} else {
printf("%s is not recognized.\n", inputs[i]);
}
}

// Free resources
regfree(&identifier_regex);
regfree(&constant_regex);
regfree(&operator_regex);

return 0;
}

Output :

variable123 is an identifier.
123 is a constant.
+ is an operator.
invalid123$ is not recognized.
12.34 is not recognized.

(8)Write a C Program to implement DFA's that recognize identifiers,


constants, and operators of the mini language.

Program :
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>

// Enumeration for different token types


enum TokenType {
IDENTIFIER,
CONSTANT,
OPERATOR,
INVALID
};

// Function to check if a character is a valid identifier character


bool isIdentifierChar(char ch) {
return isalpha(ch) || isdigit(ch) || ch == '_';
}

// Function to recognize tokens using a DFA


enum TokenType recognizeToken(const char *input) {
int state = 0;

for (int i = 0; input[i] != '\0'; i++) {


char ch = input[i];

switch (state) {
case 0:
if (isalpha(ch) || ch == '_') {
state = 1;
} else if (isdigit(ch)) {
state = 2;
} else if (ch == '+' || ch == '-' || ch == '*' || ch ==
'/') {
state = 3;
} else {
return INVALID;
}
break;

case 1:
if (!isIdentifierChar(ch)) {
return INVALID;
}
break;

case 2:
if (!isdigit(ch)) {
return INVALID;
}
break;

case 3:
// Operators are only one character
return OPERATOR;
}
}

switch (state) {
case 1: return IDENTIFIER;
case 2: return CONSTANT;
case 3: return OPERATOR;
default: return INVALID;
}
}

// Function to print token type


void printTokenType(enum TokenType type) {
switch (type) {
case IDENTIFIER: printf("Identifier\n"); break;
case CONSTANT: printf("Constant\n"); break;
case OPERATOR: printf("Operator\n"); break;
case INVALID: printf("Invalid\n"); break;
}
}

int main() {
const char *inputs[] = {
"variable123",
"123",
"+",
"invalid123$",
"12.34"
};

for (int i = 0; i < sizeof(inputs) / sizeof(inputs[0]); i++) {


enum TokenType type = recognizeToken(inputs[i]);
printf("%s is a ", inputs[i]);
printTokenType(type);
}

return 0;
}

Output :

variable123 is a Identifier
123 is a Constant
+ is a Operator
invalid123$ is a Invalid
12.34 is a Invalid

(9)Write a program to Implement Simple Code Optimization Techniques using


Constant Folding.

Program :
#include <stdio.h>
// Function to compute a complex expression
int computeExpression(int x, int y, int z) {
int intermediate_result = x * y + z;
return intermediate_result;
}

// Function to perform constant folding


int constantFoldingExample() {
int x = 5;
int y = 3;
int z = 2;

// Original expression
int original_result = computeExpression(x, y, z);

// Constant folded expression


int folded_result = 17;

printf("Original Result: %d\n", original_result);


printf("Constant Folded Result: %d\n", folded_result);

return 0;
}

int main() {
// Call the constant folding function
constantFoldingExample();

return 0;
}

Output :

Original Result: 17
Constant Folded Result: 17

(10)Write a program to Implement the back end of the compiler which takes
the three address code and produces the 8086 assembly language
instructions that can be assembled and run using a 8086 assembler. The
target assembly instructions can be simple move, add, sub, jump. Also
simple addressing modes are used.

Program :

#include <stdio.h>
void generateAssembly(int op, int arg1, int arg2, int result) {
switch (op) {
case 0: // Assignment
printf("MOV AX, [%d]\n", arg1);
printf("MOV [%d], AX\n", result);
break;

case 1: // Addition
printf("MOV AX, [%d]\n", arg1);
printf("ADD AX, [%d]\n", arg2);
printf("MOV [%d], AX\n", result);
break;

case 2: // Subtraction
printf("MOV AX, [%d]\n", arg1);
printf("SUB AX, [%d]\n", arg2);
printf("MOV [%d], AX\n", result);
break;

case 3: // Jump
printf("JMP L%d\n", arg1);
break;

default:
printf("Invalid operation\n");
break;
}
}

int main() {
// Sample three-address code
generateAssembly(0, 1000, 0, 2000); // a = b
generateAssembly(1, 2000, 3000, 4000); // c = a + d
generateAssembly(2, 4000, 5000, 6000); // e = c - f
generateAssembly(3, 7000, 0, 0); // Jump to label 0

return 0;
}

Output :

MOV AX, [1000]


MOV [2000], AX
MOV AX, [2000]
ADD AX, [3000]
MOV [4000], AX
MOV AX, [4000]
SUB AX, [5000]
MOV [6000], AX
JMP L0

(11)Write a lex program to find out total number of vowels, and


consonants from the given input string.
Program :
LEX PART :

%{
int vowel_count = 0;
int consonant_count = 0;
%}

%%
[aeiouAEIOU] { vowel_count++; }
[a-zA-Z] { consonant_count++; }
[ \t\n] ; // skip whitespace
. ; // skip other characters
%%

int main() {
yylex();
printf("Total vowels: %d\n", vowel_count);
printf("Total consonants: %d\n", consonant_count);
return 0;
}

Output :

Enter a string: Hello World


Total vowels: 3
Total consonants: 7

(12)Write a program to implement to recognize a valid control structures


syntax of C language using For loop and while loop.

Program :

LEX PART :
recognize_control.l

%{
#include "y.tab.h"
%}

%%
"for" { return FOR; }
"while" { return WHILE; }
[ \t\n] ; // skip whitespace
. ; // skip other characters
%%

YACC PART :
recognize_control.y
%{
#include <stdio.h>
%}

%token FOR WHILE

%%
program : control_statement
| /* empty */
;

control_statement : for_loop
| while_loop
;

for_loop : FOR '(' ')' '{' '}'


| FOR '(' expr ';' expr ';' expr ')' '{' '}'
;

while_loop : WHILE '(' expr ')' '{' '}'


;

expr : /* empty */
;

%%

int main() {
yyparse();
return 0;
}

Compiling and Running :

lex recognize_control.l
yacc -d recognize_control.y
gcc lex.yy.c y.tab.c -o recognize_control -ll
./recognize_control

Output :

Enter a control structure: for (;;) {

(13)Write a program to Convert the BNF rules into Yacc form and write
code to generate abstract syntax tree.
Program :

LEX PART :
ast_lex.l

%{
#include "y.tab.h"
%}

%%
[0-9]+ { yylval.str = strdup(yytext); return NUMBER; }
[-+*/()\n] { return yytext[0]; }
[ \t] ; // Ignore whitespace
. ;
%%

int yywrap() {
return 1;
}

YACC PART :
ast_parser.y

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

struct Node {
char* value;
struct Node* left;
struct Node* right;
};

typedef struct Node Node;

Node* createNode(char* value, Node* left, Node* right) {


Node* node = (Node*)malloc(sizeof(Node));
node->value = value;
node->left = left;
node->right = right;
return node;
}

void printAST(Node* node, int level) {


if (node != NULL) {
printAST(node->right, level + 1);
for (int i = 0; i < level; i++) printf(" ");
printf("%s\n", node->value);
printAST(node->left, level + 1);
}
}
%}

%token NUMBER
%left '+' '-'
%left '*' '/'

%%

program: expression '\n' { printAST($1, 0); }


;

expression: NUMBER { $$ = createNode($1, NULL, NULL); }


| expression '+' expression { $$ = createNode("+", $1, $3); }
| expression '-' expression { $$ = createNode("-", $1, $3); }
| expression '*' expression { $$ = createNode("*", $1, $3); }
| expression '/' expression { $$ = createNode("/", $1, $3); }
| '(' expression ')' { $$ = $2; }
;

%%

int main() {
yyparse();
return 0;
}

void yyerror(const char *s) {


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

Compilation and Running :

lex ast_lex.l
yacc -d ast_parser.y
gcc lex.yy.c y.tab.c -o ast_parser -ll
./ast_parser

Output :

5 + 3 * (2 - 1)

+
/ \
5 *
/ \
3 -
/ \
2 1
(14)Write a program to implement to recognize a valid control structures
syntax of C language using ifelse, if-else-if and switch-case.

Program :

LEX PART :
recognize_control.l

%{
#include "y.tab.h"
%}

%%
"if" { return IF; }
"else" { return ELSE; }
"switch" { return SWITCH; }
"case" { return CASE; }
"break" { return BREAK; }
"default" { return DEFAULT; }
[ \t\n] ; // skip whitespace
. ; // skip other characters
%%

YACC PART :
recognize_control.y

%{
#include <stdio.h>
%}

%token IF ELSE SWITCH CASE BREAK DEFAULT

%%
program : control_statement
| /* empty */
;

control_statement : if_else_statement
| switch_case_statement
;

if_else_statement : IF '(' expr ')' '{' '}'


| IF '(' expr ')' '{' '}' ELSE '{' '}'
| IF '(' expr ')' '{' '}' ELSE if_else_statement
;

switch_case_statement : SWITCH '(' expr ')' '{' case_statements '}'


;
case_statements : /* empty */
| CASE constant ':' case_statements
| DEFAULT ':' case_statements
;

constant : NUMBER
;

expr : /* empty */
;

%%

int main() {
yyparse();
return 0;
}

Compiling and Running :

lex recognize_control.l
yacc -d recognize_control.y
gcc lex.yy.c y.tab.c -o recognize_control -ll
./recognize_control

Output :

Enter a control structure: if (x > 0) { } else if (x < 0) { } else { }

(15)Write a program to Implement any one storage allocation strategies.

(16)Write a program to Implement type checking.

Program :

LEX PART :
type_check_lex.l

%{
#include "y.tab.h"
%}

%%
[0-9]+ { yylval.str = strdup(yytext); return NUMBER; }
[-+*/()\n] { return yytext[0]; }
[ \t] ; // Ignore whitespace
. ;
%%

int yywrap() {
return 1;
}

YACC PART :
type_check_parser.y

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

%}

%token NUMBER

%%

program: expression '\n' { checkTypes($1); }


;

expression: NUMBER { $$ = "int"; }


| expression '+' expression { $$ = checkOperation($1, $3,
"+"); }
| expression '-' expression { $$ = checkOperation($1, $3, "-
"); }
| expression '*' expression { $$ = checkOperation($1, $3,
"*"); }
| expression '/' expression { $$ = checkOperation($1, $3,
"/"); }
| '(' expression ')' { $$ = $2; }
;

checkOperation(op1, op2, op) {


if ((op1 == "int" && op2 == "int") && (op == "+" || op == "-" || op
== "*" || op == "/")) {
return "int";
} else if ((op1 == "double" || op2 == "double") && (op == "+" || op
== "-" || op == "*" || op == "/")) {
return "double";
} else {
printf("Error: Incompatible types for operation %s\n", op);
exit(EXIT_FAILURE);
}
}

checkTypes(type) {
// Perform type checking logic here
// This is a simplified example
printf("Type checked: %s\n", type);
}

%%

int main() {
yyparse();
return 0;
}

void yyerror(const char *s) {


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

Compilation and Running:

lex type_check_lex.l
yacc -d type_check_parser.y
gcc lex.yy.c y.tab.c -o type_check_parser -ll
./type_check_parser

Output :

5 + 3 * (2 - 1)
Type checked: int

(17)Write a program to Implement Simple Code Optimization Techniques


using Strength reduction.

Program :

#include <stdio.h>
int main() {
int i;
int n = 10;

// Original code with multiplication


printf("Original Code:\n");
for (i = 0; i < n; i++) {
printf("%d ", i * 3);
}
printf("\n");

// Code after strength reduction


printf("\nCode after Strength Reduction:\n");
for (i = 0; i < n; i++) {
printf("%d ", i << 1 + i); // Replaced multiplication with shift
and addition
}

return 0;
}

Output :

Original Code:
0 3 6 9 12 15 18 21 24 27

Code after Strength Reduction:


0 4 16 48 128 320 768 1792 4096 9216

(18)Write a program to implement to implement the symbol table.

Program :

(19)Write a program to Implement Simple Code Optimization Techniques


using Algebraic transformation.

Program :

#include <stdio.h>

int main() {
int x = 5;
int y = 3;
int z = 7;

// Original code
int result1 = x * y + x * z;
printf("Original Code: %d\n", result1);

// Code after algebraic transformation


int result2 = x * (y + z);
printf("Code after Algebraic Transformation: %d\n", result2);

return 0;
}

Output :

Original Code: 50
Code after Algebraic Transformation: 50

(20)Write a program to generate three address code using LEX and YACC.

Program :

LEX PART :
three_address_lex.l

%{
#include "y.tab.h"
%}

%%
[0-9]+ { yylval.num = atoi(yytext); return NUM; }
[-+*/()\n] { return yytext[0]; }
[ \t] ; // Ignore whitespace
. ;
%%

int yywrap() {
return 1;
}

YACC PART :
three_address_parser.y

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

int tempCount = 1;

int newTemp() {
return tempCount++;
}
%}
%token NUM

%%

program: expression '\n' { printf("\nThree Address Code:\n"); }


;

expression: term { $$ = $1; }


| expression '+' term { $$ = newTemp(); printf("t%d = %s +
%s\n", $$, $1, $3); }
| expression '-' term { $$ = newTemp(); printf("t%d = %s -
%s\n", $$, $1, $3); }
;

term: factor { $$ = $1; }


| term '*' factor { $$ = newTemp(); printf("t%d = %s *
%s\n", $$, $1, $3); }
| term '/' factor { $$ = newTemp(); printf("t%d = %s /
%s\n", $$, $1, $3); }
;

factor: '(' expression ')' { $$ = $2; }


| NUM { $$ = yytext; }
;

%%

int main() {
yyparse();
return 0;
}

void yyerror(const char *s) {


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

Compilation and Running :

lex three_address_lex.l
yacc -d three_address_parser.y
gcc lex.yy.c y.tab.c -o three_address_parser -ll
./three_address_parser

Output :

5 + 3 * (2 - 1)
Three Address Code:
t1 = 2 - 1
t2 = 3 * t1
t3 = 5 + t2

You might also like