sql-parser-tl 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,113 @@
1
+ class SQLParser::Parser
2
+
3
+ option
4
+ ignorecase
5
+
6
+ macro
7
+ DIGIT [0-9]
8
+ UINT {DIGIT}+
9
+ BLANK \s+
10
+
11
+ YEARS {UINT}
12
+ MONTHS {UINT}
13
+ DAYS {UINT}
14
+ DATE {YEARS}-{MONTHS}-{DAYS}
15
+
16
+ IDENT [\w\$]+
17
+
18
+ KW_TRAIL ([\s()]+)|$ # Keywords must trail with these characters; otherwise, aliases containing a keyword as a prefix will be misinterpreted
19
+
20
+ rule
21
+ # [:state] pattern [actions]
22
+
23
+ # literals
24
+ \"{DATE}\" { [:date_string, Date.parse(text)] }
25
+ \'{DATE}\' { [:date_string, Date.parse(text)] }
26
+
27
+ \' { @state = :STRS; [:single_quote, text] }
28
+ :STRS \' { @state = nil; [:single_quote, text] }
29
+ :STRS .*?(?=(?<!\\)\') { [:character_string_literal, text.gsub("''", "'")] }
30
+
31
+ \" { @state = :STRD; [:double_quote, text] }
32
+ :STRD \" { @state = nil; [:double_quote, text] }
33
+ :STRD .*?(?=(?<!\\)\") { [:character_string_literal, text.gsub('""', '"')] }
34
+
35
+ {UINT} { [:unsigned_integer, text.to_i] }
36
+
37
+ # skip
38
+ {BLANK} # no action
39
+
40
+ # keywords
41
+ SELECT(?={KW_TRAIL}) { [:SELECT, text] }
42
+ DATE(?={KW_TRAIL}) { [:DATE, text] }
43
+ ASC(?={KW_TRAIL}) { [:ASC, text] }
44
+ AS(?={KW_TRAIL}) { [:AS, text] }
45
+ FROM(?={KW_TRAIL}) { [:FROM, text] }
46
+ WHERE(?={KW_TRAIL}) { [:WHERE, text] }
47
+ BETWEEN(?={KW_TRAIL}) { [:BETWEEN, text] }
48
+ AND(?={KW_TRAIL}) { [:AND, text] }
49
+ NOT(?={KW_TRAIL}) { [:NOT, text] }
50
+ INNER(?={KW_TRAIL}) { [:INNER, text] }
51
+ INSERT(?={KW_TRAIL}) { [:INSERT, text] }
52
+ INTO(?={KW_TRAIL}) { [:INTO, text] }
53
+ IN(?={KW_TRAIL}) { [:IN, text] }
54
+ ORDER(?={KW_TRAIL}) { [:ORDER, text] }
55
+ OR(?={KW_TRAIL}) { [:OR, text] }
56
+ LIKE(?={KW_TRAIL}) { [:LIKE, text] }
57
+ IS(?={KW_TRAIL}) { [:IS, text] }
58
+ NULL(?={KW_TRAIL}) { [:NULL, text] }
59
+ COUNT(?={KW_TRAIL}) { [:COUNT, text] }
60
+ AVG(?={KW_TRAIL}) { [:AVG, text] }
61
+ MAX(?={KW_TRAIL}) { [:MAX, text] }
62
+ MIN(?={KW_TRAIL}) { [:MIN, text] }
63
+ SUM(?={KW_TRAIL}) { [:SUM, text] }
64
+ GROUP(?={KW_TRAIL}) { [:GROUP, text] }
65
+ BY(?={KW_TRAIL}) { [:BY, text] }
66
+ HAVING(?={KW_TRAIL}) { [:HAVING, text] }
67
+ CROSS(?={KW_TRAIL}) { [:CROSS, text] }
68
+ JOIN(?={KW_TRAIL}) { [:JOIN, text] }
69
+ ON(?={KW_TRAIL}) { [:ON, text] }
70
+ LEFT(?={KW_TRAIL}) { [:LEFT, text] }
71
+ OUTER(?={KW_TRAIL}) { [:OUTER, text] }
72
+ RIGHT(?={KW_TRAIL}) { [:RIGHT, text] }
73
+ FULL(?={KW_TRAIL}) { [:FULL, text] }
74
+ USING(?={KW_TRAIL}) { [:USING, text] }
75
+ EXISTS(?={KW_TRAIL}) { [:EXISTS, text] }
76
+ DESC(?={KW_TRAIL}) { [:DESC, text] }
77
+ CURRENT_USER(?={KW_TRAIL}) { [:CURRENT_USER, text] }
78
+ VALUES(?={KW_TRAIL}) { [:VALUES, text] }
79
+ LIMIT(?={KW_TRAIL}) { [:LIMIT, text] }
80
+ OFFSET(?={KW_TRAIL}) { [:OFFSET, text] }
81
+ DISTINCT(?={KW_TRAIL}) { [:DISTINCT, text] }
82
+ INDEX(?={KW_TRAIL}) { [:INDEX, text] }
83
+ FORCE(?={KW_TRAIL}) { [:FORCE, text] }
84
+ USE(?={KW_TRAIL}) { [:USE, text] }
85
+ IGNORE(?={KW_TRAIL}) { [:IGNORE, text] }
86
+
87
+
88
+ # tokens
89
+ E { [:E, text] }
90
+
91
+ <> { [:not_equals_operator, text] }
92
+ != { [:not_equals_operator, text] }
93
+ = { [:equals_operator, text] }
94
+ <= { [:less_than_or_equals_operator, text] }
95
+ < { [:less_than_operator, text] }
96
+ >= { [:greater_than_or_equals_operator, text] }
97
+ > { [:greater_than_operator, text] }
98
+
99
+ \( { [:left_paren, text] }
100
+ \) { [:right_paren, text] }
101
+ \* { [:asterisk, text] }
102
+ \/ { [:solidus, text] }
103
+ \+ { [:plus_sign, text] }
104
+ \- { [:minus_sign, text] }
105
+ \. { [:period, text] }
106
+ , { [:comma, text] }
107
+
108
+ # identifier
109
+ `{IDENT}` { [:identifier, text[1..-2]] }
110
+ {IDENT} { [:identifier, text] }
111
+
112
+ ---- header ----
113
+ require 'date'
@@ -0,0 +1,324 @@
1
+ #--
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by rex 1.0.5
4
+ # from lexical definition file "lib/sql-parser/parser.rex".
5
+ #++
6
+
7
+ require 'racc/parser'
8
+ class SQLParser::Parser < Racc::Parser
9
+ require 'strscan'
10
+
11
+ class ScanError < StandardError ; end
12
+
13
+ attr_reader :lineno
14
+ attr_reader :filename
15
+ attr_accessor :state
16
+
17
+ def scan_setup(str)
18
+ @ss = StringScanner.new(str)
19
+ @lineno = 1
20
+ @state = nil
21
+ end
22
+
23
+ def action
24
+ yield
25
+ end
26
+
27
+ def scan_str(str)
28
+ scan_setup(str)
29
+ do_parse
30
+ end
31
+ alias :scan :scan_str
32
+
33
+ def load_file( filename )
34
+ @filename = filename
35
+ open(filename, "r") do |f|
36
+ scan_setup(f.read)
37
+ end
38
+ end
39
+
40
+ def scan_file( filename )
41
+ load_file(filename)
42
+ do_parse
43
+ end
44
+
45
+
46
+ def next_token
47
+ return if @ss.eos?
48
+
49
+ # skips empty actions
50
+ until token = _next_token or @ss.eos?; end
51
+ token
52
+ end
53
+
54
+ def _next_token
55
+ text = @ss.peek(1)
56
+ @lineno += 1 if text == "\n"
57
+ token = case @state
58
+ when nil
59
+ case
60
+ when (text = @ss.scan(/\"[0-9]+-[0-9]+-[0-9]+\"/i))
61
+ action { [:date_string, Date.parse(text)] }
62
+
63
+ when (text = @ss.scan(/\'[0-9]+-[0-9]+-[0-9]+\'/i))
64
+ action { [:date_string, Date.parse(text)] }
65
+
66
+ when (text = @ss.scan(/\'/i))
67
+ action { @state = :STRS; [:single_quote, text] }
68
+
69
+ when (text = @ss.scan(/\"/i))
70
+ action { @state = :STRD; [:double_quote, text] }
71
+
72
+ when (text = @ss.scan(/[0-9]+/i))
73
+ action { [:unsigned_integer, text.to_i] }
74
+
75
+ when (text = @ss.scan(/\s+/i))
76
+ ;
77
+
78
+ when (text = @ss.scan(/SELECT(?=([\s()]+)|$)/i))
79
+ action { [:SELECT, text] }
80
+
81
+ when (text = @ss.scan(/DATE(?=([\s()]+)|$)/i))
82
+ action { [:DATE, text] }
83
+
84
+ when (text = @ss.scan(/ASC(?=([\s()]+)|$)/i))
85
+ action { [:ASC, text] }
86
+
87
+ when (text = @ss.scan(/AS(?=([\s()]+)|$)/i))
88
+ action { [:AS, text] }
89
+
90
+ when (text = @ss.scan(/FROM(?=([\s()]+)|$)/i))
91
+ action { [:FROM, text] }
92
+
93
+ when (text = @ss.scan(/WHERE(?=([\s()]+)|$)/i))
94
+ action { [:WHERE, text] }
95
+
96
+ when (text = @ss.scan(/BETWEEN(?=([\s()]+)|$)/i))
97
+ action { [:BETWEEN, text] }
98
+
99
+ when (text = @ss.scan(/AND(?=([\s()]+)|$)/i))
100
+ action { [:AND, text] }
101
+
102
+ when (text = @ss.scan(/NOT(?=([\s()]+)|$)/i))
103
+ action { [:NOT, text] }
104
+
105
+ when (text = @ss.scan(/INNER(?=([\s()]+)|$)/i))
106
+ action { [:INNER, text] }
107
+
108
+ when (text = @ss.scan(/INSERT(?=([\s()]+)|$)/i))
109
+ action { [:INSERT, text] }
110
+
111
+ when (text = @ss.scan(/INTO(?=([\s()]+)|$)/i))
112
+ action { [:INTO, text] }
113
+
114
+ when (text = @ss.scan(/IN(?=([\s()]+)|$)/i))
115
+ action { [:IN, text] }
116
+
117
+ when (text = @ss.scan(/ORDER(?=([\s()]+)|$)/i))
118
+ action { [:ORDER, text] }
119
+
120
+ when (text = @ss.scan(/OR(?=([\s()]+)|$)/i))
121
+ action { [:OR, text] }
122
+
123
+ when (text = @ss.scan(/LIKE(?=([\s()]+)|$)/i))
124
+ action { [:LIKE, text] }
125
+
126
+ when (text = @ss.scan(/IS(?=([\s()]+)|$)/i))
127
+ action { [:IS, text] }
128
+
129
+ when (text = @ss.scan(/NULL(?=([\s()]+)|$)/i))
130
+ action { [:NULL, text] }
131
+
132
+ when (text = @ss.scan(/COUNT(?=([\s()]+)|$)/i))
133
+ action { [:COUNT, text] }
134
+
135
+ when (text = @ss.scan(/AVG(?=([\s()]+)|$)/i))
136
+ action { [:AVG, text] }
137
+
138
+ when (text = @ss.scan(/MAX(?=([\s()]+)|$)/i))
139
+ action { [:MAX, text] }
140
+
141
+ when (text = @ss.scan(/MIN(?=([\s()]+)|$)/i))
142
+ action { [:MIN, text] }
143
+
144
+ when (text = @ss.scan(/SUM(?=([\s()]+)|$)/i))
145
+ action { [:SUM, text] }
146
+
147
+ when (text = @ss.scan(/GROUP(?=([\s()]+)|$)/i))
148
+ action { [:GROUP, text] }
149
+
150
+ when (text = @ss.scan(/BY(?=([\s()]+)|$)/i))
151
+ action { [:BY, text] }
152
+
153
+ when (text = @ss.scan(/HAVING(?=([\s()]+)|$)/i))
154
+ action { [:HAVING, text] }
155
+
156
+ when (text = @ss.scan(/CROSS(?=([\s()]+)|$)/i))
157
+ action { [:CROSS, text] }
158
+
159
+ when (text = @ss.scan(/JOIN(?=([\s()]+)|$)/i))
160
+ action { [:JOIN, text] }
161
+
162
+ when (text = @ss.scan(/ON(?=([\s()]+)|$)/i))
163
+ action { [:ON, text] }
164
+
165
+ when (text = @ss.scan(/LEFT(?=([\s()]+)|$)/i))
166
+ action { [:LEFT, text] }
167
+
168
+ when (text = @ss.scan(/OUTER(?=([\s()]+)|$)/i))
169
+ action { [:OUTER, text] }
170
+
171
+ when (text = @ss.scan(/RIGHT(?=([\s()]+)|$)/i))
172
+ action { [:RIGHT, text] }
173
+
174
+ when (text = @ss.scan(/FULL(?=([\s()]+)|$)/i))
175
+ action { [:FULL, text] }
176
+
177
+ when (text = @ss.scan(/USING(?=([\s()]+)|$)/i))
178
+ action { [:USING, text] }
179
+
180
+ when (text = @ss.scan(/EXISTS(?=([\s()]+)|$)/i))
181
+ action { [:EXISTS, text] }
182
+
183
+ when (text = @ss.scan(/DESC(?=([\s()]+)|$)/i))
184
+ action { [:DESC, text] }
185
+
186
+ when (text = @ss.scan(/CURRENT_USER(?=([\s()]+)|$)/i))
187
+ action { [:CURRENT_USER, text] }
188
+
189
+ when (text = @ss.scan(/VALUES(?=([\s()]+)|$)/i))
190
+ action { [:VALUES, text] }
191
+
192
+ when (text = @ss.scan(/LIMIT(?=([\s()]+)|$)/i))
193
+ action { [:LIMIT, text] }
194
+
195
+ when (text = @ss.scan(/OFFSET(?=([\s()]+)|$)/i))
196
+ action { [:OFFSET, text] }
197
+
198
+ when (text = @ss.scan(/DISTINCT(?=([\s()]+)|$)/i))
199
+ action { [:DISTINCT, text] }
200
+
201
+ when (text = @ss.scan(/INDEX(?=([\s()]+)|$)/i))
202
+ action { [:INDEX, text] }
203
+
204
+ when (text = @ss.scan(/FORCE(?=([\s()]+)|$)/i))
205
+ action { [:FORCE, text] }
206
+
207
+ when (text = @ss.scan(/USE(?=([\s()]+)|$)/i))
208
+ action { [:USE, text] }
209
+
210
+ when (text = @ss.scan(/IGNORE(?=([\s()]+)|$)/i))
211
+ action { [:IGNORE, text] }
212
+
213
+ when (text = @ss.scan(/E/i))
214
+ action { [:E, text] }
215
+
216
+ when (text = @ss.scan(/<>/i))
217
+ action { [:not_equals_operator, text] }
218
+
219
+ when (text = @ss.scan(/!=/i))
220
+ action { [:not_equals_operator, text] }
221
+
222
+ when (text = @ss.scan(/=/i))
223
+ action { [:equals_operator, text] }
224
+
225
+ when (text = @ss.scan(/<=/i))
226
+ action { [:less_than_or_equals_operator, text] }
227
+
228
+ when (text = @ss.scan(/</i))
229
+ action { [:less_than_operator, text] }
230
+
231
+ when (text = @ss.scan(/>=/i))
232
+ action { [:greater_than_or_equals_operator, text] }
233
+
234
+ when (text = @ss.scan(/>/i))
235
+ action { [:greater_than_operator, text] }
236
+
237
+ when (text = @ss.scan(/\(/i))
238
+ action { [:left_paren, text] }
239
+
240
+ when (text = @ss.scan(/\)/i))
241
+ action { [:right_paren, text] }
242
+
243
+ when (text = @ss.scan(/\*/i))
244
+ action { [:asterisk, text] }
245
+
246
+ when (text = @ss.scan(/\//i))
247
+ action { [:solidus, text] }
248
+
249
+ when (text = @ss.scan(/\+/i))
250
+ action { [:plus_sign, text] }
251
+
252
+ when (text = @ss.scan(/\-/i))
253
+ action { [:minus_sign, text] }
254
+
255
+ when (text = @ss.scan(/\./i))
256
+ action { [:period, text] }
257
+
258
+ when (text = @ss.scan(/,/i))
259
+ action { [:comma, text] }
260
+
261
+ when (text = @ss.scan(/`[\w\$]+`/i))
262
+ action { [:identifier, text[1..-2]] }
263
+
264
+ when (text = @ss.scan(/[\w\$]+/i))
265
+ action { [:identifier, text] }
266
+
267
+ when (text = @ss.scan(/----/i))
268
+ ;
269
+
270
+ when (text = @ss.scan(/require/i))
271
+ ;
272
+
273
+ else
274
+ text = @ss.string[@ss.pos .. -1]
275
+ raise ScanError, "can not match: '" + text + "'"
276
+ end # if
277
+
278
+ when :STRS
279
+ case
280
+ when (text = @ss.scan(/\'/i))
281
+ action { @state = nil; [:single_quote, text] }
282
+
283
+ when (text = @ss.scan(/.*?(?=(?<!\\)\')/i))
284
+ action { [:character_string_literal, text.gsub("''", "'")] }
285
+
286
+ else
287
+ text = @ss.string[@ss.pos .. -1]
288
+ raise ScanError, "can not match: '" + text + "'"
289
+ end # if
290
+
291
+ when :STRD
292
+ case
293
+ when (text = @ss.scan(/\"/i))
294
+ action { @state = nil; [:double_quote, text] }
295
+
296
+ when (text = @ss.scan(/.*?(?=(?<!\\)\")/i))
297
+ action { [:character_string_literal, text.gsub('""', '"')] }
298
+
299
+ else
300
+ text = @ss.string[@ss.pos .. -1]
301
+ raise ScanError, "can not match: '" + text + "'"
302
+ end # if
303
+
304
+ else
305
+ raise ScanError, "undefined state: '" + state.to_s + "'"
306
+ end # case state
307
+ token
308
+ end # def _next_token
309
+
310
+ end # class
311
+
312
+ if __FILE__ == $0
313
+ exit if ARGV.size != 1
314
+ filename = ARGV.shift
315
+ rex = SQLParser::Parser.new
316
+ begin
317
+ rex.load_file filename
318
+ while token = rex.next_token
319
+ p token
320
+ end
321
+ rescue
322
+ $stderr.printf "%s:%d:%s\n", rex.filename, rex.lineno, $!.message
323
+ end
324
+ end