Professional Documents
Culture Documents
Compiler Record
Compiler Record
Compiler Record
AIM:
To write a program that counts the number of characters, words and sentences in a file.
PROCEDURE:
PROGRAM CODE:
#include<iostream>
#include<fstream>
#include<string.h>
#include<cstdlib>
using namespace std;
int main()
{
int c=0,w=0,l=0;
FILE *fr;
char fname[20],ch;
cout<<"\n Enter Source File Name : ";
gets(fname);
fr=fopen(fname,"r");
if(fr==NULL)
{
cout<<"\n Invalid File Name. \n No such File or Directory ";
exit(0);
}
ch=fgetc(fr);
while(ch!=EOF)
{
if(ch!=' ' && ch!='\n')
c++;
if(ch==' ')
w++;
if(ch=='\n')
{
l++;
w++;
}
ch=fgetc(fr);
}
fclose(fr);
cout<<" -------------------------------------";
cout<<"\n Total No. of Characters : "<<c;
cout<<"\n Total No. of Words : "<<w;
cout<<"\n Total No. of Lines : "<<l;
return 0;
}
SAMPLE INPUT:
SAMPLE OUTPUT:
RESULT:
Thus, the above code to count the number of words, lines and characters in a file is executed successfully.
Exp No: 02
Date: COUNT THE NUMBER OF VOWELS AND CONSONANTS IN A FILE
AIM:
To write a program that counts the number of vowels and consonants in a file.
PROCEDURE:
PROGRAM CODE:
content = file.read()
vowel = 0
consonants = 0
print(content)
if line in "aeiouAEIOU":
vowel += 1
elif line.isalpha():
consonants += 1
print(f"Vowels: {vowel}")
print(f"Consonants: {consonants}")
SAMPLE INPUT:
SAMPLE OUTPUT:
RESULT:
Thus, the above code to count the number of vowels and consonants in a file is executed successfully.
Exp No: 03
Date: PERFORM STRING OPERATIONS
AIM:
PROCEDURE:
8. Count Vowels:
Define a list of vowel characters.
Iterate through each character in strings x and y.
If a character is present in the vowel list, increment the respective vowel counter.
Print the counts of vowels.
9. Vowel Presence Check:
Define a list of vowel characters.
Iterate through each character in strings x and y.
If a character matches a vowel, print "Vowels is present" for the corresponding string.
PROGRAM CODE:
# 1. Concatenation
str1 = "Hello"
str2 = "World"
result = ""
result += char
result += char
print("Concatenation:", result)
# 2. Length Calculation
length = 0
length += 1
print("Length:", length)
# 3. Substring
substring = ""
substring += str1[i]
print("Substring:", substring)
# 4. String Copy
copy = ""
copy += char
print("Copy:", copy)
# 5. Reverse String
reverse = ""
reverse += str1[i]
print("Reverse:", reverse)
# 6. String Comparison
str3 = "Hello"
is_equal = True
for i in range(len(str1)):
if str1[i] != str3[i]:
is_equal = False
break
# 7. Uppercase Conversion
uppercase = ""
else:
uppercase += char
# 8. Lowercase Conversion
lowercase = ""
else:
lowercase += char
count = 0
if char == 'l':
count += 1
is_palindrome = True
is_palindrome = False
break
RESULT:
Thus, we have successfully executed the ten string operations without using Built-In functions in Python.
Exp No: 04
Date: TOKEN SEPARATION USING HIGH LEVEL LANGUAGE
AIM:
To write a program for token separation using high level language like python and java.
PROCEDURE:
PROGRAM CODE:
import re
def tokenize_text(text):
# Regular expression pattern to match whitespace and punctuation
pattern = r'\s+|[,.;!?"]'
return tokens
input_text = " S.I. = (P × R × T)/100"
Output :
Tokenization using Java:
Program:
import java.util.StringTokenizer;
public class TokenizationExample
{
public static void main(String[] args)
{
String input = "A bird in the hand is worth two in the bush.";
RESULT:
Thus, we executed a program for token separation using high level language like python and java.
Exp No: 05
Date: STUDY OF LEX TOOL
Introduction:
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.
Firstly lexical analyzer creates a program lex.1 in the Lex language. Then Lex compiler runs the lex.1
program and produces a C program lex.yy.c.
Finally C compiler runs the lex.yy.c program and produces an object program a.out.
a.out is lexical analyzer that transforms an input stream into a sequence of tokens.
A Lex program is separated into three sections by %% delimiters. The formal of Lex source is as follows:
1. { definitions }
2. %%
3. { rules }
4. %%
5. { user subroutines }
Where pi describes the regular expression and action1 describes the actions what action the
lexical analyzer should take when pattern pi matches a lexeme.
To run a lex program
1) Create a file, usually named lex.l, containing regular expressions and associated actions.
2) Define rules using the format: regex { action }.
3) Run lex tool using: lex lex.l
4) The Lex tool generates a C program named lex.yy.c.
5) Create a C program that includes lex.yy.c and provides the necessary code for the rest of
the compiler or interpreter.
6) Compile the C program: gcc lex.yy.c -o lexer -ll
7) Execute the generated lexer: ./lexer input_file.txt
RESULT:
Hence the study of LEX tool has been done successfully.
Exp No: 06 a
Date: COUNT OF POSITIVE AND NEGATIVE NUMBERS
AIM:
To write a Lex program for counting the positive and negative numbers.
PROCEDURE:
PROGRAM CODE:
%{
%}
%%
^[-][0-9]+ {negative_no++;
[0-9]+ {positive_no++;
%%
int yywrap(){}
int main()
yylex();
positive_no, negative_no);
return 0;
}
Output:
RESULT:
Thus, we executed a Lex program for counting the positive and negative numbers.
Exp No: 06 b
Date: COUNT OF NUMBER OF WORDS, CHARACTERS AND LINES
AIM:
To write a Lex program for counting number of words, characters and lines.
PROCEDURE:
PROGRAM CODE:
%{
#include<stdio.h>
int lc=0,sc=0,tc=0,ch=0,wc=0;
%%
%%
int main(){
yylex();
return 0;
}
Output:
RESULT:
Thus, we executed a Lex program for counting number of words, characters and lines.
Exp No: 06 c
Date: COUNT OF VOWELS AND CONSONANTS
AIM:
PROCEDURE:
PROGRAM CODE:
%{
int vow_count=0;
%}
%%
[aeiouAEIOU] {vow_count++;}
[a-zA-Z] {const_count++;}
%%
int yywrap(){}
int main()
yylex();
return 0;
}
Output:
RESULT:
AIM:
PROCEDURE:
3. Declare a variable to store the input number and get it from the user.
PROGRAM CODE:
%{
#include<stdio.h>
int i;
%}
%%
[0-9]+ {i=atoi(yytext);
if(i%2==0)
printf("Even");
else
printf("Odd");}
%%
int yywrap(){}
int main()
yylex();
return 0;
}
Output:
RESULT:
AIM:
PROCEDURE:
PROGRAM CODE:
%{
#include<stdio.h>
#include<stdlib.h>
int flag=0;
%}
%%
%%
int yywrap(){}
int main() {
yylex();
if(flag==1)
printf("Valid \n");
else
}
Output:
RESULT:
AIM:
To write a Lex program for validation of dates and to identify whether they are valid or not.
PROCEDURE:
PROGRAM CODE:
%{
#include<stdio.h>
int valid=0;
%}
%%
([0-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([1-2][0-9][0-9][0-9]) {valid=1;}
%%
int main()
yyin=fopen("input.txt","r");
yylex();
int yywrap()
return 1;
}
OUTPUT:
RESULT:
AIM:
PROCEDURE:
1. This program will match any string that starts with the letter 'a'.
2. If the string matches this pattern, the program will print "String starts with 'a'."
3. Otherwise, it will print "String does not start with 'a'."
PROGRAM CODE:
%%
^a {
.{
%%
int main() {
yylex();
return 0;}
Output:
RESULT:
Thus, we executed a Lex program to determine if string starts with 'a' or not.
Exp No: 06 h
Date: MOBILE NUMBER VALIDATION
AIM:
PROCEDURE:
Specify the pattern that a valid mobile number should follow. For example, it could be a 10-digit
number that starts with '7', '8', or '9'.
2. Create Rules:
Set up rules in your Lex program to check if the input matches the validation pattern. If it does, label
it as a valid mobile number; otherwise, label it as invalid.
Compile your Lex program, run it, and provide mobile numbers for validation. The program will tell
you if each number is valid or not based on the rules you defined.
PROGRAM CODE:
%{
%}
%option noyywrap
%%
%%
int main()
yylex();
printf("\n");
return 0;
}
OUTPUT:
RESULT:
Hence, we have successfully executed a Lex program for mobile number validation.
Exp No: 06 i
Date: LEXICAL ANALYSER (Token Separation) USING LEX
AIM:
PROCEDURE:
1. The Lex program for tokenizing C code will recognize the following tokens:
2. Floating point numbers: Strings of digits followed by a period followed by more digits.
3. Datatypes: The keywords int, float, char, double, and void.
4. Integer numbers: Strings of digits.
5. Functions: Strings of alphanumeric characters followed by parentheses.
6. Identifiers: Strings of alphanumeric characters.
7. Operators: The symbols +, -, *, and /.
8. Delimiters: The semicolon ;.
9. Separators: The comma ,.
10. Preprocessor directives: Strings that start with the hash symbol # followed by alphanumeric
characters and periods.
The program will read the input from the file test.c and tokenize it. It will then print the tokens to the
standard output, along with their type.
PROGRAM CODE:
%{
%}
%%
; printf("%s is an delimiter\n",yytext);
, printf("%s is a separator\n",yytext);
%%
int yywrap(void)
return 1;
}
int main()
yylex();
return 0;
Test.c:
OUTPUT:
RESULT:
YACC (Yet Another Compiler Compiler)," serves as a powerful grammar parser and generator. In essence, it
functions as a tool that takes in a grammar specification and transforms it into executable code capable of
meticulously structuring input tokens into a coherent syntactic tree, aligning seamlessly with the
prescribed grammar rules.
Stephen C. Johnson developed YACC in compiler design in the early 1970s. Initially, the YACC was written in
the B programming language and was soon rewritten in C. It was originally designed for being
complemented by Lex.
In addition to that, YACC was also rewritten in OCaml, Ratfor, ML, ADA, Pascal, Java < Python, Ruby and Go.
The input of YACC in compiler design is the rule or grammar, and the output is a C program.
/* definitions */
....
%%
/* rules */
....
%%
/* auxiliary routines */
....
Definitions: these include the header files and any token information used in the syntax. These are located
at the top of the input file. Here, the tokens are defined using a modulus sign. In the YACC, numbers are
automatically assigned for tokens.
%token ID
{% #include <stdio.h> %}
Rules: The rules are defined between %% and %%. These rules define the actions for when the token is
scanned and are executed when a token matches the grammar.
Auxiliary Routines: Auxiliary routines contain the function required in the rules section. This Auxiliary
section includes the main() function, where the yyparse() function is always called.
This yyparse() function plays the role of reading the token, performing actions and then returning to the
main() after the execution or in the case of an error.
The YACC is responsible for converting these sections into subroutines which will examine the inputs. This
process is made to work by a call to a low-level scanner and is named Parsing
Workings of YACC:
YACC in compiler design is set to work in C programming language along with its parser generator.
RESULT:
AIM:
PROCEDURE:
1. Lex (pp1.l) :
Define token names for 'Zero' and 'One'.
Create a set of regular expressions and corresponding actions to recognize 0 and 1 as
tokens, setting 'yylval' accordingly. Ignore whitespace characters.
If none of the specified patterns match, return the ASCII value of the first character in
'yytext'.
2. Yacc (pp1.y) :
Declare the tokens and define the grammar rules for recognizing sequences of 'Zero' and
'One'.
In the 'main' function, call 'yyparse' to start parsing the input. If the parsing is successful,
print "Accepted." If there's an error during parsing, print "Not Accepted" and exit the
program.
3. Main Function:
In the main function, call yyparse to initiate the parsing process.
If the input string conforms to the defined grammar rules, the program prints
"Accepted."
If there's a syntax error or if the input doesn't match the grammar, the yyerror function
is called, which prints "Not Accepted.
PROGRAM CODE:
Command: vi pp1.l
pp1.l
%{
#include<stdio.h>
#include "y.tab.h"
%}
%%
1 {yylval=1;return One;}
return yytext[0];
%%
pp1.y
%{
#include<stdio.h>
#include<stdlib.h>
#include "y.tab.h"
int yylex();
%}
%%
stmt:S;
S:SA | A;
%%
int main()
{yyparse(); printf("Accepted\t");
exit(0);}
(printf("Not Accepted\n");
exit(0);
OUTPUT:
RESULT:
AIM:
PROCEDURE:
3. Main Function:
PROGRAM CODE:
%{
#include "y.tab.h"
%}
%%
[ \t] ;
. { yyerror("Invalid character"); }
%%
int yywrap() {
return 1;
}
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token NUM
%%
calclist: /* empty */
exp: NUM
if ($3 == 0) {
yyerror("Division by zero");
exit(1);
} else {
$$ = $1 / $3;
%%
int main() {
yyparse();
return 0;
./calculator
INPUT:
OUTPUT:
RESULT:
Thus, we have successfully executed the calculator program using lex and yacc.
Exp No: 10
Date: THREE ADDRESS CODE GENERATION USING LEX AND YACC
AIM:
PROCEDURE:
Generating Three Address Code using Lex and Yacc involves creating a parser that recognizes the input
language and generates the corresponding three-address code.
PROGRAM CODE:
three_address.l:
%{
#include "y.tab.h"
%}
DIGIT [0-9]
ID [a-zA-Z][a-zA-Z0-9]*
%%
[ \t\n] ;
. { yyerror("Invalid character"); }
%%
int yywrap() {
return 1;
three_address.y:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int yylex();
int temp_count = 1;
%}
%union {
int num;
char *id;}
%%
program: stmt_list
stmt_list:
statement:
free($3);
}
| term { $$ = $1; }
| factor { $$ = $1; }
| IDENTIFIER { $$ = strdup(yytext); }
%%
int main() {
yyparse();
return 0;}
char temp[10];
return strdup(temp);
}
commands to generate the Lex and Yacc files and compile the program:
./three_address
INPUT:
OUTPUT:
RESULT:
Hence the Three Address Code Generation using LEX and YACC was implemented successfully.
Exp No: 11
Date: CODE OPTIMIZER
AIM:
To develop a C program to optimize a given snip of code and get the optimized code as output
PROCEDURE:
PROGRAM CODE:
#include<stdio.h>
#include<string.h>
struct op
char l;
char r[20];
op[10], pr[10];
int main ()
int a, i, k, j, n, z = 0, m, q;
char temp, t;
char *tem;
scanf (" %c", &op[i].l); // space added before %c to consume the newline character
temp = op[i].l;
if (p)
pr[z].l = op[i].l;
z++;
z++;
printf ("\nAfter Dead Code Elimination\n");
tem = pr[m].r;
if (p)
t = pr[j].l;
pr[j].l = pr[m].l;
if (l)
a = l - pr[i].r;
pr[i].r[a] = pr[m].l;
pr[i].l = '\0';
if (pr[i].l != '\0')
return 0;}
INPUT:
OUTPUT:
RESULT:
Thus, a C program for code optimization has been developed and executed successfully.
Exp No: 12
Date: CODE GENERATION
AIM:
To develop a C program to generate assembly code from three address code using C language.
PROCEDURE:
1.Open any C compiler to write the code for code generation in C language.
4. Declare variables such as n, i, j, and the character array a to store intermediate codes.
6. Use a nested loop to gather the 3-address intermediate codes. The outer loop handles each
code, and the inner loop reads each character of the code.
7. Write the main method to get the input from the user and generate code, assemble them in
proper order.
8. Display the finally generated assembly language code. Compile the entire code in C compiler
PROGRAM CODE:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
int n,i,j;
char a[50][50];
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%c",&a[i][j]);}
for(i=0;i<n;i++)
printf("\nMov %c,R%d",a[i][3],i);
if(a[i][4]=='-')
printf("\nSub %c,R%d",a[i][5],i);}
if(a[i][4]=='+')
printf("\nAdd %c,R%d",a[i][5],i);}
if(a[i][4]=='*')
printf("\nMul %c,R%d",a[i][5],i);}
if(a[i][4]=='/')
printf("\nDiv %c,R%d",a[i][5],i);}
printf("\n");
getch();
INPUT:
OUTPUT:
RESULT:
Thus, a C program for code generation has been developed and executed successfully