To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / .svn / pristine / 1d / 1d5de2a1ef017a12eb407c0c43e77ba879705fe3.svn-base @ 1297:0a574315af3e
History | View | Annotate | Download (23.5 KB)
| 1 |
module CodeRay |
|---|---|
| 2 |
module Scanners |
| 3 |
|
| 4 |
load :html |
| 5 |
|
| 6 |
# Scanner for PHP. |
| 7 |
# |
| 8 |
# Original by Stefan Walk. |
| 9 |
class PHP < Scanner |
| 10 |
|
| 11 |
register_for :php |
| 12 |
file_extension 'php' |
| 13 |
encoding 'BINARY' |
| 14 |
|
| 15 |
KINDS_NOT_LOC = HTML::KINDS_NOT_LOC |
| 16 |
|
| 17 |
protected |
| 18 |
|
| 19 |
def setup |
| 20 |
@html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true |
| 21 |
end |
| 22 |
|
| 23 |
def reset_instance |
| 24 |
super |
| 25 |
@html_scanner.reset |
| 26 |
end |
| 27 |
|
| 28 |
module Words # :nodoc: |
| 29 |
|
| 30 |
# according to http://www.php.net/manual/en/reserved.keywords.php |
| 31 |
KEYWORDS = %w[ |
| 32 |
abstract and array as break case catch class clone const continue declare default do else elseif |
| 33 |
enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global |
| 34 |
goto if implements interface instanceof namespace new or private protected public static switch |
| 35 |
throw try use var while xor |
| 36 |
cfunction old_function |
| 37 |
] |
| 38 |
|
| 39 |
TYPES = %w[ int integer float double bool boolean string array object resource ] |
| 40 |
|
| 41 |
LANGUAGE_CONSTRUCTS = %w[ |
| 42 |
die echo empty exit eval include include_once isset list |
| 43 |
require require_once return print unset |
| 44 |
] |
| 45 |
|
| 46 |
CLASSES = %w[ Directory stdClass __PHP_Incomplete_Class exception php_user_filter Closure ] |
| 47 |
|
| 48 |
# according to http://php.net/quickref.php on 2009-04-21; |
| 49 |
# all functions with _ excluded (module functions) and selected additional functions |
| 50 |
BUILTIN_FUNCTIONS = %w[ |
| 51 |
abs acos acosh addcslashes addslashes aggregate array arsort ascii2ebcdic asin asinh asort assert atan atan2 |
| 52 |
atanh basename bcadd bccomp bcdiv bcmod bcmul bcpow bcpowmod bcscale bcsqrt bcsub bin2hex bindec |
| 53 |
bindtextdomain bzclose bzcompress bzdecompress bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite |
| 54 |
calculhmac ceil chdir checkdate checkdnsrr chgrp chmod chop chown chr chroot clearstatcache closedir closelog |
| 55 |
compact constant copy cos cosh count crc32 crypt current date dcgettext dcngettext deaggregate decbin dechex |
| 56 |
decoct define defined deg2rad delete dgettext die dirname diskfreespace dl dngettext doubleval each |
| 57 |
ebcdic2ascii echo empty end ereg eregi escapeshellarg escapeshellcmd eval exec exit exp explode expm1 extract |
| 58 |
fclose feof fflush fgetc fgetcsv fgets fgetss file fileatime filectime filegroup fileinode filemtime fileowner |
| 59 |
fileperms filepro filesize filetype floatval flock floor flush fmod fnmatch fopen fpassthru fprintf fputcsv |
| 60 |
fputs fread frenchtojd fscanf fseek fsockopen fstat ftell ftok ftruncate fwrite getallheaders getcwd getdate |
| 61 |
getenv gethostbyaddr gethostbyname gethostbynamel getimagesize getlastmod getmxrr getmygid getmyinode getmypid |
| 62 |
getmyuid getopt getprotobyname getprotobynumber getrandmax getrusage getservbyname getservbyport gettext |
| 63 |
gettimeofday gettype glob gmdate gmmktime gmstrftime gregoriantojd gzclose gzcompress gzdecode gzdeflate |
| 64 |
gzencode gzeof gzfile gzgetc gzgets gzgetss gzinflate gzopen gzpassthru gzputs gzread gzrewind gzseek gztell |
| 65 |
gzuncompress gzwrite hash header hebrev hebrevc hexdec htmlentities htmlspecialchars hypot iconv idate |
| 66 |
implode include intval ip2long iptcembed iptcparse isset |
| 67 |
jddayofweek jdmonthname jdtofrench jdtogregorian jdtojewish jdtojulian jdtounix jewishtojd join jpeg2wbmp |
| 68 |
juliantojd key krsort ksort lcfirst lchgrp lchown levenshtein link linkinfo list localeconv localtime log |
| 69 |
log10 log1p long2ip lstat ltrim mail main max md5 metaphone mhash microtime min mkdir mktime msql natcasesort |
| 70 |
natsort next ngettext nl2br nthmac octdec opendir openlog |
| 71 |
ord overload pack passthru pathinfo pclose pfsockopen phpcredits phpinfo phpversion pi png2wbmp popen pos pow |
| 72 |
prev print printf putenv quotemeta rad2deg rand range rawurldecode rawurlencode readdir readfile readgzfile |
| 73 |
readline readlink realpath recode rename require reset rewind rewinddir rmdir round rsort rtrim scandir |
| 74 |
serialize setcookie setlocale setrawcookie settype sha1 shuffle signeurlpaiement sin sinh sizeof sleep snmpget |
| 75 |
snmpgetnext snmprealwalk snmpset snmpwalk snmpwalkoid sort soundex split spliti sprintf sqrt srand sscanf stat |
| 76 |
strcasecmp strchr strcmp strcoll strcspn strftime stripcslashes stripos stripslashes stristr strlen |
| 77 |
strnatcasecmp strnatcmp strncasecmp strncmp strpbrk strpos strptime strrchr strrev strripos strrpos strspn |
| 78 |
strstr strtok strtolower strtotime strtoupper strtr strval substr symlink syslog system tan tanh tempnam |
| 79 |
textdomain time tmpfile touch trim uasort ucfirst ucwords uksort umask uniqid unixtojd unlink unpack |
| 80 |
unserialize unset urldecode urlencode usleep usort vfprintf virtual vprintf vsprintf wordwrap |
| 81 |
array_change_key_case array_chunk array_combine array_count_values array_diff array_diff_assoc |
| 82 |
array_diff_key array_diff_uassoc array_diff_ukey array_fill array_fill_keys array_filter array_flip |
| 83 |
array_intersect array_intersect_assoc array_intersect_key array_intersect_uassoc array_intersect_ukey |
| 84 |
array_key_exists array_keys array_map array_merge array_merge_recursive array_multisort array_pad |
| 85 |
array_pop array_product array_push array_rand array_reduce array_reverse array_search array_shift |
| 86 |
array_slice array_splice array_sum array_udiff array_udiff_assoc array_udiff_uassoc array_uintersect |
| 87 |
array_uintersect_assoc array_uintersect_uassoc array_unique array_unshift array_values array_walk |
| 88 |
array_walk_recursive |
| 89 |
assert_options base_convert base64_decode base64_encode |
| 90 |
chunk_split class_exists class_implements class_parents |
| 91 |
count_chars debug_backtrace debug_print_backtrace debug_zval_dump |
| 92 |
error_get_last error_log error_reporting extension_loaded |
| 93 |
file_exists file_get_contents file_put_contents load_file |
| 94 |
func_get_arg func_get_args func_num_args function_exists |
| 95 |
get_browser get_called_class get_cfg_var get_class get_class_methods get_class_vars |
| 96 |
get_current_user get_declared_classes get_declared_interfaces get_defined_constants |
| 97 |
get_defined_functions get_defined_vars get_extension_funcs get_headers get_html_translation_table |
| 98 |
get_include_path get_included_files get_loaded_extensions get_magic_quotes_gpc get_magic_quotes_runtime |
| 99 |
get_meta_tags get_object_vars get_parent_class get_required_filesget_resource_type |
| 100 |
gc_collect_cycles gc_disable gc_enable gc_enabled |
| 101 |
halt_compiler headers_list headers_sent highlight_file highlight_string |
| 102 |
html_entity_decode htmlspecialchars_decode |
| 103 |
in_array include_once inclued_get_data |
| 104 |
is_a is_array is_binary is_bool is_buffer is_callable is_dir is_double is_executable is_file is_finite |
| 105 |
is_float is_infinite is_int is_integer is_link is_long is_nan is_null is_numeric is_object is_readable |
| 106 |
is_real is_resource is_scalar is_soap_fault is_string is_subclass_of is_unicode is_uploaded_file |
| 107 |
is_writable is_writeable |
| 108 |
locale_get_default locale_set_default |
| 109 |
number_format override_function parse_str parse_url |
| 110 |
php_check_syntax php_ini_loaded_file php_ini_scanned_files php_logo_guid php_sapi_name |
| 111 |
php_strip_whitespace php_uname |
| 112 |
preg_filter preg_grep preg_last_error preg_match preg_match_all preg_quote preg_replace |
| 113 |
preg_replace_callback preg_split print_r |
| 114 |
require_once register_shutdown_function register_tick_function |
| 115 |
set_error_handler set_exception_handler set_file_buffer set_include_path |
| 116 |
set_magic_quotes_runtime set_time_limit shell_exec |
| 117 |
str_getcsv str_ireplace str_pad str_repeat str_replace str_rot13 str_shuffle str_split str_word_count |
| 118 |
strip_tags substr_compare substr_count substr_replace |
| 119 |
time_nanosleep time_sleep_until |
| 120 |
token_get_all token_name trigger_error |
| 121 |
unregister_tick_function use_soap_error_handler user_error |
| 122 |
utf8_decode utf8_encode var_dump var_export |
| 123 |
version_compare |
| 124 |
zend_logo_guid zend_thread_id zend_version |
| 125 |
create_function call_user_func_array |
| 126 |
posix_access posix_ctermid posix_get_last_error posix_getcwd posix_getegid |
| 127 |
posix_geteuid posix_getgid posix_getgrgid posix_getgrnam posix_getgroups |
| 128 |
posix_getlogin posix_getpgid posix_getpgrp posix_getpid posix_getppid |
| 129 |
posix_getpwnam posix_getpwuid posix_getrlimit posix_getsid posix_getuid |
| 130 |
posix_initgroups posix_isatty posix_kill posix_mkfifo posix_mknod |
| 131 |
posix_setegid posix_seteuid posix_setgid posix_setpgid posix_setsid |
| 132 |
posix_setuid posix_strerror posix_times posix_ttyname posix_uname |
| 133 |
pcntl_alarm pcntl_exec pcntl_fork pcntl_getpriority pcntl_setpriority |
| 134 |
pcntl_signal pcntl_signal_dispatch pcntl_sigprocmask pcntl_sigtimedwait |
| 135 |
pcntl_sigwaitinfo pcntl_wait pcntl_waitpid pcntl_wexitstatus pcntl_wifexited |
| 136 |
pcntl_wifsignaled pcntl_wifstopped pcntl_wstopsig pcntl_wtermsig |
| 137 |
] |
| 138 |
# TODO: more built-in PHP functions? |
| 139 |
|
| 140 |
EXCEPTIONS = %w[ |
| 141 |
E_ERROR E_WARNING E_PARSE E_NOTICE E_CORE_ERROR E_CORE_WARNING E_COMPILE_ERROR E_COMPILE_WARNING |
| 142 |
E_USER_ERROR E_USER_WARNING E_USER_NOTICE E_DEPRECATED E_USER_DEPRECATED E_ALL E_STRICT |
| 143 |
] |
| 144 |
|
| 145 |
CONSTANTS = %w[ |
| 146 |
null true false self parent |
| 147 |
__LINE__ __DIR__ __FILE__ __LINE__ |
| 148 |
__CLASS__ __NAMESPACE__ __METHOD__ __FUNCTION__ |
| 149 |
PHP_VERSION PHP_MAJOR_VERSION PHP_MINOR_VERSION PHP_RELEASE_VERSION PHP_VERSION_ID PHP_EXTRA_VERSION PHP_ZTS |
| 150 |
PHP_DEBUG PHP_MAXPATHLEN PHP_OS PHP_SAPI PHP_EOL PHP_INT_MAX PHP_INT_SIZE DEFAULT_INCLUDE_PATH |
| 151 |
PEAR_INSTALL_DIR PEAR_EXTENSION_DIR PHP_EXTENSION_DIR PHP_PREFIX PHP_BINDIR PHP_LIBDIR PHP_DATADIR |
| 152 |
PHP_SYSCONFDIR PHP_LOCALSTATEDIR PHP_CONFIG_FILE_PATH PHP_CONFIG_FILE_SCAN_DIR PHP_SHLIB_SUFFIX |
| 153 |
PHP_OUTPUT_HANDLER_START PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_END |
| 154 |
__COMPILER_HALT_OFFSET__ |
| 155 |
EXTR_OVERWRITE EXTR_SKIP EXTR_PREFIX_SAME EXTR_PREFIX_ALL EXTR_PREFIX_INVALID EXTR_PREFIX_IF_EXISTS |
| 156 |
EXTR_IF_EXISTS SORT_ASC SORT_DESC SORT_REGULAR SORT_NUMERIC SORT_STRING CASE_LOWER CASE_UPPER COUNT_NORMAL |
| 157 |
COUNT_RECURSIVE ASSERT_ACTIVE ASSERT_CALLBACK ASSERT_BAIL ASSERT_WARNING ASSERT_QUIET_EVAL CONNECTION_ABORTED |
| 158 |
CONNECTION_NORMAL CONNECTION_TIMEOUT INI_USER INI_PERDIR INI_SYSTEM INI_ALL M_E M_LOG2E M_LOG10E M_LN2 M_LN10 |
| 159 |
M_PI M_PI_2 M_PI_4 M_1_PI M_2_PI M_2_SQRTPI M_SQRT2 M_SQRT1_2 CRYPT_SALT_LENGTH CRYPT_STD_DES CRYPT_EXT_DES |
| 160 |
CRYPT_MD5 CRYPT_BLOWFISH DIRECTORY_SEPARATOR SEEK_SET SEEK_CUR SEEK_END LOCK_SH LOCK_EX LOCK_UN LOCK_NB |
| 161 |
HTML_SPECIALCHARS HTML_ENTITIES ENT_COMPAT ENT_QUOTES ENT_NOQUOTES INFO_GENERAL INFO_CREDITS |
| 162 |
INFO_CONFIGURATION INFO_MODULES INFO_ENVIRONMENT INFO_VARIABLES INFO_LICENSE INFO_ALL CREDITS_GROUP |
| 163 |
CREDITS_GENERAL CREDITS_SAPI CREDITS_MODULES CREDITS_DOCS CREDITS_FULLPAGE CREDITS_QA CREDITS_ALL STR_PAD_LEFT |
| 164 |
STR_PAD_RIGHT STR_PAD_BOTH PATHINFO_DIRNAME PATHINFO_BASENAME PATHINFO_EXTENSION PATH_SEPARATOR CHAR_MAX |
| 165 |
LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_ALL LC_MESSAGES ABDAY_1 ABDAY_2 ABDAY_3 ABDAY_4 ABDAY_5 |
| 166 |
ABDAY_6 ABDAY_7 DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 DAY_6 DAY_7 ABMON_1 ABMON_2 ABMON_3 ABMON_4 ABMON_5 ABMON_6 |
| 167 |
ABMON_7 ABMON_8 ABMON_9 ABMON_10 ABMON_11 ABMON_12 MON_1 MON_2 MON_3 MON_4 MON_5 MON_6 MON_7 MON_8 MON_9 |
| 168 |
MON_10 MON_11 MON_12 AM_STR PM_STR D_T_FMT D_FMT T_FMT T_FMT_AMPM ERA ERA_YEAR ERA_D_T_FMT ERA_D_FMT ERA_T_FMT |
| 169 |
ALT_DIGITS INT_CURR_SYMBOL CURRENCY_SYMBOL CRNCYSTR MON_DECIMAL_POINT MON_THOUSANDS_SEP MON_GROUPING |
| 170 |
POSITIVE_SIGN NEGATIVE_SIGN INT_FRAC_DIGITS FRAC_DIGITS P_CS_PRECEDES P_SEP_BY_SPACE N_CS_PRECEDES |
| 171 |
N_SEP_BY_SPACE P_SIGN_POSN N_SIGN_POSN DECIMAL_POINT RADIXCHAR THOUSANDS_SEP THOUSEP GROUPING YESEXPR NOEXPR |
| 172 |
YESSTR NOSTR CODESET LOG_EMERG LOG_ALERT LOG_CRIT LOG_ERR LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG LOG_KERN |
| 173 |
LOG_USER LOG_MAIL LOG_DAEMON LOG_AUTH LOG_SYSLOG LOG_LPR LOG_NEWS LOG_UUCP LOG_CRON LOG_AUTHPRIV LOG_LOCAL0 |
| 174 |
LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_PID LOG_CONS LOG_ODELAY |
| 175 |
LOG_NDELAY LOG_NOWAIT LOG_PERROR |
| 176 |
] |
| 177 |
|
| 178 |
PREDEFINED = %w[ |
| 179 |
$GLOBALS $_SERVER $_GET $_POST $_FILES $_REQUEST $_SESSION $_ENV |
| 180 |
$_COOKIE $php_errormsg $HTTP_RAW_POST_DATA $http_response_header |
| 181 |
$argc $argv |
| 182 |
] |
| 183 |
|
| 184 |
IDENT_KIND = WordList::CaseIgnoring.new(:ident). |
| 185 |
add(KEYWORDS, :keyword). |
| 186 |
add(TYPES, :predefined_type). |
| 187 |
add(LANGUAGE_CONSTRUCTS, :keyword). |
| 188 |
add(BUILTIN_FUNCTIONS, :predefined). |
| 189 |
add(CLASSES, :predefined_constant). |
| 190 |
add(EXCEPTIONS, :exception). |
| 191 |
add(CONSTANTS, :predefined_constant) |
| 192 |
|
| 193 |
VARIABLE_KIND = WordList.new(:local_variable). |
| 194 |
add(PREDEFINED, :predefined) |
| 195 |
end |
| 196 |
|
| 197 |
module RE # :nodoc: |
| 198 |
|
| 199 |
PHP_START = / |
| 200 |
<script\s+[^>]*?language\s*=\s*"php"[^>]*?> | |
| 201 |
<script\s+[^>]*?language\s*=\s*'php'[^>]*?> | |
| 202 |
<\?php\d? | |
| 203 |
<\?(?!xml) |
| 204 |
/xi |
| 205 |
|
| 206 |
PHP_END = %r! |
| 207 |
</script> | |
| 208 |
\?> |
| 209 |
!xi |
| 210 |
|
| 211 |
HTML_INDICATOR = /<!DOCTYPE html|<(?:html|body|div|p)[> ]/i |
| 212 |
|
| 213 |
IDENTIFIER = /[a-z_\x7f-\xFF][a-z0-9_\x7f-\xFF]*/i |
| 214 |
VARIABLE = /\$#{IDENTIFIER}/
|
| 215 |
|
| 216 |
OPERATOR = / |
| 217 |
\.(?!\d)=? | # dot that is not decimal point, string concatenation |
| 218 |
&& | \|\| | # logic |
| 219 |
:: | -> | => | # scope, member, dictionary |
| 220 |
\\(?!\n) | # namespace |
| 221 |
\+\+ | -- | # increment, decrement |
| 222 |
[,;?:()\[\]{}] | # simple delimiters
|
| 223 |
[-+*\/%&|^]=? | # ordinary math, binary logic, assignment shortcuts |
| 224 |
[~$] | # whatever |
| 225 |
=& | # reference assignment |
| 226 |
[=!]=?=? | <> | # comparison and assignment |
| 227 |
<<=? | >>=? | [<>]=? # comparison and shift |
| 228 |
/x |
| 229 |
|
| 230 |
end |
| 231 |
|
| 232 |
protected |
| 233 |
|
| 234 |
def scan_tokens encoder, options |
| 235 |
|
| 236 |
if check(RE::PHP_START) || # starts with <? |
| 237 |
(match?(/\s*<\S/) && check(/.{1,1000}#{RE::PHP_START}/om)) || # starts with tag and contains <?
|
| 238 |
check(/.{0,1000}#{RE::HTML_INDICATOR}/om) ||
|
| 239 |
check(/.{1,100}#{RE::PHP_START}/om) # PHP start after max 100 chars
|
| 240 |
# is HTML with embedded PHP, so start with HTML |
| 241 |
states = [:initial] |
| 242 |
else |
| 243 |
# is just PHP, so start with PHP surrounded by HTML |
| 244 |
states = [:initial, :php] |
| 245 |
end |
| 246 |
|
| 247 |
label_expected = true |
| 248 |
case_expected = false |
| 249 |
|
| 250 |
heredoc_delimiter = nil |
| 251 |
delimiter = nil |
| 252 |
modifier = nil |
| 253 |
|
| 254 |
until eos? |
| 255 |
|
| 256 |
case states.last |
| 257 |
|
| 258 |
when :initial # HTML |
| 259 |
if match = scan(RE::PHP_START) |
| 260 |
encoder.text_token match, :inline_delimiter |
| 261 |
label_expected = true |
| 262 |
states << :php |
| 263 |
else |
| 264 |
match = scan_until(/(?=#{RE::PHP_START})/o) || scan_rest
|
| 265 |
@html_scanner.tokenize match unless match.empty? |
| 266 |
end |
| 267 |
|
| 268 |
when :php |
| 269 |
if match = scan(/\s+/) |
| 270 |
encoder.text_token match, :space |
| 271 |
|
| 272 |
elsif match = scan(%r! (?m: \/\* (?: .*? \*\/ | .* ) ) | (?://|\#) .*? (?=#{RE::PHP_END}|$) !xo)
|
| 273 |
encoder.text_token match, :comment |
| 274 |
|
| 275 |
elsif match = scan(RE::IDENTIFIER) |
| 276 |
kind = Words::IDENT_KIND[match] |
| 277 |
if kind == :ident && label_expected && check(/:(?!:)/) |
| 278 |
kind = :label |
| 279 |
label_expected = true |
| 280 |
else |
| 281 |
label_expected = false |
| 282 |
if kind == :ident && match =~ /^[A-Z]/ |
| 283 |
kind = :constant |
| 284 |
elsif kind == :keyword |
| 285 |
case match |
| 286 |
when 'class' |
| 287 |
states << :class_expected |
| 288 |
when 'function' |
| 289 |
states << :function_expected |
| 290 |
when 'case', 'default' |
| 291 |
case_expected = true |
| 292 |
end |
| 293 |
elsif match == 'b' && check(/['"]/) # binary string literal |
| 294 |
modifier = match |
| 295 |
next |
| 296 |
end |
| 297 |
end |
| 298 |
encoder.text_token match, kind |
| 299 |
|
| 300 |
elsif match = scan(/(?:\d+\.\d*|\d*\.\d+)(?:e[-+]?\d+)?|\d+e[-+]?\d+/i) |
| 301 |
label_expected = false |
| 302 |
encoder.text_token match, :float |
| 303 |
|
| 304 |
elsif match = scan(/0x[0-9a-fA-F]+/) |
| 305 |
label_expected = false |
| 306 |
encoder.text_token match, :hex |
| 307 |
|
| 308 |
elsif match = scan(/\d+/) |
| 309 |
label_expected = false |
| 310 |
encoder.text_token match, :integer |
| 311 |
|
| 312 |
elsif match = scan(/['"`]/) |
| 313 |
encoder.begin_group :string |
| 314 |
if modifier |
| 315 |
encoder.text_token modifier, :modifier |
| 316 |
modifier = nil |
| 317 |
end |
| 318 |
delimiter = match |
| 319 |
encoder.text_token match, :delimiter |
| 320 |
states.push match == "'" ? :sqstring : :dqstring |
| 321 |
|
| 322 |
elsif match = scan(RE::VARIABLE) |
| 323 |
label_expected = false |
| 324 |
encoder.text_token match, Words::VARIABLE_KIND[match] |
| 325 |
|
| 326 |
elsif match = scan(/\{/)
|
| 327 |
encoder.text_token match, :operator |
| 328 |
label_expected = true |
| 329 |
states.push :php |
| 330 |
|
| 331 |
elsif match = scan(/\}/) |
| 332 |
if states.size == 1 |
| 333 |
encoder.text_token match, :error |
| 334 |
else |
| 335 |
states.pop |
| 336 |
if states.last.is_a?(::Array) |
| 337 |
delimiter = states.last[1] |
| 338 |
states[-1] = states.last[0] |
| 339 |
encoder.text_token match, :delimiter |
| 340 |
encoder.end_group :inline |
| 341 |
else |
| 342 |
encoder.text_token match, :operator |
| 343 |
label_expected = true |
| 344 |
end |
| 345 |
end |
| 346 |
|
| 347 |
elsif match = scan(/@/) |
| 348 |
label_expected = false |
| 349 |
encoder.text_token match, :exception |
| 350 |
|
| 351 |
elsif match = scan(RE::PHP_END) |
| 352 |
encoder.text_token match, :inline_delimiter |
| 353 |
states = [:initial] |
| 354 |
|
| 355 |
elsif match = scan(/<<<(?:(#{RE::IDENTIFIER})|"(#{RE::IDENTIFIER})"|'(#{RE::IDENTIFIER})')/o)
|
| 356 |
encoder.begin_group :string |
| 357 |
# warn 'heredoc in heredoc?' if heredoc_delimiter |
| 358 |
heredoc_delimiter = Regexp.escape(self[1] || self[2] || self[3]) |
| 359 |
encoder.text_token match, :delimiter |
| 360 |
states.push self[3] ? :sqstring : :dqstring |
| 361 |
heredoc_delimiter = /#{heredoc_delimiter}(?=;?$)/
|
| 362 |
|
| 363 |
elsif match = scan(/#{RE::OPERATOR}/o)
|
| 364 |
label_expected = match == ';' |
| 365 |
if case_expected |
| 366 |
label_expected = true if match == ':' |
| 367 |
case_expected = false |
| 368 |
end |
| 369 |
encoder.text_token match, :operator |
| 370 |
|
| 371 |
else |
| 372 |
encoder.text_token getch, :error |
| 373 |
|
| 374 |
end |
| 375 |
|
| 376 |
when :sqstring |
| 377 |
if match = scan(heredoc_delimiter ? /[^\\\n]+/ : /[^'\\]+/) |
| 378 |
encoder.text_token match, :content |
| 379 |
elsif !heredoc_delimiter && match = scan(/'/) |
| 380 |
encoder.text_token match, :delimiter |
| 381 |
encoder.end_group :string |
| 382 |
delimiter = nil |
| 383 |
label_expected = false |
| 384 |
states.pop |
| 385 |
elsif heredoc_delimiter && match = scan(/\n/) |
| 386 |
if scan heredoc_delimiter |
| 387 |
encoder.text_token "\n", :content |
| 388 |
encoder.text_token matched, :delimiter |
| 389 |
encoder.end_group :string |
| 390 |
heredoc_delimiter = nil |
| 391 |
label_expected = false |
| 392 |
states.pop |
| 393 |
else |
| 394 |
encoder.text_token match, :content |
| 395 |
end |
| 396 |
elsif match = scan(heredoc_delimiter ? /\\\\/ : /\\[\\'\n]/) |
| 397 |
encoder.text_token match, :char |
| 398 |
elsif match = scan(/\\./m) |
| 399 |
encoder.text_token match, :content |
| 400 |
elsif match = scan(/\\/) |
| 401 |
encoder.text_token match, :error |
| 402 |
else |
| 403 |
states.pop |
| 404 |
end |
| 405 |
|
| 406 |
when :dqstring |
| 407 |
if match = scan(heredoc_delimiter ? /[^${\\\n]+/ : (delimiter == '"' ? /[^"${\\]+/ : /[^`${\\]+/))
|
| 408 |
encoder.text_token match, :content |
| 409 |
elsif !heredoc_delimiter && match = scan(delimiter == '"' ? /"/ : /`/) |
| 410 |
encoder.text_token match, :delimiter |
| 411 |
encoder.end_group :string |
| 412 |
delimiter = nil |
| 413 |
label_expected = false |
| 414 |
states.pop |
| 415 |
elsif heredoc_delimiter && match = scan(/\n/) |
| 416 |
if scan heredoc_delimiter |
| 417 |
encoder.text_token "\n", :content |
| 418 |
encoder.text_token matched, :delimiter |
| 419 |
encoder.end_group :string |
| 420 |
heredoc_delimiter = nil |
| 421 |
label_expected = false |
| 422 |
states.pop |
| 423 |
else |
| 424 |
encoder.text_token match, :content |
| 425 |
end |
| 426 |
elsif match = scan(/\\(?:x[0-9A-Fa-f]{1,2}|[0-7]{1,3})/)
|
| 427 |
encoder.text_token match, :char |
| 428 |
elsif match = scan(heredoc_delimiter ? /\\[nrtvf\\$]/ : (delimiter == '"' ? /\\[nrtvf\\$"]/ : /\\[nrtvf\\$`]/)) |
| 429 |
encoder.text_token match, :char |
| 430 |
elsif match = scan(/\\./m) |
| 431 |
encoder.text_token match, :content |
| 432 |
elsif match = scan(/\\/) |
| 433 |
encoder.text_token match, :error |
| 434 |
elsif match = scan(/#{RE::VARIABLE}/o)
|
| 435 |
if check(/\[#{RE::IDENTIFIER}\]/o)
|
| 436 |
encoder.begin_group :inline |
| 437 |
encoder.text_token match, :local_variable |
| 438 |
encoder.text_token scan(/\[/), :operator |
| 439 |
encoder.text_token scan(/#{RE::IDENTIFIER}/o), :ident
|
| 440 |
encoder.text_token scan(/\]/), :operator |
| 441 |
encoder.end_group :inline |
| 442 |
elsif check(/\[/) |
| 443 |
match << scan(/\[['"]?#{RE::IDENTIFIER}?['"]?\]?/o)
|
| 444 |
encoder.text_token match, :error |
| 445 |
elsif check(/->#{RE::IDENTIFIER}/o)
|
| 446 |
encoder.begin_group :inline |
| 447 |
encoder.text_token match, :local_variable |
| 448 |
encoder.text_token scan(/->/), :operator |
| 449 |
encoder.text_token scan(/#{RE::IDENTIFIER}/o), :ident
|
| 450 |
encoder.end_group :inline |
| 451 |
elsif check(/->/) |
| 452 |
match << scan(/->/) |
| 453 |
encoder.text_token match, :error |
| 454 |
else |
| 455 |
encoder.text_token match, :local_variable |
| 456 |
end |
| 457 |
elsif match = scan(/\{/)
|
| 458 |
if check(/\$/) |
| 459 |
encoder.begin_group :inline |
| 460 |
states[-1] = [states.last, delimiter] |
| 461 |
delimiter = nil |
| 462 |
states.push :php |
| 463 |
encoder.text_token match, :delimiter |
| 464 |
else |
| 465 |
encoder.text_token match, :content |
| 466 |
end |
| 467 |
elsif match = scan(/\$\{#{RE::IDENTIFIER}\}/o)
|
| 468 |
encoder.text_token match, :local_variable |
| 469 |
elsif match = scan(/\$/) |
| 470 |
encoder.text_token match, :content |
| 471 |
else |
| 472 |
states.pop |
| 473 |
end |
| 474 |
|
| 475 |
when :class_expected |
| 476 |
if match = scan(/\s+/) |
| 477 |
encoder.text_token match, :space |
| 478 |
elsif match = scan(/#{RE::IDENTIFIER}/o)
|
| 479 |
encoder.text_token match, :class |
| 480 |
states.pop |
| 481 |
else |
| 482 |
states.pop |
| 483 |
end |
| 484 |
|
| 485 |
when :function_expected |
| 486 |
if match = scan(/\s+/) |
| 487 |
encoder.text_token match, :space |
| 488 |
elsif match = scan(/&/) |
| 489 |
encoder.text_token match, :operator |
| 490 |
elsif match = scan(/#{RE::IDENTIFIER}/o)
|
| 491 |
encoder.text_token match, :function |
| 492 |
states.pop |
| 493 |
else |
| 494 |
states.pop |
| 495 |
end |
| 496 |
|
| 497 |
else |
| 498 |
raise_inspect 'Unknown state!', encoder, states |
| 499 |
end |
| 500 |
|
| 501 |
end |
| 502 |
|
| 503 |
encoder |
| 504 |
end |
| 505 |
|
| 506 |
end |
| 507 |
|
| 508 |
end |
| 509 |
end |