rossoc 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +21 -0
- data/.rubocop_todo.yml +44 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +21 -0
- data/README.base.md +190 -0
- data/README.ja.md +136 -0
- data/README.md +134 -0
- data/Rakefile +14 -0
- data/exe/rossoc +6 -0
- data/lib/rossoc/backend.rb +47 -0
- data/lib/rossoc/cli.rb +46 -0
- data/lib/rossoc/frontend.rb +154 -0
- data/lib/rossoc/ir.rb +77 -0
- data/lib/rossoc/parser.racc +346 -0
- data/lib/rossoc/parser.racc.rb +1542 -0
- data/lib/rossoc/parser.rex +111 -0
- data/lib/rossoc/parser.rex.rb +301 -0
- data/lib/rossoc/sql_visitor.rb +375 -0
- data/lib/rossoc/statement.rb +455 -0
- data/lib/rossoc/version.rb +5 -0
- data/lib/rossoc/views/arduino.erb +41 -0
- data/lib/rossoc/views/dev.erb +32 -0
- data/lib/rossoc/views/mruby.erb +44 -0
- data/lib/rossoc.rb +21 -0
- data/sig/rossoc.rbs +4 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1c1044e8d160f0b6790e4bdf78ab4d638ed82e32cb50d3841946a5ac56110981
|
4
|
+
data.tar.gz: fe607e717eb85c61496d9b2727e26d3fa2f35afc503ced70164f22e032e9dc49
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c28e9e8620c54f03803d9f44ca35809eaff57ba4b3d58864d514631f6455034ebf17d1735b55357e26399c6ef59b0bfaf7fee2e13fdc9dcf2d80d5d8c48f2bcf
|
7
|
+
data.tar.gz: e2a0cb26b8e45fa2ce99761431ef0c26c285a9918e3463cc577d1003fa90a59d38b593b0382aacd59af828928847d6f1b1a0f7c9d036d0017c73a0fc7639a1d8
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
NewCops: enable
|
5
|
+
SuggestExtensions: false
|
6
|
+
Exclude:
|
7
|
+
- vendor/bundle/**/*
|
8
|
+
- "lib/rossoc/parser.racc"
|
9
|
+
- "lib/rossoc/parser.racc.rb"
|
10
|
+
- "lib/rossoc/parser.rex"
|
11
|
+
- "lib/rossoc/parser.rex.rb"
|
12
|
+
- "lib/rossoc/sql_visitor.rb"
|
13
|
+
- "lib/rossoc/statement.rb"
|
14
|
+
- "rossoc.gemspec"
|
15
|
+
|
16
|
+
Metrics/BlockLength:
|
17
|
+
Exclude:
|
18
|
+
- "spec/**/*"
|
19
|
+
|
20
|
+
Layout/LineLength:
|
21
|
+
Max: 150
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2024-07-02 13:07:48 UTC using RuboCop version 1.63.2.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 4
|
10
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
11
|
+
Metrics/AbcSize:
|
12
|
+
Max: 40
|
13
|
+
|
14
|
+
# Offense count: 1
|
15
|
+
# Configuration parameters: CountComments, CountAsOne.
|
16
|
+
Metrics/ClassLength:
|
17
|
+
Max: 118
|
18
|
+
|
19
|
+
# Offense count: 1
|
20
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
21
|
+
Metrics/CyclomaticComplexity:
|
22
|
+
Max: 9
|
23
|
+
|
24
|
+
# Offense count: 4
|
25
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
26
|
+
Metrics/MethodLength:
|
27
|
+
Max: 30
|
28
|
+
|
29
|
+
# Offense count: 1
|
30
|
+
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
31
|
+
Metrics/ParameterLists:
|
32
|
+
Max: 6
|
33
|
+
|
34
|
+
# Offense count: 1
|
35
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
36
|
+
Metrics/PerceivedComplexity:
|
37
|
+
Max: 9
|
38
|
+
|
39
|
+
# Offense count: 1
|
40
|
+
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
41
|
+
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
42
|
+
Naming/MethodParameterName:
|
43
|
+
Exclude:
|
44
|
+
- 'lib/rossoc/backend.rb'
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 arthur87
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.base.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
<!---------------------------->
|
2
|
+
<!-- multilingual suffix: en, ja -->
|
3
|
+
<!-- no suffix: en -->
|
4
|
+
<!---------------------------->
|
5
|
+
|
6
|
+
<!-- $ mmg README.base.md -->
|
7
|
+
|
8
|
+
<!-- [ja] -->
|
9
|
+
# rossoc
|
10
|
+
rossoc はSQLからコードを生成する実験的なプロジェクトです。
|
11
|
+
SQLを mruby, mruby/c, と Arduino に変換します。
|
12
|
+
|
13
|
+
<!-- [en] -->
|
14
|
+
# rossoc
|
15
|
+
rossoc is an experimental project to generate code from sql.
|
16
|
+
Converts sql to mruby, mruby/c, or Arduino source code.
|
17
|
+
|
18
|
+
<!-- [ja] -->
|
19
|
+
# ガイド
|
20
|
+
例えば、`SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)` のようなSQLは以下のようなコードに変換されます。
|
21
|
+
|
22
|
+
<!-- [en] -->
|
23
|
+
# Guide
|
24
|
+
For example, SQL like `SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)` is converted to source code like this:
|
25
|
+
|
26
|
+
<!-- [common] -->
|
27
|
+
```ruby
|
28
|
+
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9)
|
29
|
+
|
30
|
+
GPIO.setmode(11, GPIO::IN)
|
31
|
+
GPIO.setmode(1, GPIO::IN)
|
32
|
+
GPIO.setmode(2, GPIO::IN)
|
33
|
+
GPIO.setmode(3, GPIO::IN)
|
34
|
+
|
35
|
+
uart1 = UART.new(1)
|
36
|
+
|
37
|
+
while 1 do
|
38
|
+
din11 = GPIO.read(11)
|
39
|
+
din1 = GPIO.read(1)
|
40
|
+
din2 = GPIO.read(2)
|
41
|
+
din3 = GPIO.read(3)
|
42
|
+
|
43
|
+
if ((din1 == 0 && din2 <= 1) || din3 != 9)
|
44
|
+
uart1.puts("din11=#{din11}")
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
<!-- [ja] -->
|
51
|
+
この mruby コードは次のコマンドで出力できます。
|
52
|
+
|
53
|
+
<!-- [en] -->
|
54
|
+
This mruby code can be output with the following command.
|
55
|
+
|
56
|
+
<!-- [common] -->
|
57
|
+
```bash
|
58
|
+
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)' -o test.rb
|
59
|
+
```
|
60
|
+
|
61
|
+
<!-- [ja] -->
|
62
|
+
`RSLEEP` は rossoc の独自キーワードです。
|
63
|
+
RSLEEPの単位は秒で、指定した秒数分、処理を停止します。
|
64
|
+
|
65
|
+
<!-- [en] -->
|
66
|
+
`RSLEEP` is the original keyword of rossoc.
|
67
|
+
RSLEEP is measured in seconds, and processing will be suspended for the specified number of seconds.
|
68
|
+
|
69
|
+
<!-- [common] -->
|
70
|
+
```bash
|
71
|
+
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9) RSLEEP 100' -o test.rb
|
72
|
+
```
|
73
|
+
|
74
|
+
<!-- [ja] -->
|
75
|
+
`RSLEEP` を使用したコードは以下のようになります。
|
76
|
+
|
77
|
+
<!-- [en] -->
|
78
|
+
The code will look like this.
|
79
|
+
|
80
|
+
<!-- [common] -->
|
81
|
+
```ruby
|
82
|
+
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100
|
83
|
+
|
84
|
+
GPIO.setmode(11, GPIO::IN)
|
85
|
+
GPIO.setmode(1, GPIO::IN)
|
86
|
+
GPIO.setmode(2, GPIO::IN)
|
87
|
+
GPIO.setmode(3, GPIO::IN)
|
88
|
+
|
89
|
+
uart1 = UART.new(1)
|
90
|
+
|
91
|
+
while 1 do
|
92
|
+
din11 = GPIO.read(11)
|
93
|
+
din1 = GPIO.read(1)
|
94
|
+
din2 = GPIO.read(2)
|
95
|
+
din3 = GPIO.read(3)
|
96
|
+
|
97
|
+
if ((din1 == 0 && din2 <= 1) || din3 != 9)
|
98
|
+
uart1.puts("din11=#{din11}")
|
99
|
+
end
|
100
|
+
|
101
|
+
sleep(100)
|
102
|
+
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
```c
|
107
|
+
// SELECT `din11` FROM `arduino` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100
|
108
|
+
|
109
|
+
void setup() {
|
110
|
+
Serial.begin(9600);
|
111
|
+
|
112
|
+
pinMode(11, INPUT);
|
113
|
+
pinMode(1, INPUT);
|
114
|
+
pinMode(2, INPUT);
|
115
|
+
pinMode(3, INPUT);
|
116
|
+
}
|
117
|
+
|
118
|
+
void loop() {
|
119
|
+
|
120
|
+
int din11 = digitalRead(11);
|
121
|
+
int din1 = digitalRead(1);
|
122
|
+
int din2 = digitalRead(2);
|
123
|
+
int din3 = digitalRead(3);
|
124
|
+
|
125
|
+
|
126
|
+
if((din1 == 0 && din2 <= 1) || din3 != 9) {
|
127
|
+
|
128
|
+
Serial.print("din11=");
|
129
|
+
Serial.println(din11);
|
130
|
+
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
delay(100000);
|
135
|
+
|
136
|
+
}
|
137
|
+
```
|
138
|
+
|
139
|
+
<!-- [ja] -->
|
140
|
+
rossoc は `SELECT` ステートメントのみサポートしています。
|
141
|
+
カラムには `din1` から `din20` と `ain1` から `ain20` を指定できます。dinはデジタルピン、ainはアナログピンです。
|
142
|
+
テーブル名には `mruby`, `arduino` と `dev` が指定できます。
|
143
|
+
もし `dev` を指定したときシンプルなrubyコードを出力します。 このコードは物理的なボードを必要としません。
|
144
|
+
|
145
|
+
<!-- [en] -->
|
146
|
+
rossoc is only `SELECT` statements are supported.
|
147
|
+
The values that can be specified for the column name are `din1` to `din20` and `ain1` to `ain20`. din corresponds to digital pin, and ain corresponds to analog pin.
|
148
|
+
Possible values for table name are `mruby`, `arduino` and `dev`.
|
149
|
+
If you specify `dev`, simple ruby code will be output and you can run it immediately without a board.
|
150
|
+
|
151
|
+
<!-- [ja] -->
|
152
|
+
# 参考
|
153
|
+
|
154
|
+
このプロジェクトでは以下の文献、コード等を参考にしています。
|
155
|
+
|
156
|
+
<!-- [en] -->
|
157
|
+
# Reference
|
158
|
+
|
159
|
+
<!-- [common] -->
|
160
|
+
The following code is included to extend sql: https://github.com/cryodex/sql-parser
|
161
|
+
mruby, mruby/c Common I/O API Guidelines and Community-developed Libraries: https://github.com/mruby/microcontroller-peripheral-interface-guide
|
162
|
+
|
163
|
+
<!-- [ja] -->
|
164
|
+
# アーキテクチャ
|
165
|
+
rossoc はフロントエンドとバックエンドから構成されています。
|
166
|
+
独自のIR(中間表現)を介してフロントエンドとバックエンドを接続しています。
|
167
|
+
フロントエンドは、字句、構文、意味解析を実行します。
|
168
|
+
バックエンドは、ターゲットのコードを生成します。
|
169
|
+
|
170
|
+
<!-- [en] -->
|
171
|
+
# Architecture
|
172
|
+
rossoc is composed of a front-end and a back-end.
|
173
|
+
An original IR(Intermediate Representation) is used to connect the front-end and the back-end.
|
174
|
+
The front-end performs lexical, syntactic and semantic analysis.
|
175
|
+
The back-end generates code for the target.
|
176
|
+
|
177
|
+
<!-- [common] -->
|
178
|
+
```mermaid
|
179
|
+
flowchart TB
|
180
|
+
input --> FrontEnd
|
181
|
+
subgraph FrontEnd
|
182
|
+
parser --> columns --> tables --> condition --> rsleep
|
183
|
+
end
|
184
|
+
FrontEnd --> IR --> BackEnd
|
185
|
+
subgraph BackEnd
|
186
|
+
generate
|
187
|
+
write
|
188
|
+
end
|
189
|
+
write --> output
|
190
|
+
```
|
data/README.ja.md
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# rossoc
|
4
|
+
rossoc はSQLからコードを生成する実験的なプロジェクトです。
|
5
|
+
SQLを mruby, mruby/c, と Arduino に変換します。
|
6
|
+
|
7
|
+
# ガイド
|
8
|
+
例えば、`SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)` のようなSQLは以下のようなコードに変換されます。
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9)
|
12
|
+
|
13
|
+
GPIO.setmode(11, GPIO::IN)
|
14
|
+
GPIO.setmode(1, GPIO::IN)
|
15
|
+
GPIO.setmode(2, GPIO::IN)
|
16
|
+
GPIO.setmode(3, GPIO::IN)
|
17
|
+
|
18
|
+
uart1 = UART.new(1)
|
19
|
+
|
20
|
+
while 1 do
|
21
|
+
din11 = GPIO.read(11)
|
22
|
+
din1 = GPIO.read(1)
|
23
|
+
din2 = GPIO.read(2)
|
24
|
+
din3 = GPIO.read(3)
|
25
|
+
|
26
|
+
if ((din1 == 0 && din2 <= 1) || din3 != 9)
|
27
|
+
uart1.puts("din11=#{din11}")
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
この mruby コードは次のコマンドで出力できます。
|
34
|
+
|
35
|
+
```bash
|
36
|
+
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)' -o test.rb
|
37
|
+
```
|
38
|
+
|
39
|
+
`RSLEEP` は rossoc の独自キーワードです。
|
40
|
+
RSLEEPの単位は秒で、指定した秒数分、処理を停止します。
|
41
|
+
|
42
|
+
```bash
|
43
|
+
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9) RSLEEP 100' -o test.rb
|
44
|
+
```
|
45
|
+
|
46
|
+
`RSLEEP` を使用したコードは以下のようになります。
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100
|
50
|
+
|
51
|
+
GPIO.setmode(11, GPIO::IN)
|
52
|
+
GPIO.setmode(1, GPIO::IN)
|
53
|
+
GPIO.setmode(2, GPIO::IN)
|
54
|
+
GPIO.setmode(3, GPIO::IN)
|
55
|
+
|
56
|
+
uart1 = UART.new(1)
|
57
|
+
|
58
|
+
while 1 do
|
59
|
+
din11 = GPIO.read(11)
|
60
|
+
din1 = GPIO.read(1)
|
61
|
+
din2 = GPIO.read(2)
|
62
|
+
din3 = GPIO.read(3)
|
63
|
+
|
64
|
+
if ((din1 == 0 && din2 <= 1) || din3 != 9)
|
65
|
+
uart1.puts("din11=#{din11}")
|
66
|
+
end
|
67
|
+
|
68
|
+
sleep(100)
|
69
|
+
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
```c
|
74
|
+
// SELECT `din11` FROM `arduino` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100
|
75
|
+
|
76
|
+
void setup() {
|
77
|
+
Serial.begin(9600);
|
78
|
+
|
79
|
+
pinMode(11, INPUT);
|
80
|
+
pinMode(1, INPUT);
|
81
|
+
pinMode(2, INPUT);
|
82
|
+
pinMode(3, INPUT);
|
83
|
+
}
|
84
|
+
|
85
|
+
void loop() {
|
86
|
+
|
87
|
+
int din11 = digitalRead(11);
|
88
|
+
int din1 = digitalRead(1);
|
89
|
+
int din2 = digitalRead(2);
|
90
|
+
int din3 = digitalRead(3);
|
91
|
+
|
92
|
+
|
93
|
+
if((din1 == 0 && din2 <= 1) || din3 != 9) {
|
94
|
+
|
95
|
+
Serial.print("din11=");
|
96
|
+
Serial.println(din11);
|
97
|
+
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
delay(100000);
|
102
|
+
|
103
|
+
}
|
104
|
+
```
|
105
|
+
|
106
|
+
rossoc は `SELECT` ステートメントのみサポートしています。
|
107
|
+
カラムには `din1` から `din20` と `ain1` から `ain20` を指定できます。dinはデジタルピン、ainはアナログピンです。
|
108
|
+
テーブル名には `mruby`, `arduino` と `dev` が指定できます。
|
109
|
+
もし `dev` を指定したときシンプルなrubyコードを出力します。 このコードは物理的なボードを必要としません。
|
110
|
+
|
111
|
+
# 参考
|
112
|
+
|
113
|
+
このプロジェクトでは以下の文献、コード等を参考にしています。
|
114
|
+
|
115
|
+
The following code is included to extend sql: https://github.com/cryodex/sql-parser
|
116
|
+
mruby, mruby/c Common I/O API Guidelines and Community-developed Libraries: https://github.com/mruby/microcontroller-peripheral-interface-guide
|
117
|
+
|
118
|
+
# アーキテクチャ
|
119
|
+
rossoc はフロントエンドとバックエンドから構成されています。
|
120
|
+
独自のIR(中間表現)を介してフロントエンドとバックエンドを接続しています。
|
121
|
+
フロントエンドは、字句、構文、意味解析を実行します。
|
122
|
+
バックエンドは、ターゲットのコードを生成します。
|
123
|
+
|
124
|
+
```mermaid
|
125
|
+
flowchart TB
|
126
|
+
input --> FrontEnd
|
127
|
+
subgraph FrontEnd
|
128
|
+
parser --> columns --> tables --> condition --> rsleep
|
129
|
+
end
|
130
|
+
FrontEnd --> IR --> BackEnd
|
131
|
+
subgraph BackEnd
|
132
|
+
generate
|
133
|
+
write
|
134
|
+
end
|
135
|
+
write --> output
|
136
|
+
```
|
data/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# rossoc
|
4
|
+
rossoc is an experimental project to generate code from sql.
|
5
|
+
Converts sql to mruby, mruby/c, or Arduino source code.
|
6
|
+
|
7
|
+
# Guide
|
8
|
+
For example, SQL like `SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)` is converted to source code like this:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9)
|
12
|
+
|
13
|
+
GPIO.setmode(11, GPIO::IN)
|
14
|
+
GPIO.setmode(1, GPIO::IN)
|
15
|
+
GPIO.setmode(2, GPIO::IN)
|
16
|
+
GPIO.setmode(3, GPIO::IN)
|
17
|
+
|
18
|
+
uart1 = UART.new(1)
|
19
|
+
|
20
|
+
while 1 do
|
21
|
+
din11 = GPIO.read(11)
|
22
|
+
din1 = GPIO.read(1)
|
23
|
+
din2 = GPIO.read(2)
|
24
|
+
din3 = GPIO.read(3)
|
25
|
+
|
26
|
+
if ((din1 == 0 && din2 <= 1) || din3 != 9)
|
27
|
+
uart1.puts("din11=#{din11}")
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
This mruby code can be output with the following command.
|
34
|
+
|
35
|
+
```bash
|
36
|
+
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)' -o test.rb
|
37
|
+
```
|
38
|
+
|
39
|
+
`RSLEEP` is the original keyword of rossoc.
|
40
|
+
RSLEEP is measured in seconds, and processing will be suspended for the specified number of seconds.
|
41
|
+
|
42
|
+
```bash
|
43
|
+
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9) RSLEEP 100' -o test.rb
|
44
|
+
```
|
45
|
+
|
46
|
+
The code will look like this.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100
|
50
|
+
|
51
|
+
GPIO.setmode(11, GPIO::IN)
|
52
|
+
GPIO.setmode(1, GPIO::IN)
|
53
|
+
GPIO.setmode(2, GPIO::IN)
|
54
|
+
GPIO.setmode(3, GPIO::IN)
|
55
|
+
|
56
|
+
uart1 = UART.new(1)
|
57
|
+
|
58
|
+
while 1 do
|
59
|
+
din11 = GPIO.read(11)
|
60
|
+
din1 = GPIO.read(1)
|
61
|
+
din2 = GPIO.read(2)
|
62
|
+
din3 = GPIO.read(3)
|
63
|
+
|
64
|
+
if ((din1 == 0 && din2 <= 1) || din3 != 9)
|
65
|
+
uart1.puts("din11=#{din11}")
|
66
|
+
end
|
67
|
+
|
68
|
+
sleep(100)
|
69
|
+
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
```c
|
74
|
+
// SELECT `din11` FROM `arduino` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100
|
75
|
+
|
76
|
+
void setup() {
|
77
|
+
Serial.begin(9600);
|
78
|
+
|
79
|
+
pinMode(11, INPUT);
|
80
|
+
pinMode(1, INPUT);
|
81
|
+
pinMode(2, INPUT);
|
82
|
+
pinMode(3, INPUT);
|
83
|
+
}
|
84
|
+
|
85
|
+
void loop() {
|
86
|
+
|
87
|
+
int din11 = digitalRead(11);
|
88
|
+
int din1 = digitalRead(1);
|
89
|
+
int din2 = digitalRead(2);
|
90
|
+
int din3 = digitalRead(3);
|
91
|
+
|
92
|
+
|
93
|
+
if((din1 == 0 && din2 <= 1) || din3 != 9) {
|
94
|
+
|
95
|
+
Serial.print("din11=");
|
96
|
+
Serial.println(din11);
|
97
|
+
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
delay(100000);
|
102
|
+
|
103
|
+
}
|
104
|
+
```
|
105
|
+
|
106
|
+
rossoc is only `SELECT` statements are supported.
|
107
|
+
The values that can be specified for the column name are `din1` to `din20` and `ain1` to `ain20`. din corresponds to digital pin, and ain corresponds to analog pin.
|
108
|
+
Possible values for table name are `mruby`, `arduino` and `dev`.
|
109
|
+
If you specify `dev`, simple ruby code will be output and you can run it immediately without a board.
|
110
|
+
|
111
|
+
# Reference
|
112
|
+
|
113
|
+
The following code is included to extend sql: https://github.com/cryodex/sql-parser
|
114
|
+
mruby, mruby/c Common I/O API Guidelines and Community-developed Libraries: https://github.com/mruby/microcontroller-peripheral-interface-guide
|
115
|
+
|
116
|
+
# Architecture
|
117
|
+
rossoc is composed of a front-end and a back-end.
|
118
|
+
An original IR(Intermediate Representation) is used to connect the front-end and the back-end.
|
119
|
+
The front-end performs lexical, syntactic and semantic analysis.
|
120
|
+
The back-end generates code for the target.
|
121
|
+
|
122
|
+
```mermaid
|
123
|
+
flowchart TB
|
124
|
+
input --> FrontEnd
|
125
|
+
subgraph FrontEnd
|
126
|
+
parser --> columns --> tables --> condition --> rsleep
|
127
|
+
end
|
128
|
+
FrontEnd --> IR --> BackEnd
|
129
|
+
subgraph BackEnd
|
130
|
+
generate
|
131
|
+
write
|
132
|
+
end
|
133
|
+
write --> output
|
134
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
task default: %i[]
|
5
|
+
|
6
|
+
PARSER = 'lib/rossoc/parser.racc'
|
7
|
+
LEXER = 'lib/rossoc/parser.rex'
|
8
|
+
|
9
|
+
task :parser do
|
10
|
+
system "rm #{PARSER}.rb #{LEXER}.rb"
|
11
|
+
system "racc -o #{PARSER}.rb #{PARSER}"
|
12
|
+
system "rex -o #{LEXER}.rb #{LEXER}"
|
13
|
+
system 'rspec'
|
14
|
+
end
|
data/exe/rossoc
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rossoc'
|
4
|
+
|
5
|
+
# Rossoc
|
6
|
+
module Rossoc
|
7
|
+
# Backend
|
8
|
+
class Backend
|
9
|
+
class BackendError < StandardError; end
|
10
|
+
|
11
|
+
RESERVED_TABLES = %w[mruby arduino dev].freeze
|
12
|
+
|
13
|
+
def initialize(ir, output, overwrite_enable)
|
14
|
+
@ir = ir
|
15
|
+
@output = output
|
16
|
+
@content = nil
|
17
|
+
@overwrite_enable = overwrite_enable
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate
|
21
|
+
table = @ir[:table]
|
22
|
+
raise BackendError, "unknown table value #{table}." if RESERVED_TABLES.index(table).nil?
|
23
|
+
|
24
|
+
template = ERB.new(
|
25
|
+
File.read("#{__dir__}#{File::SEPARATOR}views#{File::SEPARATOR}#{table}.erb"),
|
26
|
+
trim_mode: 2
|
27
|
+
)
|
28
|
+
|
29
|
+
@content = template.result_with_hash(@ir)
|
30
|
+
end
|
31
|
+
|
32
|
+
def write
|
33
|
+
raise BackendError, 'No content.' if @content.nil?
|
34
|
+
|
35
|
+
if @output.blank?
|
36
|
+
# ファイルが指定されていないとき標準出力
|
37
|
+
puts @content
|
38
|
+
else
|
39
|
+
raise BackendError, "File exists #{@output}." if File.exist?(@output) && !@overwrite_enable
|
40
|
+
|
41
|
+
file = File.open(@output, 'w')
|
42
|
+
file.write(@content)
|
43
|
+
file.close
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/rossoc/cli.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rossoc'
|
4
|
+
require 'thor'
|
5
|
+
|
6
|
+
module Rossoc
|
7
|
+
# entry point
|
8
|
+
class CLI < Thor
|
9
|
+
class << self
|
10
|
+
def exit_on_failure?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'version', 'Show Version'
|
16
|
+
def version
|
17
|
+
puts(Rossoc::VERSION)
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'query', 'Query'
|
21
|
+
method_option :input, desc: 'Input query', aliases: '-i'
|
22
|
+
method_option :output, desc: 'Write output to <file>', aliases: '-o'
|
23
|
+
method_option :ir, desc: 'Show IR Information', type: :boolean, default: false
|
24
|
+
method_option :yes, desc: 'Overwrite output file', type: :boolean, default: false, aliases: '-y'
|
25
|
+
def query
|
26
|
+
frontend = Rossoc::Frontend.new(options[:input].to_s)
|
27
|
+
begin
|
28
|
+
ir = frontend.ir
|
29
|
+
rescue StandardError => e
|
30
|
+
warn e.message
|
31
|
+
exit(1)
|
32
|
+
end
|
33
|
+
|
34
|
+
pp ir if options[:ir]
|
35
|
+
|
36
|
+
begin
|
37
|
+
backend = Rossoc::Backend.new(ir, options[:output].to_s, options[:yes])
|
38
|
+
backend.generate
|
39
|
+
backend.write
|
40
|
+
rescue StandardError => e
|
41
|
+
warn e.message
|
42
|
+
exit(1)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|