diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 9a586ef8..9956dbd8 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -11,6 +11,6 @@ jobs: uses: golangci/golangci-lint-action@v2.3.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.28 + version: v1.34 only-new-issues: true args: --timeout=5m diff --git a/.travis.yml b/.travis.yml index add1341e..9ef6ed64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ sudo: false +dist: bionic + language: go # Do not move these lines; they are referred to by README.md. @@ -89,6 +91,11 @@ matrix: before_install: - ${TRAVIS_BUILD_DIR}/.travis/run-parts ${TRAVIS_BUILD_DIR}/.travis/deps.d/${TRAVIS_OS_NAME} +addons: + apt: + packages: + - ragel + go_import_path: gonum.org/v1/gonum # Get deps, build, test, and ensure the code is gofmt'ed. diff --git a/.travis/script.d/check-copyright.sh b/.travis/script.d/check-copyright.sh index 209dca39..afc6de39 100755 --- a/.travis/script.d/check-copyright.sh +++ b/.travis/script.d/check-copyright.sh @@ -1,4 +1,4 @@ #!/bin/bash set -e -check-copyright -notice "Copyright ©20[0-9]{2} The Gonum Authors\. All rights reserved\." +check-copyright -notice "(Copyright ©20[0-9]{2} The Gonum Authors\. All rights reserved\.|[Cc]ode generated by .*; DO NOT EDIT\.)" diff --git a/.travis/script.d/check-generate.sh b/.travis/script.d/check-generate.sh index 55de7e80..0cc63cd8 100755 --- a/.travis/script.d/check-generate.sh +++ b/.travis/script.d/check-generate.sh @@ -9,6 +9,7 @@ go generate gonum.org/v1/gonum/blas/gonum go generate gonum.org/v1/gonum/unit go generate gonum.org/v1/gonum/unit/constant go generate gonum.org/v1/gonum/graph/formats/dot +go generate gonum.org/v1/gonum/graph/formats/rdf go generate gonum.org/v1/gonum/stat/card if [ -n "$(git diff)" ]; then diff --git a/.travis/script.d/deps.sh b/.travis/script.d/deps.sh index 65dd9a3b..c1f04fc1 100755 --- a/.travis/script.d/deps.sh +++ b/.travis/script.d/deps.sh @@ -18,6 +18,8 @@ go get golang.org/x/tools/cmd/cover go get github.com/mattn/goveralls # Required for dot parser checks. go get github.com/goccmack/gocc@66c61e9 +# Required for rdf parser checks. +go get golang.org/x/tools/cmd/stringer # Clean up. # TODO(kortschak): Remove when golang/go#30515 is resolved. diff --git a/README.md b/README.md index 996e8e1d..0cfbef10 100644 --- a/README.md +++ b/README.md @@ -58,3 +58,5 @@ https://groups.google.com/forum/#!forum/gonum-dev Original code is licensed under the Gonum License found in the LICENSE file. Portions of the code are subject to the additional licenses found in THIRD_PARTY_LICENSES. All third party code is licensed either under a BSD or MIT license. Code in graph/formats/dot is dual licensed [Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/) and Gonum License, and users are free to choose the license which suits their needs for this code. + +The W3C test suites in graph/formats/rdf are distributed under both the [W3C Test Suite License](http://www.w3.org/Consortium/Legal/2008/04-testsuite-license) and the [W3C 3-clause BSD License](http://www.w3.org/Consortium/Legal/2008/03-bsd-license). \ No newline at end of file diff --git a/THIRD_PARTY_LICENSES/W3C-BSD-LICENSE b/THIRD_PARTY_LICENSES/W3C-BSD-LICENSE new file mode 100644 index 00000000..c7a01def --- /dev/null +++ b/THIRD_PARTY_LICENSES/W3C-BSD-LICENSE @@ -0,0 +1,26 @@ +Copyright © 2008 World Wide Web Consortium®, (MIT, ERCIM, Keio, Beihang) and others. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of works must retain the original copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the original copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the W3C nor the names of its contributors may be + used to endorse or promote products derived from this work without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/THIRD_PARTY_LICENSES/W3C-TestSuite-LICENSE b/THIRD_PARTY_LICENSES/W3C-TestSuite-LICENSE new file mode 100644 index 00000000..ea1fe34c --- /dev/null +++ b/THIRD_PARTY_LICENSES/W3C-TestSuite-LICENSE @@ -0,0 +1,56 @@ +Copyright © 2008 World Wide Web Consortium, (MIT, ERCIM, Keio, Beihang) and others. All Rights Reserved. +http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html + +This document, Test Suites and other documents that link to this statement are +provided by the copyright holders under the following license: By using and/or +copying this document, or the W3C document from which this statement is linked, +you (the licensee) agree that you have read, understood, and will comply with +the following terms and conditions: + +Permission to copy, and distribute the contents of this document, or the W3C +document from which this statement is linked, in any medium for any purpose and +without fee or royalty is hereby granted, provided that you include the following +on ALL copies of the document, or portions thereof, that you use: + + 1. A link or URL to the original W3C document. + 2. The pre-existing copyright notice of the original author, or if it doesn't + exist, a notice (hypertext is preferred, but a textual representation is + permitted) of the form: "Copyright © [$date-of-document] World Wide Web + Consortium, (MIT, ERCIM, Keio, Beihang) and others. All Rights Reserved. + http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html" + 3. If it exists, the STATUS of the W3C document. + +When space permits, inclusion of the full text of this NOTICE should be provided. +We request that authorship attribution be provided in any software, documents, +or other items or products that you create pursuant to the implementation of the +contents of this document, or any portion thereof. + +No right to create modifications or derivatives of W3C documents is granted +pursuant to this license. However, if additional requirements (documented in the +Copyright FAQ) are satisfied, the right to create modifications or derivatives +is sometimes granted by the W3C to individuals complying with those requirements. + +If a Test Suite distinguishes the test harness (or, framework for navigation) and +the actual tests, permission is given to remove or alter the harness or navigation +if the Test Suite in question allows to do so. The tests themselves shall NOT be +changed in any way. + +The name and trademarks of W3C and other copyright holders may NOT be used in +advertising or publicity pertaining to this document or other documents that link +to this statement without specific, written prior permission. Title to copyright +in this document will at all times remain with copyright holders. Permission is +given to use the trademarked string "W3C" within claims of performance concerning +W3C Specifications or features described therein, and there only, if the test +suite so authorizes. + +THIS WORK IS PROVIDED BY W3C, MIT, ERCIM, KEIO, BEIHANG, THE COPYRIGHT HOLDERS +AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL W3C, MIT, ERCIM, KEIO, +BEIHANG, THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/graph/formats/rdf/LICENSE.md b/graph/formats/rdf/LICENSE.md new file mode 100644 index 00000000..18aee556 --- /dev/null +++ b/graph/formats/rdf/LICENSE.md @@ -0,0 +1,10 @@ +Test suite license + +This document refers to nquad_tests.tar.gz and ntriple_tests.tar.gz. The original files can be obtained here: + +- [nquad_tests.tar.gz](https://w3c.github.io/rdf-tests/nquads/TESTS.tar.gz) +- [ntriple_tests.tar.gz](https://w3c.github.io/rdf-tests/ntriples/TESTS.tar.gz) + +Distributed under both the [W3C Test Suite License](https://www.w3.org/Consortium/Legal/2008/04-testsuite-license) and the [W3C 3-clause BSD License](https://www.w3.org/Consortium/Legal/2008/03-bsd-license). +To contribute to a W3C Test Suite, see the [policies and contribution forms](href="https://www.w3.org/2004/10/27-testcases"). + diff --git a/graph/formats/rdf/check.go b/graph/formats/rdf/check.go new file mode 100644 index 00000000..aabc28c6 --- /dev/null +++ b/graph/formats/rdf/check.go @@ -0,0 +1,526 @@ + +//line check.rl:1 +// Go code generated by go generate gonum.org/v1/gonum/graph/formats/rdf; DO NOT EDIT. + +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "fmt" + "unicode" +) + + +//line check.go:18 +const checkLabel_start int = 1 +const checkLabel_first_final int = 3 +const checkLabel_error int = 0 + +const checkLabel_en_value int = 1 + + +//line check.rl:53 + + +func checkLabelText(data []rune) (err error) { + var ( + cs, p int + pe = len(data) + eof = pe + ) + + +//line check.go:37 + { + cs = checkLabel_start + } + +//line check.rl:63 + + +//line check.go:45 + { + if p == pe { + goto _test_eof + } + switch cs { + case 1: + goto st_case_1 + case 0: + goto st_case_0 + case 3: + goto st_case_3 + case 2: + goto st_case_2 + } + goto st_out + st_case_1: + if data[p] == 95 { + goto st3 + } + switch { + case data[p] < 895: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st3 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st3 + } + default: + goto st3 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st3 + } + case data[p] > 767: + if 880 <= data[p] && data[p] <= 893 { + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + case data[p] > 8191: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8204 <= data[p] && data[p] <= 8205 { + goto st3 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st3 + } + default: + goto st3 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st3 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + goto tr0 +tr0: +//line check_actions.rl:12 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return ErrIncompleteTerm + + goto st0 +//line check.go:145 +st_case_0: + st0: + cs = 0 + goto _out + st3: + if p++; p == pe { + goto _test_eof3 + } + st_case_3: + switch data[p] { + case 45: + goto st3 + case 46: + goto st2 + case 95: + goto st3 + case 183: + goto st3 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st3 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st3 + } + default: + goto st3 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st3 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st3 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st3 + } + default: + goto st3 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st3 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + goto st0 + st2: + if p++; p == pe { + goto _test_eof2 + } + st_case_2: + switch data[p] { + case 45: + goto st3 + case 46: + goto st2 + case 95: + goto st3 + case 183: + goto st3 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st3 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st3 + } + default: + goto st3 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st3 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st3 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st3 + } + default: + goto st3 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st3 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + default: + goto st3 + } + goto tr0 + st_out: + _test_eof3: cs = 3; goto _test_eof + _test_eof2: cs = 2; goto _test_eof + + _test_eof: {} + if p == eof { + switch cs { + case 3: +//line check_actions.rl:8 + + return nil + + case 1, 2: +//line check_actions.rl:12 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return ErrIncompleteTerm + +//line check.go:338 + } + } + + _out: {} + } + +//line check.rl:65 + + return ErrInvalidTerm +} + + +//line check.go:351 +const checkLang_start int = 1 +const checkLang_first_final int = 4 +const checkLang_error int = 0 + +const checkLang_en_value int = 1 + + +//line check.rl:81 + + +func checkLangText(data []byte) (err error) { + var ( + cs, p int + pe = len(data) + eof = pe + ) + + +//line check.go:370 + { + cs = checkLang_start + } + +//line check.rl:91 + + +//line check.go:378 + { + if p == pe { + goto _test_eof + } + switch cs { + case 1: + goto st_case_1 + case 0: + goto st_case_0 + case 2: + goto st_case_2 + case 4: + goto st_case_4 + case 3: + goto st_case_3 + case 5: + goto st_case_5 + } + goto st_out + st_case_1: + if data[p] == 64 { + goto st2 + } + goto tr0 +tr0: +//line check_actions.rl:12 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return ErrIncompleteTerm + + goto st0 +//line check.go:416 +st_case_0: + st0: + cs = 0 + goto _out + st2: + if p++; p == pe { + goto _test_eof2 + } + st_case_2: + switch { + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st4 + } + case data[p] >= 65: + goto st4 + } + goto tr0 + st4: + if p++; p == pe { + goto _test_eof4 + } + st_case_4: + if data[p] == 45 { + goto st3 + } + switch { + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st4 + } + case data[p] >= 65: + goto st4 + } + goto st0 + st3: + if p++; p == pe { + goto _test_eof3 + } + st_case_3: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st5 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st5 + } + default: + goto st5 + } + goto tr0 + st5: + if p++; p == pe { + goto _test_eof5 + } + st_case_5: + if data[p] == 45 { + goto st3 + } + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st5 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st5 + } + default: + goto st5 + } + goto st0 + st_out: + _test_eof2: cs = 2; goto _test_eof + _test_eof4: cs = 4; goto _test_eof + _test_eof3: cs = 3; goto _test_eof + _test_eof5: cs = 5; goto _test_eof + + _test_eof: {} + if p == eof { + switch cs { + case 4, 5: +//line check_actions.rl:8 + + return nil + + case 1, 2, 3: +//line check_actions.rl:12 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return ErrIncompleteTerm + +//line check.go:517 + } + } + + _out: {} + } + +//line check.rl:93 + + return ErrInvalidTerm +} diff --git a/graph/formats/rdf/check.rl b/graph/formats/rdf/check.rl new file mode 100644 index 00000000..966d78cb --- /dev/null +++ b/graph/formats/rdf/check.rl @@ -0,0 +1,95 @@ +// Go code generated by go generate gonum.org/v1/gonum/graph/formats/rdf; DO NOT EDIT. + +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "fmt" + "unicode" +) + +%%{ + machine checkLabel; + + alphtype rune; + + include check "check_actions.rl"; + + alphtype rune; + + PN_CHARS_BASE = [A-Za-z] + | 0x00c0 .. 0x00d6 + | 0x00d8 .. 0x00f6 + | 0x00f8 .. 0x02ff + | 0x0370 .. 0x037d + | 0x037f .. 0x1fff + | 0x200c .. 0x200d + | 0x2070 .. 0x218f + | 0x2c00 .. 0x2fef + | 0x3001 .. 0xd7ff + | 0xf900 .. 0xfdcf + | 0xfdf0 .. 0xfffd + | 0x10000 .. 0xeffff + ; + + PN_CHARS_U = PN_CHARS_BASE | '_' | ':' ; + + PN_CHARS = PN_CHARS_U + | '-' + | [0-9] + | 0xb7 + | 0x0300 .. 0x036f + | 0x203f .. 0x2040 + ; + + BLANK_NODE_LABEL = (PN_CHARS_U | [0-9]) ((PN_CHARS | '.')* PN_CHARS)? ; + + value := BLANK_NODE_LABEL %Return @!Error ; + + write data; +}%% + +func checkLabelText(data []rune) (err error) { + var ( + cs, p int + pe = len(data) + eof = pe + ) + + %%write init; + + %%write exec; + + return ErrInvalidTerm +} + +%%{ + machine checkLang; + + alphtype byte; + + include check "check_actions.rl"; + + LANGTAG = '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ; + + value := LANGTAG %Return @!Error ; + + write data; +}%% + +func checkLangText(data []byte) (err error) { + var ( + cs, p int + pe = len(data) + eof = pe + ) + + %%write init; + + %%write exec; + + return ErrInvalidTerm +} diff --git a/graph/formats/rdf/check_actions.rl b/graph/formats/rdf/check_actions.rl new file mode 100644 index 00000000..a1979504 --- /dev/null +++ b/graph/formats/rdf/check_actions.rl @@ -0,0 +1,22 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +%%{ + machine check; + + action Return { + return nil + } + + action Error { + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return ErrIncompleteTerm + } +}%% diff --git a/graph/formats/rdf/doc.go b/graph/formats/rdf/doc.go new file mode 100644 index 00000000..adda3b29 --- /dev/null +++ b/graph/formats/rdf/doc.go @@ -0,0 +1,8 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package rdf implements decoding the RDF 1.1 N-Quads line-based plain text +// format for encoding an RDF dataset. +// N-Quad parsing is performed as defined by http://www.w3.org/TR/n-quads/ +package rdf // import "gonum.org/v1/gonum/graph/formats/rdf" diff --git a/graph/formats/rdf/extract.go b/graph/formats/rdf/extract.go new file mode 100644 index 00000000..b93e6dec --- /dev/null +++ b/graph/formats/rdf/extract.go @@ -0,0 +1,1184 @@ + +//line extract.rl:1 +// Go code generated by go generate gonum.org/v1/gonum/graph/formats/rdf; DO NOT EDIT. + +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "fmt" + "unicode" +) + + +//line extract.go:18 +const extract_start int = 1 +const extract_first_final int = 31 +const extract_error int = 0 + +const extract_en_value int = 1 + + +//line extract.rl:28 + + +func extract(data []rune) (text, qual string, kind Kind, err error) { + var ( + cs, p int + pe = len(data) + eof = pe + + iri = -1 + blank = -1 + literal = -1 + lang = -1 + + iriText string + blankText string + literalText string + langText string + ) + + +//line extract.go:47 + { + cs = extract_start + } + +//line extract.rl:48 + + +//line extract.go:55 + { + if p == pe { + goto _test_eof + } + switch cs { + case 1: + goto st_case_1 + case 0: + goto st_case_0 + case 2: + goto st_case_2 + case 3: + goto st_case_3 + case 31: + goto st_case_31 + case 4: + goto st_case_4 + case 32: + goto st_case_32 + case 5: + goto st_case_5 + case 33: + goto st_case_33 + case 6: + goto st_case_6 + case 7: + goto st_case_7 + case 8: + goto st_case_8 + case 9: + goto st_case_9 + case 34: + goto st_case_34 + case 10: + goto st_case_10 + case 11: + goto st_case_11 + case 12: + goto st_case_12 + case 13: + goto st_case_13 + case 14: + goto st_case_14 + case 15: + goto st_case_15 + case 16: + goto st_case_16 + case 17: + goto st_case_17 + case 18: + goto st_case_18 + case 19: + goto st_case_19 + case 20: + goto st_case_20 + case 21: + goto st_case_21 + case 22: + goto st_case_22 + case 23: + goto st_case_23 + case 24: + goto st_case_24 + case 25: + goto st_case_25 + case 26: + goto st_case_26 + case 27: + goto st_case_27 + case 28: + goto st_case_28 + case 29: + goto st_case_29 + case 35: + goto st_case_35 + case 30: + goto st_case_30 + } + goto st_out + st_case_1: + switch data[p] { + case 34: + goto st2 + case 60: + goto st8 + case 95: + goto st28 + } + goto tr0 +tr0: +//line extract_actions.rl:74 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return "", "", Invalid, fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return "", "", Invalid, fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return "", "", Invalid, ErrIncompleteTerm + + goto st0 +//line extract.go:158 +st_case_0: + st0: + cs = 0 + goto _out + st2: + if p++; p == pe { + goto _test_eof2 + } + st_case_2: + switch data[p] { + case 34: + goto tr5 + case 92: + goto tr6 + } + switch { + case data[p] < 11: + if 0 <= data[p] && data[p] <= 9 { + goto tr4 + } + case data[p] > 12: + if 14 <= data[p] && data[p] <= 1114111 { + goto tr4 + } + default: + goto tr4 + } + goto tr0 +tr4: +//line extract_actions.rl:34 + + literal = p + + goto st3 + st3: + if p++; p == pe { + goto _test_eof3 + } + st_case_3: +//line extract.go:198 + switch data[p] { + case 34: + goto tr8 + case 92: + goto st19 + } + switch { + case data[p] < 11: + if 0 <= data[p] && data[p] <= 9 { + goto st3 + } + case data[p] > 12: + if 14 <= data[p] && data[p] <= 1114111 { + goto st3 + } + default: + goto st3 + } + goto tr0 +tr5: +//line extract_actions.rl:34 + + literal = p + +//line extract_actions.rl:38 + + if literal < 0 { + panic("unexpected parser state: literal start not set") + } + literalText = unEscape(data[literal:p]) + kind = Literal + + goto st31 +tr8: +//line extract_actions.rl:38 + + if literal < 0 { + panic("unexpected parser state: literal start not set") + } + literalText = unEscape(data[literal:p]) + kind = Literal + + goto st31 + st31: + if p++; p == pe { + goto _test_eof31 + } + st_case_31: +//line extract.go:247 + switch data[p] { + case 64: + goto tr39 + case 94: + goto st6 + } + goto st0 +tr39: +//line extract_actions.rl:46 + + lang = p + + goto st4 + st4: + if p++; p == pe { + goto _test_eof4 + } + st_case_4: +//line extract.go:266 + switch { + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st32 + } + case data[p] >= 65: + goto st32 + } + goto tr0 + st32: + if p++; p == pe { + goto _test_eof32 + } + st_case_32: + if data[p] == 45 { + goto st5 + } + switch { + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st32 + } + case data[p] >= 65: + goto st32 + } + goto st0 + st5: + if p++; p == pe { + goto _test_eof5 + } + st_case_5: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st33 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st33 + } + default: + goto st33 + } + goto tr0 + st33: + if p++; p == pe { + goto _test_eof33 + } + st_case_33: + if data[p] == 45 { + goto st5 + } + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st33 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st33 + } + default: + goto st33 + } + goto st0 + st6: + if p++; p == pe { + goto _test_eof6 + } + st_case_6: + if data[p] == 94 { + goto st7 + } + goto tr0 + st7: + if p++; p == pe { + goto _test_eof7 + } + st_case_7: + if data[p] == 60 { + goto st8 + } + goto tr0 + st8: + if p++; p == pe { + goto _test_eof8 + } + st_case_8: + switch data[p] { + case 62: + goto tr14 + case 92: + goto tr15 + case 95: + goto tr13 + case 126: + goto tr13 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto tr13 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto tr13 + } + case data[p] >= 97: + goto tr13 + } + default: + goto tr13 + } + goto tr0 +tr13: +//line extract_actions.rl:8 + + iri = p + + goto st9 + st9: + if p++; p == pe { + goto _test_eof9 + } + st_case_9: +//line extract.go:394 + switch data[p] { + case 62: + goto tr17 + case 92: + goto st10 + case 95: + goto st9 + case 126: + goto st9 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto st9 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto st9 + } + case data[p] >= 97: + goto st9 + } + default: + goto st9 + } + goto tr0 +tr14: +//line extract_actions.rl:8 + + iri = p + +//line extract_actions.rl:12 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + iriText = unEscape(data[iri:p]) + if kind == Invalid { + kind = IRI + } + + goto st34 +tr17: +//line extract_actions.rl:12 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + iriText = unEscape(data[iri:p]) + if kind == Invalid { + kind = IRI + } + + goto st34 + st34: + if p++; p == pe { + goto _test_eof34 + } + st_case_34: +//line extract.go:456 + goto st0 +tr15: +//line extract_actions.rl:8 + + iri = p + + goto st10 + st10: + if p++; p == pe { + goto _test_eof10 + } + st_case_10: +//line extract.go:469 + switch data[p] { + case 85: + goto st11 + case 117: + goto st15 + } + goto tr0 + st11: + if p++; p == pe { + goto _test_eof11 + } + st_case_11: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st12 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st12 + } + default: + goto st12 + } + goto tr0 + st12: + if p++; p == pe { + goto _test_eof12 + } + st_case_12: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st13 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st13 + } + default: + goto st13 + } + goto tr0 + st13: + if p++; p == pe { + goto _test_eof13 + } + st_case_13: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st14 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st14 + } + default: + goto st14 + } + goto tr0 + st14: + if p++; p == pe { + goto _test_eof14 + } + st_case_14: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st15 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st15 + } + default: + goto st15 + } + goto tr0 + st15: + if p++; p == pe { + goto _test_eof15 + } + st_case_15: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st16 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st16 + } + default: + goto st16 + } + goto tr0 + st16: + if p++; p == pe { + goto _test_eof16 + } + st_case_16: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st17 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st17 + } + default: + goto st17 + } + goto tr0 + st17: + if p++; p == pe { + goto _test_eof17 + } + st_case_17: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st18 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st18 + } + default: + goto st18 + } + goto tr0 + st18: + if p++; p == pe { + goto _test_eof18 + } + st_case_18: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st9 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st9 + } + default: + goto st9 + } + goto tr0 +tr6: +//line extract_actions.rl:34 + + literal = p + + goto st19 + st19: + if p++; p == pe { + goto _test_eof19 + } + st_case_19: +//line extract.go:632 + switch data[p] { + case 34: + goto st3 + case 39: + goto st3 + case 85: + goto st20 + case 92: + goto st3 + case 98: + goto st3 + case 102: + goto st3 + case 110: + goto st3 + case 114: + goto st3 + case 116: + goto st3 + case 117: + goto st24 + } + goto tr0 + st20: + if p++; p == pe { + goto _test_eof20 + } + st_case_20: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st21 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st21 + } + default: + goto st21 + } + goto tr0 + st21: + if p++; p == pe { + goto _test_eof21 + } + st_case_21: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st22 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st22 + } + default: + goto st22 + } + goto tr0 + st22: + if p++; p == pe { + goto _test_eof22 + } + st_case_22: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st23 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st23 + } + default: + goto st23 + } + goto tr0 + st23: + if p++; p == pe { + goto _test_eof23 + } + st_case_23: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st24 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st24 + } + default: + goto st24 + } + goto tr0 + st24: + if p++; p == pe { + goto _test_eof24 + } + st_case_24: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st25 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st25 + } + default: + goto st25 + } + goto tr0 + st25: + if p++; p == pe { + goto _test_eof25 + } + st_case_25: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st26 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st26 + } + default: + goto st26 + } + goto tr0 + st26: + if p++; p == pe { + goto _test_eof26 + } + st_case_26: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st27 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st27 + } + default: + goto st27 + } + goto tr0 + st27: + if p++; p == pe { + goto _test_eof27 + } + st_case_27: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st3 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st3 + } + default: + goto st3 + } + goto tr0 + st28: + if p++; p == pe { + goto _test_eof28 + } + st_case_28: + if data[p] == 58 { + goto st29 + } + goto tr0 + st29: + if p++; p == pe { + goto _test_eof29 + } + st_case_29: + if data[p] == 95 { + goto tr36 + } + switch { + case data[p] < 895: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto tr36 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto tr36 + } + default: + goto tr36 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto tr36 + } + case data[p] > 767: + if 880 <= data[p] && data[p] <= 893 { + goto tr36 + } + default: + goto tr36 + } + default: + goto tr36 + } + case data[p] > 8191: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8204 <= data[p] && data[p] <= 8205 { + goto tr36 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto tr36 + } + default: + goto tr36 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto tr36 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto tr36 + } + default: + goto tr36 + } + default: + goto tr36 + } + default: + goto tr36 + } + goto tr0 +tr36: +//line extract_actions.rl:22 + + blank = p + + goto st35 + st35: + if p++; p == pe { + goto _test_eof35 + } + st_case_35: +//line extract.go:895 + switch data[p] { + case 45: + goto st35 + case 46: + goto st30 + case 95: + goto st35 + case 183: + goto st35 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st35 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st35 + } + default: + goto st35 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st35 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st35 + } + default: + goto st35 + } + default: + goto st35 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st35 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st35 + } + default: + goto st35 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st35 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st35 + } + default: + goto st35 + } + default: + goto st35 + } + default: + goto st35 + } + goto st0 + st30: + if p++; p == pe { + goto _test_eof30 + } + st_case_30: + switch data[p] { + case 45: + goto st35 + case 46: + goto st30 + case 95: + goto st35 + case 183: + goto st35 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st35 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st35 + } + default: + goto st35 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st35 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st35 + } + default: + goto st35 + } + default: + goto st35 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st35 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st35 + } + default: + goto st35 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st35 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st35 + } + default: + goto st35 + } + default: + goto st35 + } + default: + goto st35 + } + goto tr0 + st_out: + _test_eof2: cs = 2; goto _test_eof + _test_eof3: cs = 3; goto _test_eof + _test_eof31: cs = 31; goto _test_eof + _test_eof4: cs = 4; goto _test_eof + _test_eof32: cs = 32; goto _test_eof + _test_eof5: cs = 5; goto _test_eof + _test_eof33: cs = 33; goto _test_eof + _test_eof6: cs = 6; goto _test_eof + _test_eof7: cs = 7; goto _test_eof + _test_eof8: cs = 8; goto _test_eof + _test_eof9: cs = 9; goto _test_eof + _test_eof34: cs = 34; goto _test_eof + _test_eof10: cs = 10; goto _test_eof + _test_eof11: cs = 11; goto _test_eof + _test_eof12: cs = 12; goto _test_eof + _test_eof13: cs = 13; goto _test_eof + _test_eof14: cs = 14; goto _test_eof + _test_eof15: cs = 15; goto _test_eof + _test_eof16: cs = 16; goto _test_eof + _test_eof17: cs = 17; goto _test_eof + _test_eof18: cs = 18; goto _test_eof + _test_eof19: cs = 19; goto _test_eof + _test_eof20: cs = 20; goto _test_eof + _test_eof21: cs = 21; goto _test_eof + _test_eof22: cs = 22; goto _test_eof + _test_eof23: cs = 23; goto _test_eof + _test_eof24: cs = 24; goto _test_eof + _test_eof25: cs = 25; goto _test_eof + _test_eof26: cs = 26; goto _test_eof + _test_eof27: cs = 27; goto _test_eof + _test_eof28: cs = 28; goto _test_eof + _test_eof29: cs = 29; goto _test_eof + _test_eof35: cs = 35; goto _test_eof + _test_eof30: cs = 30; goto _test_eof + + _test_eof: {} + if p == eof { + switch cs { + case 31, 34: +//line extract_actions.rl:57 + + switch kind { + case IRI: + return iriText, "", kind, nil + case Blank: + return blankText, "", kind, nil + case Literal: + qual = iriText + if qual == "" { + qual = langText + } + return literalText, qual, kind, nil + default: + return "", "", kind, ErrInvalidTerm + } + + case 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30: +//line extract_actions.rl:74 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return "", "", Invalid, fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return "", "", Invalid, fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return "", "", Invalid, ErrIncompleteTerm + + case 35: +//line extract_actions.rl:26 + + if blank < 0 { + panic("unexpected parser state: blank start not set") + } + blankText = string(data[blank:p]) + kind = Blank + +//line extract_actions.rl:57 + + switch kind { + case IRI: + return iriText, "", kind, nil + case Blank: + return blankText, "", kind, nil + case Literal: + qual = iriText + if qual == "" { + qual = langText + } + return literalText, qual, kind, nil + default: + return "", "", kind, ErrInvalidTerm + } + + case 32, 33: +//line extract_actions.rl:50 + + if lang < 0 { + panic("unexpected parser state: lang start not set") + } + langText = string(data[lang:p]) + +//line extract_actions.rl:57 + + switch kind { + case IRI: + return iriText, "", kind, nil + case Blank: + return blankText, "", kind, nil + case Literal: + qual = iriText + if qual == "" { + qual = langText + } + return literalText, qual, kind, nil + default: + return "", "", kind, ErrInvalidTerm + } + +//line extract.go:1175 + } + } + + _out: {} + } + +//line extract.rl:50 + + return "", "", 0, ErrInvalidTerm +} diff --git a/graph/formats/rdf/extract.rl b/graph/formats/rdf/extract.rl new file mode 100644 index 00000000..d43e1363 --- /dev/null +++ b/graph/formats/rdf/extract.rl @@ -0,0 +1,52 @@ +// Go code generated by go generate gonum.org/v1/gonum/graph/formats/rdf; DO NOT EDIT. + +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "fmt" + "unicode" +) + +%%{ + machine extract; + + include extract "extract_actions.rl"; + + include nquads "nquads.rl"; + + value := ( + IRIREF + | '_:' BLANK_NODE_LABEL >StartBlank %EndBlank + | '"' STRING_LITERAL >StartLiteral %EndLiteral '"' ( '^^' IRIREF | LANGTAG >StartLang %EndLang )? + ) %Return @!Error ; + + write data; +}%% + +func extract(data []rune) (text, qual string, kind Kind, err error) { + var ( + cs, p int + pe = len(data) + eof = pe + + iri = -1 + blank = -1 + literal = -1 + lang = -1 + + iriText string + blankText string + literalText string + langText string + ) + + %%write init; + + %%write exec; + + return "", "", 0, ErrInvalidTerm +} diff --git a/graph/formats/rdf/extract_actions.rl b/graph/formats/rdf/extract_actions.rl new file mode 100644 index 00000000..cf70c5aa --- /dev/null +++ b/graph/formats/rdf/extract_actions.rl @@ -0,0 +1,84 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +%%{ + machine extract; + + action StartIRI { + iri = p + } + + action EndIRI { + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + iriText = unEscape(data[iri:p]) + if kind == Invalid { + kind = IRI + } + } + + action StartBlank { + blank = p + } + + action EndBlank { + if blank < 0 { + panic("unexpected parser state: blank start not set") + } + blankText = string(data[blank:p]) + kind = Blank + } + + action StartLiteral { + literal = p + } + + action EndLiteral { + if literal < 0 { + panic("unexpected parser state: literal start not set") + } + literalText = unEscape(data[literal:p]) + kind = Literal + } + + action StartLang { + lang = p + } + + action EndLang { + if lang < 0 { + panic("unexpected parser state: lang start not set") + } + langText = string(data[lang:p]) + } + + action Return { + switch kind { + case IRI: + return iriText, "", kind, nil + case Blank: + return blankText, "", kind, nil + case Literal: + qual = iriText + if qual == "" { + qual = langText + } + return literalText, qual, kind, nil + default: + return "", "", kind, ErrInvalidTerm + } + } + + action Error { + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return "", "", Invalid, fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalidTerm, data[p], p) + } else { + return "", "", Invalid, fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalidTerm, data[p], p) + } + } + return "", "", Invalid, ErrIncompleteTerm + } +}%% diff --git a/graph/formats/rdf/kind_string.go b/graph/formats/rdf/kind_string.go new file mode 100644 index 00000000..2ba04bab --- /dev/null +++ b/graph/formats/rdf/kind_string.go @@ -0,0 +1,26 @@ +// Code generated by "stringer -type=Kind"; DO NOT EDIT. + +package rdf + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Invalid-0] + _ = x[IRI-1] + _ = x[Literal-2] + _ = x[Blank-3] +} + +const _Kind_name = "InvalidIRILiteralBlank" + +var _Kind_index = [...]uint8{0, 7, 10, 17, 22} + +func (i Kind) String() string { + if i < 0 || i >= Kind(len(_Kind_index)-1) { + return "Kind(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Kind_name[_Kind_index[i]:_Kind_index[i+1]] +} diff --git a/graph/formats/rdf/nquad_tests.tar.gz b/graph/formats/rdf/nquad_tests.tar.gz new file mode 100644 index 00000000..f0414931 Binary files /dev/null and b/graph/formats/rdf/nquad_tests.tar.gz differ diff --git a/graph/formats/rdf/nquads.rl b/graph/formats/rdf/nquads.rl new file mode 100644 index 00000000..e687d6ab --- /dev/null +++ b/graph/formats/rdf/nquads.rl @@ -0,0 +1,83 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Ragel gramar definition derived from http://www.w3.org/TR/n-quads/#sec-grammar. + +%%{ + machine nquads; + + alphtype rune; + + PN_CHARS_BASE = [A-Za-z] + | 0x00c0 .. 0x00d6 + | 0x00d8 .. 0x00f6 + | 0x00f8 .. 0x02ff + | 0x0370 .. 0x037d + | 0x037f .. 0x1fff + | 0x200c .. 0x200d + | 0x2070 .. 0x218f + | 0x2c00 .. 0x2fef + | 0x3001 .. 0xd7ff + | 0xf900 .. 0xfdcf + | 0xfdf0 .. 0xfffd + | 0x10000 .. 0xeffff + ; + + PN_CHARS_U = PN_CHARS_BASE | '_' | ':' ; + + PN_CHARS = PN_CHARS_U + | '-' + | [0-9] + | 0xb7 + | 0x0300 .. 0x036f + | 0x203f .. 0x2040 + ; + + BLANK_NODE_LABEL = (PN_CHARS_U | [0-9]) ((PN_CHARS | '.')* PN_CHARS)? ; + + BLANK_NODE = '_:' BLANK_NODE_LABEL ; + + ECHAR = ('\\' [tbnrf"'\\]) ; + + UCHAR = ('\\u' xdigit {4} + | '\\U' xdigit {8}) + ; + + STRING_LITERAL = ( + 0x00 .. 0x09 + | 0x0b .. 0x0c + | 0x0e .. '!' + | '#' .. '[' + | ']' .. 0x10ffff + | ECHAR + | UCHAR)* + ; + + STRING_LITERAL_QUOTE = '"' STRING_LITERAL '"' ; + + IRI = ( + '!' .. ';' + | '=' + | '?' .. '[' + | ']' + | '_' + | 'a' .. 'z' + | '~' + | 0x80 .. 0x10ffff + | UCHAR)* + ; + + IRIREF = '<' IRI >StartIRI %EndIRI '>' ; + + LANGTAG = '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ; + + whitespace = [ \t] ; + + literal = STRING_LITERAL_QUOTE ('^^' IRIREF | LANGTAG)? ; + + subject = IRIREF | BLANK_NODE ; + predicate = IRIREF ; + object = IRIREF | BLANK_NODE | literal ; + graphLabel = IRIREF | BLANK_NODE ; +}%% diff --git a/graph/formats/rdf/ntriple_tests.tar.gz b/graph/formats/rdf/ntriple_tests.tar.gz new file mode 100644 index 00000000..5e2ba801 Binary files /dev/null and b/graph/formats/rdf/ntriple_tests.tar.gz differ diff --git a/graph/formats/rdf/parse.go b/graph/formats/rdf/parse.go new file mode 100644 index 00000000..4c86d276 --- /dev/null +++ b/graph/formats/rdf/parse.go @@ -0,0 +1,3624 @@ + +//line parse.rl:1 +// Go code generated by go generate gonum.org/v1/gonum/graph/formats/rdf; DO NOT EDIT. + +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "fmt" + "net/url" + "unicode" +) + + +//line parse.go:19 +const nquads_start int = 1 +const nquads_first_final int = 87 +const nquads_error int = 0 + +const nquads_en_statement int = 1 + + +//line parse.rl:31 + + +func parse(data []rune) (Statement, error) { + var ( + cs, p int + pe = len(data) + eof = pe + + subject = -1 + predicate = -1 + object = -1 + label = -1 + iri = -1 + + s Statement + ) + + +//line parse.go:46 + { + cs = nquads_start + } + +//line parse.rl:49 + + +//line parse.go:54 + { + if p == pe { + goto _test_eof + } + switch cs { + case 1: + goto st_case_1 + case 0: + goto st_case_0 + case 2: + goto st_case_2 + case 3: + goto st_case_3 + case 4: + goto st_case_4 + case 5: + goto st_case_5 + case 6: + goto st_case_6 + case 7: + goto st_case_7 + case 8: + goto st_case_8 + case 9: + goto st_case_9 + case 10: + goto st_case_10 + case 11: + goto st_case_11 + case 12: + goto st_case_12 + case 87: + goto st_case_87 + case 88: + goto st_case_88 + case 13: + goto st_case_13 + case 14: + goto st_case_14 + case 15: + goto st_case_15 + case 16: + goto st_case_16 + case 17: + goto st_case_17 + case 18: + goto st_case_18 + case 19: + goto st_case_19 + case 20: + goto st_case_20 + case 21: + goto st_case_21 + case 22: + goto st_case_22 + case 23: + goto st_case_23 + case 24: + goto st_case_24 + case 25: + goto st_case_25 + case 26: + goto st_case_26 + case 27: + goto st_case_27 + case 28: + goto st_case_28 + case 89: + goto st_case_89 + case 29: + goto st_case_29 + case 30: + goto st_case_30 + case 31: + goto st_case_31 + case 32: + goto st_case_32 + case 33: + goto st_case_33 + case 34: + goto st_case_34 + case 35: + goto st_case_35 + case 36: + goto st_case_36 + case 37: + goto st_case_37 + case 38: + goto st_case_38 + case 39: + goto st_case_39 + case 40: + goto st_case_40 + case 41: + goto st_case_41 + case 42: + goto st_case_42 + case 43: + goto st_case_43 + case 44: + goto st_case_44 + case 45: + goto st_case_45 + case 46: + goto st_case_46 + case 47: + goto st_case_47 + case 48: + goto st_case_48 + case 49: + goto st_case_49 + case 50: + goto st_case_50 + case 51: + goto st_case_51 + case 52: + goto st_case_52 + case 53: + goto st_case_53 + case 54: + goto st_case_54 + case 55: + goto st_case_55 + case 56: + goto st_case_56 + case 57: + goto st_case_57 + case 58: + goto st_case_58 + case 59: + goto st_case_59 + case 90: + goto st_case_90 + case 60: + goto st_case_60 + case 61: + goto st_case_61 + case 62: + goto st_case_62 + case 63: + goto st_case_63 + case 91: + goto st_case_91 + case 64: + goto st_case_64 + case 65: + goto st_case_65 + case 66: + goto st_case_66 + case 67: + goto st_case_67 + case 68: + goto st_case_68 + case 69: + goto st_case_69 + case 70: + goto st_case_70 + case 71: + goto st_case_71 + case 72: + goto st_case_72 + case 73: + goto st_case_73 + case 74: + goto st_case_74 + case 75: + goto st_case_75 + case 76: + goto st_case_76 + case 77: + goto st_case_77 + case 78: + goto st_case_78 + case 79: + goto st_case_79 + case 80: + goto st_case_80 + case 81: + goto st_case_81 + case 82: + goto st_case_82 + case 83: + goto st_case_83 + case 84: + goto st_case_84 + case 85: + goto st_case_85 + case 86: + goto st_case_86 + } + goto st_out + st1: + if p++; p == pe { + goto _test_eof1 + } + st_case_1: + switch data[p] { + case 9: + goto st1 + case 32: + goto st1 + case 60: + goto tr2 + case 95: + goto tr3 + } + goto tr0 +tr0: +//line parse_actions.rl:75 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return s, fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalid, data[p], p) + } else { + return s, fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalid, data[p], p) + } + } + return s, ErrIncomplete + + goto st0 +//line parse.go:275 +st_case_0: + st0: + cs = 0 + goto _out +tr2: +//line parse_actions.rl:8 + + subject = p + + goto st2 + st2: + if p++; p == pe { + goto _test_eof2 + } + st_case_2: +//line parse.go:291 + switch data[p] { + case 62: + goto tr5 + case 92: + goto tr6 + case 95: + goto tr4 + case 126: + goto tr4 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto tr4 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto tr4 + } + case data[p] >= 97: + goto tr4 + } + default: + goto tr4 + } + goto tr0 +tr4: +//line parse_actions.rl:24 + + iri = p + + goto st3 + st3: + if p++; p == pe { + goto _test_eof3 + } + st_case_3: +//line parse.go:331 + switch data[p] { + case 62: + goto tr8 + case 92: + goto st74 + case 95: + goto st3 + case 126: + goto st3 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto st3 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto st3 + } + case data[p] >= 97: + goto st3 + } + default: + goto st3 + } + goto tr0 +tr5: +//line parse_actions.rl:24 + + iri = p + +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st4 +tr8: +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st4 + st4: + if p++; p == pe { + goto _test_eof4 + } + st_case_4: +//line parse.go:397 + switch data[p] { + case 9: + goto tr10 + case 32: + goto tr10 + case 60: + goto tr11 + } + goto tr0 +tr10: +//line parse_actions.rl:28 + + if subject < 0 { + panic("unexpected parser state: subject start not set") + } + s.Subject.Value = string(data[subject:p]) + + goto st5 + st5: + if p++; p == pe { + goto _test_eof5 + } + st_case_5: +//line parse.go:421 + switch data[p] { + case 9: + goto st5 + case 32: + goto st5 + case 60: + goto tr13 + } + goto tr0 +tr11: +//line parse_actions.rl:28 + + if subject < 0 { + panic("unexpected parser state: subject start not set") + } + s.Subject.Value = string(data[subject:p]) + +//line parse_actions.rl:12 + + predicate = p + + goto st6 +tr13: +//line parse_actions.rl:12 + + predicate = p + + goto st6 + st6: + if p++; p == pe { + goto _test_eof6 + } + st_case_6: +//line parse.go:455 + switch data[p] { + case 62: + goto tr15 + case 92: + goto tr16 + case 95: + goto tr14 + case 126: + goto tr14 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto tr14 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto tr14 + } + case data[p] >= 97: + goto tr14 + } + default: + goto tr14 + } + goto tr0 +tr14: +//line parse_actions.rl:24 + + iri = p + + goto st7 + st7: + if p++; p == pe { + goto _test_eof7 + } + st_case_7: +//line parse.go:495 + switch data[p] { + case 62: + goto tr18 + case 92: + goto st65 + case 95: + goto st7 + case 126: + goto st7 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto st7 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto st7 + } + case data[p] >= 97: + goto st7 + } + default: + goto st7 + } + goto tr0 +tr15: +//line parse_actions.rl:24 + + iri = p + +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st8 +tr18: +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st8 + st8: + if p++; p == pe { + goto _test_eof8 + } + st_case_8: +//line parse.go:561 + switch data[p] { + case 9: + goto tr20 + case 32: + goto tr20 + case 34: + goto tr21 + case 60: + goto tr22 + case 95: + goto tr23 + } + goto tr0 +tr20: +//line parse_actions.rl:35 + + if predicate < 0 { + panic("unexpected parser state: predicate start not set") + } + s.Predicate.Value = string(data[predicate:p]) + + goto st9 + st9: + if p++; p == pe { + goto _test_eof9 + } + st_case_9: +//line parse.go:589 + switch data[p] { + case 9: + goto st9 + case 32: + goto st9 + case 34: + goto tr25 + case 60: + goto tr26 + case 95: + goto tr27 + } + goto tr0 +tr21: +//line parse_actions.rl:35 + + if predicate < 0 { + panic("unexpected parser state: predicate start not set") + } + s.Predicate.Value = string(data[predicate:p]) + +//line parse_actions.rl:16 + + object = p + + goto st10 +tr25: +//line parse_actions.rl:16 + + object = p + + goto st10 + st10: + if p++; p == pe { + goto _test_eof10 + } + st_case_10: +//line parse.go:627 + switch data[p] { + case 34: + goto st11 + case 92: + goto st48 + } + switch { + case data[p] < 11: + if 0 <= data[p] && data[p] <= 9 { + goto st10 + } + case data[p] > 12: + if 14 <= data[p] && data[p] <= 1114111 { + goto st10 + } + default: + goto st10 + } + goto tr0 + st11: + if p++; p == pe { + goto _test_eof11 + } + st_case_11: + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 46: + goto tr32 + case 60: + goto tr33 + case 64: + goto st30 + case 94: + goto st34 + case 95: + goto tr36 + } + goto tr0 +tr31: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + + goto st12 +tr97: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + +//line parse_actions.rl:49 + + if label < 0 { + panic("unexpected parser state: label start not set") + } + s.Label.Value = string(data[label:p]) + + goto st12 + st12: + if p++; p == pe { + goto _test_eof12 + } + st_case_12: +//line parse.go:699 + switch data[p] { + case 9: + goto st12 + case 32: + goto st12 + case 46: + goto st87 + case 60: + goto tr39 + case 95: + goto tr40 + } + goto tr0 +tr32: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + + goto st87 +tr48: +//line parse_actions.rl:49 + + if label < 0 { + panic("unexpected parser state: label start not set") + } + s.Label.Value = string(data[label:p]) + + goto st87 + st87: + if p++; p == pe { + goto _test_eof87 + } + st_case_87: +//line parse.go:736 + switch data[p] { + case 9: + goto st87 + case 32: + goto st87 + case 35: + goto tr120 + } + goto st0 +tr120: +//line parse_actions.rl:72 + + + goto st88 + st88: + if p++; p == pe { + goto _test_eof88 + } + st_case_88: +//line parse.go:756 + goto st88 +tr33: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + +//line parse_actions.rl:20 + + label = p + + goto st13 +tr39: +//line parse_actions.rl:20 + + label = p + + goto st13 + st13: + if p++; p == pe { + goto _test_eof13 + } + st_case_13: +//line parse.go:782 + switch data[p] { + case 62: + goto tr42 + case 92: + goto tr43 + case 95: + goto tr41 + case 126: + goto tr41 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto tr41 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto tr41 + } + case data[p] >= 97: + goto tr41 + } + default: + goto tr41 + } + goto tr0 +tr41: +//line parse_actions.rl:24 + + iri = p + + goto st14 + st14: + if p++; p == pe { + goto _test_eof14 + } + st_case_14: +//line parse.go:822 + switch data[p] { + case 62: + goto tr45 + case 92: + goto st17 + case 95: + goto st14 + case 126: + goto st14 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto st14 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto st14 + } + case data[p] >= 97: + goto st14 + } + default: + goto st14 + } + goto tr0 +tr42: +//line parse_actions.rl:24 + + iri = p + +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st15 +tr45: +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st15 + st15: + if p++; p == pe { + goto _test_eof15 + } + st_case_15: +//line parse.go:888 + switch data[p] { + case 9: + goto tr47 + case 32: + goto tr47 + case 46: + goto tr48 + } + goto tr0 +tr47: +//line parse_actions.rl:49 + + if label < 0 { + panic("unexpected parser state: label start not set") + } + s.Label.Value = string(data[label:p]) + + goto st16 + st16: + if p++; p == pe { + goto _test_eof16 + } + st_case_16: +//line parse.go:912 + switch data[p] { + case 9: + goto st16 + case 32: + goto st16 + case 46: + goto st87 + } + goto tr0 +tr43: +//line parse_actions.rl:24 + + iri = p + + goto st17 + st17: + if p++; p == pe { + goto _test_eof17 + } + st_case_17: +//line parse.go:933 + switch data[p] { + case 85: + goto st18 + case 117: + goto st22 + } + goto tr0 + st18: + if p++; p == pe { + goto _test_eof18 + } + st_case_18: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st19 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st19 + } + default: + goto st19 + } + goto tr0 + st19: + if p++; p == pe { + goto _test_eof19 + } + st_case_19: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st20 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st20 + } + default: + goto st20 + } + goto tr0 + st20: + if p++; p == pe { + goto _test_eof20 + } + st_case_20: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st21 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st21 + } + default: + goto st21 + } + goto tr0 + st21: + if p++; p == pe { + goto _test_eof21 + } + st_case_21: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st22 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st22 + } + default: + goto st22 + } + goto tr0 + st22: + if p++; p == pe { + goto _test_eof22 + } + st_case_22: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st23 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st23 + } + default: + goto st23 + } + goto tr0 + st23: + if p++; p == pe { + goto _test_eof23 + } + st_case_23: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st24 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st24 + } + default: + goto st24 + } + goto tr0 + st24: + if p++; p == pe { + goto _test_eof24 + } + st_case_24: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st25 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st25 + } + default: + goto st25 + } + goto tr0 + st25: + if p++; p == pe { + goto _test_eof25 + } + st_case_25: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st14 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st14 + } + default: + goto st14 + } + goto tr0 +tr36: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + +//line parse_actions.rl:20 + + label = p + + goto st26 +tr40: +//line parse_actions.rl:20 + + label = p + + goto st26 + st26: + if p++; p == pe { + goto _test_eof26 + } + st_case_26: +//line parse.go:1109 + if data[p] == 58 { + goto st27 + } + goto tr0 + st27: + if p++; p == pe { + goto _test_eof27 + } + st_case_27: + if data[p] == 95 { + goto st28 + } + switch { + case data[p] < 895: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st28 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st28 + } + default: + goto st28 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st28 + } + case data[p] > 767: + if 880 <= data[p] && data[p] <= 893 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + case data[p] > 8191: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8204 <= data[p] && data[p] <= 8205 { + goto st28 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st28 + } + default: + goto st28 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st28 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + goto tr0 + st28: + if p++; p == pe { + goto _test_eof28 + } + st_case_28: + switch data[p] { + case 9: + goto tr47 + case 32: + goto tr47 + case 45: + goto st28 + case 46: + goto tr60 + case 95: + goto st28 + case 183: + goto st28 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st28 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st28 + } + default: + goto st28 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st28 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st28 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st28 + } + default: + goto st28 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st28 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + goto tr0 +tr60: +//line parse_actions.rl:49 + + if label < 0 { + panic("unexpected parser state: label start not set") + } + s.Label.Value = string(data[label:p]) + + goto st89 + st89: + if p++; p == pe { + goto _test_eof89 + } + st_case_89: +//line parse.go:1289 + switch data[p] { + case 9: + goto st87 + case 32: + goto st87 + case 35: + goto tr120 + case 45: + goto st28 + case 46: + goto st29 + case 95: + goto st28 + case 183: + goto st28 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st28 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st28 + } + default: + goto st28 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st28 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st28 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st28 + } + default: + goto st28 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st28 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + goto st0 + st29: + if p++; p == pe { + goto _test_eof29 + } + st_case_29: + switch data[p] { + case 45: + goto st28 + case 46: + goto st29 + case 95: + goto st28 + case 183: + goto st28 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st28 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st28 + } + default: + goto st28 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st28 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st28 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st28 + } + default: + goto st28 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st28 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + default: + goto st28 + } + goto tr0 + st30: + if p++; p == pe { + goto _test_eof30 + } + st_case_30: + switch { + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st31 + } + case data[p] >= 65: + goto st31 + } + goto tr0 + st31: + if p++; p == pe { + goto _test_eof31 + } + st_case_31: + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 45: + goto st32 + case 46: + goto tr32 + case 60: + goto tr33 + case 95: + goto tr36 + } + switch { + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st31 + } + case data[p] >= 65: + goto st31 + } + goto tr0 + st32: + if p++; p == pe { + goto _test_eof32 + } + st_case_32: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st33 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st33 + } + default: + goto st33 + } + goto tr0 + st33: + if p++; p == pe { + goto _test_eof33 + } + st_case_33: + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 45: + goto st32 + case 46: + goto tr32 + case 60: + goto tr33 + case 95: + goto tr36 + } + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st33 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st33 + } + default: + goto st33 + } + goto tr0 + st34: + if p++; p == pe { + goto _test_eof34 + } + st_case_34: + if data[p] == 94 { + goto st35 + } + goto tr0 + st35: + if p++; p == pe { + goto _test_eof35 + } + st_case_35: + if data[p] == 60 { + goto st36 + } + goto tr0 +tr22: +//line parse_actions.rl:35 + + if predicate < 0 { + panic("unexpected parser state: predicate start not set") + } + s.Predicate.Value = string(data[predicate:p]) + +//line parse_actions.rl:16 + + object = p + + goto st36 +tr26: +//line parse_actions.rl:16 + + object = p + + goto st36 + st36: + if p++; p == pe { + goto _test_eof36 + } + st_case_36: +//line parse.go:1589 + switch data[p] { + case 62: + goto tr68 + case 92: + goto tr69 + case 95: + goto tr67 + case 126: + goto tr67 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto tr67 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto tr67 + } + case data[p] >= 97: + goto tr67 + } + default: + goto tr67 + } + goto tr0 +tr67: +//line parse_actions.rl:24 + + iri = p + + goto st37 + st37: + if p++; p == pe { + goto _test_eof37 + } + st_case_37: +//line parse.go:1629 + switch data[p] { + case 62: + goto tr71 + case 92: + goto st39 + case 95: + goto st37 + case 126: + goto st37 + } + switch { + case data[p] < 61: + if 33 <= data[p] && data[p] <= 59 { + goto st37 + } + case data[p] > 93: + switch { + case data[p] > 122: + if 128 <= data[p] && data[p] <= 1114111 { + goto st37 + } + case data[p] >= 97: + goto st37 + } + default: + goto st37 + } + goto tr0 +tr68: +//line parse_actions.rl:24 + + iri = p + +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st38 +tr71: +//line parse_actions.rl:56 + + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + + goto st38 + st38: + if p++; p == pe { + goto _test_eof38 + } + st_case_38: +//line parse.go:1695 + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 46: + goto tr32 + case 60: + goto tr33 + case 95: + goto tr36 + } + goto tr0 +tr69: +//line parse_actions.rl:24 + + iri = p + + goto st39 + st39: + if p++; p == pe { + goto _test_eof39 + } + st_case_39: +//line parse.go:1720 + switch data[p] { + case 85: + goto st40 + case 117: + goto st44 + } + goto tr0 + st40: + if p++; p == pe { + goto _test_eof40 + } + st_case_40: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st41 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st41 + } + default: + goto st41 + } + goto tr0 + st41: + if p++; p == pe { + goto _test_eof41 + } + st_case_41: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st42 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st42 + } + default: + goto st42 + } + goto tr0 + st42: + if p++; p == pe { + goto _test_eof42 + } + st_case_42: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st43 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st43 + } + default: + goto st43 + } + goto tr0 + st43: + if p++; p == pe { + goto _test_eof43 + } + st_case_43: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st44 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st44 + } + default: + goto st44 + } + goto tr0 + st44: + if p++; p == pe { + goto _test_eof44 + } + st_case_44: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st45 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st45 + } + default: + goto st45 + } + goto tr0 + st45: + if p++; p == pe { + goto _test_eof45 + } + st_case_45: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st46 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st46 + } + default: + goto st46 + } + goto tr0 + st46: + if p++; p == pe { + goto _test_eof46 + } + st_case_46: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st47 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st47 + } + default: + goto st47 + } + goto tr0 + st47: + if p++; p == pe { + goto _test_eof47 + } + st_case_47: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st37 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st37 + } + default: + goto st37 + } + goto tr0 + st48: + if p++; p == pe { + goto _test_eof48 + } + st_case_48: + switch data[p] { + case 34: + goto st10 + case 39: + goto st10 + case 85: + goto st49 + case 92: + goto st10 + case 98: + goto st10 + case 102: + goto st10 + case 110: + goto st10 + case 114: + goto st10 + case 116: + goto st10 + case 117: + goto st53 + } + goto tr0 + st49: + if p++; p == pe { + goto _test_eof49 + } + st_case_49: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st50 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st50 + } + default: + goto st50 + } + goto tr0 + st50: + if p++; p == pe { + goto _test_eof50 + } + st_case_50: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st51 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st51 + } + default: + goto st51 + } + goto tr0 + st51: + if p++; p == pe { + goto _test_eof51 + } + st_case_51: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st52 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st52 + } + default: + goto st52 + } + goto tr0 + st52: + if p++; p == pe { + goto _test_eof52 + } + st_case_52: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st53 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st53 + } + default: + goto st53 + } + goto tr0 + st53: + if p++; p == pe { + goto _test_eof53 + } + st_case_53: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st54 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st54 + } + default: + goto st54 + } + goto tr0 + st54: + if p++; p == pe { + goto _test_eof54 + } + st_case_54: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st55 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st55 + } + default: + goto st55 + } + goto tr0 + st55: + if p++; p == pe { + goto _test_eof55 + } + st_case_55: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st56 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st56 + } + default: + goto st56 + } + goto tr0 + st56: + if p++; p == pe { + goto _test_eof56 + } + st_case_56: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st10 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st10 + } + default: + goto st10 + } + goto tr0 +tr23: +//line parse_actions.rl:35 + + if predicate < 0 { + panic("unexpected parser state: predicate start not set") + } + s.Predicate.Value = string(data[predicate:p]) + +//line parse_actions.rl:16 + + object = p + + goto st57 +tr27: +//line parse_actions.rl:16 + + object = p + + goto st57 + st57: + if p++; p == pe { + goto _test_eof57 + } + st_case_57: +//line parse.go:2068 + if data[p] == 58 { + goto st58 + } + goto tr0 + st58: + if p++; p == pe { + goto _test_eof58 + } + st_case_58: + if data[p] == 95 { + goto st59 + } + switch { + case data[p] < 895: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st59 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st59 + } + default: + goto st59 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st59 + } + case data[p] > 767: + if 880 <= data[p] && data[p] <= 893 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + case data[p] > 8191: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8204 <= data[p] && data[p] <= 8205 { + goto st59 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st59 + } + default: + goto st59 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st59 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + goto tr0 + st59: + if p++; p == pe { + goto _test_eof59 + } + st_case_59: + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 45: + goto st59 + case 46: + goto tr91 + case 60: + goto tr33 + case 95: + goto tr92 + case 183: + goto st59 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st59 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st59 + } + default: + goto st59 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st59 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st59 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st59 + } + default: + goto st59 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st59 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + goto tr0 +tr91: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + + goto st90 + st90: + if p++; p == pe { + goto _test_eof90 + } + st_case_90: +//line parse.go:2250 + switch data[p] { + case 9: + goto st87 + case 32: + goto st87 + case 35: + goto tr120 + case 45: + goto st59 + case 46: + goto st60 + case 95: + goto st59 + case 183: + goto st59 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st59 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st59 + } + default: + goto st59 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st59 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st59 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st59 + } + default: + goto st59 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st59 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + goto st0 + st60: + if p++; p == pe { + goto _test_eof60 + } + st_case_60: + switch data[p] { + case 45: + goto st59 + case 46: + goto st60 + case 95: + goto st59 + case 183: + goto st59 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st59 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st59 + } + default: + goto st59 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st59 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st59 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st59 + } + default: + goto st59 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st59 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + goto tr0 +tr92: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + +//line parse_actions.rl:20 + + label = p + + goto st61 + st61: + if p++; p == pe { + goto _test_eof61 + } + st_case_61: +//line parse.go:2434 + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 45: + goto st59 + case 46: + goto tr91 + case 58: + goto st62 + case 60: + goto tr33 + case 95: + goto tr92 + case 183: + goto st59 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st59 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st59 + } + default: + goto st59 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st59 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st59 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st59 + } + default: + goto st59 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st59 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + default: + goto st59 + } + goto tr0 + st62: + if p++; p == pe { + goto _test_eof62 + } + st_case_62: + switch data[p] { + case 9: + goto tr31 + case 32: + goto tr31 + case 45: + goto st59 + case 46: + goto tr91 + case 60: + goto tr33 + case 95: + goto tr96 + case 183: + goto st59 + } + switch { + case data[p] < 895: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st63 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st63 + } + default: + goto st63 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st63 + } + case data[p] > 767: + switch { + case data[p] > 879: + if 880 <= data[p] && data[p] <= 893 { + goto st63 + } + case data[p] >= 768: + goto st59 + } + default: + goto st63 + } + default: + goto st63 + } + case data[p] > 8191: + switch { + case data[p] < 11264: + switch { + case data[p] < 8255: + if 8204 <= data[p] && data[p] <= 8205 { + goto st63 + } + case data[p] > 8256: + if 8304 <= data[p] && data[p] <= 8591 { + goto st63 + } + default: + goto st59 + } + case data[p] > 12271: + switch { + case data[p] < 63744: + if 12289 <= data[p] && data[p] <= 55295 { + goto st63 + } + case data[p] > 64975: + switch { + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st63 + } + case data[p] >= 65008: + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + goto tr0 +tr96: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + +//line parse_actions.rl:20 + + label = p + + goto st63 + st63: + if p++; p == pe { + goto _test_eof63 + } + st_case_63: +//line parse.go:2636 + switch data[p] { + case 9: + goto tr97 + case 32: + goto tr97 + case 45: + goto st63 + case 46: + goto tr98 + case 60: + goto tr33 + case 95: + goto tr96 + case 183: + goto st63 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st63 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st63 + } + default: + goto st63 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st63 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st63 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st63 + } + default: + goto st63 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st63 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + goto tr0 +tr98: +//line parse_actions.rl:42 + + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + +//line parse_actions.rl:49 + + if label < 0 { + panic("unexpected parser state: label start not set") + } + s.Label.Value = string(data[label:p]) + + goto st91 + st91: + if p++; p == pe { + goto _test_eof91 + } + st_case_91: +//line parse.go:2741 + switch data[p] { + case 9: + goto st87 + case 32: + goto st87 + case 35: + goto tr120 + case 45: + goto st63 + case 46: + goto st64 + case 95: + goto st63 + case 183: + goto st63 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st63 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st63 + } + default: + goto st63 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st63 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st63 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st63 + } + default: + goto st63 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st63 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + goto st0 + st64: + if p++; p == pe { + goto _test_eof64 + } + st_case_64: + switch data[p] { + case 45: + goto st63 + case 46: + goto st64 + case 95: + goto st63 + case 183: + goto st63 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st63 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st63 + } + default: + goto st63 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st63 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st63 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st63 + } + default: + goto st63 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st63 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + default: + goto st63 + } + goto tr0 +tr16: +//line parse_actions.rl:24 + + iri = p + + goto st65 + st65: + if p++; p == pe { + goto _test_eof65 + } + st_case_65: +//line parse.go:2918 + switch data[p] { + case 85: + goto st66 + case 117: + goto st70 + } + goto tr0 + st66: + if p++; p == pe { + goto _test_eof66 + } + st_case_66: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st67 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st67 + } + default: + goto st67 + } + goto tr0 + st67: + if p++; p == pe { + goto _test_eof67 + } + st_case_67: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st68 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st68 + } + default: + goto st68 + } + goto tr0 + st68: + if p++; p == pe { + goto _test_eof68 + } + st_case_68: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st69 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st69 + } + default: + goto st69 + } + goto tr0 + st69: + if p++; p == pe { + goto _test_eof69 + } + st_case_69: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st70 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st70 + } + default: + goto st70 + } + goto tr0 + st70: + if p++; p == pe { + goto _test_eof70 + } + st_case_70: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st71 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st71 + } + default: + goto st71 + } + goto tr0 + st71: + if p++; p == pe { + goto _test_eof71 + } + st_case_71: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st72 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st72 + } + default: + goto st72 + } + goto tr0 + st72: + if p++; p == pe { + goto _test_eof72 + } + st_case_72: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st73 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st73 + } + default: + goto st73 + } + goto tr0 + st73: + if p++; p == pe { + goto _test_eof73 + } + st_case_73: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st7 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st7 + } + default: + goto st7 + } + goto tr0 +tr6: +//line parse_actions.rl:24 + + iri = p + + goto st74 + st74: + if p++; p == pe { + goto _test_eof74 + } + st_case_74: +//line parse.go:3081 + switch data[p] { + case 85: + goto st75 + case 117: + goto st79 + } + goto tr0 + st75: + if p++; p == pe { + goto _test_eof75 + } + st_case_75: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st76 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st76 + } + default: + goto st76 + } + goto tr0 + st76: + if p++; p == pe { + goto _test_eof76 + } + st_case_76: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st77 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st77 + } + default: + goto st77 + } + goto tr0 + st77: + if p++; p == pe { + goto _test_eof77 + } + st_case_77: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st78 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st78 + } + default: + goto st78 + } + goto tr0 + st78: + if p++; p == pe { + goto _test_eof78 + } + st_case_78: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st79 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st79 + } + default: + goto st79 + } + goto tr0 + st79: + if p++; p == pe { + goto _test_eof79 + } + st_case_79: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st80 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st80 + } + default: + goto st80 + } + goto tr0 + st80: + if p++; p == pe { + goto _test_eof80 + } + st_case_80: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st81 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st81 + } + default: + goto st81 + } + goto tr0 + st81: + if p++; p == pe { + goto _test_eof81 + } + st_case_81: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st82 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st82 + } + default: + goto st82 + } + goto tr0 + st82: + if p++; p == pe { + goto _test_eof82 + } + st_case_82: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 57 { + goto st3 + } + case data[p] > 70: + if 97 <= data[p] && data[p] <= 102 { + goto st3 + } + default: + goto st3 + } + goto tr0 +tr3: +//line parse_actions.rl:8 + + subject = p + + goto st83 + st83: + if p++; p == pe { + goto _test_eof83 + } + st_case_83: +//line parse.go:3244 + if data[p] == 58 { + goto st84 + } + goto tr0 + st84: + if p++; p == pe { + goto _test_eof84 + } + st_case_84: + if data[p] == 95 { + goto st85 + } + switch { + case data[p] < 895: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st85 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st85 + } + default: + goto st85 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st85 + } + case data[p] > 767: + if 880 <= data[p] && data[p] <= 893 { + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + case data[p] > 8191: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8204 <= data[p] && data[p] <= 8205 { + goto st85 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st85 + } + default: + goto st85 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st85 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + goto tr0 + st85: + if p++; p == pe { + goto _test_eof85 + } + st_case_85: + switch data[p] { + case 9: + goto tr10 + case 32: + goto tr10 + case 45: + goto st85 + case 46: + goto st86 + case 60: + goto tr11 + case 95: + goto st85 + case 183: + goto st85 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st85 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st85 + } + default: + goto st85 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st85 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st85 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st85 + } + default: + goto st85 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st85 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + goto tr0 + st86: + if p++; p == pe { + goto _test_eof86 + } + st_case_86: + switch data[p] { + case 45: + goto st85 + case 46: + goto st86 + case 95: + goto st85 + case 183: + goto st85 + } + switch { + case data[p] < 8204: + switch { + case data[p] < 192: + switch { + case data[p] < 65: + if 48 <= data[p] && data[p] <= 58 { + goto st85 + } + case data[p] > 90: + if 97 <= data[p] && data[p] <= 122 { + goto st85 + } + default: + goto st85 + } + case data[p] > 214: + switch { + case data[p] < 248: + if 216 <= data[p] && data[p] <= 246 { + goto st85 + } + case data[p] > 893: + if 895 <= data[p] && data[p] <= 8191 { + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + case data[p] > 8205: + switch { + case data[p] < 12289: + switch { + case data[p] < 8304: + if 8255 <= data[p] && data[p] <= 8256 { + goto st85 + } + case data[p] > 8591: + if 11264 <= data[p] && data[p] <= 12271 { + goto st85 + } + default: + goto st85 + } + case data[p] > 55295: + switch { + case data[p] < 65008: + if 63744 <= data[p] && data[p] <= 64975 { + goto st85 + } + case data[p] > 65533: + if 65536 <= data[p] && data[p] <= 983039 { + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + default: + goto st85 + } + goto tr0 + st_out: + _test_eof1: cs = 1; goto _test_eof + _test_eof2: cs = 2; goto _test_eof + _test_eof3: cs = 3; goto _test_eof + _test_eof4: cs = 4; goto _test_eof + _test_eof5: cs = 5; goto _test_eof + _test_eof6: cs = 6; goto _test_eof + _test_eof7: cs = 7; goto _test_eof + _test_eof8: cs = 8; goto _test_eof + _test_eof9: cs = 9; goto _test_eof + _test_eof10: cs = 10; goto _test_eof + _test_eof11: cs = 11; goto _test_eof + _test_eof12: cs = 12; goto _test_eof + _test_eof87: cs = 87; goto _test_eof + _test_eof88: cs = 88; goto _test_eof + _test_eof13: cs = 13; goto _test_eof + _test_eof14: cs = 14; goto _test_eof + _test_eof15: cs = 15; goto _test_eof + _test_eof16: cs = 16; goto _test_eof + _test_eof17: cs = 17; goto _test_eof + _test_eof18: cs = 18; goto _test_eof + _test_eof19: cs = 19; goto _test_eof + _test_eof20: cs = 20; goto _test_eof + _test_eof21: cs = 21; goto _test_eof + _test_eof22: cs = 22; goto _test_eof + _test_eof23: cs = 23; goto _test_eof + _test_eof24: cs = 24; goto _test_eof + _test_eof25: cs = 25; goto _test_eof + _test_eof26: cs = 26; goto _test_eof + _test_eof27: cs = 27; goto _test_eof + _test_eof28: cs = 28; goto _test_eof + _test_eof89: cs = 89; goto _test_eof + _test_eof29: cs = 29; goto _test_eof + _test_eof30: cs = 30; goto _test_eof + _test_eof31: cs = 31; goto _test_eof + _test_eof32: cs = 32; goto _test_eof + _test_eof33: cs = 33; goto _test_eof + _test_eof34: cs = 34; goto _test_eof + _test_eof35: cs = 35; goto _test_eof + _test_eof36: cs = 36; goto _test_eof + _test_eof37: cs = 37; goto _test_eof + _test_eof38: cs = 38; goto _test_eof + _test_eof39: cs = 39; goto _test_eof + _test_eof40: cs = 40; goto _test_eof + _test_eof41: cs = 41; goto _test_eof + _test_eof42: cs = 42; goto _test_eof + _test_eof43: cs = 43; goto _test_eof + _test_eof44: cs = 44; goto _test_eof + _test_eof45: cs = 45; goto _test_eof + _test_eof46: cs = 46; goto _test_eof + _test_eof47: cs = 47; goto _test_eof + _test_eof48: cs = 48; goto _test_eof + _test_eof49: cs = 49; goto _test_eof + _test_eof50: cs = 50; goto _test_eof + _test_eof51: cs = 51; goto _test_eof + _test_eof52: cs = 52; goto _test_eof + _test_eof53: cs = 53; goto _test_eof + _test_eof54: cs = 54; goto _test_eof + _test_eof55: cs = 55; goto _test_eof + _test_eof56: cs = 56; goto _test_eof + _test_eof57: cs = 57; goto _test_eof + _test_eof58: cs = 58; goto _test_eof + _test_eof59: cs = 59; goto _test_eof + _test_eof90: cs = 90; goto _test_eof + _test_eof60: cs = 60; goto _test_eof + _test_eof61: cs = 61; goto _test_eof + _test_eof62: cs = 62; goto _test_eof + _test_eof63: cs = 63; goto _test_eof + _test_eof91: cs = 91; goto _test_eof + _test_eof64: cs = 64; goto _test_eof + _test_eof65: cs = 65; goto _test_eof + _test_eof66: cs = 66; goto _test_eof + _test_eof67: cs = 67; goto _test_eof + _test_eof68: cs = 68; goto _test_eof + _test_eof69: cs = 69; goto _test_eof + _test_eof70: cs = 70; goto _test_eof + _test_eof71: cs = 71; goto _test_eof + _test_eof72: cs = 72; goto _test_eof + _test_eof73: cs = 73; goto _test_eof + _test_eof74: cs = 74; goto _test_eof + _test_eof75: cs = 75; goto _test_eof + _test_eof76: cs = 76; goto _test_eof + _test_eof77: cs = 77; goto _test_eof + _test_eof78: cs = 78; goto _test_eof + _test_eof79: cs = 79; goto _test_eof + _test_eof80: cs = 80; goto _test_eof + _test_eof81: cs = 81; goto _test_eof + _test_eof82: cs = 82; goto _test_eof + _test_eof83: cs = 83; goto _test_eof + _test_eof84: cs = 84; goto _test_eof + _test_eof85: cs = 85; goto _test_eof + _test_eof86: cs = 86; goto _test_eof + + _test_eof: {} + if p == eof { + switch cs { + case 88: +//line parse_actions.rl:68 + + return s, nil + + case 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86: +//line parse_actions.rl:75 + + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return s, fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalid, data[p], p) + } else { + return s, fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalid, data[p], p) + } + } + return s, ErrIncomplete + + case 87, 89, 90, 91: +//line parse_actions.rl:72 + + +//line parse_actions.rl:68 + + return s, nil + +//line parse.go:3615 + } + } + + _out: {} + } + +//line parse.rl:51 + + return Statement{}, ErrInvalid +} diff --git a/graph/formats/rdf/parse.rl b/graph/formats/rdf/parse.rl new file mode 100644 index 00000000..7b3f77ef --- /dev/null +++ b/graph/formats/rdf/parse.rl @@ -0,0 +1,53 @@ +// Go code generated by go generate gonum.org/v1/gonum/graph/formats/rdf; DO NOT EDIT. + +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "fmt" + "net/url" + "unicode" +) + +%%{ + machine nquads; + + include "parse_actions.rl"; + + include "nquads.rl"; + + statement := ( + whitespace* subject >StartSubject %SetSubject + whitespace* predicate >StartPredicate %SetPredicate + whitespace* object >StartObject %SetObject + (whitespace* graphLabel >StartLabel %SetLabel)? + whitespace* '.' whitespace* ('#' any*)? >Comment + ) %Return @!Error ; + + write data; +}%% + +func parse(data []rune) (Statement, error) { + var ( + cs, p int + pe = len(data) + eof = pe + + subject = -1 + predicate = -1 + object = -1 + label = -1 + iri = -1 + + s Statement + ) + + %%write init; + + %%write exec; + + return Statement{}, ErrInvalid +} diff --git a/graph/formats/rdf/parse_actions.rl b/graph/formats/rdf/parse_actions.rl new file mode 100644 index 00000000..f41e12d3 --- /dev/null +++ b/graph/formats/rdf/parse_actions.rl @@ -0,0 +1,85 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +%%{ + machine nquads; + + action StartSubject { + subject = p + } + + action StartPredicate { + predicate = p + } + + action StartObject { + object = p + } + + action StartLabel { + label = p + } + + action StartIRI { + iri = p + } + + action SetSubject { + if subject < 0 { + panic("unexpected parser state: subject start not set") + } + s.Subject.Value = string(data[subject:p]) + } + + action SetPredicate { + if predicate < 0 { + panic("unexpected parser state: predicate start not set") + } + s.Predicate.Value = string(data[predicate:p]) + } + + action SetObject { + if object < 0 { + panic("unexpected parser state: object start not set") + } + s.Object.Value = string(data[object:p]) + } + + action SetLabel { + if label < 0 { + panic("unexpected parser state: label start not set") + } + s.Label.Value = string(data[label:p]) + } + + action EndIRI { + if iri < 0 { + panic("unexpected parser state: iri start not set") + } + switch u, err := url.Parse(string(data[iri:p])); { + case err != nil: + return s, err + case !u.IsAbs(): + return s, fmt.Errorf("%w: relative IRI ref %q", ErrInvalid, string(data[iri:p])) + } + } + + action Return { + return s, nil + } + + action Comment { + } + + action Error { + if p < len(data) { + if r := data[p]; r < unicode.MaxASCII { + return s, fmt.Errorf("%w: unexpected rune %q at %d", ErrInvalid, data[p], p) + } else { + return s, fmt.Errorf("%w: unexpected rune %q (\\u%04[2]x) at %d", ErrInvalid, data[p], p) + } + } + return s, ErrIncomplete + } +}%% diff --git a/graph/formats/rdf/rdf.go b/graph/formats/rdf/rdf.go new file mode 100644 index 00000000..63e4ddc3 --- /dev/null +++ b/graph/formats/rdf/rdf.go @@ -0,0 +1,387 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate ragel -Z -G2 parse.rl +//go:generate ragel -Z -G2 extract.rl +//go:generate ragel -Z -G2 check.rl +//go:generate stringer -type=Kind + +package rdf + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "net/url" + "strconv" + "strings" + "unicode" + "unicode/utf8" + + "gonum.org/v1/gonum/graph" +) + +var ( + _ graph.Node = Term{} + _ graph.Edge = (*Statement)(nil) + _ graph.Line = (*Statement)(nil) +) + +var ( + ErrInvalid = errors.New("invalid N-Quad") + ErrIncomplete = errors.New("incomplete N-Quad") + ErrInvalidTerm = errors.New("invalid term") + ErrIncompleteTerm = errors.New("incomplete term") +) + +// Kind represents the kind of an RDF term. +type Kind int + +const ( + // Invalid is an invalid RDF term. + Invalid Kind = iota + + // IRI is the kind of an IRI term. + // https://www.w3.org/TR/n-quads/#sec-iri + IRI + + // Literal is the kind of an RDF literal. + // https://www.w3.org/TR/n-quads/#sec-literals + Literal + + // Blank is the kind of an RDF blank node term. + // https://www.w3.org/TR/n-quads/#BNodes + Blank +) + +// Term is an RDF term. It implements the graph.Node interface. +type Term struct { + // Value is the text value of term. + Value string + + // UID is the unique ID for the term + // in a collection of RDF terms. + UID int64 +} + +// NewBlankTerm returns a Term based on the provided RDF blank node +// label. The label should not include the "_:" prefix. The returned +// Term will not have the UID set. +func NewBlankTerm(label string) (Term, error) { + err := checkLabelText([]rune(label)) + if err != nil { + return Term{}, err + } + return Term{Value: "_:" + label}, nil +} + +// NewIRITerm returns a Term based on the provided IRI which must +// be valid and include a scheme. The returned Term will not have +// the UID set. +func NewIRITerm(iri string) (Term, error) { + err := checkIRIText(iri) + if err != nil { + return Term{}, err + } + return Term{Value: escape("<", iri, ">")}, nil +} + +// NewLiteralTerm returns a Term based on the literal text and an +// optional qualifier which may either be a "@"-prefixed language +// tag or a valid IRI. The text will be escaped if necessary and quoted, +// and if an IRI is given it will be escaped if necessary. The returned +// Term will not have the UID set. +func NewLiteralTerm(text, qual string) (Term, error) { + text = escape(`"`, text, `"`) + if qual == "" { + return Term{Value: text}, nil + } + if strings.HasPrefix(qual, "@") { + err := checkLangText([]byte(qual)) + if err != nil { + return Term{}, err + } + return Term{Value: text + qual}, nil + } + err := checkIRIText(qual) + if err != nil { + return Term{}, err + } + return Term{Value: text + escape("^^<", qual, ">")}, nil +} + +func checkIRIText(iri string) error { + switch u, err := url.Parse(iri); { + case err != nil: + return err + case u.Scheme == "": + return fmt.Errorf("rdf: %w: relative IRI ref %q", ErrInvalidTerm, iri) + default: + return nil + } +} + +// Parts returns the pars of the term and the kind of the term. +// IRI node text is returned as a valid IRI with the quoting angle +// brackets removed and escape sequences interpreted, and blank +// nodes are stripped of the "_:" prefix. +// When the term is a literal, qual will either be empty, an unescaped +// IRI, or an RDF language tag prefixed with an @ symbol. The literal +// text is returned unquoted and unescaped. +func (t Term) Parts() (text, qual string, kind Kind, err error) { + return extract([]rune(t.Value)) +} + +// ID returns the value of the Term's UID field. +func (t Term) ID() int64 { return t.UID } + +// Statement is an RDF statement. It implements the graph.Edge and graph.Line +// interfaces. +type Statement struct { + Subject Term + Predicate Term + Object Term + Label Term +} + +// String returns the RDF 1.1 N-Quad formatted statement. +func (s *Statement) String() string { + if s.Label.Value == "" { + return fmt.Sprintf("%s %s %s .", s.Subject.Value, s.Predicate.Value, s.Object.Value) + } + return fmt.Sprintf("%s %s %s %s .", s.Subject.Value, s.Predicate.Value, s.Object.Value, s.Label.Value) +} + +// From returns the subject of the statement. +func (s *Statement) From() graph.Node { return s.Subject } + +// To returns the object of the statement. +func (s *Statement) To() graph.Node { return s.Object } + +// ID returns the UID of the Predicate field. +func (s *Statement) ID() int64 { return s.Predicate.UID } + +// ReversedEdge returns the receiver unaltered. If there is a semantically +// valid edge reversal operation for the data, the user should implement +// this by wrapping Statement in a type performing that operation. +// See the ReversedLine example for details. +func (s *Statement) ReversedEdge() graph.Edge { return s } + +// ReversedLine returns the receiver unaltered. If there is a semantically +// valid line reversal operation for the data, the user should implement +// this by wrapping Statement in a type performing that operation. +func (s *Statement) ReversedLine() graph.Line { return s } + +// ParseNQuad parses the statement and returns the corresponding Statement. +// All Term UID fields are zero on return. +func ParseNQuad(statement string) (*Statement, error) { + s, err := parse([]rune(statement)) + if err != nil { + return nil, err + } + return &s, err +} + +// Decoder is an RDF stream decoder. Statements returned by calls to the +// Unmarshal method have their Terms' UID fields set so that unique terms +// will have unique IDs and so can be used directly in a graph.Multi, or +// in a graph.Graph if all predicate terms are identical. IDs created by +// the decoder all exist within a single namespace and so Terms can be +// uniquely identified by their UID. Term UIDs are based from 1 to allow +// RDF-aware client graphs to assign ID if no ID has been assigned. +type Decoder struct { + scanner *bufio.Scanner + + strings store + ids map[string]int64 +} + +// NewDecoder returns a new Decoder that takes input from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + scanner: bufio.NewScanner(r), + strings: make(store), + ids: make(map[string]int64), + } +} + +// Reset resets the decoder to use the provided io.Reader, retaining +// the existing Term ID mapping. +func (dec *Decoder) Reset(r io.Reader) { + dec.scanner = bufio.NewScanner(r) + dec.strings = make(store) + if dec.ids == nil { + dec.ids = make(map[string]int64) + } +} + +// Unmarshal returns the next statement from the input stream. +func (dec *Decoder) Unmarshal() (*Statement, error) { + for dec.scanner.Scan() { + data := bytes.TrimSpace(dec.scanner.Bytes()) + if len(data) == 0 || data[0] == '#' { + continue + } + + s, err := ParseNQuad(string(data)) + if err != nil { + return nil, fmt.Errorf("rdf: failed to parse %q: %w", data, err) + } + if s == nil { + continue + } + + s.Subject.Value = dec.strings.intern(s.Subject.Value) + s.Predicate.Value = dec.strings.intern(s.Predicate.Value) + s.Object.Value = dec.strings.intern(s.Object.Value) + s.Subject.UID = dec.idFor(s.Subject.Value) + s.Object.UID = dec.idFor(s.Object.Value) + s.Predicate.UID = dec.idFor(s.Predicate.Value) + if s.Label.Value != "" { + s.Label.Value = dec.strings.intern(s.Label.Value) + s.Label.UID = dec.idFor(s.Label.Value) + } + return s, nil + } + dec.strings = nil + err := dec.scanner.Err() + if err != nil { + return nil, err + } + return nil, io.EOF +} + +func (dec *Decoder) idFor(s string) int64 { + id, ok := dec.ids[s] + if ok { + return id + } + id = int64(len(dec.ids)) + 1 + dec.ids[s] = id + return id +} + +// Terms returns the mapping between terms and graph node IDs constructed +// during decoding the RDF statement stream. +func (dec *Decoder) Terms() map[string]int64 { + return dec.ids +} + +// store is a string internment implementation. +type store map[string]string + +// intern returns an interned version of the parameter. +func (is store) intern(s string) string { + if s == "" { + return "" + } + + if len(s) < 2 || len(s) > 512 { + // Not enough benefit on average with real data. + return s + } + + t, ok := is[s] + if ok { + return t + } + is[s] = s + return s +} + +func escape(lq, s, rq string) string { + var buf strings.Builder + if lq != "" { + buf.WriteString(lq) + } + for _, r := range s { + var c byte + switch r { + case '\n': + c = 'n' + case '\r': + c = 'r' + case '"', '\\': + c = byte(r) + default: + const hex = "0123456789abcdef" + switch { + case r <= unicode.MaxASCII || strconv.IsPrint(r): + buf.WriteRune(r) + case r > utf8.MaxRune: + r = 0xFFFD + fallthrough + case r < 0x10000: + buf.WriteString("\\u") + for s := 12; s >= 0; s -= 4 { + buf.WriteByte(hex[r>>uint(s)&0xf]) + } + default: + buf.WriteString("\\U") + for s := 28; s >= 0; s -= 4 { + buf.WriteByte(hex[r>>uint(s)&0xf]) + } + } + continue + } + buf.Write([]byte{'\\', c}) + } + if rq != "" { + buf.WriteString(rq) + } + return buf.String() +} + +func unEscape(r []rune) string { + var buf strings.Builder + for i := 0; i < len(r); { + switch r[i] { + case '\\': + i++ + var c byte + switch r[i] { + case 't': + c = '\t' + case 'b': + c = '\b' + case 'n': + c = '\n' + case 'r': + c = '\r' + case 'f': + c = '\f' + case '"': + c = '"' + case '\\': + c = '\\' + case '\'': + c = '\'' + case 'u': + rc, err := strconv.ParseInt(string(r[i+1:i+5]), 16, 32) + if err != nil { + panic(fmt.Errorf("internal parser error: %w", err)) + } + buf.WriteRune(rune(rc)) + i += 5 + continue + case 'U': + rc, err := strconv.ParseInt(string(r[i+1:i+9]), 16, 32) + if err != nil { + panic(fmt.Errorf("internal parser error: %w", err)) + } + buf.WriteRune(rune(rc)) + i += 9 + continue + } + buf.WriteByte(c) + default: + buf.WriteRune(r[i]) + } + i++ + } + + return buf.String() +} diff --git a/graph/formats/rdf/rdf_example_test.go b/graph/formats/rdf/rdf_example_test.go new file mode 100644 index 00000000..d5226c90 --- /dev/null +++ b/graph/formats/rdf/rdf_example_test.go @@ -0,0 +1,115 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf_test + +import ( + "fmt" + "log" + "os" + "strings" + "text/tabwriter" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/encoding/dot" + "gonum.org/v1/gonum/graph/formats/rdf" + "gonum.org/v1/gonum/graph/multi" +) + +// dotNode implements graph.Node and dot.Node to allow the +// RDF term value to be given to the DOT encoder. +type dotNode struct { + rdf.Term +} + +func (n dotNode) DOTID() string { return n.Term.Value } + +// dotLine implements graph.Line and encoding.Attributer to +// allow the line's RDF term value to be given to the DOT +// encoder and for the nodes to be shimmed to the dotNode +// type. +// +// Because the graph here is directed and we are not performing +// any line reversals, it is safe not to implement the +// ReversedLine method on dotLine; it will never be called. +type dotLine struct { + *rdf.Statement +} + +func (l dotLine) From() graph.Node { return dotNode{l.Subject} } +func (l dotLine) To() graph.Node { return dotNode{l.Object} } + +func (l dotLine) Attributes() []encoding.Attribute { + return []encoding.Attribute{{Key: "label", Value: l.Predicate.Value}} +} + +func Example_graph() { + const statements = ` +_:alice _:bob . +_:alice "Alice" . +_:alice "Smith" . +_:bob _:alice . +_:bob "Bob" . +_:bob "Smith" . +` + + // Decode the statement stream and insert the lines into a multigraph. + g := multi.NewDirectedGraph() + dec := rdf.NewDecoder(strings.NewReader(statements)) + for { + l, err := dec.Unmarshal() + if err != nil { + break + } + + // Wrap the line with a shim type to allow the RDF values + // to be passed to the DOT marshaling routine. + g.SetLine(dotLine{l}) + } + + // Marshal the graph into DOT. + b, err := dot.MarshalMulti(g, "smiths", "", "\t") + if err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n\n", b) + + // Get the ID look-up table. + w := tabwriter.NewWriter(os.Stdout, 0, 4, 1, ' ', 0) + fmt.Fprintln(w, "Term\tID") + for t, id := range dec.Terms() { + fmt.Fprintf(w, "%s\t%d\n", t, id) + } + w.Flush() + + // Unordered output: + // + // digraph smiths { + // // Node definitions. + // "_:alice"; + // "_:bob"; + // "Alice"; + // "Smith"; + // "Bob"; + // + // // Edge definitions. + // "_:alice" -> "_:bob" [label=]; + // "_:alice" -> "Alice" [label=]; + // "_:alice" -> "Smith" [label=]; + // "_:bob" -> "_:alice" [label=]; + // "_:bob" -> "Smith" [label=]; + // "_:bob" -> "Bob" [label=]; + // } + // + // Term ID + // _:alice 1 + // _:bob 2 + // 3 + // "Alice" 4 + // 5 + // "Smith" 6 + // 7 + // "Bob" 8 +} diff --git a/graph/formats/rdf/rdf_line_example_test.go b/graph/formats/rdf/rdf_line_example_test.go new file mode 100644 index 00000000..19d08ba7 --- /dev/null +++ b/graph/formats/rdf/rdf_line_example_test.go @@ -0,0 +1,200 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf_test + +import ( + "fmt" + "log" + "strings" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/encoding/dot" + "gonum.org/v1/gonum/graph/formats/rdf" + "gonum.org/v1/gonum/graph/multi" +) + +// foodNode implements graph.Node, dot.Node and encoding.Attributer +// to allow the RDF term value to be given to the DOT encoder. +type foodNode struct { + rdf.Term +} + +func (n foodNode) DOTID() string { + text, _, kind, err := n.Term.Parts() + if err != nil { + return fmt.Sprintf("error:%s", n.Term.Value) + } + switch kind { + case rdf.Blank: + return n.Term.Value + case rdf.IRI: + return text + case rdf.Literal: + return fmt.Sprintf("%q", text) + default: + return fmt.Sprintf("invalid:%s", n.Term.Value) + } +} + +func (n foodNode) Attributes() []encoding.Attribute { + _, qual, _, err := n.Term.Parts() + if err != nil { + return []encoding.Attribute{{Key: "error", Value: err.Error()}} + } + if qual == "" { + return nil + } + parts := strings.Split(qual, ":") + return []encoding.Attribute{{Key: parts[0], Value: parts[1]}} +} + +// foodLine implements graph.Line and encoding.Attributer to +// allow the line's RDF term value to be given to the DOT +// encoder and for the nodes to be shimmed to the foodNode +// type. +// +// It also implements line reversal for the semantics of +// a food web with some taxonomic information. +type foodLine struct { + *rdf.Statement +} + +func (l foodLine) From() graph.Node { return foodNode{l.Subject} } +func (l foodLine) To() graph.Node { return foodNode{l.Object} } +func (l foodLine) ReversedLine() graph.Line { + if l.Predicate.Value == "" { + // This should remain unreversed, so return as is. + return l + } + s := *l.Statement + // Reverse the line end points. + s.Subject, s.Object = s.Object, s.Subject + // Invert the semantics of the predicate. + switch s.Predicate.Value { + case "": + s.Predicate.Value = "" + case "": + s.Predicate.Value = "" + case "": + s.Predicate.Value = "" + case "": + s.Predicate.Value = "" + default: + panic("invalid predicate") + } + // All IDs returned by the RDF parser are positive, so + // sign reverse the edge ID to avoid any collisions. + s.Predicate.UID *= -1 + return foodLine{&s} +} + +func (l foodLine) Attributes() []encoding.Attribute { + text, _, _, err := l.Predicate.Parts() + if err != nil { + return []encoding.Attribute{{Key: "error", Value: err.Error()}} + } + parts := strings.Split(text, ":") + return []encoding.Attribute{{Key: parts[0], Value: parts[1]}} +} + +// expand copies src into dst, adding the reversal of each line if it is +// distinct. +func expand(dst, src *multi.DirectedGraph) { + it := src.Edges() + for it.Next() { + lit := it.Edge().(multi.Edge) + for lit.Next() { + l := lit.Line() + r := l.ReversedLine() + dst.SetLine(l) + if l == r { + continue + } + dst.SetLine(r) + } + } +} + +func ExampleStatement_ReversedLine() { + const statements = ` +_:wolf _:animal . +_:wolf "Wolf"^^ . +_:wolf "Canis lupus"^^ . +_:wolf _:sheep . +_:sheep _:animal . +_:sheep "Sheep"^^ . +_:sheep "Ovis aries"^^ . +_:sheep _:grass . +_:grass _:plant . +_:grass "Grass"^^ . +_:grass "Lolium perenne"^^ . +_:grass "Festuca rubra"^^ . +_:grass "Poa pratensis"^^ . +` + + // Decode the statement stream and insert the lines into a multigraph. + g := multi.NewDirectedGraph() + dec := rdf.NewDecoder(strings.NewReader(statements)) + for { + l, err := dec.Unmarshal() + if err != nil { + break + } + + // Wrap the line with a shim type to allow the RDF values + // to be passed to the DOT marshaling routine. + g.SetLine(foodLine{l}) + } + + h := multi.NewDirectedGraph() + expand(h, g) + + // Marshal the graph into DOT. + b, err := dot.MarshalMulti(h, "food web", "", "\t") + if err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n\n", b) + + // Output: + // + // digraph "food web" { + // // Node definitions. + // "_:wolf"; + // "_:animal"; + // "Wolf" [tax=common]; + // "Canis lupus" [tax=binomial]; + // "_:sheep"; + // "Sheep" [tax=common]; + // "Ovis aries" [tax=binomial]; + // "_:grass"; + // "_:plant"; + // "Grass" [tax=common]; + // "Lolium perenne" [tax=binomial]; + // "Festuca rubra" [tax=binomial]; + // "Poa pratensis" [tax=binomial]; + // + // // Edge definitions. + // "_:wolf" -> "_:animal" [tax="is-a"]; + // "_:wolf" -> "Wolf" [tax=is]; + // "_:wolf" -> "Canis lupus" [tax=is]; + // "_:wolf" -> "_:sheep" [eco=eats]; + // "_:animal" -> "_:wolf" [tax=includes]; + // "_:animal" -> "_:sheep" [tax=includes]; + // "_:sheep" -> "_:wolf" [eco="eaten-by"]; + // "_:sheep" -> "_:animal" [tax="is-a"]; + // "_:sheep" -> "Sheep" [tax=is]; + // "_:sheep" -> "Ovis aries" [tax=is]; + // "_:sheep" -> "_:grass" [eco=eats]; + // "_:grass" -> "_:sheep" [eco="eaten-by"]; + // "_:grass" -> "_:plant" [tax="is-a"]; + // "_:grass" -> "Grass" [tax=is]; + // "_:grass" -> "Lolium perenne" [tax=is]; + // "_:grass" -> "Festuca rubra" [tax=is]; + // "_:grass" -> "Poa pratensis" [tax=is]; + // "_:plant" -> "_:grass" [tax=includes]; + // } +} diff --git a/graph/formats/rdf/rdf_test.go b/graph/formats/rdf/rdf_test.go new file mode 100644 index 00000000..9ff749df --- /dev/null +++ b/graph/formats/rdf/rdf_test.go @@ -0,0 +1,182 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rdf + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "os" + "path/filepath" + "reflect" + "strings" + "testing" +) + +func TestRDFWorkingGroupSuite(t *testing.T) { + for _, file := range []string{ + "ntriple_tests.tar.gz", + "nquad_tests.tar.gz", + } { + suite, err := os.Open(file) + if err != nil { + t.Fatalf("Failed to open test suite in %q: %v", file, err) + } + defer suite.Close() + + r, err := gzip.NewReader(suite) + if err != nil { + t.Fatalf("Failed to uncompress test suite in %q: %v", file, err) + } + + tr := tar.NewReader(r) + for { + h, err := tr.Next() + if err != nil { + if err == io.EOF { + break + } + t.Fatalf("Unexpected error while reading suite archive: %v", err) + } + + h.Name = filepath.Base(h.Name) + if filepath.Ext(h.Name) != ".nt" && filepath.Ext(h.Name) != ".nq" { + continue + } + if _, ok := testSuite[h.Name]; !ok { + t.Errorf("Missing test suite item %q", h.Name) + continue + } + + isBad := strings.Contains(h.Name, "bad") + + var got []statement + dec := NewDecoder(tr) + for i := 0; ; i++ { + s, err := dec.Unmarshal() + if err == io.EOF { + break + } + gotBad := err != nil + if gotBad != isBad { + t.Errorf("Unexpected error return for test suite item %q, got: %v", h.Name, err) + } + + var subj, pred, obj, lab term + if s != nil { + subj.text, subj.qual, subj.kind, _ = s.Subject.Parts() + pred.text, pred.qual, pred.kind, _ = s.Predicate.Parts() + obj.text, obj.qual, obj.kind, _ = s.Object.Parts() + lab.text, lab.qual, lab.kind, _ = s.Label.Parts() + if lab.text == "" { + lab = term{} + } + got = append(got, statement{testSuite[h.Name][i].input, subj, pred, obj, lab}) + } + + if !gotBad { + _, err = ParseNQuad(s.String()) + if err != nil { + t.Errorf("Unexpected error return for valid statement in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err) + } + + st, err := termFor(subj.text, subj.qual, subj.kind) + if err != nil { + t.Errorf("Unexpected error return for valid subject in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err) + } + pt, err := termFor(pred.text, pred.qual, pred.kind) + if err != nil { + t.Errorf("Unexpected error return for valid predicate in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err) + } + ot, err := termFor(obj.text, obj.qual, obj.kind) + if err != nil { + t.Errorf("Unexpected error return for valid object in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err) + } + lt, err := termFor(lab.text, lab.qual, lab.kind) + if err != nil { + t.Errorf("Unexpected error return for valid label in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err) + } + + // We can't check that we recreate the original from the test suite + // due to escaping, but we can check for a second pass through the + // round-trip. + c := &Statement{Subject: st, Predicate: pt, Object: ot, Label: lt} + pc, err := ParseNQuad(c.String()) + if err != nil { + t.Errorf("Unexpected error return for reconstructed statement in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err) + } + if !reflect.DeepEqual(c, pc) { + t.Errorf("Unexpected reconstruction:\norig: %#v\ncons: %#v\nparsed:%#v", s, c, pc) + } + } + } + + if !reflect.DeepEqual(testSuite[h.Name], got) { + t.Errorf("Unexpected result for test suite item %q", h.Name) + } + } + } +} + +func termFor(text, qual string, kind Kind) (Term, error) { + switch kind { + case Invalid: + return Term{}, nil + case Blank: + return NewBlankTerm(text) + case IRI: + return NewIRITerm(text) + case Literal: + return NewLiteralTerm(text, qual) + default: + panic(fmt.Sprintf("bad test kind=%d", kind)) + } +} + +var escapeSequenceTests = []struct { + escaped string + unEscaped string + canRoundTrip bool +}{ + {escaped: `plain text!`, unEscaped: "plain text!", canRoundTrip: true}, + {escaped: `\t`, unEscaped: "\t", canRoundTrip: false}, + {escaped: `\b`, unEscaped: "\b", canRoundTrip: false}, + {escaped: `\n`, unEscaped: "\n", canRoundTrip: true}, + {escaped: `\r`, unEscaped: "\r", canRoundTrip: true}, + {escaped: `\f`, unEscaped: "\f", canRoundTrip: false}, + {escaped: `\\`, unEscaped: "\\", canRoundTrip: true}, + {escaped: `\u0080`, unEscaped: "\u0080", canRoundTrip: true}, + {escaped: `\U00000080`, unEscaped: "\u0080", canRoundTrip: false}, + {escaped: `\t\b\n\r\f\"'\\`, unEscaped: "\t\b\n\r\f\"'\\", canRoundTrip: false}, + + {escaped: `\t\u0080`, unEscaped: "\t\u0080", canRoundTrip: false}, + {escaped: `\b\U00000080`, unEscaped: "\b\u0080", canRoundTrip: false}, + {escaped: `\u0080\n`, unEscaped: "\u0080\n", canRoundTrip: true}, + {escaped: `\U00000080\r`, unEscaped: "\u0080\r", canRoundTrip: false}, + {escaped: `\u00b7\f\U000000b7`, unEscaped: "·\f·", canRoundTrip: false}, + {escaped: `\U000000b7\\\u00b7`, unEscaped: "·\\·", canRoundTrip: false}, + {escaped: `\U00010105\\\U00010106`, unEscaped: "\U00010105\\\U00010106", canRoundTrip: true}, +} + +func TestUnescape(t *testing.T) { + for _, test := range escapeSequenceTests { + got := unEscape([]rune(test.escaped)) + if got != test.unEscaped { + t.Errorf("Failed to properly unescape %q, got:%q want:%q", test.escaped, got, test.unEscaped) + } + + if test.canRoundTrip { + got = escape("", test.unEscaped, "") + if got != test.escaped { + t.Errorf("Failed to properly escape %q, got:%q want:%q", test.unEscaped, got, test.escaped) + } + got = escape(`"`, test.unEscaped, `"`) + if got != `"`+test.escaped+`"` { + t.Errorf("Failed to properly escape %q quoted, got:%q want:%q", test.unEscaped, got, `"`+test.escaped+`"`) + } + } + } +} diff --git a/graph/formats/rdf/test_suite_test.go b/graph/formats/rdf/test_suite_test.go new file mode 100644 index 00000000..90415420 --- /dev/null +++ b/graph/formats/rdf/test_suite_test.go @@ -0,0 +1,1325 @@ +// Copyright ©2020 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright © 2008 World Wide Web Consortium, (MIT, ERCIM, Keio, Beihang) +// and others. All Rights Reserved. +// http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +// Used under https://www.w3.org/Consortium/Legal/2008/03-bsd-license. + +package rdf + +type statement struct { + input string + + subject, predicate, object, label term +} + +type term struct { + text string + qual string + kind Kind +} + +// Test suite values were extracted from the test case archives in this directory. +// The archives were obtained from https://w3c.github.io/rdf-tests/ntriples/ and +// https://w3c.github.io/rdf-tests/nquads/. +var testSuite = map[string][]statement{ + "comment_following_triple.nq": { + { + input: " . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + { + input: " _:o . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Blank}, + }, + { + input: " \"o\" . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + }, + { + input: " \"o\"^^ . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "http://example/dt", kind: Literal}, + }, + { + input: " \"o\"@en . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "@en", kind: Literal}, + }, + }, + "comment_following_triple.nt": { + { + input: " . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + { + input: " _:o . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Blank}, + }, + { + input: " \"o\" . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + }, + { + input: " \"o\"^^ . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "http://example/dt", kind: Literal}, + }, + { + input: " \"o\"@en . # comment", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "@en", kind: Literal}, + }, + }, + "langtagged_string.nq": { + { + input: " \"chat\"@en .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "chat", qual: "@en", kind: Literal}, + }, + }, + "langtagged_string.nt": { + { + input: " \"chat\"@en .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "chat", qual: "@en", kind: Literal}, + }, + }, + "lantag_with_subtag.nq": { + { + input: " \"Cheers\"@en-UK .", + subject: term{text: "http://example.org/ex#a", kind: IRI}, + predicate: term{text: "http://example.org/ex#b", kind: IRI}, + object: term{text: "Cheers", qual: "@en-UK", kind: Literal}, + }, + }, + "lantag_with_subtag.nt": { + { + input: " \"Cheers\"@en-UK .", + subject: term{text: "http://example.org/ex#a", kind: IRI}, + predicate: term{text: "http://example.org/ex#b", kind: IRI}, + object: term{text: "Cheers", qual: "@en-UK", kind: Literal}, + }, + }, + "literal.nq": { + { + input: " \"x\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x", kind: Literal}, + }, + }, + "literal.nt": { + { + input: " \"x\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x", kind: Literal}, + }, + }, + "literal_all_controls.nq": { + { + input: " \"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\u0008\\t\\u000B\\u000C\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\v\f\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", kind: Literal}, + }, + }, + "literal_all_controls.nt": { + { + input: " \"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\u0008\\t\\u000B\\u000C\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\v\f\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", kind: Literal}, + }, + }, + "literal_all_punctuation.nq": { + { + input: " \" !\\\"#$%&():;<=>?@[]^_`{|}~\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: " !\"#$%&():;<=>?@[]^_`{|}~", kind: Literal}, + }, + }, + "literal_all_punctuation.nt": { + { + input: " \" !\\\"#$%&():;<=>?@[]^_`{|}~\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: " !\"#$%&():;<=>?@[]^_`{|}~", kind: Literal}, + }, + }, + "literal_ascii_boundaries.nq": { + { + input: " \"\x00\t\v\f\x0e&([]\u007f\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\x00\t\v\f\x0e&([]\u007f", kind: Literal}, + }, + }, + "literal_ascii_boundaries.nt": { + { + input: " \"\x00\t\v\f\x0e&([]\u007f\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\x00\t\v\f\x0e&([]\u007f", kind: Literal}, + }, + }, + "literal_false.nq": { + { + input: " \"false\"^^ .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "false", qual: "http://www.w3.org/2001/XMLSchema#boolean", kind: Literal}, + }, + }, + "literal_false.nt": { + { + input: " \"false\"^^ .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "false", qual: "http://www.w3.org/2001/XMLSchema#boolean", kind: Literal}, + }, + }, + "literal_true.nq": { + { + input: " \"true\"^^ .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "true", qual: "http://www.w3.org/2001/XMLSchema#boolean", kind: Literal}, + }, + }, + "literal_true.nt": { + { + input: " \"true\"^^ .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "true", qual: "http://www.w3.org/2001/XMLSchema#boolean", kind: Literal}, + }, + }, + "literal_with_2_dquotes.nq": { + { + input: " \"x\\\"\\\"y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x\"\"y", kind: Literal}, + }, + }, + "literal_with_2_dquotes.nt": { + { + input: " \"x\\\"\\\"y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x\"\"y", kind: Literal}, + }, + }, + "literal_with_2_squotes.nt": { + { + input: " \"x''y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x''y", kind: Literal}, + }, + }, + "literal_with_2_squotes.nq": { + { + input: " \"x''y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x''y", kind: Literal}, + }, + }, + "literal_with_BACKSPACE.nq": { + { + input: " \"\\b\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\b", kind: Literal}, + }, + }, + "literal_with_BACKSPACE.nt": { + { + input: " \"\\b\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\b", kind: Literal}, + }, + }, + "literal_with_CARRIAGE_RETURN.nq": { + { + input: " \"\\r\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\r", kind: Literal}, + }, + }, + "literal_with_CARRIAGE_RETURN.nt": { + { + input: " \"\\r\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\r", kind: Literal}, + }, + }, + "literal_with_CHARACTER_TABULATION.nq": { + { + input: " \"\\t\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\t", kind: Literal}, + }, + }, + "literal_with_CHARACTER_TABULATION.nt": { + { + input: " \"\\t\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\t", kind: Literal}, + }, + }, + "literal_with_FORM_FEED.nq": { + { + input: " \"\\f\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\f", kind: Literal}, + }, + }, + "literal_with_FORM_FEED.nt": { + { + input: " \"\\f\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\f", kind: Literal}, + }, + }, + "literal_with_LINE_FEED.nq": { + { + input: " \"\\n\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\n", kind: Literal}, + }, + }, + "literal_with_LINE_FEED.nt": { + { + input: " \"\\n\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\n", kind: Literal}, + }, + }, + "literal_with_REVERSE_SOLIDUS.nq": { + { + input: " \"\\\\\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\\", kind: Literal}, + }, + }, + "literal_with_REVERSE_SOLIDUS.nt": { + { + input: " \"\\\\\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\\", kind: Literal}, + }, + }, + "literal_with_REVERSE_SOLIDUS2.nq": { + { + input: " \"test-\\\\\" .", + subject: term{text: "http://example.org/ns#s", kind: IRI}, + predicate: term{text: "http://example.org/ns#p1", kind: IRI}, + object: term{text: "test-\\", kind: Literal}, + }, + }, + "literal_with_REVERSE_SOLIDUS2.nt": { + { + input: " \"test-\\\\\" .", + subject: term{text: "http://example.org/ns#s", kind: IRI}, + predicate: term{text: "http://example.org/ns#p1", kind: IRI}, + object: term{text: "test-\\", kind: Literal}, + }, + }, + "literal_with_UTF8_boundaries.nq": { + { + input: " \"\u0080߿ࠀ\u0fffက쿿퀀\ud7ff\ue000�𐀀\U0003fffd\U00040000\U000ffffd\U00100000\U0010fffd\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\u0080߿ࠀ\u0fffက쿿퀀\ud7ff\ue000�𐀀\U0003fffd\U00040000\U000ffffd\U00100000\U0010fffd", kind: Literal}, + }, + }, + "literal_with_UTF8_boundaries.nt": { + { + input: " \"\u0080߿ࠀ\u0fffက쿿퀀\ud7ff\ue000�𐀀\U0003fffd\U00040000\U000ffffd\U00100000\U0010fffd\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "\u0080߿ࠀ\u0fffက쿿퀀\ud7ff\ue000�𐀀\U0003fffd\U00040000\U000ffffd\U00100000\U0010fffd", kind: Literal}, + }, + }, + "literal_with_dquote.nq": { + { + input: " \"x\\\"y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x\"y", kind: Literal}, + }, + }, + "literal_with_dquote.nt": { + { + input: " \"x\\\"y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x\"y", kind: Literal}, + }, + }, + "literal_with_numeric_escape4.nq": { + { + input: " \"\\u006F\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + }, + }, + "literal_with_numeric_escape4.nt": { + { + input: " \"\\u006F\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + }, + }, + "literal_with_numeric_escape8.nq": { + { + input: " \"\\U0000006F\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + }, + }, + "literal_with_numeric_escape8.nt": { + { + input: " \"\\U0000006F\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + }, + }, + "literal_with_squote.nq": { + { + input: " \"x'y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x'y", kind: Literal}, + }, + }, + "literal_with_squote.nt": { + { + input: " \"x'y\" .", + subject: term{text: "http://a.example/s", kind: IRI}, + predicate: term{text: "http://a.example/p", kind: IRI}, + object: term{text: "x'y", kind: Literal}, + }, + }, + "minimal_whitespace.nq": { + { + input: ".", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + { + input: "\"Alice\".", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "Alice", kind: Literal}, + }, + { + input: "_:o.", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Blank}, + }, + { + input: "_:s.", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + { + input: "_:s\"Alice\".", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "Alice", kind: Literal}, + }, + { + input: "_:s_:bnode1.", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "bnode1", kind: Blank}, + }, + }, + "minimal_whitespace.nt": { + { + input: ".", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + { + input: "\"Alice\".", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "Alice", kind: Literal}, + }, + { + input: "_:o.", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Blank}, + }, + { + input: "_:s.", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + { + input: "_:s\"Alice\".", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "Alice", kind: Literal}, + }, + { + input: "_:s_:bnode1.", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "bnode1", kind: Blank}, + }, + }, + "nq-syntax-bnode-01.nq": { + { + input: " _:g .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + label: term{text: "g", kind: Blank}, + }, + }, + "nq-syntax-bnode-02.nq": { + { + input: "_:s _:g .", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + label: term{text: "g", kind: Blank}, + }, + }, + "nq-syntax-bnode-03.nq": { + { + input: " _:o _:g .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Blank}, + label: term{text: "g", kind: Blank}, + }, + }, + "nq-syntax-bnode-04.nq": { + { + input: " \"o\" _:g .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + label: term{text: "g", kind: Blank}, + }, + }, + "nq-syntax-bnode-05.nq": { + { + input: " \"o\"@en _:g .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "@en", kind: Literal}, + label: term{text: "g", kind: Blank}, + }, + }, + "nq-syntax-bnode-06.nq": { + { + input: " \"o\"^^ _:g .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "http://www.w3.org/2001/XMLSchema#string", kind: Literal}, + label: term{text: "g", kind: Blank}, + }, + }, + "nq-syntax-uri-01.nq": { + { + input: " .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + label: term{text: "http://example/g", kind: IRI}, + }, + }, + "nq-syntax-uri-02.nq": { + { + input: "_:s .", + subject: term{text: "s", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + label: term{text: "http://example/g", kind: IRI}, + }, + }, + "nq-syntax-uri-03.nq": { + { + input: " _:o .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Blank}, + label: term{text: "http://example/g", kind: IRI}, + }, + }, + "nq-syntax-uri-04.nq": { + { + input: " \"o\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", kind: Literal}, + label: term{text: "http://example/g", kind: IRI}, + }, + }, + "nq-syntax-uri-05.nq": { + { + input: " \"o\"@en .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "@en", kind: Literal}, + label: term{text: "http://example/g", kind: IRI}, + }, + }, + "nq-syntax-uri-06.nq": { + { + input: " \"o\"^^ .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "o", qual: "http://www.w3.org/2001/XMLSchema#string", kind: Literal}, + label: term{text: "http://example/g", kind: IRI}, + }, + }, + "nt-syntax-bnode-01.nq": { + { + input: "_:a .", + subject: term{text: "a", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-bnode-01.nt": { + { + input: "_:a .", + subject: term{text: "a", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-bnode-02.nq": { + { + input: " _:a .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a", kind: Blank}, + }, + { + input: "_:a .", + subject: term{text: "a", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-bnode-02.nt": { + { + input: " _:a .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a", kind: Blank}, + }, + { + input: "_:a .", + subject: term{text: "a", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-bnode-03.nq": { + { + input: " _:1a .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "1a", kind: Blank}, + }, + { + input: "_:1a .", + subject: term{text: "1a", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-bnode-03.nt": { + { + input: " _:1a .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "1a", kind: Blank}, + }, + { + input: "_:1a .", + subject: term{text: "1a", kind: Blank}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-datatypes-01.nq": { + { + input: " \"123\"^^ .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "123", qual: "http://www.w3.org/2001/XMLSchema#byte", kind: Literal}, + }, + }, + "nt-syntax-datatypes-01.nt": { + { + input: " \"123\"^^ .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "123", qual: "http://www.w3.org/2001/XMLSchema#byte", kind: Literal}, + }, + }, + "nt-syntax-datatypes-02.nq": { + { + input: " \"123\"^^ .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "123", qual: "http://www.w3.org/2001/XMLSchema#string", kind: Literal}, + }, + }, + "nt-syntax-datatypes-02.nt": { + { + input: " \"123\"^^ .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "123", qual: "http://www.w3.org/2001/XMLSchema#string", kind: Literal}, + }, + }, + "nt-syntax-str-esc-01.nq": { + { + input: " \"a\\n\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a\n", kind: Literal}, + }, + }, + "nt-syntax-str-esc-01.nt": { + { + input: " \"a\\n\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a\n", kind: Literal}, + }, + }, + "nt-syntax-str-esc-02.nq": { + { + input: " \"a\\u0020b\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a b", kind: Literal}, + }, + }, + "nt-syntax-str-esc-02.nt": { + { + input: " \"a\\u0020b\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a b", kind: Literal}, + }, + }, + "nt-syntax-str-esc-03.nq": { + { + input: " \"a\\U00000020b\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a b", kind: Literal}, + }, + }, + "nt-syntax-str-esc-03.nt": { + { + input: " \"a\\U00000020b\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "a b", kind: Literal}, + }, + }, + "nt-syntax-string-01.nq": { + { + input: " \"string\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "string", kind: Literal}, + }, + }, + "nt-syntax-string-01.nt": { + { + input: " \"string\" .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "string", kind: Literal}, + }, + }, + "nt-syntax-string-02.nq": { + { + input: " \"string\"@en .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "string", qual: "@en", kind: Literal}, + }, + }, + "nt-syntax-string-02.nt": { + { + input: " \"string\"@en .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "string", qual: "@en", kind: Literal}, + }, + }, + "nt-syntax-string-03.nq": { + { + input: " \"string\"@en-uk .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "string", qual: "@en-uk", kind: Literal}, + }, + }, + "nt-syntax-string-03.nt": { + { + input: " \"string\"@en-uk .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "string", qual: "@en-uk", kind: Literal}, + }, + }, + "nt-syntax-subm-01.nq": { + { + input: " .", + subject: term{text: "http://example.org/resource1", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: "_:anon .", + subject: term{text: "anon", kind: Blank}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " _:anon .", + subject: term{text: "http://example.org/resource2", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "anon", kind: Blank}, + }, + { + input: " \t \t \t.", + subject: term{text: "http://example.org/resource3", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource4", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource5", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource6", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " \"simple literal\" .", + subject: term{text: "http://example.org/resource7", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "simple literal", kind: Literal}, + }, + { + input: " \"backslash:\\\\\" .", + subject: term{text: "http://example.org/resource8", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "backslash:\\", kind: Literal}, + }, + { + input: " \"dquote:\\\"\" .", + subject: term{text: "http://example.org/resource9", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "dquote:\"", kind: Literal}, + }, + { + input: " \"newline:\\n\" .", + subject: term{text: "http://example.org/resource10", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "newline:\n", kind: Literal}, + }, + { + input: " \"return\\r\" .", + subject: term{text: "http://example.org/resource11", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "return\r", kind: Literal}, + }, + { + input: " \"tab:\\t\" .", + subject: term{text: "http://example.org/resource12", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "tab:\t", kind: Literal}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource13", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " \"x\".", + subject: term{text: "http://example.org/resource14", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "x", kind: Literal}, + }, + { + input: " _:anon.", + subject: term{text: "http://example.org/resource15", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "anon", kind: Blank}, + }, + { + input: " \"\\u00E9\" .", + subject: term{text: "http://example.org/resource16", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "é", kind: Literal}, + }, + { + input: " \"\\u20AC\" .", + subject: term{text: "http://example.org/resource17", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "€", kind: Literal}, + }, + { + input: " \"\"^^ .", + subject: term{text: "http://example.org/resource21", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \" \"^^ .", + subject: term{text: "http://example.org/resource22", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: " ", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"x\"^^ .", + subject: term{text: "http://example.org/resource23", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "x", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"\\\"\"^^ .", + subject: term{text: "http://example.org/resource23", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "\"", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"\"^^ .", + subject: term{text: "http://example.org/resource24", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"a \"^^ .", + subject: term{text: "http://example.org/resource25", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "a ", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"a c\"^^ .", + subject: term{text: "http://example.org/resource26", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "a c", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"a\\n\\nc\"^^ .", + subject: term{text: "http://example.org/resource26", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "a\n\nc", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"chat\"^^ .", + subject: term{text: "http://example.org/resource27", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "chat", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"chat\"@fr .", + subject: term{text: "http://example.org/resource30", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "chat", qual: "@fr", kind: Literal}, + }, + { + input: " \"chat\"@en .", + subject: term{text: "http://example.org/resource31", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "chat", qual: "@en", kind: Literal}, + }, + { + input: " \"abc\"^^ .", + subject: term{text: "http://example.org/resource32", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "abc", qual: "http://example.org/datatype1", kind: Literal}, + }, + }, + "nt-syntax-subm-01.nt": { + { + input: " .", + subject: term{text: "http://example.org/resource1", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: "_:anon .", + subject: term{text: "anon", kind: Blank}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " _:anon .", + subject: term{text: "http://example.org/resource2", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "anon", kind: Blank}, + }, + { + input: " \t \t \t.", + subject: term{text: "http://example.org/resource3", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource4", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource5", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource6", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " \"simple literal\" .", + subject: term{text: "http://example.org/resource7", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "simple literal", kind: Literal}, + }, + { + input: " \"backslash:\\\\\" .", + subject: term{text: "http://example.org/resource8", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "backslash:\\", kind: Literal}, + }, + { + input: " \"dquote:\\\"\" .", + subject: term{text: "http://example.org/resource9", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "dquote:\"", kind: Literal}, + }, + { + input: " \"newline:\\n\" .", + subject: term{text: "http://example.org/resource10", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "newline:\n", kind: Literal}, + }, + { + input: " \"return\\r\" .", + subject: term{text: "http://example.org/resource11", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "return\r", kind: Literal}, + }, + { + input: " \"tab:\\t\" .", + subject: term{text: "http://example.org/resource12", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "tab:\t", kind: Literal}, + }, + { + input: " .", + subject: term{text: "http://example.org/resource13", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "http://example.org/resource2", kind: IRI}, + }, + { + input: " \"x\".", + subject: term{text: "http://example.org/resource14", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "x", kind: Literal}, + }, + { + input: " _:anon.", + subject: term{text: "http://example.org/resource15", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "anon", kind: Blank}, + }, + { + input: " \"\\u00E9\" .", + subject: term{text: "http://example.org/resource16", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "é", kind: Literal}, + }, + { + input: " \"\\u20AC\" .", + subject: term{text: "http://example.org/resource17", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "€", kind: Literal}, + }, + { + input: " \"\"^^ .", + subject: term{text: "http://example.org/resource21", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \" \"^^ .", + subject: term{text: "http://example.org/resource22", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: " ", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"x\"^^ .", + subject: term{text: "http://example.org/resource23", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "x", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"\\\"\"^^ .", + subject: term{text: "http://example.org/resource23", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "\"", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"\"^^ .", + subject: term{text: "http://example.org/resource24", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"a \"^^ .", + subject: term{text: "http://example.org/resource25", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "a ", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"a c\"^^ .", + subject: term{text: "http://example.org/resource26", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "a c", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"a\\n\\nc\"^^ .", + subject: term{text: "http://example.org/resource26", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "a\n\nc", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"chat\"^^ .", + subject: term{text: "http://example.org/resource27", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "chat", qual: "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", kind: Literal}, + }, + { + input: " \"chat\"@fr .", + subject: term{text: "http://example.org/resource30", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "chat", qual: "@fr", kind: Literal}, + }, + { + input: " \"chat\"@en .", + subject: term{text: "http://example.org/resource31", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "chat", qual: "@en", kind: Literal}, + }, + { + input: " \"abc\"^^ .", + subject: term{text: "http://example.org/resource32", kind: IRI}, + predicate: term{text: "http://example.org/property", kind: IRI}, + object: term{text: "abc", qual: "http://example.org/datatype1", kind: Literal}, + }, + }, + "nt-syntax-uri-01.nq": { + { + input: " .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-uri-01.nt": { + { + input: " .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-uri-02.nq": { + { + input: " .", + subject: term{text: "http://example/S", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-uri-02.nt": { + { + input: " .", + subject: term{text: "http://example/S", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-uri-03.nq": { + { + input: " .", + subject: term{text: "http://example/S", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-uri-03.nt": { + { + input: " .", + subject: term{text: "http://example/S", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "http://example/o", kind: IRI}, + }, + }, + "nt-syntax-uri-04.nq": { + { + input: " .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "scheme:!$%25&'()*+,-./0123456789:/@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~?#", kind: IRI}, + }, + }, + "nt-syntax-uri-04.nt": { + { + input: " .", + subject: term{text: "http://example/s", kind: IRI}, + predicate: term{text: "http://example/p", kind: IRI}, + object: term{text: "scheme:!$%25&'()*+,-./0123456789:/@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~?#", kind: IRI}, + }, + }, + + // Empty valid syntax. + "nt-syntax-file-01.nq": nil, + "nt-syntax-file-01.nt": nil, + "nt-syntax-file-02.nq": nil, + "nt-syntax-file-02.nt": nil, + "nt-syntax-file-03.nq": nil, + "nt-syntax-file-03.nt": nil, + + // Invalid syntax. + "nq-syntax-bad-literal-01.nq": nil, + "nq-syntax-bad-literal-02.nq": nil, + "nq-syntax-bad-literal-03.nq": nil, + "nq-syntax-bad-quint-01.nq": nil, + "nq-syntax-bad-uri-01.nq": nil, + "nt-syntax-bad-base-01.nq": nil, + "nt-syntax-bad-base-01.nt": nil, + "nt-syntax-bad-esc-01.nq": nil, + "nt-syntax-bad-esc-01.nt": nil, + "nt-syntax-bad-esc-02.nq": nil, + "nt-syntax-bad-esc-02.nt": nil, + "nt-syntax-bad-esc-03.nq": nil, + "nt-syntax-bad-esc-03.nt": nil, + "nt-syntax-bad-lang-01.nq": nil, + "nt-syntax-bad-lang-01.nt": nil, + "nt-syntax-bad-num-01.nq": nil, + "nt-syntax-bad-num-01.nt": nil, + "nt-syntax-bad-num-02.nq": nil, + "nt-syntax-bad-num-02.nt": nil, + "nt-syntax-bad-num-03.nq": nil, + "nt-syntax-bad-num-03.nt": nil, + "nt-syntax-bad-prefix-01.nq": nil, + "nt-syntax-bad-prefix-01.nt": nil, + "nt-syntax-bad-string-01.nq": nil, + "nt-syntax-bad-string-01.nt": nil, + "nt-syntax-bad-string-02.nq": nil, + "nt-syntax-bad-string-02.nt": nil, + "nt-syntax-bad-string-03.nq": nil, + "nt-syntax-bad-string-03.nt": nil, + "nt-syntax-bad-string-04.nq": nil, + "nt-syntax-bad-string-04.nt": nil, + "nt-syntax-bad-string-05.nq": nil, + "nt-syntax-bad-string-05.nt": nil, + "nt-syntax-bad-string-06.nq": nil, + "nt-syntax-bad-string-06.nt": nil, + "nt-syntax-bad-string-07.nq": nil, + "nt-syntax-bad-string-07.nt": nil, + "nt-syntax-bad-struct-01.nq": nil, + "nt-syntax-bad-struct-01.nt": nil, + "nt-syntax-bad-struct-02.nq": nil, + "nt-syntax-bad-struct-02.nt": nil, + "nt-syntax-bad-uri-01.nq": nil, + "nt-syntax-bad-uri-01.nt": nil, + "nt-syntax-bad-uri-02.nq": nil, + "nt-syntax-bad-uri-02.nt": nil, + "nt-syntax-bad-uri-03.nq": nil, + "nt-syntax-bad-uri-03.nt": nil, + "nt-syntax-bad-uri-04.nq": nil, + "nt-syntax-bad-uri-04.nt": nil, + "nt-syntax-bad-uri-05.nq": nil, + "nt-syntax-bad-uri-05.nt": nil, + "nt-syntax-bad-uri-06.nq": nil, + "nt-syntax-bad-uri-06.nt": nil, + "nt-syntax-bad-uri-07.nq": nil, + "nt-syntax-bad-uri-07.nt": nil, + "nt-syntax-bad-uri-08.nq": nil, + "nt-syntax-bad-uri-08.nt": nil, + "nt-syntax-bad-uri-09.nq": nil, + "nt-syntax-bad-uri-09.nt": nil, +} diff --git a/graph/graph.go b/graph/graph.go index c973583d..4d570778 100644 --- a/graph/graph.go +++ b/graph/graph.go @@ -19,8 +19,12 @@ type Edge interface { // To returns the to node of the edge. To() Node - // ReversedEdge returns an edge that has - // the end points of the receiver swapped. + // ReversedEdge returns the edge reversal of the receiver + // if a reversal is valid for the data type. + // When a reversal is valid an edge of the same type as + // the receiver with nodes of the receiver swapped should + // be returned, otherwise the receiver should be returned + // unaltered. ReversedEdge() Edge } diff --git a/graph/multigraph.go b/graph/multigraph.go index 038a3d51..027e4696 100644 --- a/graph/multigraph.go +++ b/graph/multigraph.go @@ -13,8 +13,12 @@ type Line interface { // To returns the to node of the edge. To() Node - // ReversedLine returns a line that has the - // end points of the receiver swapped. + // ReversedLine returns the edge reversal of the receiver + // if a reversal is valid for the data type. + // When a reversal is valid an edge of the same type as + // the receiver with nodes of the receiver swapped should + // be returned, otherwise the receiver should be returned + // unaltered. ReversedLine() Line // ID returns the unique ID for the Line.