Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - String Logic Parsing - "X AND Y OR Z"

I would like to take a and/or logic query query string of unknown length:

$logic = 'elephants and tigers or dolphins and apes or monkeys and humans and gorillas and and 133322 or 2';

And parse it into an array, I assume would look something like:

$parsed_to_or = array(
  array('elephants', 'tigers'),
  array('dolphins', 'apes'),
  array('monkeys', 'humans', 'gorillas', '133322'),
  array('2')
 );

This is what I have so far:

 $logic_e = preg_split('/\s+/', $logic); 
 $or_segments = array();
 $and_group = array();  
 foreach($logic_e as $fragment) {
  if (preg_match('/^(and|&&)$/i', $fragment)) {
   continue;
  } elseif (preg_match('/^(or|\\|\\|)$/i', $fragment)) {
   if (count($and_group)>0) {
    $or_segments[] = $and_group;
    $and_group = array();
   } continue;
  } else {
   $and_group[] = $fragment;
   continue;
  }
 } 
 if (count($and_group)>0) {
  $or_segments[] = $and_group;
  $and_group = array();
 }

Any better ways to tackle this?

like image 492
user2362840 Avatar asked May 08 '13 14:05

user2362840


1 Answers

Update: Added the ability to use && and || anywhere

You can do the following:

<?php

$logic = 'elephants && tigers || dolphins && apes || monkeys and humans and gorillas and && 133322 or 2';

$result = array();
foreach (preg_split('/ (or|\|\|) /', $logic) as $parts) {
  $bits = preg_split('/ (and|&&) /', $parts);
  for ($x=0; $x<count($bits); $x++) {
    $bits[$x] = preg_replace('/\s?(and|&&)\s?/', '', $bits[$x]);
  }
  $result[] = $bits;
}

echo '<pre>';
var_dump($result);

Which would result in the following:

array(4) {
  [0]=>
  array(2) {
    [0]=>
    string(9) "elephants"
    [1]=>
    string(6) "tigers"
  }
  [1]=>
  array(2) {
    [0]=>
    string(8) "dolphins"
    [1]=>
    string(4) "apes"
  }
  [2]=>
  array(4) {
    [0]=>
    string(7) "monkeys"
    [1]=>
    string(6) "humans"
    [2]=>
    string(8) "gorillas"
    [3]=>
    string(6) "133322"
  }
  [3]=>
  array(1) {
    [0]=>
    string(1) "2"
  }
}
like image 129
LeonardChallis Avatar answered Oct 22 '22 19:10

LeonardChallis