Example #1
0
 /**
  * Recieves parse data from the context tree. Sends the
  * data on to the code parser, then to the renderer for
  * building the result string
  */
 function addParseData($code, $context_name, array $data = array(), $complex = false)
 {
     // @todo [blocking 1.1.5] test this, esp. not passing back anything and passing back multiple
     // can use PHP code parser for this
     // @todo [blocking 1.1.9] since we are only looking for whitespace at start and end this can
     // be optimised
     if (GESHI_COMPLEX_NO == $complex) {
         $this->_addToParsedCode(array($code, $context_name, $data));
     } elseif (GESHI_COMPLEX_PASSALL == $complex) {
         // Parse all at once
         $this->_addToParsedCode($this->_codeParser->parseToken($code, $context_name, $data));
     } elseif (GESHI_COMPLEX_TOKENISE == $complex) {
         $matches = array();
         preg_match_all('/^(\\s*)(.*?)(\\s*)$/si', $code, $matches);
         //echo 'START<br />';
         //print_r($matches);
         if ($matches[1][0]) {
             $this->_addToParsedCode($this->_codeParser->parseToken($matches[1][0], $context_name, $data));
         }
         if ('' != $matches[2][0]) {
             while ('' != $matches[2][0]) {
                 $pos = geshi_get_position($matches[2][0], 'REGEX#(\\s+)#');
                 if (false !== $pos['pos']) {
                     // Parse the token up to the whitespace
                     //echo 'code: |' . substr($matches[2][0], 0, $pos['pos']) . '|<br />';
                     $this->_addToParsedCode($this->_codeParser->parseToken(substr($matches[2][0], 0, $pos['pos']), $context_name, $data));
                     // Parse the whitespace
                     //echo 'ws: |' . substr($matches[2][0], $pos['pos'], $pos['len']) . '|<br />';
                     $this->_addToParsedCode($this->_codeParser->parseToken(substr($matches[2][0], $pos['pos'], $pos['len']), $context_name, $data));
                     // Trim what we just parsed
                     $matches[2][0] = substr($matches[2][0], $pos['pos'] + $pos['len']);
                 } else {
                     // No more whitespace
                     //echo 'no more whitespace: |' . $matches[2][0] . '<br />';
                     $this->_addToParsedCode($this->_codeParser->parseToken($matches[2][0], $context_name, $data));
                     break;
                 }
             }
         }
         if ($matches[3][0]) {
             $this->_addToParsedCode($this->_codeParser->parseToken($matches[3][0], $context_name, $data));
         }
     }
     // else wtf???
 }
 /**
  * Adds code detected as being in this context to the parse data
  */
 function _addParseData($code, $first_char_of_next_context = '')
 {
     $parent_name = $this->_parentName;
     geshi_dbg('GeSHiPHPDoubleStringContext::_addParseData(' . substr($code, 0, 15) . '...)');
     while (true) {
         $earliest_data = array('pos' => false, 'len' => 0);
         foreach ($this->_regexes as $regex) {
             $data = geshi_get_position($code, $regex, 0, false, true);
             // request table
             if (false != $data['pos'] && false === $earliest_data['pos'] || false !== $data['pos'] && ($data['pos'] < $earliest_data['pos'] || $data['pos'] == $earliest_data['pos'] && $data['len'] > $earliest_data['len'])) {
                 $earliest_data = $data;
             }
         }
         if (false === $earliest_data['pos']) {
             // No more variables in this string
             break;
         }
         // bugfix: because we match a var, it might have been escaped.
         // so only do to -1 so we can catch slash if it has been
         $pos = $earliest_data['pos'] ? $earliest_data['pos'] - 1 : 0;
         $len = $earliest_data['pos'] ? $earliest_data['len'] + 1 : $earliest_data['len'];
         parent::_addParseData(substr($code, 0, $pos));
         // Now the entire possible var is in:
         $possible_var = substr($code, $pos, $len);
         geshi_dbg('Found variable at position ' . $earliest_data['pos'] . '(' . $possible_var . ')');
         // Check that the dollar sign that started this variable was not escaped
         //$first_part = str_replace('\\\\', '', substr($code, 0, $pos));
         //if ('\\' == substr($first_part, -1)) {
         // If \\ before var and { is not next character after that...
         if ('\\' == substr($possible_var, 0, 1) && '{' != substr($possible_var, 1, 1)) {
             // This variable has been escaped, so add the escaped dollar sign
             // as the correct context, and the rest of the variable (recurse to catch
             // other variables inside this possible variable)
             geshi_dbg('Variable was escaped');
             $this->_styler->addParseData(substr($possible_var, 0, 2), $parent_name . '/esc', $this->_getExtraParseData(), $this->_complexFlag);
             $this->_addParseData(substr($possible_var, 2));
         } else {
             // Add first character that might have been a \\ but in fact isn't to the parent
             // but only do it if we had to modify the position
             if ('$' != substr($possible_var, 0, 1)) {
                 parent::_addParseData(substr($possible_var, 0, 1));
                 $possible_var = substr($possible_var, 1);
             }
             // Many checks could go in here...
             // @todo [blocking 1.1.5] check for ${foo} variables: start { matched by end }
             // because at the moment ${foo is matched for example.
             if ('{' == substr($possible_var, 0, 1)) {
                 if ('}' == substr($possible_var, -1)) {
                     $start_brace = '{';
                 } else {
                     $start_brace = '';
                     parent::_addParseData('{');
                     // remove brace from $possible_var. This will only be used
                     // if the variable isn't an OO variable anyway...
                     $possible_var = substr($possible_var, 1);
                 }
             } else {
                 $start_brace = '';
             }
             if (isset($earliest_data['tab'][5])) {
                 // Then we matched off the third regex - the one that does objects
                 // The first { if there is one, and $this (which is in index 2
                 $this->_styler->addParseData($start_brace . $earliest_data['tab'][2], $parent_name . '/var', $this->_getExtraParseData(), $this->_complexFlag);
                 // The -> with any whitespace around it
                 $this->_styler->addParseData($earliest_data['tab'][3], $parent_name . '/symbol', $this->_getExtraParseData(), $this->_complexFlag);
                 // The method name
                 $this->_styler->addParseData($earliest_data['tab'][4], $parent_name . '/oodynamic', $this->_getExtraParseData(), $this->_complexFlag);
                 // The closing }, if any
                 if ($earliest_data['tab'][5]) {
                     if ($start_brace) {
                         $this->_styler->addParseData($earliest_data['tab'][5], $parent_name . '/var', $this->_getExtraParseData(), $this->_complexFlag);
                     } else {
                         parent::_addParseData('}');
                     }
                 }
             } else {
                 $this->_styler->addParseData($possible_var, $parent_name . '/var', $this->_getExtraParseData(), $this->_complexFlag);
             }
         }
         // Chop off what we have done
         $code = substr($code, $earliest_data['pos'] + $earliest_data['len']);
     }
     // Add the rest
     parent::_addParseData($code, $first_char_of_next_context);
 }
 /**
  * Checks whether the character(s) at the start of the parameter string are
  * characters that should be escaped.
  *
  * @param string The string to check the beginning of for escape characters
  * @return int|false The length of the escape character sequence, else false
  */
 function _shouldBeEscaped($code, $chars_to_escape)
 {
     geshi_dbg('Checking: ' . substr($code, 0, 15));
     foreach ($chars_to_escape as $match) {
         if ('REGEX' != substr($match, 0, 5)) {
             geshi_dbg('Test: ' . $match);
             if (substr($code, 0, 1) == $match) {
                 return 1;
             }
         } else {
             geshi_dbg('  Testing via regex: ' . $match . '... ', false);
             $data = geshi_get_position($code, $match, 0);
             if (0 === $data['pos']) {
                 geshi_dbg('match, data = ' . print_r($data, true));
                 return $data['len'];
             }
             geshi_dbg('no match');
         }
     }
     // No matches...
     return false;
 }
Example #4
0
 /**
  * GetContextEndData
  */
 function _getContextEndData($code, $context_open_key, $context_opener, $beginning_of_context)
 {
     geshi_dbg('GeSHiContext::_getContextEndData(' . $this->_contextName . ', ' . $context_open_key . ', ' . $context_opener . ', ' . $beginning_of_context . ')');
     $context_end_pos = false;
     $context_end_len = -1;
     $context_end_dlm = '';
     $offset = 0;
     // Bail out if context open key tells us that there is no ender for this context
     if (-1 == $context_open_key) {
         geshi_dbg('  no opener so no ender');
         return false;
     }
     // Balanced endings is handled here
     if (isset($this->_contextDelimiters[$context_open_key][3])) {
         $balance_opener = $this->_contextDelimiters[$context_open_key][3][0];
         $balance_closer = $this->_contextDelimiters[$context_open_key][3][1];
         // We get the first push for free
         // @todo [blocking 1.1.4] if what we are balancing against is not related
         // to the starter of the context then we have a problem... check $context_opener
         // for starter stuff instead of assuming
         $balance_count = 1;
         geshi_dbg('@w  Begun balancing');
         while ($balance_count > 0) {
             // Look for opener/closers.
             $opener_pos = geshi_get_position($code, $balance_opener, $offset);
             $closer_pos = geshi_get_position($code, $balance_closer, $offset);
             geshi_dbg('  opener pos = ' . print_r($opener_pos, true) . ', closer pos = ' . print_r($closer_pos, true));
             // Check what we found
             if (false !== $opener_pos['pos']) {
                 if (false !== $closer_pos['pos']) {
                     // Opener and closer available
                     if ($opener_pos['pos'] < $closer_pos['pos']) {
                         // Opener is closer so inc. counter
                         ++$balance_count;
                         geshi_dbg('  opener is closer so inc. to ' . $balance_count);
                         // Start searching from new pos just past where we found the opener
                         $offset = $opener_pos['pos'] + 1;
                         // @todo [blocking 1.1.4] could cache closer pos at this point?
                     } else {
                         // closer is closer (bad english heh)
                         --$balance_count;
                         $offset = $closer_pos['pos'] + 1;
                         geshi_dbg('  closer is closer so dec. to ' . $balance_count);
                     }
                 } else {
                     // No closer will ever be available yet we are still in this context...
                     // use end of code as end pos
                     // I've yet to test this case
                     geshi_dbg('@w  No closer but still in this context!');
                     return array('pos' => strlen($code), 'len' => 0, 'dlm' => '');
                 }
             } elseif (false !== $closer_pos['pos']) {
                 // No opener but closer. Nothing wrong with this
                 --$balance_count;
                 $offset = $closer_pos['pos'] + 1;
                 geshi_dbg('  only closer left, dec. to ' . $balance_count);
             } else {
                 // No opener or closer
                 // Assume that we end this context at the end of the code, with
                 // no delimiter
                 geshi_dbg('@w  No opener or closer but still in this context!');
                 return array('pos' => strlen($code), 'len' => 0, 'dlm' => '');
             }
         }
         // start looking for real end from the position where balancing ends
         // because we've found where balancing ends, but the end of the balancing
         // is likely to be the same as the end of the context
         --$offset;
     }
     foreach ($this->_contextDelimiters[$context_open_key][1] as $ender) {
         geshi_dbg('  Checking ender: ' . str_replace("\n", '\\n', $ender), false);
         $ender = $this->_substitutePlaceholders($ender);
         geshi_dbg(' converted to ' . $ender);
         // Use the offset we may have found when handling balancing of contexts (will
         // be zero if balancing not done).
         $position = geshi_get_position($code, $ender, $offset);
         geshi_dbg('    Ender ' . $ender . ': ' . print_r($position, true));
         $length = $position['len'];
         $position = $position['pos'];
         // BUGFIX:skip around crap starters
         if (false === $position) {
             continue;
         }
         if (false === $context_end_pos || $position < $context_end_pos || $position == $context_end_pos && strlen($ender) > $context_end_len) {
             $context_end_pos = $position;
             $context_end_len = $length;
             $context_end_dlm = $ender;
         }
     }
     geshi_dbg('Context ' . $this->_contextName . ' can finish at position ' . $context_end_pos);
     if (false !== $context_end_pos) {
         return array('pos' => $context_end_pos, 'len' => $context_end_len, 'dlm' => $context_end_dlm);
     } else {
         return false;
     }
 }