/**
  * Helper function, returns the tokenized version of js code
  */
 public function tokenize($code)
 {
     $tokenizer = new JavaScript_Tokenizer($code);
     return $tokenizer->tokenize();
 }
 /**
  * Parse tokens
  *
  * @param string $functionName Function name that indicates translatable string, will be tokenized
  * @param array $map Array containing what variables it will find (e.g: domain, singular, plural)
  * @return void
  */
 protected function _parse($functionName, $map)
 {
     $count = 0;
     $tokenCount = count($this->_tokens);
     // tokenize function name
     $tokenizer = new JavaScript_Tokenizer($functionName);
     $tokenPattern = $tokenizer->tokenize();
     // last token is always eof, so remove that one
     array_pop($tokenPattern);
     if (count($tokenPattern) == 0 || $tokenPattern[count($tokenPattern) - 1]->type != 'name') {
         throw new Exception('The supplied functionName to search seems to be malformed, got: ' . $functionName);
     }
     $tokenPatternHead = array_shift($tokenPattern);
     $tokenPatternTail = $tokenPattern;
     // expect an opening parenthesis after the functon name
     array_push($tokenPatternTail, new JS_Token('punc', '(', 0, 0, 0, ''));
     // run though all tokens
     do {
         // for each token
         // check against first needle part
         if ($tokenPatternHead->type == current($this->_tokens)->type && $tokenPatternHead->value == current($this->_tokens)->value) {
             // found new tokenizer start
             $match = true;
             foreach ($tokenPatternTail as $pos => $needle) {
                 if (next($this->_tokens)->type != $needle->type || current($this->_tokens)->value != $needle->value) {
                     $match = false;
                     // go these number of steps back
                     for ($i = 0; $i < $pos; $i++) {
                         prev($this->_tokens);
                     }
                     // stop
                     break;
                 }
             }
             next($this->_tokens);
             if ($match) {
                 // found new match
                 $collector = new JavaScriptStringCollector($this->_tokens);
                 // the translatable string
                 $singulars = array();
                 try {
                     $singulars = $collector->parse();
                 } catch (JavaScriptStringCollectorGotVariableException $e) {
                     $this->_markerError($this->_file, $functionName, $this->_tokens, $collector->getTokens(), __d('cake_console', "Expected a string instead of a variable."));
                     continue;
                 }
                 // jump to new current position
                 $this->_tokens = $collector->getTokens();
                 $additionalArguments = array();
                 while (current($this->_tokens)->type == 'punc' && current($this->_tokens)->value == ',') {
                     // found extra comma, so expect another string
                     next($this->_tokens);
                     // collect the string value/variable, but don't do anything with them (just for syntax checking)
                     try {
                         $collector = new JavaScriptStringCollector($this->_tokens, true);
                         array_push($additionalArguments, $collector->parse());
                         $this->_tokens = $collector->getTokens();
                     } catch (JavaScriptStringCollectorParrserException $e) {
                         $this->_markerError($this->_file, $functionName, $this->_token, $collector->getTokens());
                     }
                 }
                 // check strings if possible %s match given arguments
                 // TOD: $replacements = preg_match_all("%s", $singular, $matches);
                 // collect the domain later
                 $domain = 'bancha';
                 // add translation
                 $details = array('file' => $this->_file, 'line' => current($this->_tokens)->line + 1);
                 //$details['msgid_plural'] = $plural;
                 foreach ($singulars as $singular) {
                     $this->_addTranslation($domain, $singular, $details);
                 }
                 // expect a closing parenthesis now
                 if (current($this->_tokens)->type != 'punc' || current($this->_tokens)->value != ')') {
                     $this->_markerError($this->_file, $functionName, $this->_token, false, __d('cake_console', "Expected closing parenthesis."));
                 }
                 next($this->_tokens);
             }
         }
     } while (next($this->_tokens) !== false && current($this->_tokens)->type != 'eof');
 }