forked from xjuric29/ifj
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stack.c
212 lines (174 loc) · 5.35 KB
/
stack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
* @file stack.c
* @author Jiri Furda (xfurda00)
* @brief Source file for stack interface
* @todo
*/
#include "stack.h"
//#define STACKDEBUG
void stackInit(myStack_t *stack)
{
if(stack == NULL) // If the stack is not allocated
{
stackError(ERR_STACK_NULL);
return;
}
stack->top = -1; // Initialize top of the stack
stackPush(stack, STACK_ENDCHAR); // Push "end of stack character" as first one
}
void stackPush(myStack_t *stack, char content)
{
if(stackFull(stack)) // If the stack is full
{
stackError(ERR_STACK_FULL); // Throw an error
return;
}
(stack->top)++; // Increase index of the top of the stack
stack->arr[stack->top] = content; // Add value to the stack
}
char stackPop(myStack_t *stack)
{
if(!stackEmpty(stack)) // If the stack is not empty
{
(stack->top)--; // Decrease index of top of the stack
return stack->arr[stack->top+1]; // Return content from top of the stack
}
else
{
stackError(ERR_STACK_EMPTY); // Throw an error
return STACK_NULLCHAR;
}
}
char stackTop(myStack_t *stack)
{
if(!stackEmpty(stack)) // If the stack is not empty
{
return stack->arr[stack->top]; // Return content from top of the stack
}
else
{
stackError(ERR_STACK_EMPTY); // Throw an error
return STACK_NULLCHAR;
}
}
void stackError(stackErrorCodes_t code)
{
char *msg;
switch(code)
{
case ERR_STACK_NULL: msg="Tried to init not allocated stack"; break;
case ERR_STACK_FULL: msg="Tried to push onto full stack"; break;
case ERR_STACK_EMPTY: msg="Tried to top/pop empty stack"; break;
case ERR_STACK_SHIFT: msg="Tried to shift full stack"; break;
case ERR_STACK_TERM: msg="Terminal not found"; break;
default: msg="Undefined error"; break;
}
fprintf(stderr, "[ERROR] stack.c: %s\n", msg);
}
int stackEmpty(myStack_t *stack)
{
if(stack->top < 0)
return 1;
else
return 0;
}
int stackFull(myStack_t *stack)
{
if(stack->top >= STACK_MAX)
return 1;
else
return 0;
}
#ifdef STACKDEBUG
void stackInfo(myStack_t *stack)
{
if(stack == NULL) // If the stack is not allocated
{
stackError(ERR_STACK_NULL);
return;
}
//printf("[DBG] Stack(top=%d)='", stack->top);
printf("[DBG] STACK=");
for(int i=0; i<=stack->top; i++)
{
switch(stack->arr[i])
{
case TERM_string: printf("str"); break;
case TERM_equal: printf("="); break;
case TERM_notEqual: printf("<>"); break;
case TERM_less: printf("<"); break;
case TERM_lessEqual: printf("<="); break;
case TERM_greater: printf(">"); break;
case TERM_greaterEqual: printf(">="); break;
default: printf("%c",stack->arr[i]); break;
}
printf(" ");
}
printf("\n");
}
#endif
int stackGetTerminalIndex(myStack_t *stack)
{
char terminals[TERMINAL_COUNT] = "+-\\*/()i$";
// @todo Temporary logic solution
terminals[9] = TERM_equal;
terminals[10] = TERM_notEqual;
terminals[11] = TERM_less;
terminals[12] = TERM_lessEqual;
terminals[13] = TERM_greater;
terminals[14] = TERM_greaterEqual;
terminals[15] = TERM_string;
for(int i = stack->top; i >= 0; i--) // Start searching from top of the stack
{
for(int x = 0; x < TERMINAL_COUNT; x++) // Compare with every possible terminal
{
if(stack->arr[i] == terminals[x]) // If it's a match
return i; // Return terminal index
}
}
stackError(ERR_STACK_TERM);
return STACK_NOTFOUND;
}
void stackRightShift(myStack_t *stack, int index)
{
if(stackFull(stack)) // Shouldn't ever happen because it's checked in stackPushAtPos but just in case
{
stackError(ERR_STACK_SHIFT);
return;
}
char prev = STACK_NULLCHAR; // First index will be "empty"
for(; index <= stack->top+1; index++) // For every item in stack + one more
{
char tmp = stack->arr[index]; // Temporary save value
stack->arr[index] = prev; // Move value from previous item
prev = tmp; // Store value that used to be in this place for next run of the cycle
}
(stack->top)++; // Increase top of the stack
}
void stackPushAtPos(myStack_t *stack, char content, int pos)
{
if(pos == (stack->top) + 1) // There's no need to shift
{
stackPush(stack, content); // Use regular push function
return;
}
if(stackFull(stack)) // If the stack is full
{
stackError(ERR_STACK_FULL); // Throw an error
return;
}
stackRightShift(stack, pos); // Make space at specified position (shift everything right by one starting from that poisiton untill top of the stack)
stack->arr[pos] = content; // Add value to the stack at specified position
}
void stackShiftPush(myStack_t *stack)
{
int index = stackGetTerminalIndex(stack) + 1; // Index to position right after closest terminal
stackPushAtPos(stack, '<', index);
}
char stackGetTerminal(myStack_t *stack)
{
int index = stackGetTerminalIndex(stack); // Get index of the nearest terminal to the end of the stack
if(index == STACK_NOTFOUND) // If not found
return STACK_NULLCHAR;
return stack->arr[index]; // Return terminal
}