true, T_DNUMBER => true, T_STRING => true, T_CONSTANT_ENCAPSED_STRING => true, ); $skipTypes = array( T_WHITESPACE => true, T_COMMENT => true, T_DOC_COMMENT => true, ); $tokens = token_get_all( $string ); $count = count( $tokens ); for( $i = 0; $i < $count; ) { while( isset($skipTypes[$tokens[$i][0]] ) ) { $i++; } switch( $tokens[$i][0] ) { case T_OPEN_TAG: $i++; continue; case T_VARIABLE: // '$messages' -> 'messages' $varname = trim( substr( $tokens[$i][1], 1 ) ); $varindex = null; while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i] === '[' ) { while( isset($skipTypes[$tokens[++$i][0]] ) ); if( isset($scalarTypes[$tokens[$i][0]] ) ) { $varindex = $this->parseScalar( $tokens[$i] ); } else { throw $this->except( $tokens[$i], 'scalar index' ); } while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i] !== ']' ) { throw $this->except( $tokens[$i], ']' ); } while( isset($skipTypes[$tokens[++$i][0]] ) ); } if( $tokens[$i] !== '=' ) { throw $this->except( $tokens[$i], '=' ); } while( isset($skipTypes[$tokens[++$i][0]] ) ); if( isset($scalarTypes[$tokens[$i][0]] ) ) { $buildval = $this->parseScalar( $tokens[$i] ); } elseif( $tokens[$i][0] === T_ARRAY ) { while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i] !== '(' ) { throw $this->except( $tokens[$i], '(' ); } $buildval = array(); do { while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i] === ')' ) { break; } if( isset($scalarTypes[$tokens[$i][0]] ) ) { $key = $this->parseScalar( $tokens[$i] ); } while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i][0] !== T_DOUBLE_ARROW ) { throw $this->except( $tokens[$i], '=>' ); } while( isset($skipTypes[$tokens[++$i][0]] ) ); if( isset($scalarTypes[$tokens[$i][0]] ) ) { $val = $this->parseScalar( $tokens[$i] ); } @$buildval[$key] = $val; while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i] === ',' ) { continue; } elseif( $tokens[$i] === ')' ) { break; } else { throw $this->except( $tokens[$i], ', or )' ); } } while(true); } else { throw $this->except( $tokens[$i], 'scalar or array' ); } if( is_null( $varindex ) ) { $this->vars[$varname] = $buildval; } else { @$this->vars[$varname][$varindex] = $buildval; } while( isset($skipTypes[$tokens[++$i][0]] ) ); if( $tokens[$i] !== ';' ) { throw $this->except($tokens[$i], ';'); } $i++; break; default: throw $this->except($tokens[$i], 'open tag, whitespace, or variable.'); } } } /** * @param $got string * @param $expected string * @return Exception */ private function except( $got, $expected ) { if( is_array( $got ) ) { $got = token_name( $got[0] ) . " ('" . $got[1] . "')"; } else { $got = "'" . $got . "'"; } return new Exception( "Expected $expected, got $got" ); } /** * Parse a scalar value in PHP * * @param $token string * * @return mixed Parsed value */ function parseScalar( $token ) { if( is_array( $token ) ) { $str = $token[1]; } else { $str = $token; } if ( $str !== '' && $str[0] == '\'' ) // Single-quoted string // @fixme trim() call is due to mystery bug where whitespace gets // appended to the token; without it we ended up reading in the // extra quote on the end! return strtr( substr( trim( $str ), 1, -1 ), array( '\\\'' => '\'', '\\\\' => '\\' ) ); if ( $str !== '' && @$str[0] == '"' ) // Double-quoted string // @fixme trim() call is due to mystery bug where whitespace gets // appended to the token; without it we ended up reading in the // extra quote on the end! return stripcslashes( substr( trim( $str ), 1, -1 ) ); if ( substr( $str, 0, 4 ) === 'true' ) return true; if ( substr( $str, 0, 5 ) === 'false' ) return false; if ( substr( $str, 0, 4 ) === 'null' ) return null; // Must be some kind of numeric value, so let PHP's weak typing // be useful for a change return $str; } /** * @param $varname string * @return null|string */ function getVar( $varname ) { if( isset( $this->vars[$varname] ) ) { return $this->vars[$varname]; } else { return null; } } }