LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-18-2014, 10:45 PM   #1
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416
Blog Entries: 43

Rep: Reputation: 36
PNFHA: if-else code generation


I am trying to generate code for an if-else statement for the language I am developing. I am using bison and flex to write the language in, because it is the easiest language to write it in I have access to. However, it is still difficult for even a simple if-else statement. The problem is that the output is not always placed where I want it to be.

So what I have to do is store the output in an array, and then modify the array so that it's correct, by moving the output to where I want it. I have done this by "marking" the code with line numbers specifying where it belongs, and then moving the code to where it really belongs. The problem is that I'm depending on line numbers given by yylineno, and it is sometimes off.

I am going to a lot of work to correct the line numbers, so they will not be off. While correcting the line numbers, I have needed to count the number of if statements, so that everything will be still placed okay if there is a statement block in the if. Then I can use that value, to correct the other values. The problem now, is that the number of if statements is always reading the same.

Here is a link to the problem: http://forums.techguy.org/software-d...eneration.html
 
Old 07-19-2014, 12:05 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
I have no idea what this line-renumbering or line-moving is, but it does sound wrong. If you haven't read Pike and Kernighan's book The Unix Programming Environment then you should now. If you have, you should read it again.
 
Old 07-19-2014, 12:36 AM   #3
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
The line numbering is where I use yylineno, and "mark", the code I'm outputting, so that it has line numbers where needed. What the moving is, is then I use my move function in my array class, to "move" the elements to the correct line number they belong on. After this, I remove the line numbers. Then I can output the array and everything is in the right spot. I'll read the book to see if it helps.

I am creating this on a windows XP enviroment right now, but it should port to Linux pretty easy, and I later intend to. I just started it on Windows because that is where I normally do most of my initial programming work for applications.

This language I am creating, is supposed to be compiled to another language I created, called PNFASM, which is Portable Numbers Format Assembly Language. That can be compiled into PNF, which is Portable Numbers format, and then run by the interpreter, or translated to C++ to be compiled into a native application.
 
Old 07-19-2014, 01:00 AM   #4
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
I just read the PDF version of it. I knew the gist of it. But it doesn't talk about anything of the nature I'm doing. What I'm doing is using bison and flex. Bison comes from yacc, but has more features, and flex comes from lex, but has more features. It is a limitation of bison that the code is not output where I want it to be, because the code generation takes place in the actions, and the actions are not run in the order I would like them to be for the if-else statement. So that is why I'm moving the code to the right spot. I am storing the code in an array, so that I can do that manipulation easy, before it gets written to the file.

Perhaps there is a better way to do the code generation?
 
Old 07-19-2014, 01:25 AM   #5
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
Also see: http://www.go4expert.com/forums/pnfh...ration-t30183/
 
Old 07-19-2014, 01:36 AM   #6
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
You couldn't have the the book in half an hour. Especially not the chapters about hoc (that' what you are trying to reinvent).
 
Old 07-19-2014, 02:14 PM   #7
pwalden
Member
 
Registered: Jun 2003
Location: Washington
Distribution: Raspbian, Ubuntu, Chrome/Crouton
Posts: 374

Rep: Reputation: 50
As NevemTeve says, whatever you are doing is not very clear. Perhaps an example of your language and Bison input would help.

Bison and yacc, use stacks and token steam look-aheads to parse syntax, so he yylineno value and the index in the term stack could have have a very complicated relationship.

It sounds like you should not use Bison at all. Just use flex to tokenize and write your own simple if-then-else parser.
 
Old 07-19-2014, 02:40 PM   #8
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
I read all that was on the pdf, maybe it was a shortened version.
 
Old 07-19-2014, 02:44 PM   #9
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
The entire bison file is attatched. For it to work, it has to be renamed as a .ypp file instead of a .txt file.
Attached Files
File Type: txt pnfha.txt (136.8 KB, 19 views)
 
Old 07-19-2014, 02:47 PM   #10
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
Here is the example, I am trying to generate code for right now:

Code:
if (3 + 2)
{
 ;
 ;
 println "Hello World!";
}
else
{
 ;
 ;
 ;
 ;
 ;
 ;
 ;
 println "Hello World!";
}
It compiles to:
Code:
VERSION TVOID 0V


ALOAD TBOOLEAN true
CGOTOL TVOID 0
GOTOL TVOID 1


LBL TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
GOTOL TVOID 2


LBL TVOID 0V
PRINTLN TSTRING "Hello World!"
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
PRINTLN TSTRING "Hello World!"
GOTOL TVOID 2


LBL TVOID 0V

END TVOID 0V
It should compile to:
Code:
VERSION TVOID 0V


ALOAD TBOOLEAN true
CGOTOL TVOID 0
GOTOL TVOID 1


LBL TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
PRINTLN TSTRING "Hello World!"
GOTOL TVOID 2


LBL TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
VOID TVOID 0V
PRINTLN TSTRING "Hello World!"
GOTOL TVOID 2


LBL TVOID 0V

END TVOID 0V
 
Old 07-19-2014, 09:31 PM   #11
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
So I fixed one problem. The loop I was using to calculate the if statements was somehow off. But I figured out that what I wanted it to do was the same as this:

Code:
ifstmts = elsebegin - ifbegin - 1;
 
Old 07-19-2014, 09:38 PM   #12
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
I see now that hoc was a link. Hoc is an interpreted programming language, and my language is a compiled language. I am trying to write a compiler for my language, not an interpreter. So the action doesn't execute the code, the action takes part in generating code that will be executed, or in this case assembled later to be executed by the interpreter. The action part of the code is where my error is. The syntax part of the code works just fine.
 
Old 07-20-2014, 02:08 PM   #13
pwalden
Member
 
Registered: Jun 2003
Location: Washington
Distribution: Raspbian, Ubuntu, Chrome/Crouton
Posts: 374

Rep: Reputation: 50
You should not be using yylineno to identify jump label points. yylineno is typically used to generate the line number in warning or error messages about syntax parsing errors, not code labels.

It has been awhile since I used bison/yacc, but you be using the values returned that the parser can return to identify the label positions.

Below is probably incorrect as I have not used yacc in awhile.

%value begin_block
%value end_block
%value expression
%value stmt

:

begin_block: LEFTP { $0 = statementoutcount.length(); }
end_block: RIGHTP { $0 = statementoutcount.length(); }
if_statement: IF begin_block expression end_block stmt
{ start_position = $2; end_position = $4; ...}

Last edited by pwalden; 07-20-2014 at 05:50 PM. Reason: more info found
 
Old 07-20-2014, 09:37 PM   #14
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
I have gotten a little further. The if-else statement will work now, but not if there's something else in the file. The code is as follows:

Code:
			| IF LEFTP expression RIGHTP stmt ELSE stmt
			{
			 if (strcmp(yytext, "}") == 0)
	                  blockinelse = true;

			 if ($5.to_string().get().getString() == "}")
			  blockinif = true;


			 ifbegin = outcount;
			 if (!inblock)
			  ifbeginlineno = yylineno - 2;
			 else
                          ifbeginlineno = yylineno - 5;

			 conprint("ALOAD TBOOLEAN %s\n", $3.to_boolean().get().getString().c_str());

			 String if_body_str = "if_body_";
			 if_body_str += ifcounter;
			 String else_body_str = "else_body_";
			 else_body_str += ifcounter;
			 String after_if_str = "after_if_";
			 after_if_str += ifcounter;

			 conprint("CGOTOL TVOID %u\n", ifcounter);
			 conprint("GOTOL TVOID %u\n", ifcounter + 1);

			 labelTable.insert();
			 labelTable[labelTable.length() - 1].name(if_body_str);
			 labelTable[labelTable.length() - 1].address(labelTable.length() - 2);

			 labelTable.insert();
			 labelTable[labelTable.length() - 1].name(else_body_str);
			 labelTable[labelTable.length() - 1].address(labelTable.length() - 2);

			 labelTable.insert();
			 labelTable[labelTable.length() - 1].name(after_if_str);
			 labelTable[labelTable.length() - 1].address(labelTable.length() - 2);

			 conprint("\n\nLBL TVOID 0V\n");
			 unsigned long ifbodybegin = out.length() - 1;


			 // Calculate elsebegin...
			 unsigned long k = outcount;
			 unsigned long l = outcount;
			 unsigned long m;
			 for (unsigned long i = 0; i < statementoutcount.length(); ++i)
			 {
			  if (statementlineno[i] >= ifbeginlineno)
			  {
			   unsigned long j;
			   for (j = statementoutcount[i]; j < ifbegin; ++j, ++k)
 			    ;
			   outcount = k;
			   elsebeginlineno = j + 1;
			  }
			 }
			 elsebegin = outcount;


			 bool found = false;
			 bool multiplestmts = false;
			 unsigned long l2 = 0;
			 unsigned long n = outcount;


			 unsigned long fpos = ifbegin - 1;


			 // Calculate l2...
			 n = outcount;
			 found = false;
			 bool elsefound = false;
			 multiplestmts = false;
			 for (unsigned long i = 0; i < ifbegin; ++i)
			 {		  
			  ++l2;
			 }


			 // Mark the code...
			 for (unsigned long i = 0, m = statementlineno[i]; i < out.length(); ++i, ++m)
		         {
			  if (i < ifbegin)
			  {
                           out[i].insert(out[i].length(), ':');
			   out[i].insert();
			   String str;
			   str.from_long(m);
			   out[i] += str;
  		           out[i] += '\n';
			  }
			 }


			 // Calculate some other values...
			 n = outcount;
			 unsigned long len = out.length();
			 found = false;
			 elsefound = false;
			 multiplestmts = false;
			 for (unsigned long i = 0; i < len; ++i)
			 {
			  String str;
			  str = out[i];
			  unsigned long k = str.getString().find(':');
                          if (k == string::npos)
			  {
                           continue;
		          }
   		          found = true;
			  str = out[i].getString().substr(k + 2);
			  unsigned long l = atoi(str.getString().c_str());
			  
			  if (l2 > 1)
			   multiplestmts = true;

			  if (blockinelse == true && multiplestmts == true)
			  {
			   if (l >= (elsebeginlineno - 1))
                           {
			    elsefound = true;
			   }
			  }
			  else
			  {
			   if (l >= elsebeginlineno)
                           {
			    elsefound = true;
			   }
			  }
			 }
			 outcount = out.length() - 1;


			 // Are there multiple statements in the if?
			 bool multipleif = false;
			 unsigned long ifstmts = elsebegin - ifbegin - 1;
			 if (ifstmts > 1)
			  multipleif = true;


			 // Adjust ifsmts...
			 bool nvalues = false;
			 unsigned long ifstmtoffset = 0;
			 if (ifstmts == 19)
			 {
			  nvalues = ifbegin == 10 && elsebegin == 30 ? true : false;
			  if (!nvalues)
			  {
			   ifstmtoffset = ifbegin - 10;
			   ifstmts += ifstmtoffset;
			  }
			 }


			 // After this point, these are off, so we adjust them...
			 if (l2 == 4 && !blockinif)
			 {
			  ifbeginlineno -= 1;
			  elsebeginlineno -= 2;
			 }
			 else if (l2 == 3 && !blockinif)
			 {
			  elsebeginlineno -= 1;
			 }
			 else if (l2 >= 5 && !blockinif)
			 {
			  unsigned long l2offset = 0;
			  unsigned long i;
			  for (i = 6; i <= l2; ++i)
                           ++l2offset;

			  ifbeginlineno -= (2 + l2offset);
			  elsebeginlineno -= (3 + l2offset);
			 }
			 else if (l2 == 2 && blockinif)
			 {
			  ++elsebeginlineno;
			 }
			 else if (l2 == 4 && blockinif)
			 {
			  --ifbeginlineno;
			  --elsebeginlineno;
		         }
			 else if (l2 == 5 && blockinif)
			 {
			  ifbeginlineno -= 2;
			  elsebeginlineno -= 2;
		         }
			 else if (l2 >= 6 && blockinif)
			 {
			  unsigned long l2offset = 3;
			  unsigned long i;
			  for (i = 7; i <= l2; ++i)
                          {
			   ++l2offset;
			  }

			  ifbeginlineno -= (l2offset);
			  elsebeginlineno -= (l2offset);

			  if (ifstmts == 19)
			   elsebeginlineno += 1;
			  if (ifstmts == 20)
			   elsebeginlineno += 2;
			  if (ifstmts == 21)
			   elsebeginlineno += 3;
			  if (ifstmts >= 22)
			  {
			   unsigned long ifstmtoffset2offset = ifstmts - 22;
			   unsigned long ifstmtoffset2 = 4 + ifstmtoffset2offset;

			   elsebeginlineno += ifstmtoffset2;
			  }
			 }


			 cout << l2 << " " << ifstmts << endl;
			 cout << ifbegin << " " << elsebegin << endl;
			 cout << ifbeginlineno << " " << elsebeginlineno << endl;


			 // Count the statements before the if code...
			 unsigned long bifstmts = 0;
			 len = out.length();
			 found = false;
			 for (unsigned long i = 0; i < len; ++i)
			 {
			  String str;
			  str = out[i];
			  unsigned long k = str.getString().find(':');
                          if (k == string::npos)
			  {
                           continue;
		          }
   		          found = true;
			  str = out[i].getString().substr(k + 2);
			  unsigned long l = atoi(str.getString().c_str());
			  
			  if (l < ifbeginlineno)
			   ++bifstmts;
			 }
			 if (ifbegin == 10 && elsebegin == 26)
			  ++elsebeginlineno;
			 else if (ifbegin == 11 && elsebegin == 27)
			 {
			  ++bifstmts;
			  elsebeginlineno += 4;
			 }


			 cout << "\n\n";
			 cout << bifstmts << endl;
			

		         // Move the if code to the right spot...
			 k = ifbodybegin;
			 for (unsigned long i = bifstmts; i < statementoutcount.length(); ++i)
			 {
			  for (unsigned long j = statementoutcount[i]; j < ifbegin; ++j, ++k)
 			   out.move(j, k);
			  outcount = k;			 
			 }


			 // Conditionally adjust values in some cases...
			 unsigned long ifbeginoffset = 11, elsebeginoffset = 31;
			 if (ifbegin == 13 && elsebegin == 33)
			 {
 			  // Recalculate ifstmts...
			  ifstmts = 0;
			  for (unsigned long i = ifbodybegin; i <= elsebegin; ++i)
			   ++ifstmts;
			  if (ifstmts > 1)
			   multipleif = true;


			  // Recalculate elsebeginlineno...
			  if (l2 == 4 && !blockinif)
			  {

 			  }
			  else if (l2 == 3 && !blockinif)
			  {

			  }
			  else if (l2 >= 5 && !blockinif)
			  {
			   unsigned long l2offset = 0;
			   unsigned long i;
			   for (i = 6; i <= l2; ++i)
                            ++l2offset;
			  }
			  else if (l2 == 2 && blockinif)
			  {

			  }
			  else if (l2 == 4 && blockinif)
			  {

		          }
			  else if (l2 == 5 && blockinif)
			  {
			 
		          }
			  else if (l2 >= 6 && blockinif)
			  {
			   unsigned long l2offset = 3;
			   unsigned long i;
			   for (i = 7; i <= l2; ++i)
                           {
			    ++l2offset;
			   }

			   if (ifstmts == 17)
			    elsebeginlineno += 1;
			  }
			 }
			 else if (ifbegin == 12 && elsebegin == 32)
			 {
 			  // Recalculate ifstmts...
			  ifstmts = 0;
			  for (unsigned long i = ifbodybegin; i <= elsebegin; ++i)
			   ++ifstmts;
			  if (ifstmts > 1)
			   multipleif = true;


			  // Recalculate elsebeginlineno...
			  if (l2 == 4 && !blockinif)
			  {

 			  }
			  else if (l2 == 3 && !blockinif)
			  {

			  }
			  else if (l2 >= 5 && !blockinif)
			  {
			   unsigned long l2offset = 0;
			   unsigned long i;
			   for (i = 6; i <= l2; ++i)
                            ++l2offset;
			  }
			  else if (l2 == 2 && blockinif)
			  {

			  }
			  else if (l2 == 4 && blockinif)
			  {

		          }
			  else if (l2 == 5 && blockinif)
			  {
			 
		          }
			  else if (l2 >= 6 && blockinif)
			  {
			   unsigned long l2offset = 3;
			   unsigned long i;
			   for (i = 7; i <= l2; ++i)
                           {
			    ++l2offset;
			   }

			   if (ifstmts == 17)
			    elsebeginlineno += 2;
			  }
			 }
			 else if ((ifbeginoffset - ifbegin) >= 0 && (elsebeginoffset - elsebegin) >= 0)
			 {
			  elsebeginlineno += (3 + (11 - ifbeginoffset));
			  if ((ifbeginoffset - ifbegin) >= 1)
 			   elsebeginlineno += 2;
			 }


			 cout << "\n\n";
			 cout << l2 << " " << ifstmts << endl;
			 cout << ifbegin << " " << elsebegin << endl;
			 cout << ifbeginlineno << " " << elsebeginlineno << endl;



			 conprint("GOTOL TVOID %u\n", ifcounter + 2);
			 statementoutcount.insert();
			 statementoutcount[statementoutcount.length() - 1] = outcount - 1;
			 statementlineno.insert();
			 statementlineno[statementlineno.length() - 1] = elsebeginlineno;


			 conprint("\n\nLBL TVOID 0V\n");
			 statementoutcount.insert();
			 statementoutcount[statementoutcount.length() - 1] = outcount - 1;
			 statementlineno.insert();
			 statementlineno[statementlineno.length() - 1] = elsebeginlineno;

			 unsigned long elsebodybegin = out.length();

			 
			 // Add the else code to an array...
			 n = outcount;
			 len = out.length();
			 found = false;
			 elsefound = false;
			 multiplestmts = false;
			 l2 = 0;
			 Array<String> a;
			 for (unsigned long i = 0; i < len; ++i)
			 {
			  String str;
			  str = out[i];
			  unsigned long k = str.getString().find(':');
                          if (k == string::npos)
			  {
                           continue;
		          }
   		          found = true;
			  str = out[i].getString().substr(k + 2);
			  unsigned long l = atoi(str.getString().c_str());
			  
			  ++l2;
			  if (l2 > 1)
			   multiplestmts = true;

			  if (l >= elsebeginlineno)
			  {
			   if (l2 > 1)
			    a.insert();
			   a[a.length() - 1] = out[i];
			   out[i] = "";
                          }
			 }
			 // Sort it by line number...
			 sort_lines(a);

			
			 // ...And insert it back into the output...
	                 for (unsigned long i = 0; i < a.length(); ++i)
                         {
			  out.insert();
			  out[elsebodybegin + i] = a[i];
			 }
			 outcount = out.length();


			 conprint("GOTOL TVOID %u\n", ifcounter + 2);


			 conprint("\n\nLBL TVOID 0V\n");

			
			 // Remove the extra line number code...
 			 for (unsigned long i = 0; i < out.length(); ++i)
			 {
			  unsigned long pos = out[i].getString().find(':');
			  String str;

			  if (pos != string::npos)
			   str = out[i].getString().substr(0, pos);
			  else
			   str = out[i];

   			  out[i] = str;
			 }


			 ++ifcounter;
			}
 
Old 07-20-2014, 10:13 PM   #15
des_a
Senior Member
 
Registered: Sep 2006
Posts: 1,416

Original Poster
Blog Entries: 43

Rep: Reputation: 36
Do you mean the location tracking feature? Or if not, what feature are you talking about? Can you give me an overview of the feature you are talking about please?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Portable Numbers Format: PNFHA des_a Programming 14 07-18-2014 10:51 PM
[SOLVED] Prime Generation Code Not Working Properly ashok.g Programming 29 12-14-2009 03:59 AM
A GCC code generation problem? dogbird Programming 4 12-09-2005 11:52 AM
tool for code generation? bcalmac Linux - Software 0 08-22-2005 10:41 AM
UML and C++ code generation GŠutama Linux - Software 2 11-13-2003 06:56 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:11 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration