Version: 1.0
Type: Full Script
Category: Algorithms
License: GNU General Public License
Description: Code to interpret a search criteria which contains boolean operators (and, not , or) and opening and closing brackets ( and ) into tokens and parse it for correctness. You can then read the tokens like in a switch statement and add code such as mysql's LOCATE(<token>,<text column in a mysql table>)>0 to each non reserved (ie not "and", "or", "not", ")" , "(" ) token (a keyword) to check that it appears in the <text column in a mysql table>.
<?php
/*
** Topic: search criteria parser
** Original Author: Lee Aholima, Day Five Consulting Ltd
** History:
** 20021030 - Lee Aholima, Day Five Consulting Ltd
** Created
** 2002**** - editor, co.
** comments
**
** Description:
** Parses search criteria according to the following rules
** E -> E and T
** E -> E or T
** E -> T
** T -> not F
** T -> F
** F -> Id
** F -> (E)
**
** processes search criteria as lowercase.
*/
$rhs = array ("E and T","E or T","T","not F","F","Id","( E )" );
$lhs = array ("E","E","E","T","T","F","F");
function gettokens($str) {
/* put the string into lowercase */
$str = strtolower($str);
/* make sure ( or ) get picked up as separate tokens */
$str = str_replace("("," ( ",$str);
$str = str_replace(")"," ) ",$str);
/* get the actual tokens */
$actualtokens = explode(" ",$str);
/* trim spaces around tokens and discard those which have only spaces in them */
$h=0;
for ($i=0;$i<sizeof($actualtokens);$i++) {
$actualtokens[$i]=trim($actualtokens[$i]);
if ($actualtokens[$i] != "") {
$nospacetokens[$h++] = $actualtokens[$i];
}
}
/* now put together tokens which are actually one token e.g. upper hutt */
$onetoken = "";
$h=0;
for ($i=0;$i<sizeof($nospacetokens);$i++) {
$token = $nospacetokens[$i];
switch ($token) {
case ")" :
if ($onetoken != "") {
$tokens[$h++] = $onetoken;
$onetoken = "";
}
$tokens[$h++] = $token;
break;
case "(" :
if ($onetoken != "") {
$tokens[$h++] = $onetoken;
$onetoken = "";
}
$tokens[$h++] = $token;
break;
case "and" :
if ($onetoken != "") {
$tokens[$h++] = $onetoken;
$onetoken = "";
}
$tokens[$h++] = $token;
break;
case "or" :
if ($onetoken != "") {
$tokens[$h++] = $onetoken;
$onetoken = "";
}
$tokens[$h++] = $token;
break;
case "not" :
if ($onetoken != "") {
$tokens[$h++] = $onetoken;
$onetoken = "";
}
$tokens[$h++] = $token;
break;
default :
if ($onetoken == "") {
$onetoken = $token;
}
else {
$onetoken = $onetoken." ".$token;
}
break;
}
}
if ($onetoken != "") {
$tokens[$h++] = $onetoken;
$onetoken = "";
}
return $tokens;
}
function checkwithrules ($tokens) {
global $rhs;
global $lhs;
$i=0;
$stack="";
while ($i<sizeof($tokens)) {
$token = $tokens[$i];
switch ($token) {
case "and" :
case "or" :
case "not" :
case "(" :
case ")" :
if ($stack == "") {
$stack = $token;
}
else {
$stack = $stack." ".$token;
}
/* go through the rules */
$j=0;
while ( $j<sizeof($rhs) ) {
$len = strlen($rhs[$j]);
$lenstack = strlen($stack);
if ($lenstack < $len) {
$j++;
continue;
}
$str = substr($stack,$lenstack - $len,$len);
echo "<br>stack=".$stack.",str=".$str.",rhs[j]=".$rhs[$j];
if ( $str == $rhs[$j] ) {
$stack = substr($stack,0,$lenstack - $len);
$stack = $stack.$lhs[$j];
$j=0;
}
else {
$j++;
}
}
break;
default :
if ($stack == "") {
$stack = "Id";
}
else {
$stack = $stack." "."Id";
}
/* go through the rules */
$j=0;
while ( $j<sizeof($rhs) ) {
$len = strlen($rhs[$j]);
$lenstack = strlen($stack);
if ($lenstack < $len) {
$j++;
continue;
}
$str = substr($stack,$lenstack - $len,$len);
echo "<br>stack=".$stack.",str=".$str.",rhs[j]=".$rhs[$j];
if ( $str == $rhs[$j] ) {
$stack = substr($stack,0,$lenstack - $len);
$stack = $stack.$lhs[$j];
$j=0;
}
else {
$j++;
}
}
break;
}
$i++;
}
echo "<br>Stack = '".$stack."'";
if ($stack != "E") {
return false;
}
return true;
}
/* End of essential code */
/* Cut and paste from the top of this file to here */
/*-----------------------------------------------------------------*/
echo "<html>";
if (isset($searchcriteria)) {
echo "<br>Search criteria is '".$searchcriteria."'<br>";
echo "<br>The tokens are...<br>";
$tokens = gettokens($searchcriteria);
for ($i=0;$i<sizeof($tokens);$i++)
{
echo "<br>".$tokens[$i];
}
echo "<br><br>Now to check with the rules that it is accepted ";
echo "<br>(should be a whole lot of output showing the analysis)...";
$complieswithrules = checkwithrules($tokens);
if ($complieswithrules == true) {
echo "<br>SUCCESS: complies with the rules";
}
else {
echo "<br>ERROR: does not comply with the rules";
}
}
echo "<form name=searchform action=scp.php method=post>";
echo "<p>Please enter a search criteria an eg would be";
echo "<br>chef and (2nd or Second) and not (wellington or south island)</p>";
echo "<p><input type=text name=searchcriteria size=50 maxlength=255></p>";
echo "<p><input type=submit> <input type=reset></p>";
echo "</html>";
?>