comparison vendor/gems/coderay-1.0.0/lib/coderay/scanners/sql.rb @ 909:cbb26bc654de redmine-1.3

Update to Redmine 1.3-stable branch (Redmine SVN rev 8964)
author Chris Cannam
date Fri, 24 Feb 2012 19:09:32 +0000
parents
children
comparison
equal deleted inserted replaced
908:c6c2cbd0afee 909:cbb26bc654de
1 module CodeRay module Scanners
2
3 # by Josh Goebel
4 class SQL < Scanner
5
6 register_for :sql
7
8 KEYWORDS = %w(
9 all and any as before begin between by case check collate
10 each else end exists
11 for foreign from full group having if in inner is join
12 like not of on or order outer over references
13 then to union using values when where
14 left right distinct
15 )
16
17 OBJECTS = %w(
18 database databases table tables column columns fields index constraint
19 constraints transaction function procedure row key view trigger
20 )
21
22 COMMANDS = %w(
23 add alter comment create delete drop grant insert into select update set
24 show prompt begin commit rollback replace truncate
25 )
26
27 PREDEFINED_TYPES = %w(
28 char varchar varchar2 enum binary text tinytext mediumtext
29 longtext blob tinyblob mediumblob longblob timestamp
30 date time datetime year double decimal float int
31 integer tinyint mediumint bigint smallint unsigned bit
32 bool boolean hex bin oct
33 )
34
35 PREDEFINED_FUNCTIONS = %w( sum cast substring abs pi count min max avg now )
36
37 DIRECTIVES = %w(
38 auto_increment unique default charset initially deferred
39 deferrable cascade immediate read write asc desc after
40 primary foreign return engine
41 )
42
43 PREDEFINED_CONSTANTS = %w( null true false )
44
45 IDENT_KIND = WordList::CaseIgnoring.new(:ident).
46 add(KEYWORDS, :keyword).
47 add(OBJECTS, :type).
48 add(COMMANDS, :class).
49 add(PREDEFINED_TYPES, :predefined_type).
50 add(PREDEFINED_CONSTANTS, :predefined_constant).
51 add(PREDEFINED_FUNCTIONS, :predefined).
52 add(DIRECTIVES, :directive)
53
54 ESCAPE = / [rbfntv\n\\\/'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | . /mx
55 UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x
56
57 STRING_PREFIXES = /[xnb]|_\w+/i
58
59 def scan_tokens encoder, options
60
61 state = :initial
62 string_type = nil
63 string_content = ''
64 name_expected = false
65
66 until eos?
67
68 if state == :initial
69
70 if match = scan(/ \s+ | \\\n /x)
71 encoder.text_token match, :space
72
73 elsif match = scan(/(?:--\s?|#).*/)
74 encoder.text_token match, :comment
75
76 elsif match = scan(%r( /\* (!)? (?: .*? \*/ | .* ) )mx)
77 encoder.text_token match, self[1] ? :directive : :comment
78
79 elsif match = scan(/ [*\/=<>:;,!&^|()\[\]{}~%] | [-+\.](?!\d) /x)
80 name_expected = true if match == '.' && check(/[A-Za-z_]/)
81 encoder.text_token match, :operator
82
83 elsif match = scan(/(#{STRING_PREFIXES})?([`"'])/o)
84 prefix = self[1]
85 string_type = self[2]
86 encoder.begin_group :string
87 encoder.text_token prefix, :modifier if prefix
88 match = string_type
89 state = :string
90 encoder.text_token match, :delimiter
91
92 elsif match = scan(/ @? [A-Za-z_][A-Za-z_0-9]* /x)
93 encoder.text_token match, name_expected ? :ident : (match[0] == ?@ ? :variable : IDENT_KIND[match])
94 name_expected = false
95
96 elsif match = scan(/0[xX][0-9A-Fa-f]+/)
97 encoder.text_token match, :hex
98
99 elsif match = scan(/0[0-7]+(?![89.eEfF])/)
100 encoder.text_token match, :octal
101
102 elsif match = scan(/[-+]?(?>\d+)(?![.eEfF])/)
103 encoder.text_token match, :integer
104
105 elsif match = scan(/[-+]?(?:\d[fF]|\d*\.\d+(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)/)
106 encoder.text_token match, :float
107
108 elsif match = scan(/\\N/)
109 encoder.text_token match, :predefined_constant
110
111 else
112 encoder.text_token getch, :error
113
114 end
115
116 elsif state == :string
117 if match = scan(/[^\\"'`]+/)
118 string_content << match
119 next
120 elsif match = scan(/["'`]/)
121 if string_type == match
122 if peek(1) == string_type # doubling means escape
123 string_content << string_type << getch
124 next
125 end
126 unless string_content.empty?
127 encoder.text_token string_content, :content
128 string_content = ''
129 end
130 encoder.text_token match, :delimiter
131 encoder.end_group :string
132 state = :initial
133 string_type = nil
134 else
135 string_content << match
136 end
137 elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
138 unless string_content.empty?
139 encoder.text_token string_content, :content
140 string_content = ''
141 end
142 encoder.text_token match, :char
143 elsif match = scan(/ \\ . /mox)
144 string_content << match
145 next
146 elsif match = scan(/ \\ | $ /x)
147 unless string_content.empty?
148 encoder.text_token string_content, :content
149 string_content = ''
150 end
151 encoder.text_token match, :error
152 state = :initial
153 else
154 raise "else case \" reached; %p not handled." % peek(1), encoder
155 end
156
157 else
158 raise 'else-case reached', encoder
159
160 end
161
162 end
163
164 if state == :string
165 encoder.end_group state
166 end
167
168 encoder
169
170 end
171
172 end
173
174 end end