Mercurial > hg > soundsoftware-site
comparison vendor/plugins/coderay-0.9.2/lib/coderay/scanners/sql.rb @ 0:513646585e45
* Import Redmine trunk SVN rev 3859
author | Chris Cannam |
---|---|
date | Fri, 23 Jul 2010 15:52:44 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:513646585e45 |
---|---|
1 module CodeRay module Scanners | |
2 | |
3 # by Josh Goebel | |
4 class SQL < Scanner | |
5 | |
6 register_for :sql | |
7 | |
8 RESERVED_WORDS = %w( | |
9 create database table index trigger drop primary key set select | |
10 insert update delete replace into | |
11 on from values before and or if exists case when | |
12 then else as group order by avg where | |
13 join inner outer union engine not | |
14 like end using collate show columns begin | |
15 ) | |
16 | |
17 PREDEFINED_TYPES = %w( | |
18 char varchar enum binary text tinytext mediumtext | |
19 longtext blob tinyblob mediumblob longblob timestamp | |
20 date time datetime year double decimal float int | |
21 integer tinyint mediumint bigint smallint unsigned bit | |
22 bool boolean hex bin oct | |
23 ) | |
24 | |
25 PREDEFINED_FUNCTIONS = %w( sum cast abs pi count min max avg ) | |
26 | |
27 DIRECTIVES = %w( auto_increment unique default charset ) | |
28 | |
29 PREDEFINED_CONSTANTS = %w( null true false ) | |
30 | |
31 IDENT_KIND = CaseIgnoringWordList.new(:ident). | |
32 add(RESERVED_WORDS, :reserved). | |
33 add(PREDEFINED_TYPES, :pre_type). | |
34 add(PREDEFINED_CONSTANTS, :pre_constant). | |
35 add(PREDEFINED_FUNCTIONS, :predefined). | |
36 add(DIRECTIVES, :directive) | |
37 | |
38 ESCAPE = / [rbfntv\n\\\/'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | . /mx | |
39 UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x | |
40 | |
41 STRING_PREFIXES = /[xnb]|_\w+/i | |
42 | |
43 def scan_tokens tokens, options | |
44 | |
45 state = :initial | |
46 string_type = nil | |
47 string_content = '' | |
48 | |
49 until eos? | |
50 | |
51 kind = nil | |
52 match = nil | |
53 | |
54 if state == :initial | |
55 | |
56 if scan(/ \s+ | \\\n /x) | |
57 kind = :space | |
58 | |
59 elsif scan(/^(?:--\s?|#).*/) | |
60 kind = :comment | |
61 | |
62 elsif scan(%r! /\* (?: .*? \*/ | .* ) !mx) | |
63 kind = :comment | |
64 | |
65 elsif scan(/ [-+*\/=<>;,!&^|()\[\]{}~%] | \.(?!\d) /x) | |
66 kind = :operator | |
67 | |
68 elsif scan(/(#{STRING_PREFIXES})?([`"'])/o) | |
69 prefix = self[1] | |
70 string_type = self[2] | |
71 tokens << [:open, :string] | |
72 tokens << [prefix, :modifier] if prefix | |
73 match = string_type | |
74 state = :string | |
75 kind = :delimiter | |
76 | |
77 elsif match = scan(/ @? [A-Za-z_][A-Za-z_0-9]* /x) | |
78 kind = match[0] == ?@ ? :variable : IDENT_KIND[match.downcase] | |
79 | |
80 elsif scan(/0[xX][0-9A-Fa-f]+/) | |
81 kind = :hex | |
82 | |
83 elsif scan(/0[0-7]+(?![89.eEfF])/) | |
84 kind = :oct | |
85 | |
86 elsif scan(/(?>\d+)(?![.eEfF])/) | |
87 kind = :integer | |
88 | |
89 elsif scan(/\d[fF]|\d*\.\d+(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+/) | |
90 kind = :float | |
91 | |
92 else | |
93 getch | |
94 kind = :error | |
95 | |
96 end | |
97 | |
98 elsif state == :string | |
99 if match = scan(/[^\\"'`]+/) | |
100 string_content << match | |
101 next | |
102 elsif match = scan(/["'`]/) | |
103 if string_type == match | |
104 if peek(1) == string_type # doubling means escape | |
105 string_content << string_type << getch | |
106 next | |
107 end | |
108 unless string_content.empty? | |
109 tokens << [string_content, :content] | |
110 string_content = '' | |
111 end | |
112 tokens << [matched, :delimiter] | |
113 tokens << [:close, :string] | |
114 state = :initial | |
115 string_type = nil | |
116 next | |
117 else | |
118 string_content << match | |
119 end | |
120 next | |
121 elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) | |
122 unless string_content.empty? | |
123 tokens << [string_content, :content] | |
124 string_content = '' | |
125 end | |
126 kind = :char | |
127 elsif match = scan(/ \\ . /mox) | |
128 string_content << match | |
129 next | |
130 elsif scan(/ \\ | $ /x) | |
131 unless string_content.empty? | |
132 tokens << [string_content, :content] | |
133 string_content = '' | |
134 end | |
135 kind = :error | |
136 state = :initial | |
137 else | |
138 raise "else case \" reached; %p not handled." % peek(1), tokens | |
139 end | |
140 | |
141 else | |
142 raise 'else-case reached', tokens | |
143 | |
144 end | |
145 | |
146 match ||= matched | |
147 unless kind | |
148 raise_inspect 'Error token %p in line %d' % | |
149 [[match, kind], line], tokens, state | |
150 end | |
151 raise_inspect 'Empty token', tokens unless match | |
152 | |
153 tokens << [match, kind] | |
154 | |
155 end | |
156 tokens | |
157 | |
158 end | |
159 | |
160 end | |
161 | |
162 end end |