Changeset 842669
- Timestamp:
- 01/21/2014 09:22:11 PM (12 years ago)
- Location:
- jazzy-forms/trunk
- Files:
-
- 3 edited
-
core/Parser.php (modified) (4 diffs)
-
jazzy-forms.php (modified) (3 diffs)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
jazzy-forms/trunk/core/Parser.php
r839285 r842669 5 5 formula = comparison; 6 6 comparison = concatenation, [("<" | ">" | "<=" | "=>" | "<>"), comparison]; 7 concatenation = sum, [ "&", concatenation ]; 8 sum = product, [("+" | "-"), sum]; 9 product = exponentiation, [("*" | "/"), product]; 10 exponentiation = negation, ["^", exponentiation]; 11 negation = ["-"], percentage 7 concatenation = addition, [ "&", concatenation ]; 8 addition = subtraction, ["+", addition]; 9 subtraction = product, ["-", difference]; 10 multiplication = division, ["*", multiplication]; 11 division = exponentiation, ["/", division]; 12 exponentiation = additive_inverse, ["^", exponentiation]; 13 additive_inverse = ["-"], percentage 12 14 percentage = term ["%"] 13 15 term = number | string | function | identifier | association; … … 39 41 40 42 class Jzzf_Parser { 43 private $rest; 44 private $rule_stack; 45 private $result_stack; 46 41 47 public function __construct($tokens) { 42 48 $this->rest = $tokens; 43 } 44 49 $this->execution_stack = array(); 50 $this->result_stack = array(); 51 } 52 53 private function push_execution($step, $data=null) { 54 array_push($this->execution_stack, array($step, $data)); 55 } 56 57 private function pop_execution() { 58 return array_pop($this->execution_stack); 59 } 60 61 private function push_result($result) { 62 array_push($this->result_stack, $result); 63 } 64 65 private function pop_result() { 66 return array_pop($this->result_stack); 67 } 68 45 69 public function output() { 46 $result = $this->comparison(); 70 $this->push_execution('operation', 'comparison'); 71 while($this->execution_stack) { 72 //$this->dump(); 73 list($step, $data) = $this->pop_execution(); 74 $this->$step($data); 75 } 76 //$this->dump(); 47 77 if($this->rest) { 48 78 throw new Exception('unexpected trailing symbols'); 49 79 } 80 if(!$this->result_stack) { 81 $result = array(); 82 } else { 83 $result = $this->pop_result(); 84 } 85 if($this->result_stack) { 86 throw new Exception('internal parsing error'); 87 } 50 88 return $result; 51 89 } 52 90 53 private function comparison() { 54 return $this->operation('comparison', array('<=', '>=', '<', '>', '=', '<>'), 'concatenation'); 55 } 56 57 private function concatenation() { 58 return $this->operation('concatenation', array('&'), 'sum'); 59 } 60 61 private function sum() { 62 return $this->operation('sum', array('+', '-'), 'product'); 63 } 64 65 private function product() { 66 return $this->operation('product', array('*', '/'), 'exponentiation'); 67 } 68 69 private function exponentiation() { 70 return $this->operation('exponentiation', '^', 'negation'); 71 } 72 73 private function operation($name, $operators, $subordinate) { 74 $left = $this->$subordinate(); 75 if(!$left) { 76 return array(); 77 } 78 if($this->ahead($operators)) { 79 $op = $this->consume(); 80 $right = $this->$name(); 81 if(!$right) { 82 throw new Exception('missing right operand'); 83 return array(); 84 } 85 return array('o', $op[0], $left, $right); 86 } 87 return $left; 88 } 89 91 private function operation($rule) { 92 $left_subrules = array( 93 'comparison' => 'concatenation', 94 'concatenation' => 'addition', 95 'addition' => 'subtraction', 96 'subtraction' => 'multiplication', 97 'multiplication' => 'division', 98 'division' => 'exponentiation', 99 'exponentiation' => 'additive_inverse' 100 ); 101 $this->push_execution('operation_ahead', $rule); 102 $left_subrule = $left_subrules[$rule]; 103 if($left_subrule == 'additive_inverse') { 104 $this->push_execution($left_subrule); 105 } else { 106 $this->push_execution('operation', $left_subrules[$rule]); 107 } 108 } 109 110 private function operation_ahead($rule) { 111 static $operators = array( 112 'comparison' => array("<", ">", "<=", ">=", "<>", "="), 113 'concatenation' => array("&"), 114 'addition' => array("+"), 115 'subtraction' => array("-"), 116 'multiplication' => array("*"), 117 'division' => array("/"), 118 'exponentiation' => array("^") 119 ); 120 if($this->ahead($operators[$rule])) { 121 $operator = $this->consume(); 122 $this->push_execution('operation_production', $operator[0]); 123 $this->push_execution('operation', $rule); 124 } 125 } 126 127 private function operation_production($operator) { 128 $right = $this->pop_result(); 129 $left = $this->pop_result(); 130 $this->push_result(array('o', $operator, $left, $right)); 131 } 132 90 133 private function ahead($tokens, $skip=0) { 91 134 if(count($this->rest) <= $skip) { … … 116 159 117 160 private function arguments() { 118 $num = 0; 119 $result = array(); 120 $first = $this->comparison(); 121 if($first) { 122 $result[] = $first; 123 } 124 while(true) { 125 if($this->ahead(')')) { 126 break; 127 } 128 if($this->ahead(',')) { 129 $this->consume(); 130 $next = $this->comparison(); 131 $result[] = $next; 132 $num++; 133 } else { 134 throw new Exception("Closing bracket or comma expected"); 135 } 136 } 137 $this->consume(); // closing bracket 138 return $result; 161 if(!$this->ahead(')')) { 162 $this->push_execution('arguments_production', 1); 163 $this->push_execution('operation', 'comparison'); 164 } else { 165 $this->push_execution('arguments_production', 0); 166 } 167 } 168 169 private function arguments_production($number) { 170 if($this->ahead(')')) { 171 $this->consume(); 172 $arguments = array(); 173 for($i=0; $i<$number; $i++) { 174 $argument = $this->pop_result(); 175 array_unshift($arguments, $argument); 176 } 177 $this->push_result($arguments); 178 } elseif($this->ahead(',')) { 179 $this->consume(); 180 $this->push_execution('arguments_production', $number+1); 181 $this->push_execution('operation', 'comparison'); 182 } else { 183 throw new Exception('Closing bracket or comma expected'); 184 } 139 185 } 140 186 … … 142 188 $id = $this->consume(); 143 189 $this->consume(); 144 $args = $this->arguments(); 145 return array_merge(array('f', strtolower($id[1])), $args); 190 $this->push_execution('func_production', strtolower($id[1])); 191 $this->push_execution('arguments', 0); 192 } 193 194 private function func_production($id) { 195 $args = $this->pop_result(); 196 $result = array_merge(array('f', $id), $args); 197 $this->push_result($result); 146 198 } 147 199 148 200 private function variable() { 149 201 $id = $this->consume(); 150 return array('v', strtolower($id[1]));202 $this->push_result(array('v', strtolower($id[1]))); 151 203 } 152 204 153 205 private function association() { 154 206 $this->consume(); 155 $content = $this->comparison(); 156 if(!$content) { 157 throw new Exception('Empty bracket term'); 158 } 207 208 $this->push_execution('association_production'); 209 $this->push_execution('operation', 'comparison'); 210 } 211 212 private function association_production() { 213 $content = $this->pop_result(); 159 214 if(!$this->ahead(')')) { 160 215 throw new Exception('Close bracket expected'); 161 216 } 162 217 $this->consume(); 163 return $content;164 } 165 166 private function negation() {218 $this->push_result($content); 219 } 220 221 private function additive_inverse() { 167 222 if($this->ahead('-')) { 168 223 $this->consume(); 169 if($this->ahead('n')) { 170 $num = $this->consume(); 171 $num[1] *= (-1); 172 return $num; 173 } else { 174 $positive = $this->percentage(); 175 if(!$positive) { 176 throw new Exception('missing negation operand'); 177 return array(); 178 } 179 return array("o", "-", array("n", 0), $positive); 180 } 181 } else { 182 return $this->percentage(); 224 $this->push_execution('additive_inverse_production'); 225 } 226 $this->push_execution('percentage'); 227 } 228 229 private function additive_inverse_production() { 230 $operand = $this->pop_result(); 231 if(!$operand) { 232 throw new Exception('missing operand for additive inverse'); 233 } 234 if($operand[0] == 'n') { 235 $operand[1] *= (-1); 236 $this->push_result($operand); 237 } else { 238 $this->push_result(array("o", "-", array("n", 0), $operand)); 183 239 } 184 240 } 185 241 186 242 private function percentage() { 187 $value = $this->term(); 188 if($this->ahead('%')) { 189 if(!$value) { 190 throw new Exception("Unexpected percentage sign"); 191 } 243 $this->push_execution('percentage_production'); 244 $this->push_execution('term'); 245 } 246 247 private function percentage_production() { 248 $value = $this->pop_result(); 249 if($this->ahead(array('%'))) { 192 250 $this->consume(); 193 251 if($value[0] == 'n') { 194 252 $value[1] /= 100; 195 return $value;253 $this->push_result($value); 196 254 } else { 197 return array("o", "/", $value, array("n", 100)); 198 } 199 } 200 return $value; 255 $this->push_result(array("o", "/", $value, array("n", 100))); 256 } 257 } else { 258 $this->push_result($value); 259 } 201 260 } 202 261 203 262 private function term() { 204 //$this->dump();205 263 if($this->complete()) { 206 return array();264 $this->push_result(array()); 207 265 } 208 266 else if($this->ahead(array('n', 's'))) { // number or string 209 return $this->consume();267 $this->push_result($this->consume()); 210 268 } 211 269 else if($this->ahead('i')) { // identifier 212 270 if($this->ahead('(', 1)) { 213 return $this->func(); 214 } 215 return $this->variable(); 271 $this->push_execution('func'); 272 } else { 273 $this->push_execution('variable'); 274 } 216 275 } 217 276 else if($this->ahead('(')) { 218 return $this->association(); 219 } 220 return null; 277 $this->push_execution('association'); 278 } 279 else { 280 $this->push_result(array()); 281 } 221 282 } 222 283 223 284 // for debugging only 224 285 private function dump() { 225 print json_encode($this->rest) . "\n"; 286 print "Rest: " . json_encode($this->rest) . "\n"; 287 print "Execution stack: " . json_encode($this->execution_stack) . "\n"; 288 print "Result stack: " . json_encode($this->result_stack) . "\n"; 226 289 } 227 290 } -
jazzy-forms/trunk/jazzy-forms.php
r839285 r842669 4 4 Plugin URI: http://www.jazzyforms.com/ 5 5 Description: Online form builder with an emphasis on calculation 6 Version: 1.1 6 Version: 1.1.1 7 7 Author: Igor Prochazka 8 8 Author URI: http://www.jazzyforms.com/ … … 28 28 */ 29 29 30 define(JZZF_VERSION, 1.010 0);31 define(JZZF_VERSION_STRING, "1.010 0");30 define(JZZF_VERSION, 1.0101); 31 define(JZZF_VERSION_STRING, "1.0101"); 32 32 define(JZZF_OPTION_VERSION, 'jzzf_version'); 33 33 … … 66 66 67 67 function jzzf_admin() { 68 $page = add_menu_page( 'Forms', 'Forms', 8, 'jzzf_forms_top', 'jzzf_forms', null, 30);68 $page = add_menu_page( 'Forms', 'Forms', 8, 'jzzf_forms_top', 'jzzf_forms', null, '30.08161929'); 69 69 /* add_submenu_page('jzzf_forms_top', "Data", "Data", 8, 'jzzf_data', 'jzzf_data'); */ 70 70 add_action('admin_print_styles-' . $page, 'jzzf_head'); -
jazzy-forms/trunk/readme.txt
r839285 r842669 5 5 Requires at least: 3.2.1 6 6 Tested up to: 3.8 7 Stable tag: 1.1 7 Stable tag: 1.1.1 8 8 9 9 Online form builder, ideal for cost-estimates and calculations … … 118 118 119 119 == Changelog == 120 121 = 1.1.1 = 122 * Fix operator precedence 123 * Avoid excessive recursion (nested functions error) 124 * Avoid conflicts in backend menu position 120 125 121 126 = 1.1 =
Note: See TracChangeset
for help on using the changeset viewer.