Golangで、sqlとか、プログラムとか、DSLのパースってできないのかな、と調べていたら下記を見つけました。
2014年時点ですでにできていたんですね。。
上記では、github.com/benbjohnson/sql-parserというリポジトリで説明してくれています。
おおまかな流れは、
- Token作成
- Lexer作成
- Parser作成
といったところです。
で、それらを呼び出す、mainがない。。。ということで、フォークして、main.go
を実装してみました。
main.go
package main
import "strings"
func main() {
query := "select * from my_table"
println(query)
r := strings.NewReader(query)
//parser生成。queryをくわせる。
parser := NewParser(r)
//parse実行。SelectStatementのstructが取得できる
stmt, err := parser.Parse()
if err != nil {
println(err.Error())
}
//取得結果を標準出力。
println(stmt.TableName)
for _, field := range stmt.Fields {
println(field)
}
}
実行してみると、parser.go
で定義されたSelectStatementというstcuctが取得し、標準出力してくれます。
ここまでやって、antlrとかだと、select_statement
っていったら、grammerファイルに記述されたルールだったような。。となります。
plsql.g4
select_statement
: subquery_factoring_clause? subquery (for_update_clause | order_by_clause)*
;
もやもやっとしたまま記事を進めていくと、なんとinfluxdbの内部でも利用している、とのことでした。
ここにある、ast.goをみると、にたようなルールが記載されていました。でも長い。。
時間があるときに読み込んでみようと思います。
勉強になりました。