Skip to content
Snippets Groups Projects
Commit e356b1f4 authored by Manish R Jain's avatar Manish R Jain
Browse files

Add parser to generate SubGraph. Should be a joyous moment, don't feel it though :-).

parent 75e6d61e
No related branches found
No related tags found
No related merge requests found
/*
* Copyright 2015 Manish R Jain <manishrjain@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gql package gql
import ( import (
......
/*
* Copyright 2015 Manish R Jain <manishrjain@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gql package gql
import ( import (
......
/*
* Copyright 2015 Manish R Jain <manishrjain@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gql
import (
"errors"
"fmt"
"strconv"
"github.com/manishrjain/dgraph/query"
"github.com/manishrjain/dgraph/x"
)
func Parse(input string) (sg *query.SubGraph, rerr error) {
l := newLexer(input)
sg = nil
for item := range l.items {
if item.typ == itemText {
continue
}
if item.typ == itemOpType {
if item.val == "mutation" {
return nil, errors.New("Mutations not supported")
}
}
if item.typ == itemLeftCurl {
if sg == nil {
sg, rerr = getRoot(l)
if rerr != nil {
x.Err(glog, rerr).Error("While retrieving subgraph root")
return nil, rerr
}
} else {
godeep(l, sg)
}
}
}
return sg, nil
}
func getRoot(l *lexer) (sg *query.SubGraph, rerr error) {
item := <-l.items
if item.typ != itemName {
return nil, fmt.Errorf("Expected some name. Got: %v", item)
}
// ignore itemName for now.
item = <-l.items
if item.typ != itemLeftRound {
return nil, fmt.Errorf("Expected variable start. Got: %v", item)
}
var uid uint64
var xid string
for {
var key, val string
// Get key or close bracket
item = <-l.items
if item.typ == itemArgName {
key = item.val
} else if item.typ == itemRightRound {
break
} else {
return nil, fmt.Errorf("Expecting argument name. Got: %v", item)
}
// Get corresponding value.
item = <-l.items
if item.typ == itemArgVal {
val = item.val
} else {
return nil, fmt.Errorf("Expecting argument val. Got: %v", item)
}
if key == "uid" {
uid, rerr = strconv.ParseUint(val, 0, 64)
if rerr != nil {
return nil, rerr
}
} else if key == "xid" {
xid = val
} else {
return nil, fmt.Errorf("Expecting uid or xid. Got: %v", item)
}
}
if item.typ != itemRightRound {
return nil, fmt.Errorf("Unexpected token. Got: %v", item)
}
return query.NewGraph(uid, xid)
}
func godeep(l *lexer, sg *query.SubGraph) {
curp := sg // stores current pointer.
for {
switch item := <-l.items; {
case item.typ == itemName:
child := new(query.SubGraph)
child.Attr = item.val
sg.Children = append(sg.Children, child)
curp = child
case item.typ == itemLeftCurl:
godeep(l, curp) // recursive iteration
case item.typ == itemRightCurl:
return
case item.typ == itemLeftRound:
// absorb all these, we don't care right now.
for {
item = <-l.items
if item.typ == itemRightRound || item.typ == itemEOF {
break
}
}
default:
// continue
}
}
}
/*
* Copyright 2015 Manish R Jain <manishrjain@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gql
import (
"fmt"
"testing"
"github.com/manishrjain/dgraph/query"
)
func checkAttr(g *query.SubGraph, attr string) error {
if g.Attr != attr {
return fmt.Errorf("Expected: %v. Got: %v", attr, g.Attr)
}
return nil
}
func TestParse(t *testing.T) {
query := `
query {
me(uid:0x0a) {
friends {
name
}
gender
age
hometown
}
}
`
sg, err := Parse(query)
if err != nil {
t.Error(err)
}
if len(sg.Children) != 4 {
t.Errorf("Expected 4 children. Got: %v", len(sg.Children))
}
if err := checkAttr(sg.Children[0], "friends"); err != nil {
t.Error(err)
}
if err := checkAttr(sg.Children[1], "gender"); err != nil {
t.Error(err)
}
if err := checkAttr(sg.Children[2], "age"); err != nil {
t.Error(err)
}
if err := checkAttr(sg.Children[3], "hometown"); err != nil {
t.Error(err)
}
child := sg.Children[0]
if len(child.Children) != 1 {
t.Errorf("Expected 1 child of friends. Got: %v", len(child.Children))
}
if err := checkAttr(child.Children[0], "name"); err != nil {
t.Error(err)
}
}
func TestParse_error1(t *testing.T) {
query := `
mutation {
me(uid:0x0a) {
name
}
}
`
var err error
_, err = Parse(query)
t.Log(err)
if err == nil {
t.Error("Expected error")
}
}
func TestParse_error2(t *testing.T) {
query := `
query {
me {
name
}
}
`
var err error
_, err = Parse(query)
t.Log(err)
if err == nil {
t.Error("Expected error")
}
}
func TestParse_pass1(t *testing.T) {
query := `
{
me(uid:0x0a) {
name,
friends(xid:what) { # xid would be ignored.
}
}
}
`
sg, err := Parse(query)
if err != nil {
t.Error(err)
}
if len(sg.Children) != 2 {
t.Errorf("Expected 2. Got: %v", len(sg.Children))
}
if err := checkAttr(sg.Children[0], "name"); err != nil {
t.Error(err)
}
if err := checkAttr(sg.Children[1], "friends"); err != nil {
t.Error(err)
}
f := sg.Children[1]
if len(f.Children) != 0 {
t.Errorf("Expected 0. Got: %v", len(sg.Children))
}
}
/*
* Copyright 2015 Manish R Jain <manishrjain@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gql package gql
const ( const (
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment