This is my lex code to convert possibly nested for and do while loops into while loops. (Other control flows like if
or switch
are not supported.) The input program must be in a file called input.c
and the output will be saved in a file called out.c
. Please review the code and give suggestions regarding improving it.
%{
#include <iostream>
#include<vector>
#include<tuple>
using namespace std;
string foreword,declaration,condition1,condition2;
string loopBody = "";
vector<string> change;
vector<tuple<int,int>> stack;
int ind=0;
int changeNum = -1;
int braces=0;
void forEnd();
%}
%x FOR DOWHILE dec condtn1 condtn2 chng text oneLineFor semicolon forString doWhileString normalString
%%
<DOWHILE>\" {
ECHO;
loopBody += yytext;
BEGIN doWhileString;
}
<text>\" {
ECHO;
loopBody += yytext;
BEGIN forString;
}
<doWhileString>\" {
ECHO;
loopBody += yytext;
BEGIN DOWHILE;
}
<forString>\" {
ECHO;
loopBody += yytext;
BEGIN text;
}
<doWhileString>. {
ECHO;
loopBody += yytext;
}
<forString>. {
ECHO;
loopBody += yytext;
}
do[ ]*\{ {
stack.push_back(make_tuple(0,ind));
BEGIN DOWHILE;
}
<text>do[ ]*\{ {
stack.push_back(make_tuple(0,ind));
ind = loopBody.size();
BEGIN DOWHILE;
}
<DOWHILE>do[ ]*\{ {
stack.push_back(make_tuple(0,ind));
ind = loopBody.size();
BEGIN DOWHILE;
}
<DOWHILE>\} {
if(braces){
ECHO;
braces--;
}
}
<DOWHILE>for {
stack.push_back(make_tuple(2,ind));
ind = loopBody.size();
BEGIN FOR;
changeNum++;
}
<DOWHILE>while[ ]*\( {
ECHO;
BEGIN condtn2;
}
<condtn2>[^\)]*\) {
condition2 = yytext;
condition2 = condition2.substr(0,condition2.size()-1);
fprintf(yyout,"%s{\n",yytext);
BEGIN semicolon;
}
<semicolon>; {
fprintf(yyout,"%s}",loopBody.substr(ind).c_str());
if(stack.size()==1){
BEGIN 0;
loopBody = "";
} else{
loopBody += "while("+condition2+"){" + loopBody.substr(ind) + "}";
ind = get<1>(stack.back());
stack.pop_back();
int s = get<0>(stack.back());
if(s==0) {
BEGIN DOWHILE;
} else if (s==1){
BEGIN text;
} else if(s==2){
forEnd();
}
}
}
<text>for {
stack.push_back(make_tuple(2,ind));
ind = loopBody.size();
BEGIN FOR;
changeNum++;
}
for {
stack.push_back(make_tuple(2,ind));
ind = loopBody.size();
changeNum++;
BEGIN FOR;
}
<FOR>[ ]*\( {
foreword=yytext;
BEGIN dec;
}
<dec>[^\;]*\; {
declaration=yytext;
BEGIN condtn1;
}
<condtn1>[^\;]*\; {
condition1=yytext;
condition1 = condition1.substr(0,condition1.size()-1);
BEGIN chng;
}
<chng>[^\)]*\) {
change.push_back(yytext);
change[changeNum] = change[changeNum].substr(0, change[changeNum].size()-1);
fprintf(yyout, "%s\n", declaration.c_str());
fprintf(yyout, "while%s%s){", foreword.c_str(), condition1.c_str());
BEGIN oneLineFor;
}
<oneLineFor>\{ {
get<0>(stack.back()) = 1;
BEGIN text;
}
<oneLineFor>for {
stack.push_back(make_tuple(2,ind));
ind = loopBody.size();
BEGIN FOR;
changeNum++;
}
<oneLineFor>do[ ]*\{ {
stack.push_back(make_tuple(0,ind));
ind = loopBody.size();
BEGIN DOWHILE;
}
<oneLineFor>; {
ECHO;
forEnd();
}
<oneLineFor>\n {
ECHO;
loopBody+=yytext;
}
<oneLineFor>. {
ECHO;
loopBody+=yytext;
}
<text>\{ {
ECHO;
braces++;
}
<text>\} {
if(braces){
ECHO;
braces--;
}else{
forEnd();
}
}
<text>\n {
loopBody+=yytext;
ECHO;
}
<DOWHILE>\n {
loopBody+=yytext;
ECHO;
}
<text>. {
loopBody+=yytext;
ECHO;
}
<DOWHILE>. {
loopBody+=yytext;
ECHO;
}
\" {
ECHO;
BEGIN normalString;
}
<normalString>\" {
ECHO;
BEGIN 0;
}
<normalString>. {
ECHO;
}
. {ECHO;}
%%
int yywrap(){return 1;}
void forEnd(){
string tempChange = change[changeNum];
change.pop_back();
changeNum--;
fprintf(yyout,"%s;}",tempChange.c_str());
if(stack.size()==1){
BEGIN 0;
} else{
loopBody = loopBody.substr(0,ind) + declaration + "\nwhile(" + condition1 + "){" + loopBody.substr(ind) + tempChange + ";}";
ind = get<1>(stack.back());
stack.pop_back();
int s = get<0>(stack.back());
if(s==0) {
BEGIN DOWHILE;
} else if (s==1){
BEGIN text;
} else if (s==2){
forEnd();
}
}
}
int main()
{
extern FILE *yyin, *yyout;
yyin = fopen("input.c", "r");
yyout = fopen("out.c", "w");
yylex();
return 0;
}