File indexing completed on 2026-04-17 08:35:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <stdlib.h>
0028 #include <stdio.h>
0029 #include <ctype.h>
0030
0031 #define SHUNT_MAXOPSTACK 256
0032 #define SHUNT_MAXNUMSTACK 256
0033
0034 namespace shunt {
0035
0036 bool eval_not(bool a1, bool a2) { return !a1; }
0037 bool eval_and(bool a1, bool a2) { return a1 && a2; }
0038 bool eval_or(bool a1, bool a2) { return a1 || a2; }
0039
0040 enum { ASSOC_NONE = 0, ASSOC_LEFT, ASSOC_RIGHT };
0041
0042 struct op_s {
0043 char op;
0044 int prec;
0045 int assoc;
0046 int unary;
0047 bool (*eval)(bool a1, bool a2);
0048 } ops[] = {{'!', 10, ASSOC_RIGHT, 1, eval_not},
0049 {'&', 8, ASSOC_LEFT, 0, eval_and},
0050 {'|', 5, ASSOC_LEFT, 0, eval_or},
0051 {'(', 0, ASSOC_NONE, 0, NULL},
0052 {')', 0, ASSOC_NONE, 0, NULL}};
0053
0054 struct op_s *getop(char ch)
0055 {
0056 size_t i;
0057 for (i = 0; i < sizeof ops / sizeof ops[0]; ++i) {
0058 if (ops[i].op == ch) return ops + i;
0059 }
0060 return nullptr;
0061 }
0062
0063 void push_opstack(struct op_s *op, struct op_s **opstack, int &nopstack)
0064 {
0065 if (nopstack > SHUNT_MAXOPSTACK - 1) {
0066 fprintf(stderr, "ERROR: Operator stack overflow\n");
0067 exit(EXIT_FAILURE);
0068 }
0069 opstack[nopstack++] = op;
0070 }
0071
0072 struct op_s *pop_opstack(struct op_s **opstack, int &nopstack)
0073 {
0074 if (!nopstack) {
0075 fprintf(stderr, "ERROR: Operator stack empty\n");
0076 exit(EXIT_FAILURE);
0077 }
0078 return opstack[--nopstack];
0079 }
0080
0081 void push_numstack(bool num, bool *numstack, int &nnumstack)
0082 {
0083 if (nnumstack > SHUNT_MAXNUMSTACK - 1) {
0084 fprintf(stderr, "ERROR: Number stack overflow\n");
0085 exit(EXIT_FAILURE);
0086 }
0087 numstack[nnumstack++] = num;
0088 }
0089
0090 bool pop_numstack(bool *numstack, int &nnumstack)
0091 {
0092 if (!nnumstack) {
0093 fprintf(stderr, "ERROR: Number stack empty\n");
0094 exit(EXIT_FAILURE);
0095 }
0096 return numstack[--nnumstack];
0097 }
0098
0099 void shunt_op(struct op_s *op, struct op_s **opstack, int &nopstack, bool *numstack, int &nnumstack)
0100 {
0101 struct op_s *pop;
0102 bool n1, n2;
0103 if (op->op == '(') {
0104 push_opstack(op, opstack, nopstack);
0105 return;
0106 } else if (op->op == ')') {
0107 while (nopstack > 0 && opstack[nopstack - 1]->op != '(') {
0108 pop = pop_opstack(opstack, nopstack);
0109 n1 = pop_numstack(numstack, nnumstack);
0110 if (pop->unary)
0111 push_numstack(pop->eval(n1, false), numstack, nnumstack);
0112 else {
0113 n2 = pop_numstack(numstack, nnumstack);
0114 push_numstack(pop->eval(n2, n1), numstack, nnumstack);
0115 }
0116 }
0117 if (!(pop = pop_opstack(opstack, nopstack)) || pop->op != '(') {
0118 fprintf(stderr, "ERROR: Stack error. No matching \'(\'\n");
0119 exit(EXIT_FAILURE);
0120 }
0121 return;
0122 }
0123
0124 if (op->assoc == ASSOC_RIGHT) {
0125 while (nopstack && op->prec < opstack[nopstack - 1]->prec) {
0126 pop = pop_opstack(opstack, nopstack);
0127 n1 = pop_numstack(numstack, nnumstack);
0128 if (pop->unary)
0129 push_numstack(pop->eval(n1, 0), numstack, nnumstack);
0130 else {
0131 n2 = pop_numstack(numstack, nnumstack);
0132 push_numstack(pop->eval(n2, n1), numstack, nnumstack);
0133 }
0134 }
0135 } else {
0136 while (nopstack && op->prec <= opstack[nopstack - 1]->prec) {
0137 pop = pop_opstack(opstack, nopstack);
0138 n1 = pop_numstack(numstack, nnumstack);
0139 if (pop->unary)
0140 push_numstack(pop->eval(n1, 0), numstack, nnumstack);
0141 else {
0142 n2 = pop_numstack(numstack, nnumstack);
0143 push_numstack(pop->eval(n2, n1), numstack, nnumstack);
0144 }
0145 }
0146 }
0147 push_opstack(op, opstack, nopstack);
0148 }
0149
0150 bool logic_evaluate(std::string const &slogic)
0151 {
0152 struct op_s *opstack[SHUNT_MAXOPSTACK];
0153 int nopstack = 0;
0154
0155 bool numstack[SHUNT_MAXNUMSTACK];
0156 int nnumstack = 0;
0157 auto tstart = slogic.size();
0158 struct op_s startop = {'X', 0, ASSOC_NONE, 0, NULL};
0159 struct op_s *op = NULL;
0160 int n1, n2;
0161 struct op_s *lastop = &startop;
0162
0163 for (size_t iexpr = 0; iexpr < slogic.size(); ++iexpr) {
0164 if (tstart == slogic.size()) {
0165
0166 if ((op = getop(slogic[iexpr]))) {
0167 if (lastop && (lastop == &startop || lastop->op != ')')) {
0168 if (op->op != '(' && op->op != '!') {
0169 fprintf(stderr, "ERROR: Illegal use of binary operator (%c)\n", op->op);
0170 exit(EXIT_FAILURE);
0171 }
0172 }
0173 shunt_op(op, opstack, nopstack, numstack, nnumstack);
0174 lastop = op;
0175 } else if (isdigit(slogic[iexpr]))
0176 tstart = iexpr;
0177 else if (!isspace(slogic[iexpr])) {
0178 fprintf(stderr, "ERROR: Syntax error\n");
0179 exit(EXIT_FAILURE);
0180 }
0181 } else {
0182 if (isspace(slogic[iexpr])) {
0183 push_numstack(slogic[tstart] - '0', numstack, nnumstack);
0184 tstart = slogic.size();
0185 lastop = nullptr;
0186 } else if ((op = getop(slogic[iexpr]))) {
0187 push_numstack(slogic[tstart] - '0', numstack, nnumstack);
0188 tstart = slogic.size();
0189 shunt_op(op, opstack, nopstack, numstack, nnumstack);
0190 lastop = op;
0191 } else if (!isdigit(slogic[iexpr])) {
0192 fprintf(stderr, "ERROR: Syntax error\n");
0193 exit(EXIT_FAILURE);
0194 }
0195 }
0196 }
0197 if (tstart < slogic.size()) push_numstack(slogic[tstart] - '0', numstack, nnumstack);
0198
0199 while (nopstack) {
0200 op = pop_opstack(opstack, nopstack);
0201 n1 = pop_numstack(numstack, nnumstack);
0202 if (op->unary)
0203 push_numstack(op->eval(n1, 0), numstack, nnumstack);
0204 else {
0205 n2 = pop_numstack(numstack, nnumstack);
0206 push_numstack(op->eval(n2, n1), numstack, nnumstack);
0207 }
0208 }
0209 if (nnumstack != 1) {
0210 fprintf(stderr, "ERROR: Number stack has %d elements after evaluation. Should be 1.\n", nnumstack);
0211 exit(EXIT_FAILURE);
0212 }
0213
0214
0215 return numstack[0];
0216 }
0217 }