Activity - Query expressions solution
One pseduo code solution:
PROCESS QUERY
// Create two counters initially set to NULL:
counters_t *andSequence // holds result of current AND operations
counters_t *orSequence // accumulates the final result combining OR sequences
shortCircuit = false // stop early if AND sequence will fail
Loop over all words in query
if word == OR
// orSequence holds final result, merge in andSequence seen so far
// think of stepping back after previously stepping away to calculate AND
MERGE(andSequence, orSequence)
shortCicuit = false //reset shortCircuit
continue
if shortCircuit
// at least one word returned no results, so AND sequence will fail
// skip the words until see OR and shortCircuit is reset
continue
if word == AND
continue to next word // same as if AND wasn't there
else found non operator word
// think of stepping away to calculate AND sequence
get pages for this word with match = index_find(word)
if match == NULL // no pages contain this query word
shortCircuit = true // AND will fail for next word, so skip it and others until see OR
if andSequence != NULL
// because this word returned no pages, drop everything AND'ed so far
delete andSequence
andSequence = NULL
else // found counters for this word in index
if andSequence == NULL // this is the first word of AND sequence
andSequence = new counters
UNION(andSequence, match) //essentially copies match to andSequence
else // not first word in AND sequence
INTERSECT(andSequence, match) //intersect this word's pages
MERGE(andSequence, orSequence)
return orSequence
MERGE(andSequence, orSequence):
// push temporary result andSequence to final result orSequence
// also reset andSequence
if andSequence != NULL
if orSequence == NULL
orSequence = new counters
UNION(orSequence, andSequence) //union andSequence into orSequence
delete andSequence and set to NULL
UNION(orSequence, otherSequence)
// union orSequence and otherSequence by adding counts for matching keys
// store results in orSequence
counters_iterate(otherSequence, orSequence, unionFunction)
unionFunction(arg, key, count)
// update arg counters
wordCount = counters_get(arg, key) // returns 0 if key not found
counters_set(arg, key, count + wordCount)
INTERSECT(orSequence, otherSequence)
// intersect orSequence and otherSequence by taking of counts for matching keys
// store results in orSequence
struct twocounters args = {orSequence, otherSequence}
counters_iterate(orSequence, args, intersectFunction)
intersectFunction(arg, key, count)
counters_set(arg->orSequence, key, min(count, counters_get(args->otherSequence, key)))