summaryrefslogtreecommitdiffstats
path: root/src/search_stuff.c
blob: 5d4cb6c24f582f73f474749ea480265fce1d9b4d (plain) (blame)
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
#include "util.h"
#include "search.h"

char stk[4048];
int p = 0;

/*
 * expr : (expr) | expr op expr | not expr | term
 * op : and | or
 * term : <string>
 * 
 */

void
reverse_str(char ** s)
{
  int l = strlen(*s);
  char * rev_s = strdup(*s);
  int j = 0;
  for (int i = l - 1; i >= 0; i--, j++) {
    rev_s[j] = (*s)[i];
  }
  rev_s[j] = '\0';
  free(*s);
  *s = rev_s;
}


/*
 * Implementing https://www.javatpoint.com/convert-infix-to-prefix-notation
 *
 * ascii values:
 *   & -> 38
 *   | -> 124
 *   ( -> 40
 *   ) -> 41
 *   a-z -> 97-122
 *   A-Z -> 64-90
 *
 * precidence:
 *   & > |
 * (http://www.cs.ucc.ie/~gavin/cs1001/Notes/chap40/ch40_16.html)
 */
int
precedence(char c)
{
  switch (c) {
  case '&':
    return 100;
  case '|':
    return 50;
  default:
    return 0;
  }
}

void
infix_to_prefix(char ** s)
{
  char * prefixed = malloc(sizeof(char) * strlen(*s) * 2);
  prefixed[0] = '\0';
  char * rev_s = strdup(*s);
  reverse_str(&rev_s);

  for (int i = 0; i < strlen(rev_s); i++) {
    if (rev_s[i] == '&' ||
        rev_s[i] == '|') {
      if (p == 0) {
        stk[p++] = rev_s[i];
      } else {
        if (precedence(rev_s[i] > precedence(stk[p - 1]))) {
          stk[p++] = rev_s[i];
        } else {
          int k = strlen(prefixed);
          for (int j = p; j > 0 || precedence(rev_s[i]) < precedence(stk[p - 1]); j--) {
            prefixed[k++] = stk[j - 1];
            p--;
          }
          prefixed[k] = '\0';
          stk[p++] = rev_s[i];
        }
      }
    }
    else if (rev_s[i] == '(') {
      stk[p++] = rev_s[i];
    }
    else if (rev_s[i] == ')') {
      int k = strlen(prefixed);
      prefixed[k++] = rev_s[i];
      for (int j = p; j > 0 && stk[j] != ')'; j--) {
        prefixed[k++] = stk[j - 1];
        p--;
      }
      prefixed[k] = '\0';
    }
    else {
      int k = strlen(prefixed);
      prefixed[k] = rev_s[i];
      prefixed[k+1] = '\0';
    }
  }

  int k = strlen(prefixed);
  prefixed[k++] = ' '; // add space after the first operator
  for (int j = p; j > 0; j--) {
    prefixed[k++] = stk[j - 1];
    p--;
  }
  prefixed[k] = '\0';

  printf("rev %s\n", prefixed);
  for (int i = 0; i < strlen(prefixed); i++) {
    if (prefixed[i] == '(' &&
        i < strlen(prefixed) &&
        (prefixed[i+1] == '&' || prefixed[i+1] == '|')) {
      prefixed[i] = prefixed[i+1];
      prefixed[i+1] = '(';
    }
  }

  printf("rev fixed %s\n", prefixed);
  reverse_str(&prefixed);
  free(rev_s);
  free(*s);
  *s = prefixed;
}