From 435a932f3f4f3dc9f889eb22221bd9452f1abe4c Mon Sep 17 00:00:00 2001 From: Aravind Rao Date: Thu, 2 Mar 2017 17:22:20 -0800 Subject: [PATCH 1/5] parse construct statement --- bql/grammar/grammar.go | 22 ++++++++++++++++++++++ bql/grammar/grammar_test.go | 10 +++++++++- bql/lexer/lexer.go | 13 +++++++++++-- bql/lexer/lexer_test.go | 8 +++++++- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/bql/grammar/grammar.go b/bql/grammar/grammar.go index ab1c18e8..e36021e5 100644 --- a/bql/grammar/grammar.go +++ b/bql/grammar/grammar.go @@ -88,6 +88,19 @@ func BQL() *Grammar { NewTokenType(lexer.ItemSemicolon), }, }, + { + Elements: []Element{ + NewTokenType(lexer.ItemConstruct), + NewSymbol("CONSTRUCT_FACTS"), + NewTokenType(lexer.ItemInto), + NewSymbol("GRAPHS"), + NewTokenType(lexer.ItemFrom), + NewSymbol("GRAPHS"), + NewSymbol("WHERE"), + NewSymbol("HAVING"), + NewTokenType(lexer.ItemSemicolon), + }, + }, }, "CREATE_GRAPHS": []*Clause{ { @@ -191,6 +204,15 @@ func BQL() *Grammar { }, }, }, + "CONSTRUCT_FACTS": []*Clause{ + { + Elements: []Element{ + NewTokenType(lexer.ItemLBracket), + NewSymbol("CLAUSES"), + NewTokenType(lexer.ItemRBracket), + }, + }, + }, "CLAUSES": []*Clause{ { Elements: []Element{ diff --git a/bql/grammar/grammar_test.go b/bql/grammar/grammar_test.go index 71211c22..56cc70bd 100644 --- a/bql/grammar/grammar_test.go +++ b/bql/grammar/grammar_test.go @@ -113,6 +113,10 @@ func TestAcceptByParse(t *testing.T) { /room<000> "connects_to"@[] /room<001>};`, `delete data from ?world {/room<000> "named"@[] "Hallway"^^type:text. /room<000> "connects_to"@[] /room<001>};`, + // Test Construct clause. + `construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, + `construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, + } p, err := NewParser(BQL()) if err != nil { @@ -207,6 +211,10 @@ func TestRejectByParse(t *testing.T) { // Drop graphs. `drop graph ;`, `drop graph ?a ?b, ?c;`, + // Construct clause without source. + `construct {?s "foo"@[,] ?o} into ?a where{?s "foo"@[,] ?o} having ?s = ?o;`, + // Construct clause without destination. + `construct {?s "foo"@[,] ?o} from ?b where{?s "foo"@[,] ?o} having ?s = ?o;`, } p, err := NewParser(BQL()) if err != nil { @@ -344,7 +352,7 @@ func TestRejectByParseAndSemantic(t *testing.T) { } } -func TestSemanticStatementGraphClausesLenghtCorrectness(t *testing.T) { +func TestSemanticStatementGraphClausesLengthCorrectness(t *testing.T) { table := []struct { query string want int diff --git a/bql/lexer/lexer.go b/bql/lexer/lexer.go index 24416401..a2931acf 100644 --- a/bql/lexer/lexer.go +++ b/bql/lexer/lexer.go @@ -42,6 +42,8 @@ const ( ItemDelete // ItemCreate represents the creation of a graph in BQL. ItemCreate + // ItemConstruct represents the construct keyword in BQL. + ItemConstruct // ItemDrop represent the destruction of a graph in BQL. ItemDrop // ItemGraph represent the graph to be created of destroyed in BQL. @@ -143,6 +145,8 @@ func (tt TokenType) String() string { return "DELETE" case ItemCreate: return "CREATE" + case ItemConstruct: + return "CONSTRUCT" case ItemDrop: return "DROP" case ItemGraph: @@ -256,6 +260,7 @@ const ( insert = "insert" delete = "delete" create = "create" + construct = "construct" drop = "drop" graph = "graph" data = "data" @@ -462,6 +467,10 @@ func lexKeyword(l *lexer) stateFn { consumeKeyword(l, ItemCreate) return lexSpace } + if strings.EqualFold(input, construct) { + consumeKeyword(l, ItemConstruct) + return lexSpace + } if strings.EqualFold(input, drop) { consumeKeyword(l, ItemDrop) return lexSpace @@ -618,7 +627,7 @@ func lexPredicateOrLiteral(l *lexer) stateFn { return lexLiteral } -// lexPredicate lexes a predicate of out of the input. +// lexPredicate lexes a predicate out of the input. func lexPredicate(l *lexer) stateFn { l.next() for done := false; !done; { @@ -669,7 +678,7 @@ func lexPredicate(l *lexer) stateFn { return lexSpace } -// lexPredicate lexes a literal of out of the input. +// lexLiteral lexes a literal out of the input. func lexLiteral(l *lexer) stateFn { l.next() for done := false; !done; { diff --git a/bql/lexer/lexer_test.go b/bql/lexer/lexer_test.go index ffc37d92..2122b01d 100644 --- a/bql/lexer/lexer_test.go +++ b/bql/lexer/lexer_test.go @@ -47,7 +47,7 @@ func TestIndividualTokens(t *testing.T) { {Type: ItemEOF}}}, {`SeLeCt FrOm WhErE As BeFoRe AfTeR BeTwEeN CoUnT SuM GrOuP bY HaViNg LiMiT OrDeR AsC DeSc NoT AnD Or Id TyPe At DiStInCt InSeRt DeLeTe DaTa InTo - CrEaTe DrOp GrApH`, + cONsTruCT CrEaTe DrOp GrApH`, []Token{ {Type: ItemQuery, Text: "SeLeCt"}, {Type: ItemFrom, Text: "FrOm"}, @@ -76,6 +76,7 @@ func TestIndividualTokens(t *testing.T) { {Type: ItemDelete, Text: "DeLeTe"}, {Type: ItemData, Text: "DaTa"}, {Type: ItemInto, Text: "InTo"}, + {Type: ItemConstruct, Text: "cONsTruCT"}, {Type: ItemCreate, Text: "CrEaTe"}, {Type: ItemDrop, Text: "DrOp"}, {Type: ItemGraph, Text: "GrApH"}, @@ -208,6 +209,11 @@ func TestValidTokenQuery(t *testing.T) { ItemBinding, ItemLT, ItemBinding, ItemAnd, ItemNot, ItemBinding, ItemOr, ItemBinding, ItemEQ, ItemBinding, ItemLimit, ItemLiteral, ItemSemicolon, ItemEOF}}, + {`construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, []TokenType{ + ItemConstruct, ItemLBracket, ItemBinding, ItemPredicateBound, ItemBinding, + ItemRBracket, ItemInto, ItemBinding, ItemFrom, ItemBinding, ItemWhere, + ItemLBracket, ItemBinding, ItemPredicateBound, ItemBinding, ItemRBracket, + ItemSemicolon, ItemEOF}}, } for _, test := range table { _, c := lex(test.input, 0) From 728c937c14514ae4eea079b03150e6584205d414 Mon Sep 17 00:00:00 2001 From: Aravind Rao Date: Mon, 10 Apr 2017 15:13:31 -0700 Subject: [PATCH 2/5] Rewrite CONSTRUCT query --- bql/grammar/grammar.go | 97 +++++++++++++++++++++++++++++++++---- bql/grammar/grammar_test.go | 13 +++++ bql/lexer/lexer.go | 28 +++++++++-- bql/lexer/lexer_test.go | 16 ++++++ 4 files changed, 141 insertions(+), 13 deletions(-) diff --git a/bql/grammar/grammar.go b/bql/grammar/grammar.go index e36021e5..606ca7c4 100644 --- a/bql/grammar/grammar.go +++ b/bql/grammar/grammar.go @@ -204,15 +204,6 @@ func BQL() *Grammar { }, }, }, - "CONSTRUCT_FACTS": []*Clause{ - { - Elements: []Element{ - NewTokenType(lexer.ItemLBracket), - NewSymbol("CLAUSES"), - NewTokenType(lexer.ItemRBracket), - }, - }, - }, "CLAUSES": []*Clause{ { Elements: []Element{ @@ -755,6 +746,94 @@ func BQL() *Grammar { }, {}, }, + "CONSTRUCT_FACTS": []*Clause{ + { + Elements: []Element{ + NewTokenType(lexer.ItemLBracket), + NewSymbol("CONSTRUCT_TRIPLES"), + NewTokenType(lexer.ItemRBracket), + }, + }, + }, + "CONSTRUCT_TRIPLES": []*Clause{ + { + Elements: []Element{ + NewTokenType(lexer.ItemNode), + NewSymbol("CONSTRUCT_PREDICATE"), + NewSymbol("CONSTRUCT_OBJECT"), + NewSymbol("MORE_CONSTRUCT_TRIPLES"), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemBlankNode), + NewSymbol("CONSTRUCT_PREDICATE"), + NewSymbol("CONSTRUCT_OBJECT"), + NewSymbol("MORE_CONSTRUCT_TRIPLES"), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemBinding), + NewSymbol("CONSTRUCT_PREDICATE"), + NewSymbol("CONSTRUCT_OBJECT"), + NewSymbol("MORE_CONSTRUCT_TRIPLES"), + }, + }, + }, + "CONSTRUCT_PREDICATE": []*Clause{ + { + Elements: []Element{ + NewTokenType(lexer.ItemPredicate), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemPredicateBound), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemBinding), + }, + }, + }, + "CONSTRUCT_OBJECT": []*Clause{ + { + Elements: []Element{ + NewTokenType(lexer.ItemNode), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemPredicate), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemPredicateBound), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemLiteral), + }, + }, + { + Elements: []Element{ + NewTokenType(lexer.ItemBinding), + }, + }, + }, + "MORE_CONSTRUCT_TRIPLES": []*Clause{ + { + Elements: []Element{ + NewTokenType(lexer.ItemDot), + NewSymbol("CONSTRUCT_TRIPLES"), + }, + }, + {}, + }, } } diff --git a/bql/grammar/grammar_test.go b/bql/grammar/grammar_test.go index 56cc70bd..7db5668e 100644 --- a/bql/grammar/grammar_test.go +++ b/bql/grammar/grammar_test.go @@ -116,6 +116,12 @@ func TestAcceptByParse(t *testing.T) { // Test Construct clause. `construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, `construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, + `construct {?s ?p ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, + `construct {?s ?p ?o. + _:v "_subject"@[] ?s. + _:v "_predicate"@[] ?p. + _:v "_object"@[] ?o. + _:v "some_pred"@[] ?k } into ?a from ?b where {?s "foo"@[,] ?o};`, } p, err := NewParser(BQL()) @@ -215,6 +221,13 @@ func TestRejectByParse(t *testing.T) { `construct {?s "foo"@[,] ?o} into ?a where{?s "foo"@[,] ?o} having ?s = ?o;`, // Construct clause without destination. `construct {?s "foo"@[,] ?o} from ?b where{?s "foo"@[,] ?o} having ?s = ?o;`, + // Construct clause with badly formed blank node. + `construct {?s ?p ?o. + _v "some_pred"@[] ?k } into ?a from ?b where {?s "foo"@[,] ?o};`, + // Construct clause with badle formed triple. + `construct {?s ?p ?o. + _:v "some_pred"@[]} into ?a from ?b where {?s "foo"@[,] ?o};`, + } p, err := NewParser(BQL()) if err != nil { diff --git a/bql/lexer/lexer.go b/bql/lexer/lexer.go index a2931acf..c28f4b40 100644 --- a/bql/lexer/lexer.go +++ b/bql/lexer/lexer.go @@ -33,7 +33,6 @@ const ( ItemError TokenType = iota // ItemEOF indicates end of input to be scanned in BQL. ItemEOF - // ItemQuery represents the select keyword in BQL. ItemQuery // ItemInsert represents insert keyword in BQL. @@ -90,19 +89,18 @@ const ( ItemDesc // ItemLimit represents the limit clause in BQL. ItemLimit - // ItemBinding represents a variable binding in BQL. ItemBinding - // ItemNode represents a BadWolf node in BQL. ItemNode + // ItemBlankNode represents a blank BadWolf node in BQL. + ItemBlankNode // ItemLiteral represents a BadWolf literal in BQL. ItemLiteral // ItemPredicate represents a BadWolf predicates in BQL. ItemPredicate // ItemPredicateBound represents a BadWolf predicate bound in BQL. ItemPredicateBound - // ItemLBracket represents the left opening bracket token in BQL. ItemLBracket // ItemRBracket represents the right opening bracket token in BQL. @@ -189,6 +187,8 @@ func (tt TokenType) String() string { return "BINDING" case ItemNode: return "NODE" + case ItemBlankNode: + return "BLANK_NODE" case ItemLiteral: return "LITERAL" case ItemPredicate: @@ -248,6 +248,7 @@ const ( semicolon = rune(';') comma = rune(',') slash = rune('/') + underscore = rune('_') backSlash = rune('\\') lt = rune('<') gt = rune('>') @@ -356,6 +357,9 @@ func lexToken(l *lexer) stateFn { return lexBinding case slash: return lexNode + case underscore: + l.next() + return lexBlankNode case quote: return lexPredicateOrLiteral } @@ -612,6 +616,22 @@ func lexNode(l *lexer) stateFn { return lexSpace } +// lexBlankNode tries to lex a blank node out of the input +func lexBlankNode(l *lexer) stateFn { + if r := l.next(); r != colon { + l.emitError("blank node should start with _:") + return nil + } + for { + if r := l.next(); !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != rune('_') || r == eof { + l.backup() + l.emit(ItemBlankNode) + break + } + } + return lexSpace +} + // lexPredicateOrLiteral tries to lex a predicate or a literal out of the input. func lexPredicateOrLiteral(l *lexer) stateFn { text := l.input[l.pos:] diff --git a/bql/lexer/lexer_test.go b/bql/lexer/lexer_test.go index 2122b01d..d0ef3913 100644 --- a/bql/lexer/lexer_test.go +++ b/bql/lexer/lexer_test.go @@ -102,6 +102,16 @@ func TestIndividualTokens(t *testing.T) { {Type: ItemError, Text: "/_ delimiter"}, {Type: ItemEOF}}}, + {"_:v1 _:foo_bar", + []Token{ + {Type: ItemBlankNode, Text: "_:v1"}, + {Type: ItemBlankNode, Text: "_:foo_bar"}, + {Type: ItemEOF}}}, + {"_v1", + []Token{ + {Type: ItemError, Text: "_v", + ErrorMessage: "[lexer:0:2] blank node should start with _:"}, + {Type: ItemEOF}}}, {`"true"^^type:bool "1"^^type:int64"2"^^type:float64"t"^^type:text`, []Token{ {Type: ItemLiteral, Text: `"true"^^type:bool`}, @@ -214,6 +224,12 @@ func TestValidTokenQuery(t *testing.T) { ItemRBracket, ItemInto, ItemBinding, ItemFrom, ItemBinding, ItemWhere, ItemLBracket, ItemBinding, ItemPredicateBound, ItemBinding, ItemRBracket, ItemSemicolon, ItemEOF}}, + {`construct {_:v1 "predicate"@[] ?p. + _:v1 "object"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, []TokenType{ + ItemConstruct, ItemLBracket, ItemBlankNode, ItemPredicate, ItemBinding, ItemDot, + ItemBlankNode, ItemPredicateBound, ItemBinding, ItemRBracket, ItemInto, ItemBinding, + ItemFrom, ItemBinding, ItemWhere, ItemLBracket, ItemBinding, ItemPredicateBound, + ItemBinding, ItemRBracket, ItemSemicolon, ItemEOF}}, } for _, test := range table { _, c := lex(test.input, 0) From 97e1eeea1b98a3ac9100bd35fc9ec8dec3004369 Mon Sep 17 00:00:00 2001 From: Aravind Rao Date: Tue, 11 Apr 2017 11:54:00 -0700 Subject: [PATCH 3/5] Removed Predicate Bounds; Force BNode Label to start with letter --- bql/grammar/grammar.go | 10 ---------- bql/grammar/grammar_test.go | 8 ++++---- bql/lexer/lexer.go | 8 ++++++-- bql/lexer/lexer_test.go | 11 +++++++++++ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/bql/grammar/grammar.go b/bql/grammar/grammar.go index 606ca7c4..6e847129 100644 --- a/bql/grammar/grammar.go +++ b/bql/grammar/grammar.go @@ -787,11 +787,6 @@ func BQL() *Grammar { NewTokenType(lexer.ItemPredicate), }, }, - { - Elements: []Element{ - NewTokenType(lexer.ItemPredicateBound), - }, - }, { Elements: []Element{ NewTokenType(lexer.ItemBinding), @@ -809,11 +804,6 @@ func BQL() *Grammar { NewTokenType(lexer.ItemPredicate), }, }, - { - Elements: []Element{ - NewTokenType(lexer.ItemPredicateBound), - }, - }, { Elements: []Element{ NewTokenType(lexer.ItemLiteral), diff --git a/bql/grammar/grammar_test.go b/bql/grammar/grammar_test.go index 7db5668e..5842ce99 100644 --- a/bql/grammar/grammar_test.go +++ b/bql/grammar/grammar_test.go @@ -114,14 +114,14 @@ func TestAcceptByParse(t *testing.T) { `delete data from ?world {/room<000> "named"@[] "Hallway"^^type:text. /room<000> "connects_to"@[] /room<001>};`, // Test Construct clause. - `construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, - `construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, + `construct {?s "foo"@[] ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, + `construct {?s "foo"@[] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, `construct {?s ?p ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, `construct {?s ?p ?o. _:v "_subject"@[] ?s. _:v "_predicate"@[] ?p. _:v "_object"@[] ?o. - _:v "some_pred"@[] ?k } into ?a from ?b where {?s "foo"@[,] ?o};`, + _:v "some_pred"@[2006-01-02T15:04:05.999999999Z07:00] ?k } into ?a from ?b where {?s "foo"@[,] ?o};`, } p, err := NewParser(BQL()) @@ -224,7 +224,7 @@ func TestRejectByParse(t *testing.T) { // Construct clause with badly formed blank node. `construct {?s ?p ?o. _v "some_pred"@[] ?k } into ?a from ?b where {?s "foo"@[,] ?o};`, - // Construct clause with badle formed triple. + // Construct clause with badly formed triple. `construct {?s ?p ?o. _:v "some_pred"@[]} into ?a from ?b where {?s "foo"@[,] ?o};`, diff --git a/bql/lexer/lexer.go b/bql/lexer/lexer.go index c28f4b40..c0d1d3db 100644 --- a/bql/lexer/lexer.go +++ b/bql/lexer/lexer.go @@ -309,7 +309,7 @@ func (t *Token) String() string { return fmt.Sprintf("(%s, %s, %s)", t.Type, t.Text, t.ErrorMessage) } -// stateFn represents the state of the scanner as a function that returns +// stateFn represents the state of the scanner as a function that returns // the next state. type stateFn func(*lexer) stateFn @@ -412,7 +412,7 @@ func lexToken(l *lexer) stateFn { return nil // Stop the run loop. } -// isSingleSymbolToken check if a single char should be lexed. +// isSingleSymbolToken checks if a single char should be lexed. func isSingleSymbolToken(l *lexer, tt TokenType, symbol rune) stateFn { if r := l.peek(); r == symbol { l.next() @@ -622,6 +622,10 @@ func lexBlankNode(l *lexer) stateFn { l.emitError("blank node should start with _:") return nil } + if r := l.next(); !unicode.IsLetter(r) { + l.emitError("blank node label should begin with a letter") + return nil + } for { if r := l.next(); !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != rune('_') || r == eof { l.backup() diff --git a/bql/lexer/lexer_test.go b/bql/lexer/lexer_test.go index d0ef3913..43227759 100644 --- a/bql/lexer/lexer_test.go +++ b/bql/lexer/lexer_test.go @@ -112,6 +112,17 @@ func TestIndividualTokens(t *testing.T) { {Type: ItemError, Text: "_v", ErrorMessage: "[lexer:0:2] blank node should start with _:"}, {Type: ItemEOF}}}, + + {"_:1v", + []Token{ + {Type: ItemError, Text: "_:1", + ErrorMessage: "[lexer:0:3] blank node label should begin with a letter"}, + {Type: ItemEOF}}}, + {"_:_", + []Token{ + {Type: ItemError, Text: "_:_", + ErrorMessage: "[lexer:0:3] blank node label should begin with a letter"}, + {Type: ItemEOF}}}, {`"true"^^type:bool "1"^^type:int64"2"^^type:float64"t"^^type:text`, []Token{ {Type: ItemLiteral, Text: `"true"^^type:bool`}, From 7b6a98b37721691c50efbd9541a9e4525dc87a14 Mon Sep 17 00:00:00 2001 From: Aravind Rao Date: Tue, 11 Apr 2017 12:01:57 -0700 Subject: [PATCH 4/5] Fixed Lexer test that included bounded predicates --- bql/lexer/lexer_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bql/lexer/lexer_test.go b/bql/lexer/lexer_test.go index 43227759..a0e47c8a 100644 --- a/bql/lexer/lexer_test.go +++ b/bql/lexer/lexer_test.go @@ -230,16 +230,16 @@ func TestValidTokenQuery(t *testing.T) { ItemBinding, ItemLT, ItemBinding, ItemAnd, ItemNot, ItemBinding, ItemOr, ItemBinding, ItemEQ, ItemBinding, ItemLimit, ItemLiteral, ItemSemicolon, ItemEOF}}, - {`construct {?s "foo"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, []TokenType{ - ItemConstruct, ItemLBracket, ItemBinding, ItemPredicateBound, ItemBinding, + {`construct {?s "foo"@[] ?o} into ?a from ?b where {?s "foo"@[] ?o};`, []TokenType{ + ItemConstruct, ItemLBracket, ItemBinding, ItemPredicate, ItemBinding, ItemRBracket, ItemInto, ItemBinding, ItemFrom, ItemBinding, ItemWhere, - ItemLBracket, ItemBinding, ItemPredicateBound, ItemBinding, ItemRBracket, + ItemLBracket, ItemBinding, ItemPredicate, ItemBinding, ItemRBracket, ItemSemicolon, ItemEOF}}, {`construct {_:v1 "predicate"@[] ?p. - _:v1 "object"@[,] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, []TokenType{ + _:v1 "object"@[] ?o} into ?a from ?b where {?s "foo"@[] ?o};`, []TokenType{ ItemConstruct, ItemLBracket, ItemBlankNode, ItemPredicate, ItemBinding, ItemDot, - ItemBlankNode, ItemPredicateBound, ItemBinding, ItemRBracket, ItemInto, ItemBinding, - ItemFrom, ItemBinding, ItemWhere, ItemLBracket, ItemBinding, ItemPredicateBound, + ItemBlankNode, ItemPredicate, ItemBinding, ItemRBracket, ItemInto, ItemBinding, + ItemFrom, ItemBinding, ItemWhere, ItemLBracket, ItemBinding, ItemPredicate, ItemBinding, ItemRBracket, ItemSemicolon, ItemEOF}}, } for _, test := range table { From 3f4f00ce305e4a973625a850cbf3c6388f0eee34 Mon Sep 17 00:00:00 2001 From: Aravind Rao Date: Wed, 19 Apr 2017 22:18:42 -0700 Subject: [PATCH 5/5] Added semantically valid test cases --- bql/grammar/grammar_test.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bql/grammar/grammar_test.go b/bql/grammar/grammar_test.go index 5842ce99..7c3c5d02 100644 --- a/bql/grammar/grammar_test.go +++ b/bql/grammar/grammar_test.go @@ -114,15 +114,17 @@ func TestAcceptByParse(t *testing.T) { `delete data from ?world {/room<000> "named"@[] "Hallway"^^type:text. /room<000> "connects_to"@[] /room<001>};`, // Test Construct clause. - `construct {?s "foo"@[] ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, - `construct {?s "foo"@[] ?o} into ?a from ?b where {?s "foo"@[,] ?o};`, - `construct {?s ?p ?o} into ?a from ?b where {?s "foo"@[,] ?o} having ?s = ?o;`, + `construct {?s "new_predicate"@[] ?o} into ?a from ?b where {?s "old_predicate"@[,] ?o} having ?s = ?o;`, + `construct {?s "new_predicate"@[] ?o} into ?a from ?b where {?s "old_predicate"@[,] ?o};`, + `construct {?s ?p ?o} into ?a from ?b where {?n "_subject"@[] ?s. + ?n "_predicate"@[] ?p. + ?n "_object"@[] ?o};`, `construct {?s ?p ?o. _:v "_subject"@[] ?s. _:v "_predicate"@[] ?p. - _:v "_object"@[] ?o. - _:v "some_pred"@[2006-01-02T15:04:05.999999999Z07:00] ?k } into ?a from ?b where {?s "foo"@[,] ?o};`, - + _:v "_object"@[] ?o} into ?a from ?b where {?n "_subject"@[] ?s. + ?n "_predicate"@[] ?p. + ?n "_object"@[] ?o};`, } p, err := NewParser(BQL()) if err != nil {