Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/lipsum/PhutilContextFreeGrammar.php
12249 views
1
<?php
2
3
/**
4
* Generate nonsense test data according to a context-free grammar definition.
5
*/
6
abstract class PhutilContextFreeGrammar extends Phobject {
7
8
private $limit = 65535;
9
10
abstract protected function getRules();
11
12
public function generateSeveral($count, $implode = ' ') {
13
$paragraph = array();
14
for ($ii = 0; $ii < $count; $ii++) {
15
$paragraph[$ii] = $this->generate();
16
}
17
return implode($implode, $paragraph);
18
}
19
20
public function generate() {
21
$count = 0;
22
$rules = $this->getRules();
23
return $this->applyRules('[start]', $count, $rules);
24
}
25
26
final protected function applyRules($input, &$count, array $rules) {
27
if (++$count > $this->limit) {
28
throw new Exception(pht('Token replacement count exceeded limit!'));
29
}
30
31
$matches = null;
32
preg_match_all('/(\\[[^\\]]+\\])/', $input, $matches, PREG_OFFSET_CAPTURE);
33
34
foreach (array_reverse($matches[1]) as $token_spec) {
35
list($token, $offset) = $token_spec;
36
$token_name = substr($token, 1, -1);
37
$options = array();
38
39
if (($name_end = strpos($token_name, ','))) {
40
$options_parser = new PhutilSimpleOptions();
41
$options = $options_parser->parse($token_name);
42
$token_name = substr($token_name, 0, $name_end);
43
}
44
45
if (empty($rules[$token_name])) {
46
throw new Exception(pht("Invalid token '%s' in grammar.", $token_name));
47
}
48
49
$key = array_rand($rules[$token_name]);
50
$replacement = $this->applyRules($rules[$token_name][$key],
51
$count, $rules);
52
53
if (isset($options['indent'])) {
54
if (is_numeric($options['indent'])) {
55
$replacement = self::strPadLines($replacement, $options['indent']);
56
} else {
57
$replacement = self::strPadLines($replacement);
58
}
59
}
60
if (isset($options['trim'])) {
61
switch ($options['trim']) {
62
case 'left':
63
$replacement = ltrim($replacement);
64
break;
65
case 'right':
66
$replacement = rtrim($replacement);
67
break;
68
default:
69
case 'both':
70
$replacement = trim($replacement);
71
break;
72
}
73
}
74
if (isset($options['block'])) {
75
$replacement = "\n".$replacement."\n";
76
}
77
78
$input = substr_replace($input, $replacement, $offset, strlen($token));
79
}
80
81
return $input;
82
}
83
84
private static function strPadLines($text, $num_spaces = 2) {
85
$text_lines = phutil_split_lines($text);
86
foreach ($text_lines as $linenr => $line) {
87
$text_lines[$linenr] = str_repeat(' ', $num_spaces).$line;
88
}
89
90
return implode('', $text_lines);
91
}
92
93
}
94
95