Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / I18n / Translator / Plural / Parser.php
blob2929b56c3b6bf70e2f66a55dbe4132dcfdc039c7
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\I18n\Translator\Plural;
12 use Zend\I18n\Exception;
14 /**
15 * Plural rule parser.
17 * This plural rule parser is implemented after the article "Top Down Operator
18 * Precedence" described in <http://javascript.crockford.com/tdop/tdop.html>.
20 class Parser
22 /**
23 * String to parse.
25 * @var string
27 protected $string;
29 /**
30 * Current lexer position in the string.
32 * @var int
34 protected $currentPos;
36 /**
37 * Current token.
39 * @var Symbol
41 protected $currentToken;
43 /**
44 * Table of symbols.
46 * @var array
48 protected $symbolTable = array();
50 /**
51 * Create a new plural parser.
54 public function __construct()
56 $this->populateSymbolTable();
59 /**
60 * Populate the symbol table.
62 * @return void
64 protected function populateSymbolTable()
66 // Ternary operators
67 $this->registerSymbol('?', 20)->setLeftDenotationGetter(
68 function (Symbol $self, Symbol $left) {
69 $self->first = $left;
70 $self->second = $self->parser->expression();
71 $self->parser->advance(':');
72 $self->third = $self->parser->expression();
73 return $self;
76 $this->registerSymbol(':');
78 // Boolean operators
79 $this->registerLeftInfixSymbol('||', 30);
80 $this->registerLeftInfixSymbol('&&', 40);
82 // Equal operators
83 $this->registerLeftInfixSymbol('==', 50);
84 $this->registerLeftInfixSymbol('!=', 50);
86 // Compare operators
87 $this->registerLeftInfixSymbol('>', 50);
88 $this->registerLeftInfixSymbol('<', 50);
89 $this->registerLeftInfixSymbol('>=', 50);
90 $this->registerLeftInfixSymbol('<=', 50);
92 // Add operators
93 $this->registerLeftInfixSymbol('-', 60);
94 $this->registerLeftInfixSymbol('+', 60);
96 // Multiply operators
97 $this->registerLeftInfixSymbol('*', 70);
98 $this->registerLeftInfixSymbol('/', 70);
99 $this->registerLeftInfixSymbol('%', 70);
101 // Not operator
102 $this->registerPrefixSymbol('!', 80);
104 // Literals
105 $this->registerSymbol('n')->setNullDenotationGetter(
106 function (Symbol $self) {
107 return $self;
110 $this->registerSymbol('number')->setNullDenotationGetter(
111 function (Symbol $self) {
112 return $self;
116 // Parentheses
117 $this->registerSymbol('(')->setNullDenotationGetter(
118 function (Symbol $self) {
119 $expression = $self->parser->expression();
120 $self->parser->advance(')');
121 return $expression;
124 $this->registerSymbol(')');
126 // Eof
127 $this->registerSymbol('eof');
131 * Register a left infix symbol.
133 * @param string $id
134 * @param int $leftBindingPower
135 * @return void
137 protected function registerLeftInfixSymbol($id, $leftBindingPower)
139 $this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter(
140 function (Symbol $self, Symbol $left) use ($leftBindingPower) {
141 $self->first = $left;
142 $self->second = $self->parser->expression($leftBindingPower);
143 return $self;
149 * Register a right infix symbol.
151 * @param string $id
152 * @param int $leftBindingPower
153 * @return void
155 protected function registerRightInfixSymbol($id, $leftBindingPower)
157 $this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter(
158 function (Symbol $self, Symbol $left) use ($leftBindingPower) {
159 $self->first = $left;
160 $self->second = $self->parser->expression($leftBindingPower - 1);
161 return $self;
167 * Register a prefix symbol.
169 * @param string $id
170 * @param int $leftBindingPower
171 * @return void
173 protected function registerPrefixSymbol($id, $leftBindingPower)
175 $this->registerSymbol($id, $leftBindingPower)->setNullDenotationGetter(
176 function (Symbol $self) use ($leftBindingPower) {
177 $self->first = $self->parser->expression($leftBindingPower);
178 $self->second = null;
179 return $self;
185 * Register a symbol.
187 * @param string $id
188 * @param int $leftBindingPower
189 * @return Symbol
191 protected function registerSymbol($id, $leftBindingPower = 0)
193 if (isset($this->symbolTable[$id])) {
194 $symbol = $this->symbolTable[$id];
195 $symbol->leftBindingPower = max(
196 $symbol->leftBindingPower,
197 $leftBindingPower
199 } else {
200 $symbol = new Symbol($this, $id, $leftBindingPower);
201 $this->symbolTable[$id] = $symbol;
204 return $symbol;
208 * Get a new symbol.
210 * @param string $id
212 protected function getSymbol($id)
214 if (!isset($this->symbolTable[$id])) {
215 // Unkown symbol exception
218 return clone $this->symbolTable[$id];
222 * Parse a string.
224 * @param string $string
225 * @return array
227 public function parse($string)
229 $this->string = $string . "\0";
230 $this->currentPos = 0;
231 $this->currentToken = $this->getNextToken();
233 return $this->expression();
237 * Parse an expression.
239 * @param int $rightBindingPower
240 * @return Symbol
242 public function expression($rightBindingPower = 0)
244 $token = $this->currentToken;
245 $this->currentToken = $this->getNextToken();
246 $left = $token->getNullDenotation();
248 while ($rightBindingPower < $this->currentToken->leftBindingPower) {
249 $token = $this->currentToken;
250 $this->currentToken = $this->getNextToken();
251 $left = $token->getLeftDenotation($left);
254 return $left;
258 * Advance the current token and optionally check the old token id.
260 * @param string $id
261 * @return void
262 * @throws Exception\ParseException
264 public function advance($id = null)
266 if ($id !== null && $this->currentToken->id !== $id) {
267 throw new Exception\ParseException(sprintf(
268 'Expected token with id %s but received %s',
269 $id, $this->currentToken->id
273 $this->currentToken = $this->getNextToken();
277 * Get the next token.
279 * @return array
280 * @throws Exception\ParseException
282 protected function getNextToken()
284 while ($this->string[$this->currentPos] === ' ' || $this->string[$this->currentPos] === "\t") {
285 $this->currentPos++;
288 $result = $this->string[$this->currentPos++];
289 $value = null;
291 switch ($result) {
292 case '0':
293 case '1':
294 case '2':
295 case '3':
296 case '4':
297 case '5':
298 case '6':
299 case '7':
300 case '8':
301 case '9':
302 while (ctype_digit($this->string[$this->currentPos])) {
303 $result .= $this->string[$this->currentPos++];
306 $id = 'number';
307 $value = (int) $result;
308 break;
310 case '=':
311 case '&':
312 case '|':
313 if ($this->string[$this->currentPos] === $result) {
314 $this->currentPos++;
315 $id = $result . $result;
316 } else {
317 // Yield error
319 break;
321 case '!':
322 case '<':
323 case '>':
324 if ($this->string[$this->currentPos] === '=') {
325 $this->currentPos++;
326 $result .= '=';
329 $id = $result;
330 break;
332 case '*':
333 case '/':
334 case '%':
335 case '+':
336 case '-':
337 case 'n':
338 case '?':
339 case ':':
340 case '(':
341 case ')':
342 $id = $result;
343 break;
345 case ';':
346 case "\n":
347 case "\0":
348 $id = 'eof';
349 $this->currentPos--;
350 break;
352 default:
353 throw new Exception\ParseException(sprintf(
354 'Found invalid character "%s" in input stream',
355 $result
357 break;
360 $token = $this->getSymbol($id);
361 $token->value = $value;
363 return $token;