Files

Class Index [+]

Quicksearch

CodeRay::Scanners::PHP

Original by Stefan Walk.

Constants

KINDS_NOT_LOC

Public Instance Methods

reset_instance() click to toggle source
    # File lib/coderay/scanners/php.rb, line 18
18:     def reset_instance
19:       super
20:       @html_scanner.reset
21:     end
scan_tokens(tokens, options) click to toggle source
     # File lib/coderay/scanners/php.rb, line 227
227:     def scan_tokens tokens, options
228:       
229:       if check(RE::PHP_START) ||  # starts with <?
230:        (match?(/\s*<\S/) && exist?(RE::PHP_START)) || # starts with tag and contains <?
231:        exist?(RE::HTML_INDICATOR) ||
232:        check(/.{1,100}#{RE::PHP_START}/m)  # PHP start after max 100 chars
233:         # is HTML with embedded PHP, so start with HTML
234:         states = [:initial]
235:       else
236:         # is just PHP, so start with PHP surrounded by HTML
237:         states = [:initial, :php]
238:       end
239:       
240:       label_expected = true
241:       case_expected = false
242:       
243:       heredoc_delimiter = nil
244:       delimiter = nil
245:       modifier = nil
246:       
247:       until eos?
248:         
249:         match = nil
250:         kind = nil
251:         
252:         case states.last
253:         
254:         when :initial  # HTML
255:           if scan RE::PHP_START
256:             kind = :inline_delimiter
257:             label_expected = true
258:             states << :php
259:           else
260:             match = scan_until(/(?=#{RE::PHP_START})/) || scan_until(/\z/)
261:             @html_scanner.tokenize match unless match.empty?
262:             next
263:           end
264:         
265:         when :php
266:           if match = scan(/\s+/)
267:             tokens << [match, :space]
268:             next
269:           
270:           elsif scan(% (?m: \/\* (?: .*? \*\/ | .* ) ) | (?://|\#) .*? (?=#{RE::PHP_END}|$) !o)
271:             kind = :comment
272:           
273:           elsif match = scan(RE::IDENTIFIER)
274:             kind = Words::IDENT_KIND[match]
275:             if kind == :ident && label_expected && check(/:(?!:)/)
276:               kind = :label
277:               label_expected = true
278:             else
279:               label_expected = false
280:               if kind == :ident && match =~ /^[A-Z]/
281:                 kind = :constant
282:               elsif kind == :reserved
283:                 case match
284:                 when 'class'
285:                   states << :class_expected
286:                 when 'function'
287:                   states << :function_expected
288:                 when 'case', 'default'
289:                   case_expected = true
290:                 end
291:               elsif match == 'b' && check(/['"]/)  # binary string literal
292:                 modifier = match
293:                 next
294:               end
295:             end
296:           
297:           elsif scan(/(?:\d+\.\d*|\d*\.\d+)(?:e[-+]?\d+)?|\d+e[-+]?\d+/)
298:             label_expected = false
299:             kind = :float
300:           
301:           elsif scan(/0x[0-9a-fA-F]+/)
302:             label_expected = false
303:             kind = :hex
304:           
305:           elsif scan(/\d+/)
306:             label_expected = false
307:             kind = :integer
308:           
309:           elsif scan(/'/)
310:             tokens << [:open, :string]
311:             if modifier
312:               tokens << [modifier, :modifier]
313:               modifier = nil
314:             end
315:             kind = :delimiter
316:             states.push :sqstring
317:           
318:           elsif match = scan(/["`]/)
319:             tokens << [:open, :string]
320:             if modifier
321:               tokens << [modifier, :modifier]
322:               modifier = nil
323:             end
324:             delimiter = match
325:             kind = :delimiter
326:             states.push :dqstring
327:           
328:           elsif match = scan(RE::VARIABLE)
329:             label_expected = false
330:             kind = Words::VARIABLE_KIND[match]
331:           
332:           elsif scan(/\{/)
333:             kind = :operator
334:             label_expected = true
335:             states.push :php
336:           
337:           elsif scan(/\}/)
338:             if states.size == 1
339:               kind = :error
340:             else
341:               states.pop
342:               if states.last.is_a?(::Array)
343:                 delimiter = states.last[1]
344:                 states[1] = states.last[0]
345:                 tokens << [matched, :delimiter]
346:                 tokens << [:close, :inline]
347:                 next
348:               else
349:                 kind = :operator
350:                 label_expected = true
351:               end
352:             end
353:           
354:           elsif scan(/@/)
355:             label_expected = false
356:             kind = :exception
357:           
358:           elsif scan RE::PHP_END
359:             kind = :inline_delimiter
360:             states = [:initial]
361:           
362:           elsif match = scan(/<<<(?:(#{RE::IDENTIFIER})|"(#{RE::IDENTIFIER})"|'(#{RE::IDENTIFIER})')/)
363:             tokens << [:open, :string]
364:             warn 'heredoc in heredoc?' if heredoc_delimiter
365:             heredoc_delimiter = Regexp.escape(self[1] || self[2] || self[3])
366:             kind = :delimiter
367:             states.push self[3] ? :sqstring : :dqstring
368:             heredoc_delimiter = /#{heredoc_delimiter}(?=;?$)/
369:           
370:           elsif match = scan(/#{RE::OPERATOR}/)
371:             label_expected = match == ';'
372:             if case_expected
373:               label_expected = true if match == ':'
374:               case_expected = false
375:             end
376:             kind = :operator
377:           
378:           else
379:             getch
380:             kind = :error
381:           
382:           end
383:         
384:         when :sqstring
385:           if scan(heredoc_delimiter ? /[^\\\n]+/ : /[^'\\]+/)
386:             kind = :content
387:           elsif !heredoc_delimiter && scan(/'/)
388:             tokens << [matched, :delimiter]
389:             tokens << [:close, :string]
390:             delimiter = nil
391:             label_expected = false
392:             states.pop
393:             next
394:           elsif heredoc_delimiter && match = scan(/\n/)
395:             kind = :content
396:             if scan heredoc_delimiter
397:               tokens << ["\n", :content]
398:               tokens << [matched, :delimiter]
399:               tokens << [:close, :string]
400:               heredoc_delimiter = nil
401:               label_expected = false
402:               states.pop
403:               next
404:             end
405:           elsif scan(heredoc_delimiter ? /\\\\/ : /\\[\\'\n]/)
406:             kind = :char
407:           elsif scan(/\\./)
408:             kind = :content
409:           elsif scan(/\\/)
410:             kind = :error
411:           end
412:         
413:         when :dqstring
414:           if scan(heredoc_delimiter ? /[^${\\\n]+/ : (delimiter == '"' ? /[^"${\\]+/ : /[^`${\\]+/))
415:             kind = :content
416:           elsif !heredoc_delimiter && scan(delimiter == '"' ? /"/ : /`/)
417:             tokens << [matched, :delimiter]
418:             tokens << [:close, :string]
419:             delimiter = nil
420:             label_expected = false
421:             states.pop
422:             next
423:           elsif heredoc_delimiter && match = scan(/\n/)
424:             kind = :content
425:             if scan heredoc_delimiter
426:               tokens << ["\n", :content]
427:               tokens << [matched, :delimiter]
428:               tokens << [:close, :string]
429:               heredoc_delimiter = nil
430:               label_expected = false
431:               states.pop
432:               next
433:             end
434:           elsif scan(/\\(?:x[0-9A-Fa-f]{1,2}|[0-7]{1,3})/)
435:             kind = :char
436:           elsif scan(heredoc_delimiter ? /\\[nrtvf\\$]/ : (delimiter == '"' ? /\\[nrtvf\\$"]/ : /\\[nrtvf\\$`]/))
437:             kind = :char
438:           elsif scan(/\\./)
439:             kind = :content
440:           elsif scan(/\\/)
441:             kind = :error
442:           elsif match = scan(/#{RE::VARIABLE}/)
443:             kind = :local_variable
444:             if check(/\[#{RE::IDENTIFIER}\]/)
445:               tokens << [:open, :inline]
446:               tokens << [match, :local_variable]
447:               tokens << [scan(/\[/), :operator]
448:               tokens << [scan(/#{RE::IDENTIFIER}/), :ident]
449:               tokens << [scan(/\]/), :operator]
450:               tokens << [:close, :inline]
451:               next
452:             elsif check(/\[/)
453:               match << scan(/\[['"]?#{RE::IDENTIFIER}?['"]?\]?/)
454:               kind = :error
455:             elsif check(/->#{RE::IDENTIFIER}/)
456:               tokens << [:open, :inline]
457:               tokens << [match, :local_variable]
458:               tokens << [scan(/->/), :operator]
459:               tokens << [scan(/#{RE::IDENTIFIER}/), :ident]
460:               tokens << [:close, :inline]
461:               next
462:             elsif check(/->/)
463:               match << scan(/->/)
464:               kind = :error
465:             end
466:           elsif match = scan(/\{/)
467:             if check(/\$/)
468:               kind = :delimiter
469:               states[1] = [states.last, delimiter]
470:               delimiter = nil
471:               states.push :php
472:               tokens << [:open, :inline]
473:             else
474:               kind = :string
475:             end
476:           elsif scan(/\$\{#{RE::IDENTIFIER}\}/)
477:             kind = :local_variable
478:           elsif scan(/\$/)
479:             kind = :content
480:           end
481:         
482:         when :class_expected
483:           if scan(/\s+/)
484:             kind = :space
485:           elsif match = scan(/#{RE::IDENTIFIER}/)
486:             kind = :class
487:             states.pop
488:           else
489:             states.pop
490:             next
491:           end
492:         
493:         when :function_expected
494:           if scan(/\s+/)
495:             kind = :space
496:           elsif scan(/&/)
497:             kind = :operator
498:           elsif match = scan(/#{RE::IDENTIFIER}/)
499:             kind = :function
500:             states.pop
501:           else
502:             states.pop
503:             next
504:           end
505:         
506:         else
507:           raise_inspect 'Unknown state!', tokens, states
508:         end
509:         
510:         match ||= matched
511:         if $CODERAY_DEBUG and not kind
512:           raise_inspect 'Error token %p in line %d' %
513:             [[match, kind], line], tokens, states
514:         end
515:         raise_inspect 'Empty token', tokens, states unless match
516:         
517:         tokens << [match, kind]
518:         
519:       end
520:       
521:       tokens
522:     end
setup() click to toggle source
    # File lib/coderay/scanners/php.rb, line 14
14:     def setup
15:       @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true
16:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.