$start = abs($HTTP_GET_VARS['start']); } else { $start = 1; } if ($HTTP_GET_VARS['step']) { $step = abs($HTTP_GET_VARS['step']); } else { $step = 10; } $stop = $start + $step; ///////////////////////////////////////////////////// // Put the search term in LoC syntax ///////////////////////////////////////////////////// // convert query syntax from my form of CCL/whatver to the weird prefix // notation used by LoC $term = Query_Convertor::convert_query($term); //@attr 1=4 title //@attr 1=1003 author //@attr 1=7 ISBN //@attr 1=16 LoC Call number if (strlen($term) > 255) { ShelveIt::$messages['warnings'][] = "Your search is too long. It has been truncated from" . strlen($term) . "to 255 characters (including markup). This may cause your search to fail entirely."; $term = substr($term, 0, 255); } switch ($HTTP_GET_VARS['type']) { case Title: $term = '@attr 1=4 ' . $term; break; case Author: $term = '@attr 1=1003 ' . $term; break;
public static function convert_query($query) { // initialize vars $rpn = ""; $stack = array(); //last was an operand $lastWasOpd = false; // put spaces on either side of parens to guarantee they're // seperate tokens $query = str_replace(')', ' ) ', $query); $query = str_replace('(', ' ( ', $query); // break the query into tokens, delimited by spaces self::$tokens = explode(" ", $query); self::$token_count = count(self::$tokens); //while( false ) { for ($i = 0; $i < self::$token_count; $i++) { //ignore empty tokens if (self::$tokens[$i] != "") { if (self::$tokens[$i] == '(') { // push it onto the stack $stack[] = '('; $lastWasOpd = false; } else { if (self::$tokens[$i] == ')') { $lastWasOpd = true; // Keep popping from the stack and prepending to RPN string // until we reach the left parenthesis. $popped = array_pop($stack); while ($popped != '(') { // If stack becomes empty and we didn't reach the left // parenthesis then break out with error "Unbalanced // parenthesis" if ($popped == null) { die("ERROR! Unbalanced parentheses"); } $rpn = $popped . ' ' . $rpn; $lastWasOpd = false; $popped = array_pop($stack); } } else { if (isset(self::$operatorMapping[self::$tokens[$i]])) { // 3. Operator: If stack is empty or operator has a higher // precedence than the top of the stack then push operator // into stack. // Else if operator has lower precedence then we keep // popping and prepending to RPN string, self is repeated // until operator in stack has lower precedence than the // current operator. $curOp = self::$operatorMapping[self::$tokens[$i]]; $topOp = array_pop($stack); if ($topOp == null || $topOp == '(' || self::get_precedence($curOp) > self::get_precedence($topOp)) { $stack[] = $topOp; $stack[] = $curOp; } else { while ($topOp != null && $topOp != '(' && self::get_precedence($curOp) <= self::get_precedence($topOp)) { $rpn = $curOp . ' ' . $rpn; // incrementation step $curOp = $topOp; $topOp = array_pop($stack); } // we may have popped off one extra, if so put it back on if ($topOp == null) { $stack[] = $curOp; } else { $stack[] = $topOp; } } $lastWasOpd = false; } else { //self must be an operand if ($lastWasOpd) { // insert an implicit AND and rewind to handle it self::$tokens[$i - 1] = "AND"; $i -= 2; } else { $fchar = self::$tokens[$i][0]; // detect quotes // note: passing i by ref causes it to be in the right // place. The return value is, therefore, stored in the // last token that was part of the quote. Self both // spares a temp var and allows the part afterwards to // be general if ($fchar == '"' || $fchar == '\'') { // collect quoted part into the last token forming it $temp = self::collect_string($fchar, $i); // note self has to be done because of // strangess in eval order - $i is // incremented in collect string, but the // left-hand of the assignment occurs // before the call self::$tokens[$i] = $temp; } $rpn = self::convert_operand(self::$tokens[$i]) . ' ' . $rpn; $lastWasOpd = true; } } } } } } // if any operators remain on the stack, prepend them now for ($topOp = array_pop($stack); $topOp != null; $topOp = array_pop($stack)) { $rpn = $topOp . ' ' . $rpn; } return $rpn; }