Compiler Design Lab
Compiler Design Lab
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum {
IDENTIFIER,
KEYWORD,
OPERATOR,
INTEGER_LITERAL,
FLOAT_LITERAL,
STRING_LITERAL,
COMMENT,
NEWLINE,
OTHER
} TokenType;
typedef struct {
TokenType type;
char lexeme[100];
} Token;
Token token;
memset(&token, 0, sizeof(Token));
while (isspace(*program)) {
program++;
}
// Identifier or keyword
size_t lexeme_len = 0;
token.lexeme[lexeme_len++] = *program++;
token.lexeme[lexeme_len] = '\0';
if (strcmp(token.lexeme, "if") == 0 ||
strcmp(token.lexeme, "else") == 0 ||
strcmp(token.lexeme, "while") == 0 ||
strcmp(token.lexeme, "int") == 0 ||
strcmp(token.lexeme, "float") == 0 ||
strcmp(token.lexeme, "char") == 0) {
token.type = KEYWORD;
} else {
token.type = IDENTIFIER;
} else if (isdigit(*program)) {
size_t lexeme_len = 0;
token.lexeme[lexeme_len++] = *program++;
token.lexeme[lexeme_len] = '\0';
// Check if it's a float literal
token.type = FLOAT_LITERAL;
} else {
token.type = INTEGER_LITERAL;
token.lexeme[0] = *program++;
size_t lexeme_len = 1;
token.lexeme[lexeme_len++] = *program++;
if (*program == token.lexeme[0]) {
token.lexeme[lexeme_len++] = *program++;
token.lexeme[lexeme_len] = '\0';
token.type = STRING_LITERAL;
} else {
token.type = OTHER;
// Operator
token.lexeme[0] = *program++;
token.lexeme[1] = '\0';
token.type = OPERATOR;
// Comment
size_t lexeme_len = 0;
while (*program != '\0' && *program != '\n') {
token.lexeme[lexeme_len++] = *program++;
token.lexeme[lexeme_len] = '\0';
token.type = COMMENT;
// Newline
token.lexeme[0] = *program++;
token.lexeme[1] = '\0';
token.type = NEWLINE;
} else {
// Other
token.lexeme[0] = *program++;
token.lexeme[1] = '\0';
token.type = OTHER;
return token;
int main() {
"}\n";
Token token;
printf("Token\t\tLexeme\n");
current += strlen(token.lexeme);
return 0;
Output:
Token Lexeme
KEYWORD int
IDENTIFIER main
OPERATOR (
OPERATOR )
OPERATOR {
NEWLINE \n
KEYWORD int
IDENTIFIER x
OPERATOR =
INTEGER_LITERAL 42
OPERATOR ;
NEWLINE \n
IDENTIFIER printf
OPERATOR (
OPERATOR )
OPERATOR ;
NEWLINE \n
KEYWORD return
INTEGER_LITERAL 0
OPERATOR ;
NEWLINE \n
OPERATOR }
NEWLINE \n
Program:
Certainly! Here's an example of a Lex program that implements a simple lexical analyzer:
```lex
%{
#include <stdio.h>
%}
%%
%%
int main() {
yylex();
return 0;
```
2. Open a terminal and navigate to the directory containing the `lexer.l` file.
3. Run the following command to generate the C code from the Lex file:
```
lex lexer.l
```
This command will generate a file named `lex.yy.c` that contains the C code for the lexical analyzer.
```
```
This command will generate an executable named `lexer` (or any name specified after `-o`).
```
./lexer
```
6. Enter the input string when prompted, and the program will analyze the input string and print the
corresponding tokens.
```
$ ./lexer
Enter the input string: 123 + abc * 456
INTEGER: 123
OPERATOR: +
IDENTIFIER: abc
OPERATOR: *
INTEGER: 456
```
In this example, the input string "123 + abc * 456" is entered. The lexical analyzer identifies the
tokens as INTEGER, OPERATOR, IDENTIFIER, OPERATOR, and INTEGER, respectively, and prints them
accordingly.
Program:
#include <stdio.h>
#include <stdlib.h>
#include "lex.yy.c"
int main() {
yylex();
printf("Token\t\tLexeme\n");
while (yylex()) {
return 0;
}
Output:
To provide the complete output for the above program, I would need the Lex file ( .l )
that defines the regular expressions and actions for each token. Since you haven't
provided a specific Lex file, I can't generate the output. However, I can guide you on
how to create a Lex file for your specific token validation requirements.
1. Create a new file called lexer.l (or any name of your choice) and open it in a
text editor.
2. Define the regular expressions and corresponding actions for each token you
want to validate. For example:
%{
#include <stdio.h>
%}
%%
%%
int main() {
yylex();
return 0;
In this example, we define three tokens: NUMBER for numeric literals, IDENTIFIER for
alphanumeric identifiers, and OPERATOR for arithmetic operators (+ , - , * , / ).
Enter the input string when prompted, and the program will output the tokens and their
corresponding lexemes.
4. Write a C program to implement the Brute force technique of Top down Parsing.
#include<stdio.h>
#include<string.h>
char input[10];
int i,error;
void E();
void T();
void Eprime();
void Tprime();
void F();
int main()
i=0;
error=0;
gets(input);
E();
printf("\nAccepted..!!!\n");
else
printf("\nRejected..!!!\n");
return 0;
}
void E()
T();
Eprime();
void Eprime()
if(input[i]=='+')
i++;
T();
Eprime();
void T()
F();
Tprime();
void Tprime()
if(input[i]=='*')
i++;
F();
Tprime();
void F()
{
if(input[i]=='(')
i++;
E();
if(input[i]==')')
i++;
else
error=1;
else if(isalnum(input[i]))
i++;
else
error=1;
Output:
Program
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
// Function prototypes
void expression();
void term();
void factor();
void error();
// Global variables
char token;
char input[100];
int index = 0;
void nextToken() {
token = input[index++];
if (token == expectedToken) {
nextToken();
} else {
error();
void parse() {
nextToken();
expression();
if (token == '\0') {
printf("Parsing successful!\n");
} else {
error();
}
// Grammar rules
void expression() {
term();
nextToken();
term();
void term() {
factor();
nextToken();
factor();
void factor() {
if (isdigit(token)) {
nextToken();
nextToken();
expression();
match(')');
} else {
error();
void error() {
printf("Error: Invalid expression!\n");
exit(1);
int main() {
parse();
return 0;
output
Parsing successful!
Output2
6.Write C program to compute the First and Follow Sets for the given Grammar
Program:
int count, n = 0;
int kay;
char done[count];
int ptr = -1;
if (xxx == 1)
continue;
// Function call
findfirst(c, 0, 0);
ptr += 1;
if (first[i] == calc_first[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
printf("%c, ", first[i]);
calc_first[point1][point2++] = first[i];
}
}
printf("}\n");
jm = n;
point1++;
}
printf("\n");
printf("-----------------------------------------------\n\n");
char donee[count];
ptr = -1;
// Checking if Follow of ck
// has already been calculated
for(kay = 0; kay <= ptr; kay++)
if(ck == donee[kay])
xxx = 1;
if (xxx == 1)
continue;
land += 1;
// Function call
follow(ck);
ptr += 1;
void follow(char c)
{
int i, j;
Exp 7:
#include<stdio.h>
#include<string.h>
int main()
char gram[20],part1[20],part2[20],modifiedGram[20],newGram[20],tempGram[20];
int i,j=0,k=0,l=0,pos;
gets(gram);
for(i=0;gram[i]!='|';i++,j++)
part1[j]=gram[i];
part1[j]='\0';
for(j=++i,i=0;gram[j]!='\0';j++,i++)
part2[i]=gram[j];
part2[i]='\0';
for(i=0;i<strlen(part1)||i<strlen(part2);i++){
if(part1[i]==part2[i]){
modifiedGram[k]=part1[i];
k++;
pos=i+1;
for(i=pos,j=0;part1[i]!='\0';i++,j++){
newGram[j]=part1[i];
newGram[j++]='|';
for(i=pos;part2[i]!='\0';i++,j++){
newGram[j]=part2[i];
modifiedGram[k]='X';
modifiedGram[++k]='\0';
newGram[j]='\0';
printf(" A->%s",modifiedGram);
printf("\n X->%s\n",newGram);
Output:
:
8.Write a C program to check the validity of input string using Predictive Parser
#include <stdio.h>
#include <string.h>
int numr(char c)
{
switch (c)
{
case 'S':
return 0;
case 'A':
return 1;
case 'B':
return 2;
case 'C':
return 3;
case 'a':
return 0;
case 'b':
return 1;
case 'c':
return 2;
case 'd':
return 3;
case '$':
return 4;
}
return (2);
}
int main()
{
int i, j, k;
fflush(stdin);
strcpy(table[0][1], "a");
strcpy(table[0][2], "b");
strcpy(table[0][3], "c");
strcpy(table[0][4], "d");
strcpy(table[0][5], "$");
strcpy(table[1][0], "S");
strcpy(table[2][0], "A");
strcpy(table[3][0], "B");
strcpy(table[4][0], "C");
printf("\n--------------------------------------------------------\n");
Output:
9. Write a C program for implementation of LR parsing algorithm to accept a given input string
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct {
char lhs;
char rhs[10];
} Production;
Production productions[] = {
{'S', "E"},
{'E', "E+T"},
{'E', "T"},
{'T', "T*F"},
{'T', "F"},
{'F', "(E)"},
{'F', "id"}
};
char actionTable[7][5][10] = {
};
int gotoTable[7][3] = {
{1, 2, 3},
{-1, 9, 3}
};
char stack[MAX_STACK_SIZE];
char input[100];
int inputIndex = 0;
void push(char c) {
stack[++top] = c;
char pop() {
return stack[top--];
pop();
push(lhs);
push(newState + '0');
}
bool parseInputString() {
push('0');
while (true) {
if (lookahead == '\0') {
return true;
char action[10];
if (action[0] == '\0') {
return false;
if (action[0] == 'S') {
push(lookahead);
push(newState + '0');
inputIndex++;
reduce(productionIndex);
return true;
int main() {
if (result) {
} else {
return 0;
Output:
10. Write a C program for implementation of a Shift Reduce Parser using Stack Data Structure to
accept a given input string of a given grammar
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char productions[3][10] = {
"E->E+T",
"E->T",
"T->T*F"
};
int action_table[6][3] = {
};
int goto_table[6][2] = {
};
int stack[MAX_STACK_SIZE];
char input[MAX_INPUT_SIZE];
printf("Stack overflow\n");
exit(1);
stack[++top] = symbol;
int pop() {
if (top < 0) {
printf("Stack underflow\n");
exit(1);
return stack[top--];
void parse_input() {
push(0);
input[i] == '*' ? 1 : 2;
state = stack[top];
action = action_table[state][symbol];
// Shift the input symbol onto the stack
if (action == 2) {
push(symbol + 3);
push(next_state);
i++;
else if (action == 3) {
action = pop();
next_state = stack[top];
switch (action) {
case 0:
push(3);
break;
case 1:
push(1);
break;
case 2:
push(5);
break;
push(goto_table[next_state][action]);
else {
exit(1);
}
// Accept the input string if the stack contains only the starting symbol
} else {
int main() {
scanf("%s", input);
parse_input();
return 0;
Output:
11. Simulate the calculator using LEX and YACC tool
Program:
%{
#include "calculator.tab.h"
%}
%%
\n return '\n';
. return yytext[0];
%%
int yywrap() {
return 1;
%{
#include <stdio.h>
%}
%token NUMBER
%%
;
statement: expr { $$ = $1; }
| /* Empty statement */
| term { $$ = $1; }
| factor { $$ = $1; }
%%
int main() {
yyparse();
return 0;
return 1;
bison -d calculator.y
1.
2. This will generate lex.yy.c, calculator.tab.c , and calculator.tab.h files.
3. Compile the generated code with the following command:
2+3*4
Result: 14
10 / (2 + 3)
Result: 2
Program:
%{
#include <stdio.h>
%}
%token NUMBER
%token IDENTIFIER
%token IF
%token ELSE
%token WHILE
%token PRINT
%left '+' '-'
%%
program: statement
| program statement
statement: assignment
| if_statement
| while_loop
| print_statement
| IF '(' expression ')' '{' program '}' ELSE '{' program '}'
| NUMBER
| IDENTIFIER
%%
int main() {
yyparse();
return 0;
return 1;
Output:
| NUMBER { $$ = $1; }
| IDENTIFIER { $$ = lookup_variable($1); }
Similarly, you can add semantic actions to other production rules (e.g., assignment ,
if_statement, while_loop , print_statement) to define the desired behavior or actions.
13. Write a C program for generating the three address code of a given expression/statement
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char op;
char arg1[10];
char arg2[10];
char result[10];
} ThreeAddressCode;
ThreeAddressCode code[MAX_EXPR_LENGTH];
int codeIndex = 0;
int tempIndex = 1;
int labelIndex = 1;
char* newTemp() {
return temp;
char* newLabel() {
void generateCode(char op, const char* arg1, const char* arg2, const char* result) {
code[codeIndex].op = op;
strcpy(code[codeIndex].arg1, arg1);
strcpy(code[codeIndex].arg2, arg2);
strcpy(code[codeIndex].result, result);
codeIndex++;
void printCode() {
char operandStack[MAX_EXPR_LENGTH];
if (isdigit(currentChar)) {
operandStack[++top] = *temp;
operandStack[++top] = *result;
if (top != 0) {
exit(1);
int main() {
char expression[MAX_EXPR_LENGTH];
generateExpressionCode(expression);
printCode();
return 0;
Output:
14. Write a C program for implementation of a Code Generation Algorithm of a given
expression/statement.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char op;
char arg1[10];
char arg2[10];
char result[10];
} ThreeAddressCode;
ThreeAddressCode code[MAX_EXPR_LENGTH];
int codeIndex = 0;
int tempIndex = 1;
char* newTemp() {
return temp;
void generateCode(char op, const char* arg1, const char* arg2, const char* result) {
code[codeIndex].op = op;
strcpy(code[codeIndex].arg1, arg1);
strcpy(code[codeIndex].arg2, arg2);
strcpy(code[codeIndex].result, result);
codeIndex++;
void printCode() {
printf("Generated Code:\n");
char operandStack[MAX_EXPR_LENGTH];
if (isdigit(currentChar)) {
operandStack[++top] = *temp;
operandStack[++top] = *result;
if (top != 0) {
exit(1);
int main() {
char expression[MAX_EXPR_LENGTH];
generateExpressionCode(expression);
printCode();
return 0;
Output: