Mercurial > hg > soundsoftware-site
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 |