Path: blob/master/src/infrastructure/lipsum/PhutilContextFreeGrammar.php
12249 views
<?php12/**3* Generate nonsense test data according to a context-free grammar definition.4*/5abstract class PhutilContextFreeGrammar extends Phobject {67private $limit = 65535;89abstract protected function getRules();1011public function generateSeveral($count, $implode = ' ') {12$paragraph = array();13for ($ii = 0; $ii < $count; $ii++) {14$paragraph[$ii] = $this->generate();15}16return implode($implode, $paragraph);17}1819public function generate() {20$count = 0;21$rules = $this->getRules();22return $this->applyRules('[start]', $count, $rules);23}2425final protected function applyRules($input, &$count, array $rules) {26if (++$count > $this->limit) {27throw new Exception(pht('Token replacement count exceeded limit!'));28}2930$matches = null;31preg_match_all('/(\\[[^\\]]+\\])/', $input, $matches, PREG_OFFSET_CAPTURE);3233foreach (array_reverse($matches[1]) as $token_spec) {34list($token, $offset) = $token_spec;35$token_name = substr($token, 1, -1);36$options = array();3738if (($name_end = strpos($token_name, ','))) {39$options_parser = new PhutilSimpleOptions();40$options = $options_parser->parse($token_name);41$token_name = substr($token_name, 0, $name_end);42}4344if (empty($rules[$token_name])) {45throw new Exception(pht("Invalid token '%s' in grammar.", $token_name));46}4748$key = array_rand($rules[$token_name]);49$replacement = $this->applyRules($rules[$token_name][$key],50$count, $rules);5152if (isset($options['indent'])) {53if (is_numeric($options['indent'])) {54$replacement = self::strPadLines($replacement, $options['indent']);55} else {56$replacement = self::strPadLines($replacement);57}58}59if (isset($options['trim'])) {60switch ($options['trim']) {61case 'left':62$replacement = ltrim($replacement);63break;64case 'right':65$replacement = rtrim($replacement);66break;67default:68case 'both':69$replacement = trim($replacement);70break;71}72}73if (isset($options['block'])) {74$replacement = "\n".$replacement."\n";75}7677$input = substr_replace($input, $replacement, $offset, strlen($token));78}7980return $input;81}8283private static function strPadLines($text, $num_spaces = 2) {84$text_lines = phutil_split_lines($text);85foreach ($text_lines as $linenr => $line) {86$text_lines[$linenr] = str_repeat(' ', $num_spaces).$line;87}8889return implode('', $text_lines);90}9192}939495