Class | CodeRay::Scanners::Java |
In: |
lib/coderay/scanners/java.rb
|
Parent: | Scanner |
KEYWORDS | = | %w[ break case catch continue default do else false finally for if instanceof new null return switch throw true try typeof while debugger export import package ] | TODO: Check this! | |
MAGIC_VARIABLES | = | %w[ this super ] | ||
TYPES | = | %w[ boolean byte char class interface double enum float String int long short void ] << '[]' | ||
DIRECTIVES | = | %w[ abstract extends final implements native private protected public static strictfp synchronized threadsafe throws transient volatile ] | ||
IDENT_KIND | = | WordList.new(:ident). add(KEYWORDS, :keyword). add(MAGIC_VARIABLES, :local_variable). add(TYPES, :type). add(BuiltinTypes::List, :pre_type). add(DIRECTIVES, :directive) | Reserved for future use. | |
ESCAPE | = | / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x | ||
UNICODE_ESCAPE | = | / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x | ||
STRING_CONTENT_PATTERN | = | { "'" => /[^\\']+/, '"' => /[^\\"]+/, '/' => /[^\\\/]+/, } | ||
IDENT | = | /[a-zA-Z_][A-Za-z_0-9]*/ |
# File lib/coderay/scanners/java.rb, line 45 45: def scan_tokens tokens, options 46: 47: state = :initial 48: string_delimiter = nil 49: import_clause = class_name_follows = last_token_dot = false 50: 51: until eos? 52: 53: kind = nil 54: match = nil 55: 56: case state 57: 58: when :initial 59: 60: if match = scan(/ \s+ | \\\n /x) 61: tokens << [match, :space] 62: next 63: 64: elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) 65: kind = :comment 66: 67: elsif import_clause && scan(/ #{IDENT} (?: \. #{IDENT} )* /ox) 68: kind = :include 69: 70: elsif match = scan(/ #{IDENT} | \[\] /ox) 71: kind = IDENT_KIND[match] 72: if last_token_dot 73: kind = :ident 74: elsif class_name_follows 75: kind = :class 76: class_name_follows = false 77: else 78: import_clause = true if match == 'import' 79: class_name_follows = true if match == 'class' || match == 'interface' 80: end 81: 82: elsif scan(/ \.(?!\d) | [,?:(\[)\]}] | -- | \+\+ | && | \|\| | \*\*=? | [-+*\/%^~&|<>=!]=? | <<<?=? | >>>?=? /x) 83: kind = :operator 84: 85: elsif scan(/;/) 86: import_clause = false 87: kind = :operator 88: 89: elsif scan(/\{/) 90: class_name_follows = false 91: kind = :operator 92: 93: elsif check(/[\d.]/) 94: if scan(/0[xX][0-9A-Fa-f]+/) 95: kind = :hex 96: elsif scan(/(?>0[0-7]+)(?![89.eEfF])/) 97: kind = :oct 98: elsif scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/) 99: kind = :float 100: elsif scan(/\d+[lL]?/) 101: kind = :integer 102: end 103: 104: elsif match = scan(/["']/) 105: tokens << [:open, :string] 106: state = :string 107: string_delimiter = match 108: kind = :delimiter 109: 110: elsif scan(/ @ #{IDENT} /ox) 111: kind = :annotation 112: 113: else 114: getch 115: kind = :error 116: 117: end 118: 119: when :string 120: if scan(STRING_CONTENT_PATTERN[string_delimiter]) 121: kind = :content 122: elsif match = scan(/["'\/]/) 123: tokens << [match, :delimiter] 124: tokens << [:close, state] 125: string_delimiter = nil 126: state = :initial 127: next 128: elsif state == :string && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)) 129: if string_delimiter == "'" && !(match == "\\\\" || match == "\\'") 130: kind = :content 131: else 132: kind = :char 133: end 134: elsif scan(/\\./m) 135: kind = :content 136: elsif scan(/ \\ | $ /x) 137: tokens << [:close, :delimiter] 138: kind = :error 139: state = :initial 140: else 141: raise_inspect "else case \" reached; %p not handled." % peek(1), tokens 142: end 143: 144: else 145: raise_inspect 'Unknown state', tokens 146: 147: end 148: 149: match ||= matched 150: if $DEBUG and not kind 151: raise_inspect 'Error token %p in line %d' % 152: [[match, kind], line], tokens 153: end 154: raise_inspect 'Empty token', tokens unless match 155: 156: last_token_dot = match == '.' 157: 158: tokens << [match, kind] 159: 160: end 161: 162: if state == :string 163: tokens << [:close, state] 164: end 165: 166: tokens 167: end