@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
at upstream/main 205 lines 4.8 kB view raw
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}