/**
  * Parses a non-bracketed expression
  *
  * Returns a ClauseGroup for a multi-part expression, or returns a string for an
  * expression containing just one (<col> <test> <value>) part
  */
 private function parse($clause)
 {
     // If the input string is essentially empty then return null
     if (trim($clause) == '') {
         return null;
     }
     // Ensure that ANDs and ORs are not mixed
     $strAnd = ClauseGroup::BOOLEAN_AND;
     $strOr = ClauseGroup::BOOLEAN_OR;
     $boolAnd = strpos($clause, " {$strAnd} ") !== false;
     $boolOr = strpos($clause, " {$strOr} ") !== false;
     if ($boolAnd && $boolOr) {
         throw new SyntaxError("Need to bracket ANDs and ORs to indicate precedence in clause <{$clause}>");
     }
     if ($boolOr) {
         $split = $strOr;
     } elseif ($boolAnd) {
         $split = $strAnd;
     } else {
         $split = null;
     }
     // If applicable, split the clause into subclauses and decide the type
     if ($split) {
         $subClauses = explode(" {$split} ", $clause);
     } else {
         $subClauses = array($clause);
     }
     $group = new ClauseGroup();
     $group->setType($split);
     // Then add all the subclauses in
     foreach ($subClauses as $subClause) {
         if (trim($subClause) != '') {
             QuotedStringParser::insertStrings($subClause, $this->strings);
             $group->addSubclause($subClause);
         }
     }
     // If there is only one subclause, return a string rather than a ClauseGroup
     /*
     		$subClauseArray = $group->getSubclauses();
     		if (count($subClauseArray) == 1)
     		{
     			return $subClauseArray[0];
     		}
     		else
     		{
     			return $group;
     		}*/
     return $group;
 }
$t->diag('QuotedStringParser::replace');
$subject = 'person.age = 18';
$result = QuotedStringParser::replace($subject, 'Hello', 'Goodbye');
$t->ok($subject === $result, "Search for something that doesn't exist in a non-quoted string");
$result = QuotedStringParser::replace($subject, '=', '!=');
$ok = $result === 'person.age != 18';
$t->ok($ok, "Search for something that exists in a non-quoted string");
$subject = "rule.cond = 'LIKE'";
$result = QuotedStringParser::replace($subject, 'LIKE', 'HATE');
$t->ok($subject === $result, "Search for something that exists only within a quoted string");
$result = QuotedStringParser::replace($subject, 'WIBBLE', 'BLAH');
$t->ok($subject === $result, "Search for something that does not exist at all in a quoted string");
$result = QuotedStringParser::replace($subject, '=', '<>');
$ok = $result === "rule.cond <> 'LIKE'";
$t->ok($ok, "Search for something that exists outside of a quoted string");
$subject = "(person.name > 21 AND name='(not sure)')";
$result = QuotedStringParser::replace($subject, '\\(', '');
$result = QuotedStringParser::replace($result, '\\)', '');
$ok = $result === "person.name > 21 AND name='(not sure)'";
$t->ok($ok, "Remove brackets, but not in string");
$t = new lime_test(3, new lime_output_color());
$t->diag('QuotedStringParser::extractStrings');
$subject = "person.location IN ('Brum','Coventry')";
$strs = array();
QuotedStringParser::extractStrings($subject, $strs);
$t->ok($subject == "person.location IN (%%0,%%1)", 'Extract strings from an IN clause');
$subject = "person.name = '%%0'";
$strs = array();
QuotedStringParser::extractStrings($subject, $strs);
$t->ok($subject == "person.name = %%0", "Check that tokens don't confuse string extraction");
$t->ok($strs[0] == "'%%0'", "Check that strings are correctly saved");