tags:

views:

131

answers:

5

Hello

I'm trying to develop a function that can sort through a string that looks like this:

Donny went to the {park|store|{beach with friends|beach alone}} so he could get a breath of fresh air. 

What I intend to do is search the text recursively for {} patterns where there is no { or } inside the {}, so only the innermost sandwiched text is selected, where I will then run a php to array the contents and select one at random, repeating process until the whole string has been parsed, showing a complete sentence.

I just cannot wrap my head around regular expressions though.

Appreciate any help!

+1  A: 

Regexes are not capable of counting and therefore cannot find matching brackets reliably.

What you need is a grammar.

See this related question.

Ben S
Amen, brother!!
Agos
No, what he needs is a function which *uses* a regular expression. There is no need to solve the whole problem with a single regex.
kemp
Regex is overkill for such a simple operation. Save yourself some headaches later and write it "longhand" now.
Billy ONeal
No, he doesn't need a grammar and regexp is just the right tool for the job. See kemp's and mine answers.
stereofrog
A: 

You could do this with a lexer/parser. I don't know of any options in PHP (but since there are XML parsers in PHP, there are no doubt generic parsers). On the other hand, what you're asking to do is not too complicated. Using strings in PHP (substring, etc.) you could probably do this in a few recursive functions.

You will then finally have created a MadLibz generator in PHP with a simple grammar. Pretty cool.

Yar
+1  A: 
$str="Donny went to the {park|store|{beach {with friends}|beach alone}} so he could get a breath of fresh air. ";
$s = explode("}",$str);
foreach($s as $v){
 if(strpos($v,"{")!==FALSE){
  $t=explode("{",$v);
  print end($t)."\n";
 }
}

output

$ php test.php
with friends
ghostdog74
+2  A: 

Don't know about maths theory behind this ;-/ but in practice that's quite easy. Try

$text = "Donny went to the {park|store|{beach with friends|beach alone}} so he could get a breath of fresh air. ";

function rnd($matches) {
    $words = explode('|', $matches[1]);
    return $words[rand() % count($words)];
}

do {
    $text = preg_replace_callback('~{([^{}]+)}~', 'rnd', $text, -1, $count);
} while($count > 0);

echo $text;
stereofrog
A: 

Regular expressions don't deal well with recursive stuff, but PHP does:

$str = 'Donny went to the {park|store|{beach with friends|beach alone}} so he could get a breath of fresh air.';

echo parse_string($str), "\n";

function parse_string($string) {
    if ( preg_match('/\{([^{}]+)\}/', $string, $matches) ) {
        $inner_elements = explode('|', $matches[1]);
        $random_element = $inner_elements[array_rand($inner_elements)];
        $string = str_replace($matches[0], $random_element, $string);
        $string = parse_string($string);
    }
    return $string;
}
kemp
Why the downvote? The code is perfectly working and answers the question.
kemp
Downvote compensated. The code does the trick (although mine is nicer;)
stereofrog