This is OperatorStack.m in view mode; [Download] [Up]
/***(OperatorStack.m)********************************************************** *H* Push down stack for numeric operators V0.0, 09-FEB-91 * *C* V0.0 09-FEB-91 Initial version --MDM * ******************************************************************************/ /* Standard C Library includes */ #import <stdio.h> /* Standard I/O functions and definitions */ #import <stdlib.h> /* Standard C memory allocation prototypes */ #import "OperatorStack.h" /* OperatorStack interface specification */ /* Class Private Data */ typedef struct OSoperator { char *name; int precedence; int n_operands; } OToperator; /* Table describing each operator */ static OToperator OVopTable[OPCODE_OpCodes] = { { "Equals", 4, 1 }, { "Plus", 14, 2 }, { "Minus", 14, 2 }, { "Multiply", 15, 2 }, { "Divide", 15, 2 }, { "OpenParen", 5, 0 }, { "CloseParen", 6, 0 }, { "SIN", 17, 1 }, { "ASIN", 17, 1 }, { "SINH", 17, 1 }, { "ASINH", 17, 1 }, { "COS", 17, 1 }, { "ACOS", 17, 1 }, { "COSH", 17, 1 }, { "ACOSH", 17, 1 }, { "TAN", 17, 1 }, { "ATAN", 17, 1 }, { "TANH", 17, 1 }, { "ATANH", 17, 1 }, { "EXP", 17, 1 }, { "LN", 17, 1 }, { "LOG", 17, 1 }, { "10^X", 17, 1 }, { "X^Y", 16, 2 }, { "XrootY", 16, 2 }, { "XSquared", 17, 1 }, { "SqrRoot", 17, 1 }, { "1overX", 17, 1 }, { "Factorial", 17, 1 }, { "Pi", 17, 1 }, { "Modify", 15, 2 }, { "Integer", 17, 1 }, { "And", 10, 2 }, { "Or", 8, 2 }, { "Not", 17, 1 }, { "Xor", 9, 2 }, { "LShift", 17, 1 }, { "RShift", 17, 1 } }; @implementation OperatorStack /* Private Object Wide Definitions */ #define OCnullStack (OToperStackItem *) 0 /****************************************************************************** * INSTANCE METHOD:- init * * Initialize a new instance of a OperatorStack class. * ******************************************************************************/ - init {/* BEGIN:-init */ self = [super init]; OVstackTop = OCnullStack; OVstackSize = 0; return self; }/* END:-init */ /****************************************************************************** * INSTANCE METHOD:- free * * All data currently on the OperatorStack is poped and freed, returning the * * allocated memory back to the system pool. * ******************************************************************************/ - free { /* Local Variables */ OToperStackItem *tmp_blink; /* BEGIN free */ while (OVstackTop != OCnullStack) {/* Get pointer to lower stack item and free top item */ tmp_blink = OVstackTop->blink; free( (char *) OVstackTop ); OVstackTop = tmp_blink; OVstackSize = 0; } /* Request super class to perform its free method */ return [super free]; }/* END free */ /****************************************************************************** * INSTANCE METHOD:- ClearStack * * Pop and free each element on the stack until the stack is empty. * ******************************************************************************/ - ClearStack { /* Local Variables */ OToperStackItem *tmp_blink; /* BEGIN Clear */ while ( OVstackTop ) {/* Stack is not empty, free top item */ tmp_blink = OVstackTop->blink; free ( (char *) OVstackTop ); OVstackTop = tmp_blink; } OVstackSize = 0; return self; }/* END ClearStack */ /****************************************************************************** * INSTANCE METHOD:- ComparePrecedence * * Compares the precedence of opcode against the opcode on the top of the * * stack and returns the difference in the result argument. The comparison is * * made by subtracting the numerical precedence value of the supplied opcode * * with that of the opcode on the top of the stack. If the stack is empty the * * supplied opcode is compared against a precedence value of zero. The * * returned value has the following meanings: * * result >= 1: opcode has higher precedence stack top opcode. * * result == 0: opcode and stack top opcode are of equal precedence. * * result <= 1: opcode is of lesser precedence than stack top opcode. * ******************************************************************************/ - ComparePrecedence: (int) opcode: (int *) result {/* BEGIN ComparePrecedence */ if (opcode < 0 || opcode > OPCODE_LastOpCode) return nil; /* return failure status */ if ( OVstackSize > 0 ) /* Stack is not empty, use precedence of opcode on stack top */ *result = OVopTable[opcode].precedence - OVopTable[OVstackTop->opcode].precedence; else /* Stack is empty, assume a precedence value of zero */ *result = OVopTable[opcode].precedence - 0; return self; }/* END ComparePrecedence */ /****************************************************************************** * INSTANCE METHOD:- GetSize * * Return the current number of items in the Value Stack. * ******************************************************************************/ - (unsigned long) GetSize {/* BEGIN GetSize */ return OVstackSize; }/* END GetSize */ /****************************************************************************** * INSTANCE METHOD:- NumberOfOperands * * Return the operands that the given opcode requires. * ******************************************************************************/ - NumberOfOperands :(int)opcode :(int*)noperands {/* BEGIN NumberOfOperands */ if ( opcode >= OPCODE_Equals && opcode <= OPCODE_LastOpCode ) {/* The caller supplied a legal opcode, return successfully */ *noperands = OVopTable[opcode].n_operands; return self; } else /* The caller supplied an invalid opcode, return with error status */ return nil; }/* END NumberOfOperands */ /****************************************************************************** * INSTANCE METHOD:- Peek * * Return the value on the top of the stack without removing it from the * * stack. * ******************************************************************************/ - Peek: (int *) opcode {/* BEGIN Peek */ if ( OVstackTop ) {/* The stack is not emptry */ *opcode = OVstackTop->opcode; return self; /* succesful status */ } else {/* Report illegal reference to standard error */ #ifdef DEBUG fprintf(stderr, "OperatorStack: Peek on empty stack returning -1\n"); #endif *opcode = -1; return nil; /* failure status */ } }/* END Peek */ /****************************************************************************** * INSTANCE METHOD:- Pop * * Return the value opcode on the top of the stack and free top stack item. * ******************************************************************************/ - Pop: (int *) opcode { /* Local Variables */ OToperStackItem *tmp_blink; /* BEGIN Pop */ if ( OVstackTop ) {/* Stack is not empty, free top item and return top value */ *opcode = OVstackTop->opcode; tmp_blink = OVstackTop->blink; free ( (char *) OVstackTop ); OVstackTop = tmp_blink; OVstackSize--; return self; } else {/* Stack is empty report error, return -1 */ #ifdef DEBUG fprintf(stderr, "OperatorStack: Pop on empty stack returning -1\n"); #endif *opcode = -1; return nil; /* failure status */ } }/* END Pop */ /****************************************************************************** * INSTANCE METHOD:- Push * * Push an opcode value on the stack. We allocate a new stack item setting * * its opcode field to the supplied opcode value, and its blink field to point * * to the current stack top. If a new stack item cannot be allocated an error * * message is written to stderr. * ******************************************************************************/ - Push: (int) opcode { /* Local Variables */ OToperStackItem *new_item; /* BEGIN Push */ /* Allocate a new stack item */ new_item = (OToperStackItem *) malloc(sizeof(OToperStackItem)); if ( new_item ) {/* New stack item allocated, initialize and link in new stack top */ new_item->opcode = opcode; new_item->blink = OVstackTop; OVstackTop = new_item; OVstackSize++; return self; } else {/* Allocation failed, report error to stderr */ #ifdef DEBUG fprintf(stderr, "OperatorStack: Push allocation failure\n"); #endif return nil; } }/* END Push */ /****************************************************************************** * INSTANCE METHOD:- PrintStack * * Print out the contents of the stack to standard output. * ******************************************************************************/ - PrintStack { /* Local Variables */ OToperStackItem *trace_link; int oti; /* operator table index */ long level; /* BEGIN PrintStack */ if ( OVstackTop ) {/* The stack is not empty so dump its contents */ trace_link = OVstackTop; level = 0; while ( trace_link ) {/* Not at bottom, print this item */ oti = trace_link->opcode; #ifdef DEBUG printf("%s\t%d\t%d\t:(%ld)\n", OVopTable[oti].name, OVopTable[oti].precedence, OVopTable[oti].n_operands, level--); #endif trace_link = trace_link->blink; } } else {/* Stack is empty so print a message */ #ifdef DEBUG printf("OperatorStack: stack empty\n"); #endif } return self; }/* END PrintStack */ @end /* ValueStack Implementation */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.