@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * Generates non-sense code snippets according to context-free rules, respecting
5 * indentation etc.
6 *
7 * Also provides a common ruleset shared among many mainstream programming
8 * languages (that is, not Lisp).
9 */
10abstract class PhutilCodeSnippetContextFreeGrammar
11 extends PhutilContextFreeGrammar {
12
13 public function generate() {
14 // A trailing newline is favorable for source code
15 return trim(parent::generate())."\n";
16 }
17
18 final protected function getRules() {
19 return array_merge(
20 $this->getStartGrammarSet(),
21 $this->getStmtGrammarSet(),
22 array_mergev($this->buildRuleSet()));
23 }
24
25 abstract protected function buildRuleSet();
26
27 protected function buildGrammarSet($name, array $set) {
28 return array(
29 $name => $set,
30 );
31 }
32
33 protected function getStartGrammarSet() {
34 return $this->buildGrammarSet('start',
35 array(
36 "[stmt]\n[stmt]",
37 "[stmt]\n[stmt]\n[stmt]",
38 "[stmt]\n[stmt]\n[stmt]\n[stmt]",
39 ));
40 }
41
42 protected function getStmtGrammarSet() {
43 return $this->buildGrammarSet('stmt',
44 array(
45 '[assignment][term]',
46 '[assignment][term]',
47 '[assignment][term]',
48 '[assignment][term]',
49 '[funccall][term]',
50 '[funccall][term]',
51 '[funccall][term]',
52 '[funccall][term]',
53 '[cond]',
54 '[loop]',
55 ));
56 }
57
58 protected function getFuncNameGrammarSet() {
59 return $this->buildGrammarSet('funcname',
60 array(
61 'do_something',
62 'nonempty',
63 'noOp',
64 'call_user_func',
65 'getenv',
66 'render',
67 'super',
68 'derpify',
69 'awesomize',
70 'equals',
71 'run',
72 'flee',
73 'fight',
74 'notify',
75 'listen',
76 'calculate',
77 'aim',
78 'open',
79 ));
80 }
81
82 protected function getVarNameGrammarSet() {
83 return $this->buildGrammarSet('varname',
84 array(
85 'is_something',
86 'object',
87 'name',
88 'token',
89 'label',
90 'piece_of_the_pie',
91 'type',
92 'state',
93 'param',
94 'action',
95 'key',
96 'timeout',
97 'result',
98 ));
99 }
100
101 protected function getNullExprGrammarSet() {
102 return $this->buildGrammarSet('null', array('null'));
103 }
104
105 protected function getNumberGrammarSet() {
106 return $this->buildGrammarSet('number',
107 array(
108 mt_rand(-1, 100),
109 mt_rand(-100, 1000),
110 mt_rand(-1000, 5000),
111 mt_rand(0, 1).'.'.mt_rand(1, 1000),
112 mt_rand(0, 50).'.'.mt_rand(1, 1000),
113 ));
114 }
115
116 protected function getExprGrammarSet() {
117 return $this->buildGrammarSet('expr',
118 array(
119 '[null]',
120 '[number]',
121 '[number]',
122 '[varname]',
123 '[varname]',
124 '[boolval]',
125 '[boolval]',
126 '[boolexpr]',
127 '[boolexpr]',
128 '[funccall]',
129 '[arithexpr]',
130 '[arithexpr]',
131 // Some random strings
132 '"'.Filesystem::readRandomCharacters(4).'"',
133 '"'.Filesystem::readRandomCharacters(5).'"',
134 ));
135 }
136
137 protected function getBoolExprGrammarSet() {
138 return $this->buildGrammarSet('boolexpr',
139 array(
140 '[varname]',
141 '![varname]',
142 '[varname] == [boolval]',
143 '[varname] != [boolval]',
144 '[ternary]',
145 ));
146 }
147
148 protected function getBoolValGrammarSet() {
149 return $this->buildGrammarSet('boolval',
150 array(
151 'true',
152 'false',
153 ));
154 }
155
156 protected function getArithExprGrammarSet() {
157 return $this->buildGrammarSet('arithexpr',
158 array(
159 '[varname]++',
160 '++[varname]',
161 '[varname] + [number]',
162 '[varname]--',
163 '--[varname]',
164 '[varname] - [number]',
165 ));
166 }
167
168 protected function getAssignmentGrammarSet() {
169 return $this->buildGrammarSet('assignment',
170 array(
171 '[varname] = [expr]',
172 '[varname] = [arithexpr]',
173 '[varname] += [expr]',
174 ));
175 }
176
177 protected function getCondGrammarSet() {
178 return $this->buildGrammarSet('cond',
179 array(
180 'if ([boolexpr]) {[stmt, indent, block]}',
181 'if ([boolexpr]) {[stmt, indent, block]} else {[stmt, indent, block]}',
182 ));
183 }
184
185 protected function getLoopGrammarSet() {
186 return $this->buildGrammarSet('loop',
187 array(
188 'while ([boolexpr]) {[stmt, indent, block]}',
189 'do {[stmt, indent, block]} while ([boolexpr])[term]',
190 'for ([assignment]; [boolexpr]; [expr]) {[stmt, indent, block]}',
191 ));
192 }
193
194 protected function getTernaryExprGrammarSet() {
195 return $this->buildGrammarSet('ternary',
196 array(
197 '[boolexpr] ? [expr] : [expr]',
198 ));
199 }
200
201 protected function getStmtTerminationGrammarSet() {
202 return $this->buildGrammarSet('term', array(''));
203 }
204
205}