MediaWiki  1.34.0
ExprParser.php
Go to the documentation of this file.
1 <?php
20 
21 use UtfNormal\Validator;
22 
23 // @codeCoverageIgnoreStart
24 
25 // Character classes
26 define( 'EXPR_WHITE_CLASS', " \t\r\n" );
27 define( 'EXPR_NUMBER_CLASS', '0123456789.' );
28 
29 // Token types
30 define( 'EXPR_WHITE', 1 );
31 define( 'EXPR_NUMBER', 2 );
32 define( 'EXPR_NEGATIVE', 3 );
33 define( 'EXPR_POSITIVE', 4 );
34 define( 'EXPR_PLUS', 5 );
35 define( 'EXPR_MINUS', 6 );
36 define( 'EXPR_TIMES', 7 );
37 define( 'EXPR_DIVIDE', 8 );
38 define( 'EXPR_MOD', 9 );
39 define( 'EXPR_OPEN', 10 );
40 define( 'EXPR_CLOSE', 11 );
41 define( 'EXPR_AND', 12 );
42 define( 'EXPR_OR', 13 );
43 define( 'EXPR_NOT', 14 );
44 define( 'EXPR_EQUALITY', 15 );
45 define( 'EXPR_LESS', 16 );
46 define( 'EXPR_GREATER', 17 );
47 define( 'EXPR_LESSEQ', 18 );
48 define( 'EXPR_GREATEREQ', 19 );
49 define( 'EXPR_NOTEQ', 20 );
50 define( 'EXPR_ROUND', 21 );
51 define( 'EXPR_EXPONENT', 22 );
52 define( 'EXPR_SINE', 23 );
53 define( 'EXPR_COSINE', 24 );
54 define( 'EXPR_TANGENS', 25 );
55 define( 'EXPR_ARCSINE', 26 );
56 define( 'EXPR_ARCCOS', 27 );
57 define( 'EXPR_ARCTAN', 28 );
58 define( 'EXPR_EXP', 29 );
59 define( 'EXPR_LN', 30 );
60 define( 'EXPR_ABS', 31 );
61 define( 'EXPR_FLOOR', 32 );
62 define( 'EXPR_TRUNC', 33 );
63 define( 'EXPR_CEIL', 34 );
64 define( 'EXPR_POW', 35 );
65 define( 'EXPR_PI', 36 );
66 define( 'EXPR_FMOD', 37 );
67 define( 'EXPR_SQRT', 38 );
68 
69 // @codeCoverageIgnoreEnd
70 
71 class ExprParser {
72  public $maxStackSize = 100;
73 
74  public $precedence = [
75  EXPR_NEGATIVE => 10,
76  EXPR_POSITIVE => 10,
77  EXPR_EXPONENT => 10,
78  EXPR_SINE => 9,
79  EXPR_COSINE => 9,
80  EXPR_TANGENS => 9,
81  EXPR_ARCSINE => 9,
82  EXPR_ARCCOS => 9,
83  EXPR_ARCTAN => 9,
84  EXPR_EXP => 9,
85  EXPR_LN => 9,
86  EXPR_ABS => 9,
87  EXPR_FLOOR => 9,
88  EXPR_TRUNC => 9,
89  EXPR_CEIL => 9,
90  EXPR_NOT => 9,
91  EXPR_SQRT => 9,
92  EXPR_POW => 8,
93  EXPR_TIMES => 7,
94  EXPR_DIVIDE => 7,
95  EXPR_MOD => 7,
96  EXPR_FMOD => 7,
97  EXPR_PLUS => 6,
98  EXPR_MINUS => 6,
99  EXPR_ROUND => 5,
100  EXPR_EQUALITY => 4,
101  EXPR_LESS => 4,
102  EXPR_GREATER => 4,
103  EXPR_LESSEQ => 4,
104  EXPR_GREATEREQ => 4,
105  EXPR_NOTEQ => 4,
106  EXPR_AND => 3,
107  EXPR_OR => 2,
108  EXPR_PI => 0,
109  EXPR_OPEN => -1,
110  EXPR_CLOSE => -1,
111  ];
112 
113  public $names = [
114  EXPR_NEGATIVE => '-',
115  EXPR_POSITIVE => '+',
116  EXPR_NOT => 'not',
117  EXPR_TIMES => '*',
118  EXPR_DIVIDE => '/',
119  EXPR_MOD => 'mod',
120  EXPR_FMOD => 'fmod',
121  EXPR_PLUS => '+',
122  EXPR_MINUS => '-',
123  EXPR_ROUND => 'round',
124  EXPR_EQUALITY => '=',
125  EXPR_LESS => '<',
126  EXPR_GREATER => '>',
127  EXPR_LESSEQ => '<=',
128  EXPR_GREATEREQ => '>=',
129  EXPR_NOTEQ => '<>',
130  EXPR_AND => 'and',
131  EXPR_OR => 'or',
132  EXPR_EXPONENT => 'e',
133  EXPR_SINE => 'sin',
134  EXPR_COSINE => 'cos',
135  EXPR_TANGENS => 'tan',
136  EXPR_ARCSINE => 'asin',
137  EXPR_ARCCOS => 'acos',
138  EXPR_ARCTAN => 'atan',
139  EXPR_LN => 'ln',
140  EXPR_EXP => 'exp',
141  EXPR_ABS => 'abs',
142  EXPR_FLOOR => 'floor',
143  EXPR_TRUNC => 'trunc',
144  EXPR_CEIL => 'ceil',
145  EXPR_POW => '^',
146  EXPR_PI => 'pi',
147  EXPR_SQRT => 'sqrt',
148  ];
149 
150  public $words = [
151  'mod' => EXPR_MOD,
152  'fmod' => EXPR_FMOD,
153  'and' => EXPR_AND,
154  'or' => EXPR_OR,
155  'not' => EXPR_NOT,
156  'round' => EXPR_ROUND,
157  'div' => EXPR_DIVIDE,
158  'e' => EXPR_EXPONENT,
159  'sin' => EXPR_SINE,
160  'cos' => EXPR_COSINE,
161  'tan' => EXPR_TANGENS,
162  'asin' => EXPR_ARCSINE,
163  'acos' => EXPR_ARCCOS,
164  'atan' => EXPR_ARCTAN,
165  'exp' => EXPR_EXP,
166  'ln' => EXPR_LN,
167  'abs' => EXPR_ABS,
168  'trunc' => EXPR_TRUNC,
169  'floor' => EXPR_FLOOR,
170  'ceil' => EXPR_CEIL,
171  'pi' => EXPR_PI,
172  'sqrt' => EXPR_SQRT,
173  ];
174 
185  public function doExpression( $expr ) {
186  $operands = [];
187  $operators = [];
188 
189  # Unescape inequality operators
190  $expr = strtr( $expr, [ '&lt;' => '<', '&gt;' => '>',
191  '&minus;' => '-', '−' => '-' ] );
192 
193  $p = 0;
194  $end = strlen( $expr );
195  $expecting = 'expression';
196  $name = '';
197 
198  while ( $p < $end ) {
199  if ( count( $operands ) > $this->maxStackSize || count( $operators ) > $this->maxStackSize ) {
200  throw new ExprError( 'stack_exhausted' );
201  }
202  $char = $expr[$p];
203  $char2 = substr( $expr, $p, 2 );
204 
205  // Mega if-elseif-else construct
206  // Only binary operators fall through for processing at the bottom, the rest
207  // finish their processing and continue
208 
209  // First the unlimited length classes
210 
211  // @phan-suppress-next-line PhanParamSuspiciousOrder false positive
212  if ( false !== strpos( EXPR_WHITE_CLASS, $char ) ) {
213  // Whitespace
214  $p += strspn( $expr, EXPR_WHITE_CLASS, $p );
215  continue;
216  // @phan-suppress-next-line PhanParamSuspiciousOrder false positive
217  } elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) {
218  // Number
219  if ( $expecting !== 'expression' ) {
220  throw new ExprError( 'unexpected_number' );
221  }
222 
223  // Find the rest of it
224  $length = strspn( $expr, EXPR_NUMBER_CLASS, $p );
225  // Convert it to float, silently removing double decimal points
226  $operands[] = (float)substr( $expr, $p, $length );
227  $p += $length;
228  $expecting = 'operator';
229  continue;
230  } elseif ( ctype_alpha( $char ) ) {
231  // Word
232  // Find the rest of it
233  $remaining = substr( $expr, $p );
234  if ( !preg_match( '/^[A-Za-z]*/', $remaining, $matches ) ) {
235  // This should be unreachable
236  throw new ExprError( 'preg_match_failure' );
237  }
238  $word = strtolower( $matches[0] );
239  $p += strlen( $word );
240 
241  // Interpret the word
242  if ( !isset( $this->words[$word] ) ) {
243  throw new ExprError( 'unrecognised_word', $word );
244  }
245  $op = $this->words[$word];
246  switch ( $op ) {
247  // constant
248  case EXPR_EXPONENT:
249  if ( $expecting !== 'expression' ) {
250  break;
251  }
252  $operands[] = exp( 1 );
253  $expecting = 'operator';
254  continue 2;
255  case EXPR_PI:
256  if ( $expecting !== 'expression' ) {
257  throw new ExprError( 'unexpected_number' );
258  }
259  $operands[] = pi();
260  $expecting = 'operator';
261  continue 2;
262  // Unary operator
263  case EXPR_NOT:
264  case EXPR_SINE:
265  case EXPR_COSINE:
266  case EXPR_TANGENS:
267  case EXPR_ARCSINE:
268  case EXPR_ARCCOS:
269  case EXPR_ARCTAN:
270  case EXPR_EXP:
271  case EXPR_LN:
272  case EXPR_ABS:
273  case EXPR_FLOOR:
274  case EXPR_TRUNC:
275  case EXPR_CEIL:
276  case EXPR_SQRT:
277  if ( $expecting !== 'expression' ) {
278  throw new ExprError( 'unexpected_operator', $word );
279  }
280  $operators[] = $op;
281  continue 2;
282  }
283  // Binary operator, fall through
284  $name = $word;
285  } elseif ( $char2 === '<=' ) {
286  $name = $char2;
287  $op = EXPR_LESSEQ;
288  $p += 2;
289  } elseif ( $char2 === '>=' ) {
290  $name = $char2;
291  $op = EXPR_GREATEREQ;
292  $p += 2;
293  } elseif ( $char2 === '<>' || $char2 === '!=' ) {
294  $name = $char2;
295  $op = EXPR_NOTEQ;
296  $p += 2;
297  } elseif ( $char === '+' ) {
298  ++$p;
299  if ( $expecting === 'expression' ) {
300  // Unary plus
301  $operators[] = EXPR_POSITIVE;
302  continue;
303  } else {
304  // Binary plus
305  $op = EXPR_PLUS;
306  }
307  } elseif ( $char === '-' ) {
308  ++$p;
309  if ( $expecting === 'expression' ) {
310  // Unary minus
311  $operators[] = EXPR_NEGATIVE;
312  continue;
313  } else {
314  // Binary minus
315  $op = EXPR_MINUS;
316  }
317  } elseif ( $char === '*' ) {
318  $name = $char;
319  $op = EXPR_TIMES;
320  ++$p;
321  } elseif ( $char === '/' ) {
322  $name = $char;
323  $op = EXPR_DIVIDE;
324  ++$p;
325  } elseif ( $char === '^' ) {
326  $name = $char;
327  $op = EXPR_POW;
328  ++$p;
329  } elseif ( $char === '(' ) {
330  if ( $expecting === 'operator' ) {
331  throw new ExprError( 'unexpected_operator', '(' );
332  }
333  $operators[] = EXPR_OPEN;
334  ++$p;
335  continue;
336  } elseif ( $char === ')' ) {
337  $lastOp = end( $operators );
338  while ( $lastOp && $lastOp != EXPR_OPEN ) {
339  $this->doOperation( $lastOp, $operands );
340  array_pop( $operators );
341  $lastOp = end( $operators );
342  }
343  if ( $lastOp ) {
344  array_pop( $operators );
345  } else {
346  throw new ExprError( 'unexpected_closing_bracket' );
347  }
348  $expecting = 'operator';
349  ++$p;
350  continue;
351  } elseif ( $char === '=' ) {
352  $name = $char;
353  $op = EXPR_EQUALITY;
354  ++$p;
355  } elseif ( $char === '<' ) {
356  $name = $char;
357  $op = EXPR_LESS;
358  ++$p;
359  } elseif ( $char === '>' ) {
360  $name = $char;
361  $op = EXPR_GREATER;
362  ++$p;
363  } else {
364  $utfExpr = Validator::cleanUp( substr( $expr, $p ) );
365  throw new ExprError( 'unrecognised_punctuation', mb_substr( $utfExpr, 0, 1 ) );
366  }
367 
368  // Binary operator processing
369  if ( $expecting === 'expression' ) {
370  throw new ExprError( 'unexpected_operator', $name );
371  }
372 
373  // Shunting yard magic
374  $lastOp = end( $operators );
375  while ( $lastOp && $this->precedence[$op] <= $this->precedence[$lastOp] ) {
376  $this->doOperation( $lastOp, $operands );
377  array_pop( $operators );
378  $lastOp = end( $operators );
379  }
380  $operators[] = $op;
381  $expecting = 'expression';
382  }
383 
384  // Finish off the operator array
385  // @codingStandardsIgnoreStart
386  while ( $op = array_pop( $operators ) ) {
387  // @codingStandardsIgnoreEnd
388  if ( $op == EXPR_OPEN ) {
389  throw new ExprError( 'unclosed_bracket' );
390  }
391  $this->doOperation( $op, $operands );
392  }
393 
394  return implode( "<br />\n", $operands );
395  }
396 
402  public function doOperation( $op, &$stack ) {
403  switch ( $op ) {
404  case EXPR_NEGATIVE:
405  if ( count( $stack ) < 1 ) {
406  throw new ExprError( 'missing_operand', $this->names[$op] );
407  }
408  $arg = array_pop( $stack );
409  $stack[] = -$arg;
410  break;
411  case EXPR_POSITIVE:
412  if ( count( $stack ) < 1 ) {
413  throw new ExprError( 'missing_operand', $this->names[$op] );
414  }
415  break;
416  case EXPR_TIMES:
417  if ( count( $stack ) < 2 ) {
418  throw new ExprError( 'missing_operand', $this->names[$op] );
419  }
420  $right = array_pop( $stack );
421  $left = array_pop( $stack );
422  $stack[] = $left * $right;
423  break;
424  case EXPR_DIVIDE:
425  if ( count( $stack ) < 2 ) {
426  throw new ExprError( 'missing_operand', $this->names[$op] );
427  }
428  $right = array_pop( $stack );
429  $left = array_pop( $stack );
430  if ( !$right ) {
431  throw new ExprError( 'division_by_zero', $this->names[$op] );
432  }
433  $stack[] = $left / $right;
434  break;
435  case EXPR_MOD:
436  if ( count( $stack ) < 2 ) {
437  throw new ExprError( 'missing_operand', $this->names[$op] );
438  }
439  $right = (int)array_pop( $stack );
440  $left = (int)array_pop( $stack );
441  if ( !$right ) {
442  throw new ExprError( 'division_by_zero', $this->names[$op] );
443  }
444  $stack[] = $left % $right;
445  break;
446  case EXPR_FMOD:
447  if ( count( $stack ) < 2 ) {
448  throw new ExprError( 'missing_operand', $this->names[$op] );
449  }
450  $right = (double)array_pop( $stack );
451  $left = (double)array_pop( $stack );
452  if ( !$right ) {
453  throw new ExprError( 'division_by_zero', $this->names[$op] );
454  }
455  $stack[] = fmod( $left, $right );
456  break;
457  case EXPR_PLUS:
458  if ( count( $stack ) < 2 ) {
459  throw new ExprError( 'missing_operand', $this->names[$op] );
460  }
461  $right = array_pop( $stack );
462  $left = array_pop( $stack );
463  $stack[] = $left + $right;
464  break;
465  case EXPR_MINUS:
466  if ( count( $stack ) < 2 ) {
467  throw new ExprError( 'missing_operand', $this->names[$op] );
468  }
469  $right = array_pop( $stack );
470  $left = array_pop( $stack );
471  $stack[] = $left - $right;
472  break;
473  case EXPR_AND:
474  if ( count( $stack ) < 2 ) {
475  throw new ExprError( 'missing_operand', $this->names[$op] );
476  }
477  $right = array_pop( $stack );
478  $left = array_pop( $stack );
479  $stack[] = ( $left && $right ) ? 1 : 0;
480  break;
481  case EXPR_OR:
482  if ( count( $stack ) < 2 ) {
483  throw new ExprError( 'missing_operand', $this->names[$op] );
484  }
485  $right = array_pop( $stack );
486  $left = array_pop( $stack );
487  $stack[] = ( $left || $right ) ? 1 : 0;
488  break;
489  case EXPR_EQUALITY:
490  if ( count( $stack ) < 2 ) {
491  throw new ExprError( 'missing_operand', $this->names[$op] );
492  }
493  $right = array_pop( $stack );
494  $left = array_pop( $stack );
495  $stack[] = ( $left == $right ) ? 1 : 0;
496  break;
497  case EXPR_NOT:
498  if ( count( $stack ) < 1 ) {
499  throw new ExprError( 'missing_operand', $this->names[$op] );
500  }
501  $arg = array_pop( $stack );
502  $stack[] = ( !$arg ) ? 1 : 0;
503  break;
504  case EXPR_ROUND:
505  if ( count( $stack ) < 2 ) {
506  throw new ExprError( 'missing_operand', $this->names[$op] );
507  }
508  $digits = (int)array_pop( $stack );
509  $value = array_pop( $stack );
510  $stack[] = round( $value, $digits );
511  break;
512  case EXPR_LESS:
513  if ( count( $stack ) < 2 ) {
514  throw new ExprError( 'missing_operand', $this->names[$op] );
515  }
516  $right = array_pop( $stack );
517  $left = array_pop( $stack );
518  $stack[] = ( $left < $right ) ? 1 : 0;
519  break;
520  case EXPR_GREATER:
521  if ( count( $stack ) < 2 ) {
522  throw new ExprError( 'missing_operand', $this->names[$op] );
523  }
524  $right = array_pop( $stack );
525  $left = array_pop( $stack );
526  $stack[] = ( $left > $right ) ? 1 : 0;
527  break;
528  case EXPR_LESSEQ:
529  if ( count( $stack ) < 2 ) {
530  throw new ExprError( 'missing_operand', $this->names[$op] );
531  }
532  $right = array_pop( $stack );
533  $left = array_pop( $stack );
534  $stack[] = ( $left <= $right ) ? 1 : 0;
535  break;
536  case EXPR_GREATEREQ:
537  if ( count( $stack ) < 2 ) {
538  throw new ExprError( 'missing_operand', $this->names[$op] );
539  }
540  $right = array_pop( $stack );
541  $left = array_pop( $stack );
542  $stack[] = ( $left >= $right ) ? 1 : 0;
543  break;
544  case EXPR_NOTEQ:
545  if ( count( $stack ) < 2 ) {
546  throw new ExprError( 'missing_operand', $this->names[$op] );
547  }
548  $right = array_pop( $stack );
549  $left = array_pop( $stack );
550  $stack[] = ( $left != $right ) ? 1 : 0;
551  break;
552  case EXPR_EXPONENT:
553  if ( count( $stack ) < 2 ) {
554  throw new ExprError( 'missing_operand', $this->names[$op] );
555  }
556  $right = array_pop( $stack );
557  $left = array_pop( $stack );
558  $stack[] = $left * pow( 10, $right );
559  break;
560  case EXPR_SINE:
561  if ( count( $stack ) < 1 ) {
562  throw new ExprError( 'missing_operand', $this->names[$op] );
563  }
564  $arg = array_pop( $stack );
565  $stack[] = sin( $arg );
566  break;
567  case EXPR_COSINE:
568  if ( count( $stack ) < 1 ) {
569  throw new ExprError( 'missing_operand', $this->names[$op] );
570  }
571  $arg = array_pop( $stack );
572  $stack[] = cos( $arg );
573  break;
574  case EXPR_TANGENS:
575  if ( count( $stack ) < 1 ) {
576  throw new ExprError( 'missing_operand', $this->names[$op] );
577  }
578  $arg = array_pop( $stack );
579  $stack[] = tan( $arg );
580  break;
581  case EXPR_ARCSINE:
582  if ( count( $stack ) < 1 ) {
583  throw new ExprError( 'missing_operand', $this->names[$op] );
584  }
585  $arg = array_pop( $stack );
586  if ( $arg < -1 || $arg > 1 ) {
587  throw new ExprError( 'invalid_argument', $this->names[$op] );
588  }
589  $stack[] = asin( $arg );
590  break;
591  case EXPR_ARCCOS:
592  if ( count( $stack ) < 1 ) {
593  throw new ExprError( 'missing_operand', $this->names[$op] );
594  }
595  $arg = array_pop( $stack );
596  if ( $arg < -1 || $arg > 1 ) {
597  throw new ExprError( 'invalid_argument', $this->names[$op] );
598  }
599  $stack[] = acos( $arg );
600  break;
601  case EXPR_ARCTAN:
602  if ( count( $stack ) < 1 ) {
603  throw new ExprError( 'missing_operand', $this->names[$op] );
604  }
605  $arg = array_pop( $stack );
606  $stack[] = atan( $arg );
607  break;
608  case EXPR_EXP:
609  if ( count( $stack ) < 1 ) {
610  throw new ExprError( 'missing_operand', $this->names[$op] );
611  }
612  $arg = array_pop( $stack );
613  $stack[] = exp( $arg );
614  break;
615  case EXPR_LN:
616  if ( count( $stack ) < 1 ) {
617  throw new ExprError( 'missing_operand', $this->names[$op] );
618  }
619  $arg = array_pop( $stack );
620  if ( $arg <= 0 ) {
621  throw new ExprError( 'invalid_argument_ln', $this->names[$op] );
622  }
623  $stack[] = log( $arg );
624  break;
625  case EXPR_ABS:
626  if ( count( $stack ) < 1 ) {
627  throw new ExprError( 'missing_operand', $this->names[$op] );
628  }
629  $arg = array_pop( $stack );
630  $stack[] = abs( $arg );
631  break;
632  case EXPR_FLOOR:
633  if ( count( $stack ) < 1 ) {
634  throw new ExprError( 'missing_operand', $this->names[$op] );
635  }
636  $arg = array_pop( $stack );
637  $stack[] = floor( $arg );
638  break;
639  case EXPR_TRUNC:
640  if ( count( $stack ) < 1 ) {
641  throw new ExprError( 'missing_operand', $this->names[$op] );
642  }
643  $arg = array_pop( $stack );
644  $stack[] = (int)$arg;
645  break;
646  case EXPR_CEIL:
647  if ( count( $stack ) < 1 ) {
648  throw new ExprError( 'missing_operand', $this->names[$op] );
649  }
650  $arg = array_pop( $stack );
651  $stack[] = ceil( $arg );
652  break;
653  case EXPR_POW:
654  if ( count( $stack ) < 2 ) {
655  throw new ExprError( 'missing_operand', $this->names[$op] );
656  }
657  $right = array_pop( $stack );
658  $left = array_pop( $stack );
659  $result = pow( $left, $right );
660  if ( $result === false ) {
661  throw new ExprError( 'division_by_zero', $this->names[$op] );
662  }
663  $stack[] = $result;
664  break;
665  case EXPR_SQRT:
666  if ( count( $stack ) < 1 ) {
667  throw new ExprError( 'missing_operand', $this->names[$op] );
668  }
669  $arg = array_pop( $stack );
670  $result = sqrt( $arg );
671  if ( is_nan( $result ) ) {
672  throw new ExprError( 'not_a_number', $this->names[$op] );
673  }
674  $stack[] = $result;
675  break;
676  default:
677  // Should be impossible to reach here.
678  // @codeCoverageIgnoreStart
679  throw new ExprError( 'unknown_error' );
680  // @codeCoverageIgnoreEnd
681  }
682  }
683 }
MediaWiki\Extensions\ParserFunctions\EXPR_TIMES
const EXPR_TIMES
Definition: ExprParser.php:36
MediaWiki\Extensions\ParserFunctions\EXPR_OPEN
const EXPR_OPEN
Definition: ExprParser.php:39
MediaWiki\Extensions\ParserFunctions\EXPR_NUMBER_CLASS
const EXPR_NUMBER_CLASS
Definition: ExprParser.php:27
MediaWiki\Extensions\ParserFunctions\ExprParser
Definition: ExprParser.php:71
MediaWiki\Extensions\ParserFunctions\EXPR_EQUALITY
const EXPR_EQUALITY
Definition: ExprParser.php:44
MediaWiki\Extensions\ParserFunctions\ExprParser\doExpression
doExpression( $expr)
Evaluate a mathematical expression.
Definition: ExprParser.php:185
MediaWiki\Extensions\ParserFunctions\EXPR_SINE
const EXPR_SINE
Definition: ExprParser.php:52
MediaWiki\Extensions\ParserFunctions\EXPR_FMOD
const EXPR_FMOD
Definition: ExprParser.php:66
MediaWiki\Extensions\ParserFunctions\EXPR_ARCSINE
const EXPR_ARCSINE
Definition: ExprParser.php:55
MediaWiki\Extensions\ParserFunctions\ExprParser\doOperation
doOperation( $op, &$stack)
Definition: ExprParser.php:402
MediaWiki\Extensions\ParserFunctions\ExprParser\$names
$names
Definition: ExprParser.php:113
MediaWiki\Extensions\ParserFunctions\EXPR_POW
const EXPR_POW
Definition: ExprParser.php:64
MediaWiki\Extensions\ParserFunctions\EXPR_EXP
const EXPR_EXP
Definition: ExprParser.php:58
MediaWiki\Extensions\ParserFunctions\ExprParser\$maxStackSize
$maxStackSize
Definition: ExprParser.php:72
MediaWiki\Extensions\ParserFunctions\EXPR_LESS
const EXPR_LESS
Definition: ExprParser.php:45
MediaWiki\Extensions\ParserFunctions\EXPR_LESSEQ
const EXPR_LESSEQ
Definition: ExprParser.php:47
MediaWiki\Extensions\ParserFunctions\EXPR_OR
const EXPR_OR
Definition: ExprParser.php:42
$matches
$matches
Definition: NoLocalSettings.php:24
MediaWiki\Extensions\ParserFunctions\ExprParser\$words
$words
Definition: ExprParser.php:150
MediaWiki\Extensions\ParserFunctions\EXPR_SQRT
const EXPR_SQRT
Definition: ExprParser.php:67
MediaWiki\Extensions\ParserFunctions\EXPR_DIVIDE
const EXPR_DIVIDE
Definition: ExprParser.php:37
MediaWiki\Extensions\ParserFunctions\EXPR_MOD
const EXPR_MOD
Definition: ExprParser.php:38
MediaWiki\Extensions\ParserFunctions\EXPR_CLOSE
const EXPR_CLOSE
Definition: ExprParser.php:40
MediaWiki\Extensions\ParserFunctions\EXPR_ARCCOS
const EXPR_ARCCOS
Definition: ExprParser.php:56
MediaWiki\Extensions\ParserFunctions\EXPR_NOTEQ
const EXPR_NOTEQ
Definition: ExprParser.php:49
MediaWiki\Extensions\ParserFunctions\EXPR_MINUS
const EXPR_MINUS
Definition: ExprParser.php:35
MediaWiki\Extensions\ParserFunctions\EXPR_CEIL
const EXPR_CEIL
Definition: ExprParser.php:63
MediaWiki\Extensions\ParserFunctions
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
Definition: ExprError.php:19
MediaWiki\Extensions\ParserFunctions\EXPR_COSINE
const EXPR_COSINE
Definition: ExprParser.php:53
MediaWiki\Extensions\ParserFunctions\EXPR_ROUND
const EXPR_ROUND
Definition: ExprParser.php:50
MediaWiki\Extensions\ParserFunctions\EXPR_WHITE_CLASS
const EXPR_WHITE_CLASS
Definition: ExprParser.php:26
MediaWiki\Extensions\ParserFunctions\EXPR_GREATER
const EXPR_GREATER
Definition: ExprParser.php:46
MediaWiki\Extensions\ParserFunctions\EXPR_AND
const EXPR_AND
Definition: ExprParser.php:41
MediaWiki\Extensions\ParserFunctions\EXPR_NOT
const EXPR_NOT
Definition: ExprParser.php:43
MediaWiki\Extensions\ParserFunctions\EXPR_PLUS
const EXPR_PLUS
Definition: ExprParser.php:34
MediaWiki\Extensions\ParserFunctions\ExprError
Definition: ExprError.php:24
MediaWiki\Extensions\ParserFunctions\EXPR_TRUNC
const EXPR_TRUNC
Definition: ExprParser.php:62
MediaWiki\Extensions\ParserFunctions\EXPR_TANGENS
const EXPR_TANGENS
Definition: ExprParser.php:54
MediaWiki\Extensions\ParserFunctions\ExprParser\$precedence
$precedence
Definition: ExprParser.php:74
MediaWiki\Extensions\ParserFunctions\EXPR_FLOOR
const EXPR_FLOOR
Definition: ExprParser.php:61
MediaWiki\Extensions\ParserFunctions\EXPR_EXPONENT
const EXPR_EXPONENT
Definition: ExprParser.php:51
MediaWiki\Extensions\ParserFunctions\EXPR_PI
const EXPR_PI
Definition: ExprParser.php:65
MediaWiki\Extensions\ParserFunctions\EXPR_POSITIVE
const EXPR_POSITIVE
Definition: ExprParser.php:33
MediaWiki\Extensions\ParserFunctions\EXPR_ABS
const EXPR_ABS
Definition: ExprParser.php:60
MediaWiki\Extensions\ParserFunctions\EXPR_GREATEREQ
const EXPR_GREATEREQ
Definition: ExprParser.php:48
MediaWiki\Extensions\ParserFunctions\EXPR_ARCTAN
const EXPR_ARCTAN
Definition: ExprParser.php:57
MediaWiki\Extensions\ParserFunctions\EXPR_NEGATIVE
const EXPR_NEGATIVE
Definition: ExprParser.php:32
MediaWiki\Extensions\ParserFunctions\EXPR_LN
const EXPR_LN
Definition: ExprParser.php:59