summaryrefslogtreecommitdiffstats
path: root/vendor/plugins/coderay-0.7.6.227/lib/coderay/scanners/javascript.rb
blob: 419a5255be939527c06fcfbcab378f1eaf0e2b1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# http://pastie.textmate.org/50774/
module CodeRay module Scanners
	
	class JavaScript < Scanner

		register_for :javascript
		
		RESERVED_WORDS = [
			'asm', 'break', 'case', 'continue', 'default', 'do', 'else',
			'for', 'goto', 'if', 'return', 'switch', 'while',
#			'struct', 'union', 'enum', 'typedef',
#			'static', 'register', 'auto', 'extern',
#			'sizeof',
      'typeof',
#			'volatile', 'const',  # C89
#			'inline', 'restrict', # C99			
			'var', 'function','try','new','in',
			'instanceof','throw','catch'
		]

		PREDEFINED_CONSTANTS = [
			'void', 'null', 'this',
			'true', 'false','undefined',
		]

		IDENT_KIND = WordList.new(:ident).
			add(RESERVED_WORDS, :reserved).
			add(PREDEFINED_CONSTANTS, :pre_constant)

		ESCAPE = / [rbfnrtv\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

		def scan_tokens tokens, options

			state = :initial
			string_type = nil
			regexp_allowed = true

			until eos?

				kind = :error
				match = nil

				if state == :initial
					
					if scan(/ \s+ | \\\n /x)
						kind = :space
						
					elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
						kind = :comment
						regexp_allowed = false

					elsif match = scan(/ \# \s* if \s* 0 /x)
						match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
						kind = :comment
						regexp_allowed = false

				  elsif regexp_allowed and scan(/\//)
				    tokens << [:open, :regexp]
				    state = :regex
						kind = :delimiter
						
					elsif scan(/ [-+*\/=<>?:;,!&^|()\[\]{}~%] | \.(?!\d) /x)
						kind = :operator
						regexp_allowed=true
						
					elsif match = scan(/ [$A-Za-z_][A-Za-z_0-9]* /x)
						kind = IDENT_KIND[match]
#						if kind == :ident and check(/:(?!:)/)
#							match << scan(/:/)
#							kind = :label
#						end
						regexp_allowed=false
						
					elsif match = scan(/["']/)
						tokens << [:open, :string]
            string_type = matched
						state = :string
						kind = :delimiter
						
#					elsif scan(/#\s*(\w*)/)
#						kind = :preprocessor  # FIXME multiline preprocs
#						state = :include_expected if self[1] == 'include'
#						
#					elsif scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
#						kind = :char
				
					elsif scan(/0[xX][0-9A-Fa-f]+/)
						kind = :hex
						regexp_allowed=false
						
					elsif scan(/(?:0[0-7]+)(?![89.eEfF])/)
						kind = :oct
						regexp_allowed=false
						
					elsif scan(/(?:\d+)(?![.eEfF])/)
						kind = :integer
						regexp_allowed=false
						
					elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
						kind = :float
						regexp_allowed=false

					else
						getch
					end
					
				elsif state == :regex
					if scan(/[^\\\/]+/)
						kind = :content
				  elsif scan(/\\\/|\\\\/)
						kind = :content
				  elsif scan(/\//)
					  tokens << [matched, :delimiter]
				    tokens << [:close, :regexp]
				    state = :initial
				    next
				  else
				    getch
				    kind = :content
					end
				  
				elsif state == :string
					if scan(/[^\\"']+/)
						kind = :content
					elsif scan(/["']/)
						if string_type==matched
						  tokens << [matched, :delimiter]
						  tokens << [:close, :string]
						  state = :initial
						  string_type=nil
						  next
						else
						  kind = :content
						end
					elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
						kind = :char
					elsif scan(/ \\ | $ /x)
						kind = :error
						state = :initial
					else
						raise "else case \" reached; %p not handled." % peek(1), tokens
					end
					
#				elsif state == :include_expected
#					if scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
#						kind = :include
#						state = :initial
#						
#					elsif match = scan(/\s+/)
#						kind = :space
#						state = :initial if match.index ?\n
#						
#					else
#						getch
#						
#					end
#					
				else
					raise 'else-case reached', tokens
					
				end
				
				match ||= matched
#				raise [match, kind], tokens if kind == :error
        
				tokens << [match, kind]
				
			end
		  tokens
			
		end

	end

end end