From 00e88fea594441a2e92d26d190765edf3b01f99f Mon Sep 17 00:00:00 2001
From: Manish R Jain <manishrjain@gmail.com>
Date: Mon, 2 Nov 2015 18:38:47 +1100
Subject: [PATCH] Add tests for parser

---
 rdf/parse.go      | 11 +++++++++
 rdf/parse_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++-
 rdf/state.go      |  9 +++++++-
 3 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/rdf/parse.go b/rdf/parse.go
index de9661e7..b9412d36 100644
--- a/rdf/parse.go
+++ b/rdf/parse.go
@@ -45,6 +45,7 @@ func Parse(line string) (rnq NQuad, rerr error) {
 	l := lex.NewLexer(line)
 	go run(l)
 	var oval string
+	var vend bool
 	for item := range l.Items {
 		if item.Typ == itemSubject {
 			rnq.Subject = stripBracketsIfPresent(item.Val)
@@ -62,12 +63,22 @@ func Parse(line string) (rnq NQuad, rerr error) {
 			rnq.Language = item.Val
 		}
 		if item.Typ == itemObjectType {
+			// TODO: Strictly parse common types like integers, floats etc.
 			if len(oval) == 0 {
 				glog.Fatalf(
 					"itemObject should be emitted before itemObjectType. Input: %q", line)
 			}
 			oval += "@@" + stripBracketsIfPresent(item.Val)
 		}
+		if item.Typ == lex.ItemError {
+			return rnq, fmt.Errorf(item.Val)
+		}
+		if item.Typ == itemValidEnd {
+			vend = true
+		}
+	}
+	if !vend {
+		return rnq, fmt.Errorf("Invalid end of input")
 	}
 	if len(oval) > 0 {
 		rnq.ObjectValue = oval
diff --git a/rdf/parse_test.go b/rdf/parse_test.go
index 2d26986c..fa14448e 100644
--- a/rdf/parse_test.go
+++ b/rdf/parse_test.go
@@ -100,6 +100,56 @@ var testNQuads = []struct {
 			ObjectValue: nil,
 		},
 	},
+	{
+		input:  "_:alice .",
+		hasErr: true,
+	},
+	{
+		input:  "_:alice knows .",
+		hasErr: true,
+	},
+	{
+		input:  `_:alice "knows" stuff .`,
+		hasErr: true,
+	},
+	{
+		input:  "_:alice <knows> stuff .",
+		hasErr: true,
+	},
+	{
+		input:  "_:alice <knows> <stuff>",
+		hasErr: true,
+	},
+	{
+		input:  `"_:alice" <knows> <stuff> .`,
+		hasErr: true,
+	},
+	{
+		input:  `_:alice <knows> "stuff .`,
+		hasErr: true,
+	},
+	{
+		input:  `_:alice <knows> "stuff"@-en .`,
+		hasErr: true,
+	},
+	{
+		input:  `_:alice <knows> "stuff"^<string> .`,
+		hasErr: true,
+	},
+	{
+		input:  `_:alice <knows> "stuff"^^xs:string .`,
+		hasErr: true,
+	},
+	{
+		input: `_:alice <knows> "stuff"^^<xs:string> .`,
+		nq: NQuad{
+			Subject:     "_:alice",
+			Predicate:   "knows",
+			ObjectId:    "",
+			ObjectValue: "stuff@@xs:string",
+		},
+		hasErr: false,
+	},
 }
 
 func TestLex(t *testing.T) {
@@ -107,9 +157,15 @@ func TestLex(t *testing.T) {
 		rnq, err := Parse(test.input)
 		if test.hasErr {
 			if err == nil {
-				t.Errorf("Expected error for input: %q", test.input)
+				t.Errorf("Expected error for input: %q. Output: %+v", test.input, rnq)
+			}
+			continue
+		} else {
+			if err != nil {
+				t.Errorf("Unexpected error: %v", err)
 			}
 		}
+
 		if !reflect.DeepEqual(rnq, test.nq) {
 			t.Errorf("Expected %v. Got: %v", test.nq, rnq)
 		}
diff --git a/rdf/state.go b/rdf/state.go
index ca8af393..bc4d8925 100644
--- a/rdf/state.go
+++ b/rdf/state.go
@@ -32,6 +32,7 @@ const (
 	itemLiteral                            // literal, 10
 	itemLanguage                           // language, 11
 	itemObjectType                         // object type, 12
+	itemValidEnd                           // end with dot, 13
 )
 
 const (
@@ -82,7 +83,13 @@ Loop:
 			l.Emit(itemText)
 			return lexObject
 
-		case r == '.' || r == lex.EOF:
+		case r == lex.EOF:
+			break Loop
+
+		case r == '.':
+			if l.Depth > AT_OBJECT {
+				l.Emit(itemValidEnd)
+			}
 			break Loop
 		}
 	}
-- 
GitLab