rossoc 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rossoc'
4
+
5
+ # Rossoc
6
+ module Rossoc
7
+ # Frontend
8
+ # rubocop:disable Metrics/ClassLength
9
+ class Frontend
10
+ class FrontendError < StandardError; end
11
+
12
+ RESERVED_PINS = %w[
13
+ din0 din1 din2 din3 din4 din5 din6 din7 din8 din9 din10
14
+ din11 din12 din13 din14 din15 din16 din17 din18 din19 din20
15
+ ain0 ain1 ain2 ain3 ain4 ain5 ain6 ain7 ain8 ain9 ain10
16
+ ain11 ain12 ain13 ain14 ain15 ain16 ain17 ain18 ain19 ain20
17
+ ].freeze
18
+
19
+ def initialize(input)
20
+ @input = input
21
+ @out_pins = Set.new
22
+ @in_pins = Set.new
23
+ @table = nil
24
+ @where = nil
25
+ @ast = nil
26
+ @sleep_sec = 0
27
+ @speed = 9600
28
+ end
29
+
30
+ def ir
31
+ parser(@input)
32
+ check_columns
33
+ check_tables
34
+ check_condition
35
+ check_rsleep
36
+ check_rspeed
37
+
38
+ Rossoc::Ir.new(@in_pins, @out_pins, @table, @where, @ast,
39
+ @sleep_sec, @speed).result
40
+ end
41
+
42
+ private
43
+
44
+ def parser(sql)
45
+ parser = SQLParser::Parser.new
46
+ @ast = parser.scan_str(sql)
47
+ rescue Racc::ParseError => e
48
+ raise FrontendError, e
49
+ end
50
+
51
+ def check_columns
52
+ columns = @ast.query_expression.list.columns
53
+ columns.each do |column|
54
+ name = column.name
55
+ index = RESERVED_PINS.index(name)
56
+ raise FrontendError, "unknown column value #{name}." if index.nil?
57
+
58
+ @in_pins.add(name)
59
+ @out_pins.add(name)
60
+ end
61
+ rescue StandardError
62
+ raise FrontendError, 'unsupported column.'
63
+ end
64
+
65
+ def check_tables
66
+ tables = @ast.query_expression.table_expression.from_clause.tables
67
+ tables.each do |table|
68
+ @table = table.name
69
+ end
70
+ rescue e
71
+ raise e
72
+ end
73
+
74
+ def check_condition
75
+ begin
76
+ condition = if @ast.query_expression.table_expression.where_clause.nil?
77
+ nil
78
+ else
79
+ @ast.query_expression.table_expression.where_clause.search_condition
80
+ end
81
+ rescue e
82
+ raise e
83
+ end
84
+
85
+ if condition.nil?
86
+ @where = 1
87
+ else
88
+ condition_parser(condition)
89
+
90
+ tokens = condition.to_sql.split
91
+ tokens.each_with_index do |token, index|
92
+ case token
93
+ when '='
94
+ token = '=='
95
+ when 'AND'
96
+ token = '&&'
97
+ when 'OR'
98
+ token = '||'
99
+ when '<>'
100
+ token = '!='
101
+ end
102
+ tokens[index] = token.gsub('`', '')
103
+ end
104
+
105
+ @where = tokens.join(' ')
106
+ end
107
+ end
108
+
109
+ def condition_parser(condition)
110
+ root_words = ['SQLParser::Statement::Equals',
111
+ 'SQLParser::Statement::Greater',
112
+ 'SQLParser::Statement::GreaterOrEquals',
113
+ 'SQLParser::Statement::Less',
114
+ 'SQLParser::Statement::LessOrEquals',
115
+ 'SQLParser::Statement::And',
116
+ 'SQLParser::Statement::Or']
117
+ not_words = ['SQLParser::Statement::Not']
118
+ value_words = ['SQLParser::Statement::Float',
119
+ 'SQLParser::Statement::Integer']
120
+ column_words = ['SQLParser::Statement::Column']
121
+
122
+ if root_words.include?(condition.class.to_s)
123
+ condition_parser(condition.left)
124
+ condition_parser(condition.right)
125
+ elsif not_words.include?(condition.class.to_s)
126
+ condition_parser(condition.value.left)
127
+ condition_parser(condition.value.right)
128
+ elsif column_words.include?(condition.class.to_s)
129
+ name = condition.name
130
+ index = RESERVED_PINS.index(name)
131
+ raise FrontendError, "unknown column value #{name}." if index.nil?
132
+
133
+ @in_pins.add(name)
134
+ elsif value_words.include?(condition.class.to_s)
135
+ # none
136
+ else
137
+ raise FrontendError, "unknown token value #{condition}."
138
+ end
139
+ end
140
+
141
+ def check_rsleep
142
+ return if @ast.rsleep.nil?
143
+
144
+ @sleep_sec = @ast.rsleep.rsleep_specification.value
145
+ end
146
+
147
+ def check_rspeed
148
+ return if @ast.rspeed.nil?
149
+
150
+ @speed = @ast.rspeed.rspeed_specification.value
151
+ end
152
+ end
153
+ # rubocop:enable Metrics/ClassLength
154
+ end
data/lib/rossoc/ir.rb ADDED
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rossoc'
4
+
5
+ # Rossoc
6
+ module Rossoc
7
+ # Ir
8
+ class Ir
9
+ # rubocop:disable Metrics/ParameterLists
10
+ def initialize(in_pins, out_pins, table, where, ast,
11
+ sleep_sec, speed)
12
+ @in_pins = in_pins
13
+ @out_pins = out_pins
14
+ @table = table
15
+ @where = where
16
+ @ast = ast
17
+ @sleep = Rsleep.new(sleep_sec)
18
+ @speed = speed
19
+ end
20
+ # rubocop:enable Metrics/ParameterLists
21
+
22
+ # rubocop:disable Metrics/MethodLength
23
+ def result
24
+ din_pins = Set.new
25
+ ain_pins = Set.new
26
+ dout_pins = Set.new
27
+ aout_pins = Set.new
28
+
29
+ [@in_pins, @out_pins].each_with_index do |pins, i|
30
+ pins.each do |pin|
31
+ n = pin.gsub(/din|ain/, '').to_i
32
+ if pin.start_with?('din')
33
+ if i.zero?
34
+ din_pins.add(n)
35
+ else
36
+ dout_pins.add(n)
37
+ end
38
+ elsif i.zero?
39
+ ain_pins.add(n)
40
+ else
41
+ aout_pins.add(n)
42
+ end
43
+ end
44
+ end
45
+
46
+ {
47
+ din_pins: din_pins,
48
+ ain_pins: ain_pins,
49
+ dout_pins: dout_pins,
50
+ aout_pins: aout_pins,
51
+ table: @table,
52
+ where: @where,
53
+ ast: @ast,
54
+ sleep: @sleep,
55
+ speed: @speed
56
+ }
57
+ end
58
+ # rubocop:enable Metrics/MethodLength
59
+
60
+ # RSLEEP
61
+ class Rsleep
62
+ def initialize(second)
63
+ @second = second
64
+ end
65
+
66
+ def positive?
67
+ @second.positive?
68
+ end
69
+
70
+ attr_reader :second
71
+
72
+ def millisecond
73
+ (@second * 1000).to_i
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,346 @@
1
+ #
2
+ # Original source code
3
+ # sql-parser
4
+ # https://github.com/cryodex/sql-parser
5
+ #
6
+
7
+ class SQLParser::Parser
8
+
9
+ rule
10
+ # dynamic sql
11
+
12
+ direct_sql_statement
13
+ : direct_sql_data_statement
14
+
15
+ direct_sql_data_statement
16
+ : direct_select_statement_multiple_rows
17
+ | insert_specification
18
+
19
+ direct_select_statement_multiple_rows
20
+ : query_expression order_by_clause rsleep_clause rspeed_clause { result = SQLParser::Statement::DirectSelect.new(val[0], val[1], val[2], val[3]) }
21
+
22
+ # module contents
23
+ rsleep_clause
24
+ : # no action
25
+ | RSLEEP unsigned_literal { result = SQLParser::Statement::Rsleep.new(val[1]) }
26
+
27
+ rspeed_clause
28
+ : # no action
29
+ | RSPEED unsigned_literal { result = SQLParser::Statement::Rspeed.new(val[1]) }
30
+
31
+ order_by_clause
32
+ : # no action
33
+ | ORDER BY sort_specification_list { result = SQLParser::Statement::OrderBy.new(val[2]) }
34
+
35
+ sort_specification_list
36
+ : sort_specification_list comma sort_specification { result = Array(val[0]) + Array(val[2]) }
37
+ | sort_specification
38
+
39
+ sort_specification
40
+ : sort_key ordering_specification { result = val[1].new(val[0]) }
41
+
42
+ sort_key
43
+ : column_name
44
+ | unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
45
+
46
+ ordering_specification
47
+ : { result = SQLParser::Statement::Ascending } # default
48
+ | ASC { result = SQLParser::Statement::Ascending }
49
+ | DESC { result = SQLParser::Statement::Descending }
50
+
51
+ # queries
52
+ subquery
53
+ # FIXME: shortcut
54
+ : left_paren query_expression right_paren { result = SQLParser::Statement::Subquery.new(val[1]) }
55
+
56
+ query_expression
57
+ : query_specification
58
+
59
+ insert_specification
60
+ : INSERT INTO table_reference value_list { result = SQLParser::Statement::Insert.new(val[2], nil, val[3]) }
61
+ | INSERT INTO table_reference column_list value_list { result = SQLParser::Statement::Insert.new(val[2], val[3], val[4]) }
62
+
63
+ column_list
64
+ : left_paren in_column_list right_paren { result = SQLParser::Statement::InColumnList.new(val[1]) }
65
+
66
+ in_column_list
67
+ : value_expression comma in_column_list { result = Array(val[0]) + Array(val[2]) }
68
+ | value_expression
69
+
70
+ value_list
71
+ : VALUES left_paren in_value_list right_paren { result = SQLParser::Statement::InValueList.new(val[2]) }
72
+
73
+ query_specification
74
+ : SELECT select_list table_expression { result = SQLParser::Statement::Select.new(val[1], val[2]) }
75
+ | SELECT select_list { result = SQLParser::Statement::Select.new(val[1]) }
76
+
77
+ select_list
78
+ : asterisk { result = SQLParser::Statement::All.new }
79
+ | select_sublist { result = SQLParser::Statement::SelectList.new(val[0]) }
80
+
81
+ select_sublist
82
+ : derived_column comma select_sublist { result = Array(val[0]) + Array(val[2]) }
83
+ | derived_column
84
+
85
+ derived_column
86
+ : value_expression AS column_name { result = SQLParser::Statement::As.new(val[0], val[2]) }
87
+ | value_expression column_name { result = SQLParser::Statement::As.new(val[0], val[1]) }
88
+ | value_expression
89
+
90
+ table_expression
91
+ : from_clause where_clause group_by_clause having_clause { result = SQLParser::Statement::TableExpression.new(val[0], val[1], val[2], val[3]) }
92
+
93
+ from_clause
94
+ : FROM table_reference { result = SQLParser::Statement::FromClause.new(val[1]) }
95
+
96
+ table_reference
97
+ : table_name AS column_name { result = SQLParser::Statement::As.new(val[0], val[2]) }
98
+ | table_name column_name { result = SQLParser::Statement::As.new(val[0], val[1]) }
99
+ | table_name
100
+ | joined_table
101
+
102
+ table_subquery
103
+ : subquery
104
+
105
+ joined_table
106
+ : cross_join
107
+ | qualified_join
108
+
109
+ cross_join
110
+ : table_reference comma table_name { result = SQLParser::Statement::CrossJoin.new(val[0], val[2]) }
111
+ | table_reference CROSS JOIN table_name { result = SQLParser::Statement::CrossJoin.new(val[0], val[3]) }
112
+
113
+ qualified_join
114
+ : table_reference join_type JOIN table_reference join_specification { result = val[1].new(val[0], val[3], val[4]) }
115
+
116
+ join_type
117
+ : INNER { result = SQLParser::Statement::InnerJoin }
118
+ | LEFT OUTER { result = SQLParser::Statement::LeftOuterJoin }
119
+ | LEFT { result = SQLParser::Statement::LeftJoin }
120
+ | RIGHT OUTER { result = SQLParser::Statement::RightOuterJoin }
121
+ | RIGHT { result = SQLParser::Statement::RightJoin }
122
+ | FULL { result = SQLParser::Statement::FullJoin }
123
+ | FULL OUTER { result = SQLParser::Statement::FullOuterJoin }
124
+
125
+ join_specification
126
+ : join_condition
127
+ | named_columns_join
128
+
129
+ join_condition
130
+ : ON search_condition { result = SQLParser::Statement::On.new(val[1]) }
131
+
132
+ named_columns_join
133
+ : USING left_paren join_column_list right_paren { result = SQLParser::Statement::Using.new(val[2]) }
134
+
135
+ join_column_list
136
+ : column_name_list
137
+
138
+ where_clause
139
+ : # no action
140
+ | WHERE search_condition { result = SQLParser::Statement::WhereClause.new(val[1]) }
141
+
142
+ group_by_clause
143
+ : # no action
144
+ | GROUP BY grouping_column_reference_list { result = SQLParser::Statement::GroupByClause.new(val[2]) }
145
+
146
+ grouping_column_reference_list
147
+ : grouping_column_reference_list comma grouping_column_reference { result = Array(val[0]) + Array(val[2]) }
148
+ | grouping_column_reference
149
+
150
+ grouping_column_reference
151
+ : column_reference
152
+
153
+ having_clause
154
+ : # no action
155
+ | HAVING search_condition { result = SQLParser::Statement::HavingClause.new(val[1]) }
156
+
157
+ # query expression components
158
+ row_subquery
159
+ : subquery
160
+
161
+ between_predicate
162
+ : row_value_constructor NOT BETWEEN row_value_constructor AND row_value_constructor { result = SQLParser::Statement::Not.new(SQLParser::Statement::Between.new(val[0], val[3], val[5])) }
163
+ | row_value_constructor BETWEEN row_value_constructor AND row_value_constructor { result = SQLParser::Statement::Between.new(val[0], val[2], val[4]) }
164
+
165
+ in_predicate
166
+ : row_value_constructor NOT IN in_predicate_value { result = SQLParser::Statement::Not.new(SQLParser::Statement::In.new(val[0], val[3])) }
167
+ | row_value_constructor IN in_predicate_value { result = SQLParser::Statement::In.new(val[0], val[2]) }
168
+
169
+ in_predicate_value
170
+ : table_subquery
171
+ | left_paren in_value_list right_paren { result = SQLParser::Statement::InValueList.new(val[1]) }
172
+
173
+ in_value_list
174
+ : value_expression comma in_value_list { result = Array(val[0]) + Array(val[2]) }
175
+ | value_expression
176
+
177
+ like_predicate
178
+ # FIXME: the SQL-92 grammar indicates these should be
179
+ # character_value_expression nodes, but changing them causes reduce/reduce
180
+ # conflicts.
181
+ : row_value_constructor NOT LIKE row_value_constructor { result = SQLParser::Statement::Not.new(SQLParser::Statement::Like.new(val[0], val[3])) }
182
+ | row_value_constructor LIKE row_value_constructor { result = SQLParser::Statement::Like.new(val[0], val[2]) }
183
+
184
+ null_predicate
185
+ : row_value_constructor IS NOT NULL { result = SQLParser::Statement::Not.new(SQLParser::Statement::Is.new(val[0], SQLParser::Statement::Null.new)) }
186
+ | row_value_constructor IS NULL { result = SQLParser::Statement::Is.new(val[0], SQLParser::Statement::Null.new) }
187
+
188
+ exists_predicate
189
+ : EXISTS table_subquery { result = SQLParser::Statement::Exists.new(val[1]) }
190
+
191
+ # constraints
192
+ table_name
193
+ : identifier { result = SQLParser::Statement::Table.new(val[0]) }
194
+
195
+ column_name_list
196
+ : column_name_list comma column_name { result = Array(val[0]) + Array(val[2]) }
197
+ | column_name
198
+
199
+ # search condition
200
+ search_condition
201
+ : boolean_term
202
+ | search_condition OR boolean_term { result = SQLParser::Statement::Or.new(val[0], val[2]) }
203
+
204
+ boolean_term
205
+ : boolean_factor
206
+ | boolean_term AND boolean_factor { result = SQLParser::Statement::And.new(val[0], val[2]) }
207
+
208
+ boolean_factor:
209
+ : NOT boolean_test { result = SQLParser::Statement::Not.new(val[1]) }
210
+ | boolean_test
211
+
212
+ boolean_test
213
+ : boolean_primary
214
+
215
+ boolean_primary
216
+ : predicate
217
+ | left_paren search_condition right_paren { result = val[1] }
218
+
219
+ predicate
220
+ : comparison_predicate
221
+ | between_predicate
222
+ | in_predicate
223
+ | like_predicate
224
+ | null_predicate
225
+ | exists_predicate
226
+
227
+ comparison_predicate
228
+ : row_value_constructor equals_operator row_value_constructor { result = SQLParser::Statement::Equals.new(val[0], val[2]) }
229
+ | row_value_constructor not_equals_operator row_value_constructor { result = SQLParser::Statement::Not.new(SQLParser::Statement::Equals.new(val[0], val[2])) }
230
+ | row_value_constructor less_than_operator row_value_constructor { result = SQLParser::Statement::Less.new(val[0], val[2]) }
231
+ | row_value_constructor greater_than_operator row_value_constructor { result = SQLParser::Statement::Greater.new(val[0], val[2]) }
232
+ | row_value_constructor less_than_or_equals_operator row_value_constructor { result = SQLParser::Statement::LessOrEquals.new(val[0], val[2]) }
233
+ | row_value_constructor greater_than_or_equals_operator row_value_constructor { result = SQLParser::Statement::GreaterOrEquals.new(val[0], val[2]) }
234
+
235
+ row_value_constructor
236
+ : row_value_constructor_element
237
+ | row_subquery
238
+
239
+ row_value_constructor_element
240
+ : value_expression
241
+
242
+ value_expression
243
+ : numeric_value_expression
244
+ | general_literal
245
+
246
+ numeric_value_expression
247
+ : term plus_sign numeric_value_expression { result = SQLParser::Statement::Add.new(val[0], val[2]) }
248
+ | term minus_sign numeric_value_expression { result = SQLParser::Statement::Subtract.new(val[0], val[2]) }
249
+ | term
250
+
251
+ term
252
+ : factor asterisk term { result = SQLParser::Statement::Multiply.new(val[0], val[2]) }
253
+ | factor solidus term { result = SQLParser::Statement::Divide.new(val[0], val[2]) }
254
+ | factor
255
+
256
+ factor
257
+ : sign value_expression_primary { result = val[0].new(val[1]) }
258
+ | value_expression_primary
259
+
260
+ value_expression_primary
261
+ : unsigned_value_specification
262
+ | column_reference
263
+ | set_function_specification
264
+ | left_paren value_expression right_paren { result = val[1] }
265
+
266
+ unsigned_value_specification
267
+ : unsigned_literal
268
+ | general_value_specification
269
+
270
+ unsigned_literal
271
+ : unsigned_numeric_literal
272
+ | general_literal
273
+
274
+ general_value_specification
275
+ : CURRENT_USER { result = SQLParser::Statement::CurrentUser.new }
276
+
277
+ column_reference
278
+ : qualifier period column_name { result = SQLParser::Statement::QualifiedColumn.new(val[0], val[2]) }
279
+ | column_name
280
+
281
+ qualifier
282
+ : table_name
283
+
284
+ set_function_specification
285
+ : COUNT left_paren asterisk right_paren { result = SQLParser::Statement::Count.new(SQLParser::Statement::All.new) }
286
+ | general_set_function
287
+
288
+ general_set_function
289
+ : COUNT left_paren value_expression right_paren { result = SQLParser::Statement::Count.new(val[2]) }
290
+ | AVG left_paren value_expression right_paren { result = SQLParser::Statement::Average.new(val[2]) }
291
+ | MAX left_paren value_expression right_paren { result = SQLParser::Statement::Maximum.new(val[2]) }
292
+ | MIN left_paren value_expression right_paren { result = SQLParser::Statement::Minimum.new(val[2]) }
293
+ | SUM left_paren value_expression right_paren { result = SQLParser::Statement::Sum.new(val[2]) }
294
+
295
+ # literal numbers, strings, dates and times
296
+ unsigned_numeric_literal
297
+ : exact_numeric_literal
298
+ | approximate_numeric_literal
299
+
300
+ exact_numeric_literal
301
+ : unsigned_integer period unsigned_integer { result = SQLParser::Statement::Float.new("#{val[0]}.#{val[2]}".to_f) }
302
+ | unsigned_integer period { result = SQLParser::Statement::Float.new(val[0]) }
303
+ | period unsigned_integer { result = SQLParser::Statement::Float.new("0.#{val[1]}".to_f) }
304
+ | unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
305
+
306
+ approximate_numeric_literal
307
+ : mantissa E exponent { result = SQLParser::Statement::ApproximateFloat.new(val[0], val[2]) }
308
+
309
+ mantissa
310
+ : exact_numeric_literal
311
+
312
+ exponent
313
+ : signed_integer
314
+
315
+ signed_integer
316
+ : sign unsigned_integer { result = val[0].new(SQLParser::Statement::Integer.new(val[1])) }
317
+ | unsigned_integer { result = SQLParser::Statement::Integer.new(val[0]) }
318
+
319
+ sign
320
+ : plus_sign { result = SQLParser::Statement::UnaryPlus }
321
+ | minus_sign { result = SQLParser::Statement::UnaryMinus }
322
+
323
+ # sql module
324
+ column_name
325
+ : identifier { result = SQLParser::Statement::Column.new(val[0]) }
326
+
327
+ # literals
328
+ general_literal
329
+ : quote character_string_literal quote { result = SQLParser::Statement::String.new(val[1]) }
330
+ | quote quote { result = SQLParser::Statement::String.new('') }
331
+ | datetime_literal
332
+
333
+ datetime_literal
334
+ : date_literal
335
+
336
+ date_literal
337
+ : DATE date_string { result = SQLParser::Statement::Date.new(val[1]) }
338
+
339
+ ---- header ----
340
+ require File.dirname(__FILE__) + '/parser.rex.rb'
341
+
342
+ ---- inner ----
343
+
344
+ def self.parse(sql)
345
+ new.scan_str(sql)
346
+ end