rossoc 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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