Translating entire program to goto's

Hi guys,

Having some issues here. I am required to translate an entire program into SIMPLE C, (goto's for all loops) and then from there for our next project we will be translating it into assembler. I have the majority of the project translated and i have it running with only one "for" loop and one "if" not yet translated. The problem is, the for loop spans almost all the code, and I'm not sure how to include goto's correctly to do what I want. What this program does is translate any statement from infix to postfix. EX) (A+B)/(C-D) would be AB+CD-/
Could you please take a look at it, and possibly shed some light on how to write this for loop? I've been at it for days to no avail. If you search "PROBLEM" i used this word to mark where I need help. Throughout the entire project, I have commented out the loop it originally was, and my translation is under each one. It should be fairly easy to read. Thanks to anyone who can help

//C PROGRAM TO CONVERT GIVEN VALID INFIX EXPRESSION INTO POSTFIX EXPRESSION USING STACKS.
#include<stdio.h>
#include<conio.h>
#include<string.h>

//The bottom of the stack is stack[MAX-1]
//The stack grows towards stack[0]
#define MAX 20
char stack[MAX];
int top=MAX; //top will become top-1 as soon as the first push is executed

char infix[20],postfix[20];
char symbol;

//Push an operator onto the stack
void push(char item)
{
top--;
stack[top]=item;
}



//Pop an operator off the stack
char pop()
{
char a;
a=stack[top];
stack[top]='\0'; //Lorenzen unneccessarily deletes the popped operators from the stack as a debugging aid
top++;
return a;
}

//Determine the precedence of the current input operator
//This can't be translated into assembler because assembler has no switch, case, or break
/*
int prcd(char symbol)
{
switch(symbol)
{
case '+':
case '-':return 2;
break;

case '*':
case '/':return 4;
break;

case '^':
case '$':return 6;
break;

case '(':
case ')':
case '#':return 1;
break;

}
}
*/
int prcd(char symbol){
char ax;

if(symbol == '+') goto RETURN2;
if(symbol == '-') goto RETURN2;

if(symbol == '*') goto RETURN4;
if(symbol == '/') goto RETURN4;

if(symbol == '^') goto RETURN6;
if(symbol == '$') goto RETURN6;

if(symbol == '(') goto RETURN1;
if(symbol == ')') goto RETURN1;
if(symbol == '#') goto RETURN1;

RETURN2:
ax = 2;
goto END_CASE;

RETURN4:
ax = 4;
goto END_CASE; //"useless" but good if someone else adds more values to case

RETURN6:
ax = 6;
goto END_CASE;

RETURN1:
ax = 1;
goto END_CASE;

END_CASE: return(ax); //only 1 return per function in asm
}


//Return TRUE if the current input symbol is an operator
//Return FALSE if the current input symbol is an operand
int isoperator(char symbol)
{
//This code performs a linear search of the array from right to left.
//Since we insert symbol in the leftmost array position, we will always find the searched for symbol in the array.
//If we find it in the leftmost position, it wasn't part of the original initialization of the array.
#define NUMBER_OPERATORS 7
char operators[NUMBER_OPERATORS+2]=" +-*/^()"; //null char is automatically inserted at end of string initialization

operators[0]=symbol; //insert symbol in leftmost element of the array
int i=NUMBER_OPERATORS;

/*
while (symbol != operators[i])
i = i-1;
*/

goto WHILE_COND;

WHILE_TOP:
i = i-1;
goto WHILE_COND;
WHILE_COND:
if(symbol != operators[i]) goto WHILE_TOP;
if(symbol == operators[i]) goto WHILE_END;
WHILE_END:;

//If i!=0, symbol was found in the original initialization of the array and return 1 (equivalent to true)
//Else symbol wasn't part of the original initialization of the array and i==0 (equivalent to false).

/*
if (i!=0)
i=1;
*/

if (i != 0)
goto TRUE_PART;
goto END_IF;
TRUE_PART:
i = 1;
END_IF:;

isoperatorExit: return(i);
}

//Convert the input infix expression to postfix
void convertip(char infix[],char postfix[])
{
int i,j=0;
push('#');


for(i=0;i<strlen(infix);i++) //PROBLEM - THIS FOR LOOP SPANS ALMOST WHOLE PROGRAM, HOW DO I USE goto's?
{
symbol=infix[i];

//If the symbol is not an operator (ie it is an operand), append the operand to the postfix string
if(isoperator(symbol)==0) //if isoperator has returned FALSE
{
postfix[j]=symbol; //PROBLEM - ALSO CAN'T FIGURE OUT THIS IF
j++;
goto exitNestedIf;
}



//!!!!!!!!!!!!!!!!!!!!!!!!Now we know the symbol must be an operator!!!!!!!!!!!!!!!!!!!!!!!!


//If the operator is an open parenthesis, push it

/*
if (symbol == '(' ){
push(symbol);
goto exitNestedIf;}
*/

if( symbol=='(' )
goto TRUE_STMNT;
if( symbol != '(' )
goto END_IF;
TRUE_STMNT:
{push(symbol);
goto exitNestedIf;}
END_IF:;

//If the operator is a close parenthesis,
// pop the stack and append operators to the postfix string until the matching open parenthesis is found
// pop the matching open parenthesis
/*
if( symbol==')' )
{
while( stack[top]!='(' )
{
postfix[j]=pop();
j++;
}
pop();//pop out (.
goto exitNestedIf;
}
*/

goto IF_WHILE_START;

IF_WHILE_START:
if (symbol == ')' ) goto IF_WHILE;
if (symbol != ')' ) goto IF_WHILE_END_WITHOUT_POP;
IF_WHILE:
if (stack[top]!= '(' )
goto IF_WHILE_TRUE;
if (stack[top] == '(' )
goto IF_WHILE_END_WITH_POP;
IF_WHILE_TRUE:
{postfix[j]=pop();
j++;
goto IF_WHILE_START;}

IF_WHILE_END_WITH_POP:
{pop();
goto exitNestedIf;}

IF_WHILE_END_WITHOUT_POP:;

//If the precedence of the input operator is > the precedence of the operator on the top of the stack
// push the operator

/*
if(prcd(symbol)>prcd(stack[top]))
{
push(symbol);
goto exitNestedIf;
}
*/

goto IF_START2;

IF_START2:
if(prcd(symbol)>prcd(stack[top])) goto IF_COND2;
if(prcd(symbol)<=prcd(stack[top])) goto IF_END3;

IF_COND2:
{push(symbol);
goto exitNestedIf;}

IF_END3:;

//While the precedence of the input operator is <= the precedence of the operator on the top of the stack
// pop the operator and append the operator to the postfix string
//Push the input operator.

/*
while(prcd(symbol)<=prcd(stack[top]))
{
postfix[j]=pop();
j++;
}
push(symbol);
goto exitNestedIf; //Though unnecessary, makes code symetrical and additional if clauses could be added.
*/

goto WHILE_COND2;

WHILE_COND2:
if (prcd(symbol)<=prcd(stack[top])) goto WHILE_BODY2;
if (prcd(symbol)>prcd(stack[top])) goto WHILE_END3;

WHILE_BODY2:
{postfix[j]=pop();
j++;}

//MIGHT BE MISSING push(symbol) here. see above

WHILE_END3:;


exitNestedIf:;

}//end of for. //PROBLEM - END OF FOR LOOP

//While the stack is not empty, pop operators and append them to the postfix string

/*
while(stack[top]!='#')
{
postfix[j]=pop();
j++;
}
pop(); //pop the # stack bottom marker

//Append the null character to the postfix string to end it.
postfix[j]='\0';
*/

goto WHILE_CONDITION2;

WHILE_BODY:
{postfix[j]=pop();
j++;}
goto WHILE_CONDITION2;

WHILE_CONDITION2:
if(stack[top]!='#') goto WHILE_BODY;
if(stack[top]=='#') goto WHILE_END2;

WHILE_END2:;

}



void main()
{
printf("Enter the valid infix string:\n");
gets(infix);
convertip(infix,postfix);
printf("The corresponding postfix string is:\n");
puts(postfix);
getch();
}
First - could you please use code tags - the <> button on the right.

Now for a devilish comment :-D

If you were going to use goto's exclusively - then you wouldn't have any functions per say. You would goto the start of the function, then goto back again instead of return. You could try numbering your labels in steps of 10, in order through the code - like GWBASIC line numbers. That way you can add extra ones in without driving yourself nuts!!!

Edit: Or have both numbers & names if that is easier (like for function names)

I know this is annoying, but that is what asm is like. When I was learning asm, the most common statement was "My head hurts"

Edit2:

//This can't be translated into assembler because assembler has no switch, case, or break

Would it be even further annoying if I said that all C++ code can converted to assembler?

You guessed it - they are achieved with goto's !!!!!! So with you C program, any kind of flow control can be achieved with if's & goto's.

In asm, the only way to alter the flow control is via a jmp instruction. There are various way's of deciding whether to jmp or not.

HTH & Good Luck !!!!
Last edited on
Topic archived. No new replies allowed.