CD515
CD515
BTCS604-18 2224515
Submitted to :- Submitted by :-
Section:- D
Semester:- 6th
1|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
INDEX
2|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
11. Convert the BNF rules into Yacc form and 42-44
write code to generate abstract syntax tree for
the mini language specified in Note 1.
3|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 1
Design a lexical analyzer for given language and the lexical analyzer should ignore
redundant spaces, tabs and new lines. It should also ignore comments. Although the syntax
specification states that identifiers can be arbitrarily long, you may restrict the length to
some reasonable value. Simulate the same in C language.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_IDENTIFIER_LENGTH 32
5|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
} else if (ch == '/') {
// Check for comments
char next_ch = fgetc(source);
if (next_ch == '/') {
// Skip single-line comment
while ((ch = fgetc(source)) != EOF && ch != '\n');
} else if (next_ch == '*') {
// Skip multi-line comment
while ((ch = fgetc(source)) != EOF) {
if (ch == '*' && (ch = fgetc(source)) == '/') {
break;
}
}
} else {
// Not a comment, return the character
ungetc(next_ch, source);
return;
}
} else {
// Not a whitespace or comment, break
ungetc(ch, source);
return;
}
}
}
char ch;
skip_whitespace_and_comments(source);
ch = fgetc(source);
// End of file
if (ch == EOF) {
[Link] = TOKEN_EOF;
return token;
}
6|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
do {
[Link][i++] = ch;
if (i >= MAX_IDENTIFIER_LENGTH) break;
ch = fgetc(source);
} while (isalnum(ch) || ch == '_');
[Link][i] = '\0';
return token;
}
7|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
case TOKEN_KEYWORD:
printf("KEYWORD: %s\n", [Link]);
break;
case TOKEN_IDENTIFIER:
printf("IDENTIFIER: %s\n", [Link]);
break;
case TOKEN_NUMBER:
printf("NUMBER: %s\n", [Link]);
break;
case TOKEN_OPERATOR:
printf("OPERATOR: %s\n", [Link]);
break;
case TOKEN_EOF:
printf("END OF FILE\n");
break;
case TOKEN_UNKNOWN:
printf("UNKNOWN: %s\n", [Link]);
break;
}
}
int main() {
FILE *source = fopen("test.c", "r");
if (!source) {
printf("Error: Could not open file\n");
return 1;
}
Token token;
do {
token = get_next_token(source);
print_token(token);
} while ([Link] != TOKEN_EOF);
fclose(source);
return 0;
}
Output:
KEYWORD: int
IDENTIFIER: main
OPERATOR:
( OPERATOR: )
OPERATOR:
{ KEYWORD: int
8|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
IDENTIFIER: a
OPERATOR: =
NUMBER: 5
OPERATOR: ;
KEYWORD: if
OPERATOR:
( IDENTIFIER:
a OPERATOR:
> NUMBER: 0
OPERATOR: )
OPERATOR: {
IDENTIFIER: a
OPERATOR: =
IDENTIFIER: a
OPERATOR: +
NUMBER: 10
OPERATOR: ;
OPERATOR: }
KEYWORD: return
IDENTIFIER: a
OPERATOR: ;
OPERATOR: }
9|Page
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 2
#include <stdio.h>
#include <string.h>
int main() {
char line[256];
return 0;
}
Output:
Enter a line of code: // This is a comment
The line is a comment.
10 | P a g
e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 3
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char input[100];
11 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
} else if (match_a_b_plus(input)) {
printf("The string matches pattern 'a*b+'\n");
} else if (match_abb(input)) {
printf("The string matches pattern 'abb'\n");
} else {
printf("The string does not match any of the patterns\n");
}
return 0;
}
Output:
Enter a string: abbbb
The string matches pattern 'a*b+'
12 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 4
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define NUM_KEYWORDS 32
13 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
int main() {
char identifier[100];
return 0;
}
Output:
Enter an identifier: myVariable
14 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 5
#include <stdio.h>
#include <string.h>
int main() {
char input[100];
15 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
}
return 0;
}
Output:
Enter an operator: +
'+' is a valid operator.
Enter an operator: ==
'==' is a valid operator.
16 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 6
Implement the lexical analyzer using JLex, flex or other lexical analyzer generating tools.
/* program name is lexp.l */
%{
/* program to recognize a c program */
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 |do |if |break |continue |void |switch |case |long |struct |const
|typedef |return
|else |goto {printf("\n\t%s is a KEYWORD",yytext);}
"/*" {COMMENT = 1;}
/*{printf("\n\n\t%s is a COMMENT\n",yytext);}*/
"*/" {COMMENT = 0;}
/* printf("\n\n\t%s is a COMMENT\n",yytext);}*/
{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 main(int argc,char **argv)
{
if (argc > 1)
{
FILE *file;
file = fopen(argv[1],"r");
if(!file)
{
printf("could not open %s \n",argv[1]);
exit(0);
}
yyin = file;
}
yylex();
printf("\n\n");
return 0;
} int yywrap()
17 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
{
return 0;
}
Output:
Input:
$vi var.c
#include<stdio.h>
main()
int a,b;
Output:
$lex lex.l
$cc [Link].c
$./[Link] var.c
FUNCTION
main (
BLOCK BEGINS
int is a KEYWORD
a IDENTIFIER
b IDENTIFIER
BLOCK ENDS
18 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 7
Write a C program for implementing the functionalities of predictive parser for the
mini language specified in Note 1.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Grammar symbols
#define NUM 0
#define ID 1
#define PLUS 2
#define MINUS 3
#define MUL 4
#define DIV 5
#define LPAREN 6
#define RPAREN 7
#define ASSIGN 8
#define END 9
19 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
}
20 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
// Function to get the next token from the token list
char* getNextToken() {
if (tokenIndex < numTokens)
{ return tokens[tokenIndex+
+];
}
return NULL;
}
21 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
// Function to parse T
void parseT() {
printf("Parsing T -> F T'\n");
parseF();
parseTPrime();
}
22 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
parseTPrime();
} else if (match("/")) {
parseF();
parseTPrime();
}
}
}
// Function to parse F
void parseF() {
printf("Parsing F -> ( E ) | id | num\n");
char* token = getNextToken();
if (token != NULL && strcmp(token, "(") == 0) {
match("(");
parseE();
match(")");
} else if (token != NULL && isNumber(token)) {
match(token);
} else if (token != NULL && strcmp(token, "id") == 0) {
match("id");
}
}
int main() {
char input[200];
// Start parsing
printf("Parsing process:\n");
while (stackTop != -1) {
char currentSymbol = peek();
char* currentToken = getNextToken();
if (currentSymbol == 'E') {
parseE();
} else if (currentSymbol == 'E\'') {
parseEPrime();
23 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
} else if (currentSymbol == 'T') {
parseT();
} else if (currentSymbol == 'T\'') {
parseTPrime();
} else if (currentSymbol == 'F') {
parseF();
}
// Continue parsing as needed
}
return 0;
}
Output:
Enter the expression: 3 + 5 * ( 2 - 8 )
Parsing process:
Parsing E -> T E'
Parsing T -> F T'
Parsing F -> num
Parsing T' -> * F T'
Parsing F -> num
Parsing T' -> ε
Parsing E' -> + T E'
Parsing T -> F T'
Parsing F -> num
Parsing T' -> ε
Parsing E' -> ε
24 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Grammar symbols
#define NUM 0
#define ID 1
#define PLUS 2
#define MUL 3
#define LPAREN 4
#define RPAREN 5
#define EPSILON 6
#define END 7
25 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
// Function to check if a string is a number
int isNumber(char *str) {
for (int i = 0; str[i] != '\0'; i++) {
if (!isdigit(str[i]))
{ return 0;
}
}
return 1;
}
26 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
char* currentToken = getNextToken();
if (currentToken && strcmp(currentToken, expected) == 0)
{ return 1; // Match and consume
}
return 0; // No match
27 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
}
if (isalpha(currentSymbol) || isdigit(currentSymbol)) {
// If the current symbol on the stack is terminal and matches the token
if (currentSymbol == currentToken[0]) {
printf("Matched token: %s\n", currentToken);
pop();
} else {
printf("Error: Unexpected token %s\n", currentToken);
return;
}
} else if (currentSymbol == 'E') {
parseE();
} else if (currentSymbol == 'E\'') {
parseEPrime();
} else if (currentSymbol == 'T') {
parseT();
} else if (currentSymbol == 'T\'') {
parseTPrime();
} else if (currentSymbol == 'F') {
parseF();
}
}
28 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
}
29 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
match(")");
} else if (token != NULL && strcmp(token, "id") == 0) {
match("id");
} else if (token != NULL && isNumber(token)) {
match("num");
}
}
int main() {
char input[200];
return 0;
}
Output:
Enter the expression: id + num * ( id + num )
Parsing E -> T E'
Parsing T -> F T'
Parsing F -> id
Parsing T' -> ε
Parsing E' -> + T E'
Parsing T -> F T'
Parsing F -> num
Parsing T' -> * F T'
Parsing F ->
( Parsing E -> T E'
Parsing T -> F T'
Parsing F -> id
Parsing T' -> ε
Parsing E' -> + T E'
Parsing T -> F T'
Parsing F -> num
Parsing T' -> ε
Parsing E' -> ε
Parsing T' -> ε
Parsing E' -> ε
30 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
31 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
// Function to get the next token from the token list
void nextToken() {
if (tokenIndex < numTokens)
{ strcpy(currentToken, tokens[tokenIndex+
+]);
} else {
strcpy(currentToken, "EOF"); // End of input
}
}
32 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
33 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
}
}
34 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
void parse() {
nextToken(); // Start by reading the first token
parseE(); // Start parsing the expression
if (strcmp(currentToken, "EOF") != 0) {
printf("Syntax Error: Unexpected token '%s'\n", currentToken);
exit(1);
}
}
// Main function
int main() {
char input[200];
printf("Enter the expression: ");
fgets(input, sizeof(input), stdin);
printf("Parsing successful!\n");
return 0;
}
Output:
Parsing E -> T E'
Parsing T -> F T'
Parsing F -> id
Parsing T' -> ε
Parsing E' -> + T E'
Parsing T -> F T'
Parsing F -> num
Parsing T' -> * F T'
Parsing F ->
( Parsing E -> T E'
Parsing T -> F T'
Parsing F -> id
Parsing T' -> ε
Parsing E' -> - T E'
Parsing T -> F T'
Parsing F -> num
Parsing T' -> ε
Parsing E' -> ε
Parsing T' -> ε
Parsing E' -> ε
Parsing successful!
35 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 9
Write a C program to implement LALR parsing.
#include <stdio.h>
#include <stdlib.h>
#define MAX_STATES 4
#define MAX_SYMBOLS 3
#define MAX_INPUT 10
enum Symbols {
S NT_A = 3 // Non-terminal A
};
int actionTable[MAX_STATES][MAX_SYMBOLS] = {
};
36 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
int gotoTable[MAX_STATES][MAX_SYMBOLS] = {
};
int stack[MAX_STATES];
stack[++stackTop] = state;
int pop() {
return stack[stackTop--];
37 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
void printStack() {
printf("Stack: ");
printf("\n");
int inputPos = 0;
while (1) {
push(action);
inputPos++;
38 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
} else if (action < 0) { // Reduce operation (negative values)
// Pop the stack based on the length of the RHS of the rule
pop(); // Pop A
pop(); // Pop A
push(gotoState);
printf("Accept\n");
break;
printf("Syntax error!\n");
break;
int main() {
39 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
// Test input: "a a" (which should reduce to S)
int input[] = {T_A, T_A, T_END}; // Represents the string "a a" followed by the end-of-input
symbol
parse(input);
return 0;
Output:
Input :a a
Output: Shift: 0
Stack: 0 1
Shift: 0
Stack: 0 1 1
Stack: 0 2
Stack: 2
Accept
40 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 10
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
41 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
}
// Pop the remaining operators from the stack and print them
while (top != -1) {
printf("%c ", pop());
}
}
// Main function
int main() {
42 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
char expression[MAX];
return 0;
}
Output:
Enter an infix expression: a + b * c
Postfix Expression: a b c * +
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int index = 0;
char expression[100];
43 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
num = num * 10 + (expression[index] - '0');
index++;
}
return num;
}
if (op == '*') {
result *= nextFactor;
} else {
printf("Error: Division is not supported in this simple calculator.\n");
exit(1);
}
}
return result;
}
44 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
skipWhitespace();
int nextTerm = term();
if (op == '+') {
result += nextTerm;
} else {
result -= nextTerm;
}
}
return result;
}
int main() {
printf("Enter an expression (digits, +, *): ");
fgets(expression, sizeof(expression), stdin);
return 0;
}
Output:
Enter an expression (digits, +, *): 3 + 5 * 2
The result of the expression is: 13
45 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 11
Convert the BNF rules into Yacc form and write code to generate abstract syntax tree for
the mini language specified in Note 1.
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
47 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
ASTNode* new_op_node(int op_type, ASTNode* left, ASTNode* right)
{ ASTNode* node = (ASTNode*)malloc(sizeof(ASTNode));
node->type = op_type;
node->[Link] = left;
node->[Link] = right;
return node;
}
%}
%union
{ int
num;
char* id;
ASTNode* ast;
}
%%
program:
48 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
49 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
expression { printf("AST for expression: "); print_ast($1); printf("\n"); }
;
expression:
expression '+' term { $$ = new_op_node(AST_ADD, $1, $3); }
| expression '*' term { $$ = new_op_node(AST_MUL, $1, $3); }
| term { $$ = $1; }
;
term:
factor { $$ = $1; }
| factor '*' term { $$ = new_op_node(AST_MUL, $1, $3); }
| factor '/' term { $$ = new_op_node(AST_MUL, $1, $3); } // Assuming no division
;
factor:
'(' expression ')' { $$ = $2; }
| NUMBER { $$ = new_num_node($1); }
| IDENTIFIER { $$ = new_id_node($1); }
;
%%
int main() {
printf("Enter an expression: ");
yyparse();
return 0;
}
Output:
3+5*x
AST for expression: (3 + (5 * x))
50 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
Experiment – 12
Write a C program to generate machine code from abstract syntax tree generated by the
parser. The instruction set specified in Note 2 may be considered as the target code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
52 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
ASTNode* node =
(ASTNode*)malloc(sizeof(ASTNode)); node->type =
op_type;
node->[Link] = left;
node->[Link] = right;
return node;
}
// Case 3: Addition
else if (node->type == AST_ADD)
{ generate_machine_code(node->[Link],
reg_counter); int left_reg = (*reg_counter) - 1;
generate_machine_code(node->[Link], reg_counter);
int right_reg = (*reg_counter) - 1;
printf("ADD R%d, R%d\n", left_reg, right_reg);
}
// Case 4: Multiplication
else if (node->type == AST_MUL)
{ generate_machine_code(node->[Link],
reg_counter); int left_reg = (*reg_counter) - 1;
generate_machine_code(node->[Link], reg_counter);
int right_reg = (*reg_counter) - 1;
printf("MUL R%d, R%d\n", left_reg, right_reg);
}
}
int main() {
// Example AST: 3 + 5 * x
// Construct AST for (3 + (5 * x))
ASTNode* x = new_id_node("x");
53 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
54 | P a g e
Compiler Design Lab Ritik
BTCS604-18 2224515
ASTNode* five = new_num_node(5);
ASTNode* three = new_num_node(3);
ASTNode* mul = new_op_node(AST_MUL, five, x);
ASTNode* add = new_op_node(AST_ADD, three, mul);
return 0;
}
Output:
Input: 3 + 5 * x
55 | P a g e