Parsing a string with recursive parentheses

I am trying to parse a string with the following structure in PHP:

a,b,c(d,e,f(g),h,i(j,k)),l,m,n(o),p

For example, the β€œreal” line would be:

id,topic,member(name,email,group(id,name)),message(id,title,body)

My end result should be an array:

[
   id => null,
   topic => null
   member => [
      name => null,
      email => null,
      group => [
         id => null,
         name => null
      ]
   ],
   message => [
      id => null,
      title => null,
      body => null
  ]
]

I tried recursive regex but lost it completely. I have some success in repeating string characters, but it seems a bit "complicated", and I'm sure that this is what a regular expression can handle, I just don't know how to do it.

The goal is to analyze the field request parameter for the REST API to allow the client to select the fields that he wants from a collection of complex objects, and I do not want to limit the "depth" of the field selection.

+4
1

Wiktor, . , , .

, $tokenMap. T_FIELD, T_SEPARATOR, T_OPEN T_CLOSE. $structure.
. , (generate()).

Demo

A ideone.com.

:

// this is our $tokenMap
$tokenMap = array(
    '[^,()]+'       => T_FIELD,     # not comma or parentheses
    ','             => T_SEPARATOR, # a comma
    '\('            => T_OPEN,      # an opening parenthesis
    '\)'            => T_CLOSE      # a closing parenthesis
);

// this is your string
$string = "id,topic,member(name,email,group(id,name)),message(id,title,body)";

// a recursive function to actually build the structure
function generate($arr=array(), $idx=0) {
    $output = array();
    $current = null;
    for($i=$idx;$i<count($arr);$i++) {
        list($element, $type) = $arr[$i];
        if ($type == T_OPEN)
            $output[$current] = generate($arr, $i+1);
        elseif ($type == T_CLOSE)
            return $output;
        elseif ($type == T_FIELD) {
            $output[$element] = null;
            $current = $element;
        }
    }
    return $output;
}

$lex = new Lexer($tokenMap);
$structure = $lex->lex($string);

print_r(generate($structure));
+2

Source: https://habr.com/ru/post/1628937/


All Articles