Tech Support Guy banner

PNFHA: if-else code generation

2281 Views 5 Replies 1 Participant Last post by  des000
I am trying to add an if and if-else statement to my language called PNFHA (Portable Numbers Format High-Level Language A). I am using bison and flex to write the language. This language is a compiler to my PNFASM language (Portable Numbers Format Asembler). I have correctly parsed the if and if-else statements. I have gotten everything in the if statement to work. However, I am having trouble with the code generation of the if-else statement. The code for the else keeps getting put in the if instead of the else, because of the way bison works.

So what I did, is modified the parser to use an Array (my Array class), instead of outputting the output directly to the file. That way, before code generation is done, I can easily modify it. So I worked out a solution where extra code was generated telling which line number the code really belongs on. Then I move the code to the correct line numbers, and then I delete the extra information. The moving process seems to work. However, there is one little problem I need to solve before this will work entirely.

The code seems to need to know whether there is a code block or not, and whether this is in the else or not. I can tell if I am in a block or not, but to tell whether the block is in the else part or not, I seem to need a look ahead token. However, the bison look ahead token is not filled at this point in my code. It is YYEMPTY. It is that way either way. How can I test if we are in a block in the else part or not without using that feature, or how can I make the feature work at that point?
Status
Not open for further replies.
1 - 6 of 6 Posts
Here is my updated code for the if-else statement:

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

             cout << blockfound << endl;


             ifbegin = out.length() - 1;
             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;
             l2 = 0;
             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;


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

              ifbeginlineno -= (2 + l2offset);
              elsebeginlineno -= (3 + l2offset);
             }
             cout << l2 << endl;
             cout << ifbeginlineno << " " << elsebeginlineno << endl;


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


             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;
            }
However, whenever there is a block in the if, it fails to work so far.
See less See more
I now have updated the code to include some new calculations:

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

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


             ifbegin = out.length() - 1;
             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;
             l2 = 0;
             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 = 0;
             for (unsigned long i = 0; i < out.length(); ++i)
             {
              if (i > ifbegin && i < elsebegin)
              {
               ++ifstmts;
              }
             }
             if (ifstmts > 1)
              multipleif = true;


             // 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 == 6)
               elsebeginlineno += 1;
              if (ifstmts == 5)
               elsebeginlineno += 2;
             }
             cout << l2 << " " << ifstmts << endl;
             cout << ifbegin << " " << elsebegin << endl;
             cout << ifbeginlineno << " " << elsebeginlineno << endl;


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


             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;
            }
The problem here is that the ifstmts is always the same.
See less See more
So the update, retyped here, for convienience, is that I have code being generated, and the code for this:

Code:
;
if (3 + 2)
 ;
end 0;
Compiles to this:

Code:
VERSION TVOID 0V

VOID TVOID 0V
; Begin if :1
ALOAD TBOOLEAN true
CGOTOL TVOID if_part
GOTOL TVOID else_part_or_end

LBL TVOID 0V
VOID TVOID 0V
; End if code :1
GOTOL TVOID end

LBL TVOID 0V
; End if or else code :1
QUIT TVOID 0
END TVOID 0V
This is an intermediate step. I want the code to compile to this:

Code:
[CODE]
VERSION TVOID 0V

VOID TVOID 0V
; Begin if :1
ALOAD TBOOLEAN true
CGOTOL TVOID 0
GOTOL TVOID 1

LBL TVOID 0V
VOID TVOID 0V
; End if code :1
GOTOL TVOID 1

LBL TVOID 0V
; End if or else code :1
QUIT TVOID 0
I also want it to be able to compile any kind of if-else statement. The code for the if-else statement is:

Code:
if_statement:  IF LEFTP expression
   {
    ASTNode if_statementp1("if_statementp1");
    ++ifcounter;
    ifgoto = ifcounter < 2 ? ifcounter : ifcounter + 1;
    String if_body_str = "if_body_";
    if_body_str += ifgoto - 1;
    labelTable.insert();
    labelTable[labelTable.length() - 1].name(if_body_str);
    labelTable[labelTable.length() - 1].address(labelTable.length() - 2);
    if_statementp1.conprint("; Begin if :%u\n", ifcounter);
    if_statementp1.conprint("ALOAD TBOOLEAN %s\n", $3.to_boolean().get().getString().c_str());
    if_statementp1.conprint("CGOTOL TVOID if_part :%u\n", ifcounter);
    if_statementp1.conprint("GOTOL TVOID else_part_or_end :%u\n", ifcounter);
    if_statementp1.conprint("\n\nLBL TVOID 0V\n");

    tree.add_node(if_statementp1);  
   }
     RIGHTP stmt
   {
    ASTNode if_statementp2("if_statementp2");
    // Code for if will be inserted here...
    if_statementp2.conprint("; End if code :%u\n", ifcounter);
    ifbegin = outcount;
    String after_if_str = "after_if_";
     after_if_str += ifgoto - 1;
    labelTable.insert();
    labelTable[labelTable.length() - 1].name(after_if_str);
    labelTable[labelTable.length() - 1].address(labelTable.length() - 2);
    if_statementp2.conprint("GOTOL TVOID end\n");
    endifbegin = outcount - 1;

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

    tree.add_node(if_statementp2);
   }
   opt_else
   {
    --ifcounter;
    ++ifnest;
   }
   ;
opt_else:  | ELSE stmt
   {
    ASTNode if_statementp3("if_statementp3");
    ++elsecounter;
    
    // Code for else will be inserted here if exists...
    if_statementp3.conprint("; End if or else code :%u\n", ifcounter);
    elsebegin = outcount;
    String else_body_str = "else_body_";
    else_body_str += ifcounter;
    String after_if_str = "after_if_";
     after_if_str += ifgoto - 1;
    labelTable.remove();
    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);
    if_statementp3.conprint("GOTOL TVOID end\n");
    if_statementp3.conprint("\n\nLBL TVOID 0V\n");
    if_statementp3.conprint("; End if :%u\n", ifcounter);

    tree.add_node(if_statementp3);
   }
   ;
The partial algorithm I'm using to transform the code to the desired result is:

Code:
  1. Count the labels until there is an if-else.
  2. Count the if else labels.
  3. Replace end with the results of (step 1 - 1) + (step 2 - 1).
  4. Count the labels from the if begin until the if code end.
I need a complete algorithm please, and/or it modified to work.
See less See more
1 - 6 of 6 Posts
Status
Not open for further replies.
Top