Skip to content

Instantly share code, notes, and snippets.

@anisbhsl
Created January 20, 2020 06:50
Show Gist options
  • Save anisbhsl/b0026cb9eb5b23d6890b4bf923736e9d to your computer and use it in GitHub Desktop.
Save anisbhsl/b0026cb9eb5b23d6890b4bf923736e9d to your computer and use it in GitHub Desktop.
PEG parser for SQL queries (Select and Insert) in Go
/*Initializer code block */
{
package main
import (
"strconv"
"strings"
)
type SelectQuery struct{
SelectFields []string
Table string
Parsed bool
}
type InsertQuery struct{
TableName string
Fields []string
Values [][]string
}
func main(){
if len(os.Args)!=2{
log.Fatal("Usage sql 'EXPR'")
}
opts:=Memoize(true)
got,err:=ParseReader("",strings.NewReader(os.Args[1]),opts)
if err!=nil{
log.Fatal(err)
}
fmt.Println("parsed---> ",got)
}
func toIfaceSlice(v interface{}) []interface{} {
if v == nil {
return nil
}
return v.([]interface{})
}
func joinInterface(j []interface{})string{
m:=""
for _,v:=range j{
m+=fmt.Sprintf("%s",v)
}
return m
}
}
PARSE <- query:SQL EOF{
fmt.Println("query received:",query)
return query,nil
}
SQL <- query:(SELECT_STMT / INSERT_STMT){
return query,nil
}
SELECT_STMT <- _ SELECT_TOKEN _ f1:SelectField fx:SelectFieldRest*_ FROM_TOKEN _ tableName:TableName {
fields:=[]string{}
fields=append(fields,f1.(string))
for _,v:=range toIfaceSlice(fx){
fields=append(fields,v.(string))
}
fmt.Println("[[select]] fields",fields)
return SelectQuery{
SelectFields:fields,
Table:tableName.(string),
Parsed:true,
},nil
}
INSERT_STMT <- _ INSERT_TOKEN _ table:TableName _ f:SelectField _ fx:SelectFieldRest*
_ VALUES_TOKEN _ v:SelectInsertRow _ vx:SelectInsertRowsRest* {
fields:=[]string{}
fields=append(fields,f.(string))
for _,v:=range toIfaceSlice(fx){
fields=append(fields,v.(string))
}
fmt.Println("[[insert]] fields:",fields)
values:=[][]string{}
values=append(values,v.([]string))
for _,v:=range vx.([]interface{}){
values=append(values,v.([]string))
}
return InsertQuery{
TableName:table.(string),
Fields:fields,
Values:values,
},nil
}
/*Define Tokens HERE */
SELECT_TOKEN <- "SELECT"i
FROM_TOKEN <- "FROM"i
INSERT_TOKEN<- "INSERT INTO"i
VALUES_TOKEN <- "VALUES"i
LEFT_PARENTHESIS_TOKEN <- "("
RIGHT_PARENTHESIS_TOKEN <- ")"
/* Define codes here */
SelectFieldRest <- "," _ f:SelectField RIGHT_PARENTHESIS_TOKEN?{
return f,nil
}
SelectField
<- LEFT_PARENTHESIS_TOKEN? field:FieldName RIGHT_PARENTHESIS_TOKEN?{
return field,nil
}
FieldName <- [a-zA-Z]+{
return string(c.text),nil
}
TableName <- _ [a-zA-z]+{
return string(c.text),nil
}
SelectInsertRowsRest <- "," row:SelectInsertRow {
return row,nil
}
SelectInsertRow<- LEFT_PARENTHESIS_TOKEN _ v:SelectValue _ vx:SelectValueRest* _ RIGHT_PARENTHESIS_TOKEN{
values:=[]string{}
values=append(values,v.(string))
for _,val:=range vx.([]interface{}){
values=append(values,val.(string))
}
return values,nil
}
SelectValueRest <- "," _ f:SelectValue {
return f,nil
}
SelectValue <- [a-zA-z0-9?/]*{
return string(c.text),nil
}
/*--------------------*/
_ <- ( WhiteSpace / NewLine )*
WhiteSpace "whitespace"
<- " "
/ "\t"
/ "\v"
/ "\f"
NewLine "newline" <- "\r\n"
/ "\r"
/ "\n"
/ "\u2028"
/ "\u2029"
EOF <- !.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment