├── .gitignore ├── tests └── turtle │ ├── turtle-syntax-file-01.ttl │ ├── turtle-syntax-file-02.ttl │ ├── turtle-syntax-kw-01.ttl │ ├── turtle-syntax-kw-02.ttl │ ├── turtle-syntax-number-01.ttl │ ├── turtle-syntax-number-02.ttl │ ├── turtle-syntax-number-03.ttl │ ├── turtle-syntax-number-09.ttl │ ├── turtle-syntax-number-10.ttl │ ├── turtle-syntax-number-11.ttl │ ├── turtle-subm-01.ttl │ ├── LITERAL1.nt │ ├── LITERAL1.ttl │ ├── LITERAL2.ttl │ ├── first.ttl │ ├── last.ttl │ ├── turtle-syntax-file-03.ttl │ ├── bareword_integer.ttl │ ├── literal_true.ttl │ ├── turtle-syntax-bad-base-01.ttl │ ├── turtle-syntax-number-05.ttl │ ├── turtle-syntax-number-08.ttl │ ├── LITERAL_LONG1.ttl │ ├── LITERAL_LONG2.ttl │ ├── bareword_a_predicate.ttl │ ├── bareword_decimal.ttl │ ├── bareword_double.ttl │ ├── collection_object.ttl │ ├── collection_subject.ttl │ ├── double_lower_case_e.ttl │ ├── empty_collection.ttl │ ├── literal_false.ttl │ ├── negative_numeric.ttl │ ├── nested_collection.ttl │ ├── positive_numeric.ttl │ ├── turtle-syntax-bad-missing-ns-dot-end.ttl │ ├── turtle-syntax-base-01.ttl │ ├── turtle-syntax-base-02.ttl │ ├── turtle-syntax-number-04.ttl │ ├── turtle-syntax-number-06.ttl │ ├── turtle-syntax-number-07.ttl │ ├── IRI_spo.nt │ ├── langtagged_non_LONG.nt │ ├── literal_with_BACKSPACE.ttl │ ├── literal_with_FORM_FEED.ttl │ ├── literal_with_LINE_FEED.nt │ ├── numeric_with_leading_0.ttl │ ├── turtle-syntax-bad-prefix-03.ttl │ ├── turtle-syntax-prefix-02.ttl │ ├── IRI_subject.ttl │ ├── LITERAL_LONG1_with_1_squote.nt │ ├── LITERAL_LONG2_with_1_squote.nt │ ├── anonymous_blank_node_object.ttl │ ├── anonymous_blank_node_subject.ttl │ ├── blankNodePropertyList_containing_collection.ttl │ ├── labeled_blank_node_object.nt │ ├── labeled_blank_node_object.ttl │ ├── labeled_blank_node_subject.nt │ ├── labeled_blank_node_subject.ttl │ ├── langtagged_LONG.ttl │ ├── langtagged_non_LONG.ttl │ ├── lantag_with_subtag.nt │ ├── lantag_with_subtag.ttl │ ├── literal_with_BACKSPACE.nt │ ├── literal_with_CARRIAGE_RETURN.nt │ ├── literal_with_FORM_FEED.nt │ ├── literal_with_REVERSE_SOLIDUS.nt │ ├── literal_with_REVERSE_SOLIDUS.ttl │ ├── literal_with_numeric_escape4.nt │ ├── sole_blankNodePropertyList.ttl │ ├── turtle-subm-17.ttl │ ├── turtle-syntax-prefix-01.ttl │ ├── LITERAL1_ascii_boundaries.ttl │ ├── LITERAL2_ascii_boundaries.ttl │ ├── LITERAL_LONG1_with_1_squote.ttl │ ├── LITERAL_LONG1_with_2_squotes.nt │ ├── LITERAL_LONG2_with_1_squote.ttl │ ├── LITERAL_LONG2_with_2_squotes.nt │ ├── literal_with_CARRIAGE_RETURN.ttl │ ├── literal_with_CHARACTER_TABULATION.nt │ ├── literal_with_CHARACTER_TABULATION.ttl │ ├── literal_with_LINE_FEED.ttl │ ├── literal_with_escaped_BACKSPACE.ttl │ ├── literal_with_escaped_FORM_FEED.ttl │ ├── literal_with_escaped_LINE_FEED.ttl │ ├── literal_with_numeric_escape4.ttl │ ├── turtle-subm-09.ttl │ ├── turtle-syntax-bad-missing-ns-dot-start.ttl │ ├── turtle-syntax-base-04.ttl │ ├── LITERAL_LONG1_ascii_boundaries.ttl │ ├── LITERAL_LONG1_with_2_squotes.ttl │ ├── LITERAL_LONG2_ascii_boundaries.ttl │ ├── LITERAL_LONG2_with_2_squotes.ttl │ ├── labeled_blank_node_with_leading_digit.ttl │ ├── literal_with_escaped_CARRIAGE_RETURN.ttl │ ├── literal_with_numeric_escape8.ttl │ ├── localname_with_COLON.nt │ ├── turtle-subm-22.ttl │ ├── turtle-subm-24.nt │ ├── turtle-syntax-bad-kw-01.ttl │ ├── turtle-syntax-bad-kw-02.ttl │ ├── turtle-syntax-bad-kw-03.ttl │ ├── turtle-syntax-base-03.ttl │ ├── turtle-syntax-bnode-01.ttl │ ├── turtle-syntax-bnode-02.ttl │ ├── turtle-syntax-kw-03.ttl │ ├── turtle-syntax-lists-01.ttl │ ├── turtle-syntax-prefix-03.ttl │ ├── turtle-syntax-prefix-05.ttl │ ├── HYPHEN_MINUS_in_localName.nt │ ├── LITERAL_LONG1_ascii_boundaries.nt │ ├── LITERAL_LONG2_ascii_boundaries.nt │ ├── comment_following_PNAME_NS.nt │ ├── labeled_blank_node_with_leading_underscore.ttl │ ├── literal_with_escaped_CHARACTER_TABULATION.ttl │ ├── localName_with_leading_digit.nt │ ├── percent_escaped_localName.nt │ ├── prefix_reassigned_and_used.nt │ ├── repeated_semis_not_at_end.nt │ ├── turtle-syntax-bad-kw-04.ttl │ ├── turtle-syntax-bad-kw-05.ttl │ ├── turtle-syntax-bad-n3-extras-07.ttl │ ├── turtle-syntax-bad-n3-extras-08.ttl │ ├── turtle-syntax-bad-n3-extras-13.ttl │ ├── turtle-syntax-bad-prefix-01.ttl │ ├── turtle-syntax-bnode-06.ttl │ ├── turtle-syntax-bnode-08.ttl │ ├── turtle-syntax-lists-03.ttl │ ├── turtle-syntax-lists-04.ttl │ ├── turtle-syntax-prefix-04.ttl │ ├── underscore_in_localName.nt │ ├── LITERAL1_all_punctuation.nt │ ├── LITERAL1_all_punctuation.ttl │ ├── SPARQL_style_base.ttl │ ├── labeled_blank_node_with_non_leading_extras.ttl │ ├── langtagged_LONG_with_subtag.nt │ ├── localName_with_leading_underscore.nt │ ├── old_style_base.ttl │ ├── repeated_semis_not_at_end.ttl │ ├── turtle-subm-08.ttl │ ├── turtle-subm-19.ttl │ ├── turtle-subm-21.nt │ ├── turtle-syntax-bad-ln-dash-start.ttl │ ├── turtle-syntax-bad-ln-escape.ttl │ ├── turtle-syntax-bad-string-01.ttl │ ├── turtle-syntax-bad-string-02.ttl │ ├── turtle-syntax-bad-string-03.ttl │ ├── turtle-syntax-bnode-03.ttl │ ├── turtle-syntax-lists-02.ttl │ ├── turtle-syntax-struct-01.ttl │ ├── LITERAL1_all_controls.ttl │ ├── LITERAL1_with_UTF8_boundaries.ttl │ ├── LITERAL2_with_UTF8_boundaries.ttl │ ├── LITERAL_LONG2_with_REVERSE_SOLIDUS.nt │ ├── SPARQL_style_prefix.ttl │ ├── old_style_prefix.ttl │ ├── prefix_only_IRI.ttl │ ├── turtle-subm-18.ttl │ ├── turtle-subm-20.ttl │ ├── turtle-syntax-bad-base-02.ttl │ ├── turtle-syntax-bad-ln-escape-start.ttl │ ├── turtle-syntax-bad-prefix-05.ttl │ ├── turtle-syntax-bad-string-04.ttl │ ├── turtle-syntax-ns-dots.ttl │ ├── turtle-syntax-pname-esc-03.ttl │ ├── IRIREF_datatype.nt │ ├── IRIREF_datatype.ttl │ ├── IRI_with_four_digit_numeric_escape.ttl │ ├── LITERAL1_ascii_boundaries.nt │ ├── LITERAL2_ascii_boundaries.nt │ ├── LITERAL_LONG1_with_UTF8_boundaries.ttl │ ├── LITERAL_LONG2_with_REVERSE_SOLIDUS.ttl │ ├── LITERAL_LONG2_with_UTF8_boundaries.ttl │ ├── bareword_double.nt │ ├── default_namespace_IRI.ttl │ ├── literal_true.nt │ ├── localname_with_COLON.ttl │ ├── number_sign_following_PNAME_NS.nt │ ├── number_sign_following_localName.nt │ ├── prefixed_IRI_object.ttl │ ├── prefixed_IRI_predicate.ttl │ ├── turtle-subm-07.ttl │ ├── turtle-subm-15.nt │ ├── turtle-subm-25.nt │ ├── turtle-syntax-bad-blank-label-dot-end.ttl │ ├── turtle-syntax-bad-ns-dot-end.ttl │ ├── turtle-syntax-bad-struct-12.ttl │ ├── turtle-syntax-bad-struct-13.ttl │ ├── turtle-syntax-bnode-04.ttl │ ├── turtle-syntax-bnode-05.ttl │ ├── turtle-syntax-bnode-07.ttl │ ├── turtle-syntax-struct-02.ttl │ ├── HYPHEN_MINUS_in_localName.ttl │ ├── IRI_with_eight_digit_numeric_escape.ttl │ ├── bareword_decimal.nt │ ├── double_lower_case_e.nt │ ├── empty_collection.nt │ ├── literal_false.nt │ ├── localName_with_leading_digit.ttl │ ├── negative_numeric.nt │ ├── percent_escaped_localName.ttl │ ├── positive_numeric.nt │ ├── reserved_escaped_localName.nt │ ├── turtle-syntax-bad-ns-dot-start.ttl │ ├── turtle-syntax-bad-num-01.ttl │ ├── turtle-syntax-bad-num-02.ttl │ ├── turtle-syntax-bad-num-03.ttl │ ├── turtle-syntax-bad-num-04.ttl │ ├── turtle-syntax-bad-num-05.ttl │ ├── turtle-syntax-bad-prefix-04.ttl │ ├── turtle-syntax-bnode-09.ttl │ ├── turtle-syntax-datatypes-01.ttl │ ├── turtle-syntax-lists-05.ttl │ ├── turtle-syntax-str-esc-01.ttl │ ├── turtle-syntax-string-01.ttl │ ├── turtle-syntax-string-04.ttl │ ├── underscore_in_localName.ttl │ ├── bareword_a_predicate.nt │ ├── localName_with_leading_underscore.ttl │ ├── numeric_with_leading_0.nt │ ├── objectList_with_two_objects.ttl │ ├── turtle-subm-17.nt │ ├── turtle-syntax-bad-pname-02.ttl │ ├── turtle-syntax-str-esc-02.ttl │ ├── turtle-syntax-string-02.ttl │ ├── turtle-syntax-string-05.ttl │ ├── turtle-syntax-struct-03.ttl │ ├── turtle-syntax-struct-04.ttl │ ├── turtle-syntax-struct-05.ttl │ ├── comment_following_PNAME_NS.ttl │ ├── turtle-subm-03.ttl │ ├── turtle-subm-04.ttl │ ├── turtle-subm-07.nt │ ├── turtle-subm-14.ttl │ ├── turtle-subm-21.ttl │ ├── turtle-subm-24.ttl │ ├── turtle-syntax-bad-n3-extras-02.ttl │ ├── turtle-syntax-bad-n3-extras-06.ttl │ ├── turtle-syntax-bad-n3-extras-09.ttl │ ├── turtle-syntax-bad-n3-extras-10.ttl │ ├── turtle-syntax-bad-pname-01.ttl │ ├── turtle-syntax-bad-pname-03.ttl │ ├── turtle-syntax-str-esc-03.ttl │ ├── turtle-syntax-string-03.ttl │ ├── turtle-syntax-string-06.ttl │ ├── turtle-syntax-string-08.ttl │ ├── turtle-syntax-string-09.ttl │ ├── blankNodePropertyList_as_object.ttl │ ├── blankNodePropertyList_as_subject.ttl │ ├── comment_following_localName.ttl │ ├── localName_with_non_leading_extras.ttl │ ├── prefix_with_non_leading_extras.ttl │ ├── turtle-subm-18.nt │ ├── turtle-syntax-bad-base-03.ttl │ ├── turtle-syntax-bad-n3-extras-05.ttl │ ├── turtle-syntax-bad-n3-extras-11.ttl │ ├── turtle-syntax-bad-n3-extras-12.ttl │ ├── turtle-syntax-string-07.ttl │ ├── turtle-syntax-string-10.ttl │ ├── turtle-syntax-string-11.ttl │ ├── number_sign_following_PNAME_NS.ttl │ ├── number_sign_following_localName.ttl │ ├── turtle-subm-09.nt │ ├── turtle-syntax-bad-number-dot-in-anon.ttl │ ├── turtle-syntax-bad-string-06.ttl │ ├── turtle-syntax-bad-string-07.ttl │ ├── turtle-syntax-bad-struct-02.ttl │ ├── turtle-syntax-pname-esc-01.ttl │ ├── blankNodePropertyList_as_object.nt │ ├── blankNodePropertyList_as_subject.nt │ ├── labeled_blank_node_with_PN_CHARS_BASE_character_boundaries.ttl │ ├── langtagged_LONG_with_subtag.ttl │ ├── localName_with_non_leading_extras.nt │ ├── repeated_semis_at_end.ttl │ ├── turtle-subm-15.ttl │ ├── turtle-syntax-bad-esc-01.ttl │ ├── turtle-syntax-bad-esc-02.ttl │ ├── turtle-syntax-bad-lang-01.ttl │ ├── turtle-syntax-bad-struct-16.ttl │ ├── turtle-syntax-bad-struct-17.ttl │ ├── turtle-syntax-ln-dots.ttl │ ├── turtle-syntax-prefix-07.ttl │ ├── prefixed_name_datatype.ttl │ ├── turtle-eval-struct-01.nt │ ├── turtle-eval-struct-01.ttl │ ├── turtle-subm-01.nt │ ├── turtle-subm-05.ttl │ ├── turtle-subm-14.nt │ ├── turtle-syntax-bad-esc-03.ttl │ ├── turtle-syntax-bad-esc-04.ttl │ ├── turtle-syntax-bad-string-05.ttl │ ├── turtle-syntax-bad-struct-14.ttl │ ├── turtle-syntax-bad-struct-15.ttl │ ├── turtle-syntax-bnode-10.ttl │ ├── turtle-syntax-pname-esc-02.ttl │ ├── turtle-syntax-prefix-08.ttl │ ├── turtle-syntax-uri-01.ttl │ ├── prefix_reassigned_and_used.ttl │ ├── turtle-subm-25.ttl │ ├── nested_blankNodePropertyLists.ttl │ ├── predicateObjectList_with_two_objectLists.ttl │ ├── reserved_escaped_localName.ttl │ ├── turtle-subm-05.nt │ ├── turtle-syntax-bad-n3-extras-01.ttl │ ├── turtle-eval-bad-04.ttl │ ├── turtle-subm-06.ttl │ ├── turtle-syntax-bad-struct-08.ttl │ ├── objectList_with_two_objects.nt │ ├── turtle-syntax-bad-struct-06.ttl │ ├── turtle-syntax-bad-struct-07.ttl │ ├── IRI_with_all_punctuation.nt │ ├── IRI_with_all_punctuation.ttl │ ├── localName_with_nfc_PN_CHARS_BASE_character_boundaries.ttl │ ├── turtle-syntax-bad-prefix-02.ttl │ ├── turtle-syntax-bad-struct-04.ttl │ ├── turtle-syntax-bad-struct-05.ttl │ ├── turtle-syntax-bad-struct-09.ttl │ ├── turtle-syntax-bad-struct-11.ttl │ ├── turtle-syntax-uri-02.ttl │ ├── nested_blankNodePropertyLists.nt │ ├── turtle-eval-bad-02.ttl │ ├── turtle-eval-bad-03.ttl │ ├── turtle-syntax-bad-uri-01.ttl │ ├── turtle-syntax-prefix-09.ttl │ ├── turtle-syntax-uri-03.ttl │ ├── two_LITERAL_LONG2s.nt │ ├── localName_with_assigned_nfc_PN_CHARS_BASE_character_boundaries.ttl │ ├── localName_with_assigned_nfc_bmp_PN_CHARS_BASE_character_boundaries.ttl │ ├── predicateObjectList_with_two_objectLists.nt │ ├── turtle-syntax-bad-struct-01.ttl │ ├── turtle-syntax-bad-uri-02.ttl │ ├── turtle-syntax-ln-colons.ttl │ ├── blankNodePropertyList_with_multiple_triples.ttl │ ├── turtle-syntax-bad-LITERAL2_with_langtag_and_datatype.ttl │ ├── turtle-syntax-bad-n3-extras-04.ttl │ ├── turtle-syntax-bad-uri-03.ttl │ ├── turtle-syntax-datatypes-02.ttl │ ├── turtle-eval-bad-01.ttl │ ├── prefix_with_PN_CHARS_BASE_character_boundaries.ttl │ ├── turtle-syntax-bad-uri-04.ttl │ ├── turtle-syntax-bad-uri-05.ttl │ ├── LITERAL_with_UTF8_boundaries.nt │ ├── turtle-syntax-prefix-06.ttl │ ├── two_LITERAL_LONG2s.ttl │ ├── blankNodePropertyList_with_multiple_triples.nt │ ├── turtle-syntax-bad-n3-extras-03.ttl │ ├── turtle-syntax-blank-label.ttl │ ├── turtle-syntax-bad-struct-03.ttl │ ├── turtle-subm-22.nt │ ├── turtle-subm-02.ttl │ ├── turtle-subm-16.nt │ ├── turtle-syntax-uri-04.ttl │ ├── LITERAL1_all_controls.nt │ ├── turtle-eval-struct-02.ttl │ ├── localName_with_assigned_nfc_bmp_PN_CHARS_BASE_character_boundaries.nt │ ├── turtle-eval-struct-02.nt │ ├── localName_with_nfc_PN_CHARS_BASE_character_boundaries.nt │ ├── localName_with_assigned_nfc_PN_CHARS_BASE_character_boundaries.nt │ ├── turtle-subm-03.nt │ ├── turtle-subm-04.nt │ ├── collection_object.nt │ ├── collection_subject.nt │ ├── turtle-subm-02.nt │ ├── turtle-subm-06.nt │ ├── turtle-syntax-bad-struct-10.ttl │ ├── blankNodePropertyList_containing_collection.nt │ ├── turtle-subm-12.nt │ ├── turtle-subm-19.nt │ ├── turtle-subm-20.nt │ ├── turtle-subm-11.ttl │ ├── turtle-subm-13.nt │ ├── turtle-subm-10.ttl │ ├── turtle-subm-23.ttl │ ├── turtle-subm-13.ttl │ ├── turtle-subm-12.ttl │ ├── turtle-subm-10.nt │ ├── turtle-subm-08.nt │ ├── turtle-subm-27.ttl │ ├── nested_collection.nt │ ├── turtle-subm-27.nt │ ├── turtle-subm-16.ttl │ ├── turtle-subm-11.nt │ ├── turtle-subm-23.nt │ ├── first.nt │ ├── last.nt │ ├── turtle-subm-26.nt │ ├── turtle-subm-26.ttl │ ├── README │ └── LICENSE ├── go.mod ├── go.sum ├── lexer.go ├── token.go ├── rdf_test.go ├── matchers.go ├── isomorphism.go ├── rdf.go ├── statefns.go ├── ttl_test.go └── parser.go /.gitignore: -------------------------------------------------------------------------------- 1 | grammar.y 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-file-01.ttl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-file-02.ttl: -------------------------------------------------------------------------------- 1 | #Empty file. 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-kw-01.ttl: -------------------------------------------------------------------------------- 1 |

true . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-kw-02.ttl: -------------------------------------------------------------------------------- 1 |

false . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-01.ttl: -------------------------------------------------------------------------------- 1 |

123 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-02.ttl: -------------------------------------------------------------------------------- 1 |

-123 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-03.ttl: -------------------------------------------------------------------------------- 1 |

+123 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-09.ttl: -------------------------------------------------------------------------------- 1 |

123.0e1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-10.ttl: -------------------------------------------------------------------------------- 1 |

-123e-1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-11.ttl: -------------------------------------------------------------------------------- 1 |

123.E+1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : <#> . 2 | [] :x :y . 3 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1.nt: -------------------------------------------------------------------------------- 1 | "x" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1.ttl: -------------------------------------------------------------------------------- 1 | 'x' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL2.ttl: -------------------------------------------------------------------------------- 1 | "x" . 2 | -------------------------------------------------------------------------------- /tests/turtle/first.ttl: -------------------------------------------------------------------------------- 1 | ((1) 2) . 2 | -------------------------------------------------------------------------------- /tests/turtle/last.ttl: -------------------------------------------------------------------------------- 1 | (1 (2)) . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-file-03.ttl: -------------------------------------------------------------------------------- 1 | #One comment, one empty line. 2 | 3 | -------------------------------------------------------------------------------- /tests/turtle/bareword_integer.ttl: -------------------------------------------------------------------------------- 1 | 1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_true.ttl: -------------------------------------------------------------------------------- 1 | true . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-base-01.ttl: -------------------------------------------------------------------------------- 1 | # @base without URI. 2 | @base . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-05.ttl: -------------------------------------------------------------------------------- 1 | # This is a decimal. 2 |

.1 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-08.ttl: -------------------------------------------------------------------------------- 1 | # This is an integer 2 |

123. 3 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1.ttl: -------------------------------------------------------------------------------- 1 | '''x''' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2.ttl: -------------------------------------------------------------------------------- 1 | """x""" . 2 | -------------------------------------------------------------------------------- /tests/turtle/bareword_a_predicate.ttl: -------------------------------------------------------------------------------- 1 | a . 2 | -------------------------------------------------------------------------------- /tests/turtle/bareword_decimal.ttl: -------------------------------------------------------------------------------- 1 | 1.0 . 2 | -------------------------------------------------------------------------------- /tests/turtle/bareword_double.ttl: -------------------------------------------------------------------------------- 1 | 1E0 . 2 | -------------------------------------------------------------------------------- /tests/turtle/collection_object.ttl: -------------------------------------------------------------------------------- 1 | (1) . 2 | -------------------------------------------------------------------------------- /tests/turtle/collection_subject.ttl: -------------------------------------------------------------------------------- 1 | (1) . 2 | -------------------------------------------------------------------------------- /tests/turtle/double_lower_case_e.ttl: -------------------------------------------------------------------------------- 1 | 1e0 . 2 | -------------------------------------------------------------------------------- /tests/turtle/empty_collection.ttl: -------------------------------------------------------------------------------- 1 | () . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_false.ttl: -------------------------------------------------------------------------------- 1 | false . 2 | -------------------------------------------------------------------------------- /tests/turtle/negative_numeric.ttl: -------------------------------------------------------------------------------- 1 | -1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/nested_collection.ttl: -------------------------------------------------------------------------------- 1 | ((1)) . 2 | -------------------------------------------------------------------------------- /tests/turtle/positive_numeric.ttl: -------------------------------------------------------------------------------- 1 | +1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-missing-ns-dot-end.ttl: -------------------------------------------------------------------------------- 1 | valid:s valid:p invalid.:o . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-base-01.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-base-02.ttl: -------------------------------------------------------------------------------- 1 | BASE 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-04.ttl: -------------------------------------------------------------------------------- 1 | # This is a decimal. 2 |

123.0 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-06.ttl: -------------------------------------------------------------------------------- 1 | # This is a decimal. 2 |

-123.0 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-number-07.ttl: -------------------------------------------------------------------------------- 1 | # This is a decimal. 2 |

+123.0 . 3 | -------------------------------------------------------------------------------- /tests/turtle/IRI_spo.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/langtagged_non_LONG.nt: -------------------------------------------------------------------------------- 1 | "chat"@en . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_BACKSPACE.ttl: -------------------------------------------------------------------------------- 1 | '' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_FORM_FEED.ttl: -------------------------------------------------------------------------------- 1 | ' ' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_LINE_FEED.nt: -------------------------------------------------------------------------------- 1 | "\n" . 2 | -------------------------------------------------------------------------------- /tests/turtle/numeric_with_leading_0.ttl: -------------------------------------------------------------------------------- 1 | 01 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-prefix-03.ttl: -------------------------------------------------------------------------------- 1 | # @prefix without URI. 2 | @prefix ex: . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-02.ttl: -------------------------------------------------------------------------------- 1 | PreFIX : 2 | -------------------------------------------------------------------------------- /tests/turtle/IRI_subject.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_with_1_squote.nt: -------------------------------------------------------------------------------- 1 | "x'y" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_1_squote.nt: -------------------------------------------------------------------------------- 1 | "x\"y" . 2 | -------------------------------------------------------------------------------- /tests/turtle/anonymous_blank_node_object.ttl: -------------------------------------------------------------------------------- 1 | [] . 2 | -------------------------------------------------------------------------------- /tests/turtle/anonymous_blank_node_subject.ttl: -------------------------------------------------------------------------------- 1 | [] . 2 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_containing_collection.ttl: -------------------------------------------------------------------------------- 1 | [ (1) ] . 2 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_object.nt: -------------------------------------------------------------------------------- 1 | _:b1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_object.ttl: -------------------------------------------------------------------------------- 1 | _:o . 2 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_subject.nt: -------------------------------------------------------------------------------- 1 | _:b1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_subject.ttl: -------------------------------------------------------------------------------- 1 | _:s . 2 | -------------------------------------------------------------------------------- /tests/turtle/langtagged_LONG.ttl: -------------------------------------------------------------------------------- 1 | """chat"""@en . 2 | -------------------------------------------------------------------------------- /tests/turtle/langtagged_non_LONG.ttl: -------------------------------------------------------------------------------- 1 | "chat"@en . 2 | -------------------------------------------------------------------------------- /tests/turtle/lantag_with_subtag.nt: -------------------------------------------------------------------------------- 1 | "chat"@en-us . 2 | -------------------------------------------------------------------------------- /tests/turtle/lantag_with_subtag.ttl: -------------------------------------------------------------------------------- 1 | "chat"@en-us . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_BACKSPACE.nt: -------------------------------------------------------------------------------- 1 | "\u0008" . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_CARRIAGE_RETURN.nt: -------------------------------------------------------------------------------- 1 | "\r" . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_FORM_FEED.nt: -------------------------------------------------------------------------------- 1 | "\u000C" . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_REVERSE_SOLIDUS.nt: -------------------------------------------------------------------------------- 1 | "\\" . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_REVERSE_SOLIDUS.ttl: -------------------------------------------------------------------------------- 1 | '\\' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_numeric_escape4.nt: -------------------------------------------------------------------------------- 1 | "o" . 2 | -------------------------------------------------------------------------------- /tests/turtle/sole_blankNodePropertyList.ttl: -------------------------------------------------------------------------------- 1 | [ ] . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-17.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :a :b 1.0 . 4 | 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_ascii_boundaries.ttl: -------------------------------------------------------------------------------- 1 | ' &([]' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL2_ascii_boundaries.ttl: -------------------------------------------------------------------------------- 1 | " !#[]" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_with_1_squote.ttl: -------------------------------------------------------------------------------- 1 | '''x'y''' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_with_2_squotes.nt: -------------------------------------------------------------------------------- 1 | "x''y" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_1_squote.ttl: -------------------------------------------------------------------------------- 1 | """x"y""" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_2_squotes.nt: -------------------------------------------------------------------------------- 1 | "x\"\"y" . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_CARRIAGE_RETURN.ttl: -------------------------------------------------------------------------------- 1 | ''' ''' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_CHARACTER_TABULATION.nt: -------------------------------------------------------------------------------- 1 | "\t" . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_CHARACTER_TABULATION.ttl: -------------------------------------------------------------------------------- 1 | ' ' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_LINE_FEED.ttl: -------------------------------------------------------------------------------- 1 | ''' 2 | ''' . 3 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_escaped_BACKSPACE.ttl: -------------------------------------------------------------------------------- 1 | '\b' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_escaped_FORM_FEED.ttl: -------------------------------------------------------------------------------- 1 | '\f' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_escaped_LINE_FEED.ttl: -------------------------------------------------------------------------------- 1 | '\n' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_numeric_escape4.ttl: -------------------------------------------------------------------------------- 1 | '\u006F' . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-09.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b ( ) . 3 | 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-missing-ns-dot-start.ttl: -------------------------------------------------------------------------------- 1 | .undefined:s .undefined:p .undefined:o . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-base-04.ttl: -------------------------------------------------------------------------------- 1 | base 2 |

. 3 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_ascii_boundaries.ttl: -------------------------------------------------------------------------------- 1 | '&([]' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_with_2_squotes.ttl: -------------------------------------------------------------------------------- 1 | '''x''y''' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_ascii_boundaries.ttl: -------------------------------------------------------------------------------- 1 | "!#[]" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_2_squotes.ttl: -------------------------------------------------------------------------------- 1 | """x""y""" . 2 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_with_leading_digit.ttl: -------------------------------------------------------------------------------- 1 | _:0 . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_escaped_CARRIAGE_RETURN.ttl: -------------------------------------------------------------------------------- 1 | '\r' . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_numeric_escape8.ttl: -------------------------------------------------------------------------------- 1 | '\U0000006F' . 2 | -------------------------------------------------------------------------------- /tests/turtle/localname_with_COLON.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-22.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b true . 3 | :c :d false . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-24.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-kw-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s A :C . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-kw-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | a :p :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-kw-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p a . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-base-03.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 |

. 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | [] :p :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p [] . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-kw-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s a :C . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-lists-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p () . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-03.ttl: -------------------------------------------------------------------------------- 1 | PREFIX : 2 | :s :p :123 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-05.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | : : : . 3 | -------------------------------------------------------------------------------- /tests/turtle/HYPHEN_MINUS_in_localName.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_ascii_boundaries.nt: -------------------------------------------------------------------------------- 1 | "\u0000&([]\u007F" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_ascii_boundaries.nt: -------------------------------------------------------------------------------- 1 | "\u0000!#[]\u007F" . 2 | -------------------------------------------------------------------------------- /tests/turtle/comment_following_PNAME_NS.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_with_leading_underscore.ttl: -------------------------------------------------------------------------------- 1 | _:_ . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_with_escaped_CHARACTER_TABULATION.ttl: -------------------------------------------------------------------------------- 1 | '\t' . 2 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_leading_digit.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/percent_escaped_localName.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/prefix_reassigned_and_used.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/repeated_semis_not_at_end.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-kw-04.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | true :p :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-kw-05.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s true :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-07.ttl: -------------------------------------------------------------------------------- 1 | # @keywords is not Turtle 2 | @keywords a . 3 | x a Item . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-08.ttl: -------------------------------------------------------------------------------- 1 | # @keywords is not Turtle 2 | @keywords a . 3 | x a Item . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-13.ttl: -------------------------------------------------------------------------------- 1 | # @keywords is not Turtle 2 | @keywords . 3 | x @a Item . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-prefix-01.ttl: -------------------------------------------------------------------------------- 1 | # No prefix 2 | :s "x" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-06.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | _:a :p :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-08.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | [ :p :o ] . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-lists-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | (1) :p (1) . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-lists-04.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | (()) :p (()) . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-04.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :%20 . 3 | -------------------------------------------------------------------------------- /tests/turtle/underscore_in_localName.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_all_punctuation.nt: -------------------------------------------------------------------------------- 1 | " !\"#$%&():;<=>?@[]^_`{|}~" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_all_punctuation.ttl: -------------------------------------------------------------------------------- 1 | ' !"#$%&():;<=>?@[]^_`{|}~' . 2 | -------------------------------------------------------------------------------- /tests/turtle/SPARQL_style_base.ttl: -------------------------------------------------------------------------------- 1 | BASE 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_with_non_leading_extras.ttl: -------------------------------------------------------------------------------- 1 | _:a·̀ͯ‿.⁀ . 2 | -------------------------------------------------------------------------------- /tests/turtle/langtagged_LONG_with_subtag.nt: -------------------------------------------------------------------------------- 1 | "Cheers"@en-UK . 2 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_leading_underscore.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/old_style_base.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/repeated_semis_not_at_end.ttl: -------------------------------------------------------------------------------- 1 | ;; . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-08.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b ( "apple" "banana" ) . 3 | 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-19.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b 1.0 . 3 | :c :d 1 . 4 | :e :f 1.0e0 . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-21.nt: -------------------------------------------------------------------------------- 1 | "John said: \"Hello World!\"" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-ln-dash-start.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :-o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-ln-escape.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :o%2 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p "abc' . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p 'abc" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p '''abc' . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p [ :q :o ] . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-lists-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p (1 "2" :o) . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-struct-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :o1 , :o2 . 3 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_all_controls.ttl: -------------------------------------------------------------------------------- 1 | ' ' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_with_UTF8_boundaries.ttl: -------------------------------------------------------------------------------- 1 | '€߿ࠀ࿿က쿿퀀퟿�𐀀𿿽񀀀󿿽􀀀􏿽' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL2_with_UTF8_boundaries.ttl: -------------------------------------------------------------------------------- 1 | "€߿ࠀ࿿က쿿퀀퟿�𐀀𿿽񀀀󿿽􀀀􏿽" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_REVERSE_SOLIDUS.nt: -------------------------------------------------------------------------------- 1 | "test-\\" . 2 | -------------------------------------------------------------------------------- /tests/turtle/SPARQL_style_prefix.ttl: -------------------------------------------------------------------------------- 1 | PREFIX p: 2 | p:s . 3 | -------------------------------------------------------------------------------- /tests/turtle/old_style_prefix.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:s . 3 | -------------------------------------------------------------------------------- /tests/turtle/prefix_only_IRI.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p: . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-18.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :a :b "" . 4 | 5 | :c :d """""" . 6 | 7 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-20.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :a :b -1.0 . 3 | :c :d -1 . 4 | :e :f -1.0e0 . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-base-02.ttl: -------------------------------------------------------------------------------- 1 | # @base in wrong case. 2 | @BASE . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-ln-escape-start.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :%2o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-prefix-05.ttl: -------------------------------------------------------------------------------- 1 | # @prefix without : 2 | @prefix x . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-04.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p """abc''' . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-ns-dots.ttl: -------------------------------------------------------------------------------- 1 | @prefix e.g: . 2 | e.g:s e.g:p e.g:o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-pname-esc-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :xyz\~ :abc\.: : . 3 | -------------------------------------------------------------------------------- /tests/turtle/IRIREF_datatype.nt: -------------------------------------------------------------------------------- 1 | "1"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/IRIREF_datatype.ttl: -------------------------------------------------------------------------------- 1 | "1"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/IRI_with_four_digit_numeric_escape.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_ascii_boundaries.nt: -------------------------------------------------------------------------------- 1 | "\u0000\t\u000B\u000C\u000E&([]\u007F" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL2_ascii_boundaries.nt: -------------------------------------------------------------------------------- 1 | "\u0000\t\u000B\u000C\u000E!#[]\u007F" . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG1_with_UTF8_boundaries.ttl: -------------------------------------------------------------------------------- 1 | '''€߿ࠀ࿿က쿿퀀퟿�𐀀𿿽񀀀󿿽􀀀􏿽''' . 2 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_REVERSE_SOLIDUS.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :s :p1 """test-\\""" . 4 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_LONG2_with_UTF8_boundaries.ttl: -------------------------------------------------------------------------------- 1 | """€߿ࠀ࿿က쿿퀀퟿�𐀀𿿽񀀀󿿽􀀀􏿽""" . 2 | -------------------------------------------------------------------------------- /tests/turtle/bareword_double.nt: -------------------------------------------------------------------------------- 1 | "1E0"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/default_namespace_IRI.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s . 3 | -------------------------------------------------------------------------------- /tests/turtle/literal_true.nt: -------------------------------------------------------------------------------- 1 | "true"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/localname_with_COLON.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:s: . 3 | -------------------------------------------------------------------------------- /tests/turtle/number_sign_following_PNAME_NS.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/number_sign_following_localName.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/prefixed_IRI_object.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:o . 3 | -------------------------------------------------------------------------------- /tests/turtle/prefixed_IRI_predicate.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:p . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-07.ttl: -------------------------------------------------------------------------------- 1 | # 'a' only allowed as a predicate 2 | @prefix : . 3 | :a a :b . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-15.nt: -------------------------------------------------------------------------------- 1 | "a long\n\tliteral\nwith\nnewlines" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-25.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-blank-label-dot-end.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | _:b1. :p :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-ns-dot-end.ttl: -------------------------------------------------------------------------------- 1 | @prefix eg. : . 2 | eg.:s eg.:p eg.:o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-12.ttl: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-13.ttl: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-04.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p [ :q1 :o1 ; :q2 :o2 ] . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-05.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | [ :q1 :o1 ; :q2 :o2 ] :p :o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-07.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p _:a . 3 | _:a :p :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-struct-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p1 :o1 ; 3 | :p2 :o2 . 4 | -------------------------------------------------------------------------------- /tests/turtle/HYPHEN_MINUS_in_localName.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:s- . 3 | -------------------------------------------------------------------------------- /tests/turtle/IRI_with_eight_digit_numeric_escape.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/bareword_decimal.nt: -------------------------------------------------------------------------------- 1 | "1.0"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/double_lower_case_e.nt: -------------------------------------------------------------------------------- 1 | "1e0"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/empty_collection.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/literal_false.nt: -------------------------------------------------------------------------------- 1 | "false"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_leading_digit.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:0 . 3 | -------------------------------------------------------------------------------- /tests/turtle/negative_numeric.nt: -------------------------------------------------------------------------------- 1 | "-1"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/percent_escaped_localName.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:%25 . 3 | -------------------------------------------------------------------------------- /tests/turtle/positive_numeric.nt: -------------------------------------------------------------------------------- 1 | "+1"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/reserved_escaped_localName.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-ns-dot-start.ttl: -------------------------------------------------------------------------------- 1 | @prefix .eg : . 2 | .eg:s .eg:p .eg:o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-num-01.ttl: -------------------------------------------------------------------------------- 1 | 123.abc . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-num-02.ttl: -------------------------------------------------------------------------------- 1 | 123e . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-num-03.ttl: -------------------------------------------------------------------------------- 1 | 123abc . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-num-04.ttl: -------------------------------------------------------------------------------- 1 | 0x123 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-num-05.ttl: -------------------------------------------------------------------------------- 1 | +-1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-prefix-04.ttl: -------------------------------------------------------------------------------- 1 | # @prefix without prefix name . 2 | @prefix . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-09.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | [ :p :o1,:2 ] . 3 | :s :p :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-datatypes-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix xsd: . 2 |

"123"^^xsd:byte . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-lists-05.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | (1 2 (1 2)) :p (( "a") "b" :o) . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-str-esc-01.ttl: -------------------------------------------------------------------------------- 1 | "a\n" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-01.ttl: -------------------------------------------------------------------------------- 1 | "string" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-04.ttl: -------------------------------------------------------------------------------- 1 | 'string' . 2 | -------------------------------------------------------------------------------- /tests/turtle/underscore_in_localName.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:s_ . 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/deiu/gon3 2 | 3 | go 1.23 4 | 5 | require github.com/rychipman/easylex v0.0.0-20160129204217-49ee7767142f 6 | -------------------------------------------------------------------------------- /tests/turtle/bareword_a_predicate.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_leading_underscore.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:_ . 3 | -------------------------------------------------------------------------------- /tests/turtle/numeric_with_leading_0.nt: -------------------------------------------------------------------------------- 1 | "01"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/objectList_with_two_objects.ttl: -------------------------------------------------------------------------------- 1 | , . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-17.nt: -------------------------------------------------------------------------------- 1 | "1.0"^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-pname-02.ttl: -------------------------------------------------------------------------------- 1 | # Bad %-sequence 2 | @prefix : . 3 | :a%2 :p :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-str-esc-02.ttl: -------------------------------------------------------------------------------- 1 | "a\u0020b" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-02.ttl: -------------------------------------------------------------------------------- 1 | "string"@en . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-05.ttl: -------------------------------------------------------------------------------- 1 | 'string'@en . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-struct-03.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p1 :o1 ; 3 | :p2 :o2 ; 4 | . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-struct-04.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p1 :o1 ;; 3 | :p2 :o2 4 | . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-struct-05.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p1 :o1 ; 3 | :p2 :o2 ;; 4 | . 5 | -------------------------------------------------------------------------------- /tests/turtle/comment_following_PNAME_NS.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:#comment 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-03.ttl: -------------------------------------------------------------------------------- 1 | # Test , operator 2 | @prefix : . 3 | :a :b :c, 4 | :d, 5 | :e . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-04.ttl: -------------------------------------------------------------------------------- 1 | # Test ; operator 2 | @prefix : . 3 | :a :b :c ; 4 | :d :e ; 5 | :f :g . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-07.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-14.ttl: -------------------------------------------------------------------------------- 1 | # Test for : allowed 2 | @prefix : . 3 | 4 | [] : [] . 5 | 6 | : : : . 7 | 8 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-21.ttl: -------------------------------------------------------------------------------- 1 | # Test long literal 2 | @prefix : . 3 | :a :b """John said: "Hello World!\"""" . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-24.ttl: -------------------------------------------------------------------------------- 1 | # comment line with no final newline test 2 | @prefix : . 3 | :a :b :c . 4 | #foo 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-02.ttl: -------------------------------------------------------------------------------- 1 | # = is not Turtle 2 | @prefix : . 3 | 4 | :a = :b . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-06.ttl: -------------------------------------------------------------------------------- 1 | # = is not Turtle 2 | @prefix : . 3 | 4 | :a.:b.:c . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-09.ttl: -------------------------------------------------------------------------------- 1 | # => is not Turtle 2 | @prefix : . 3 | :s => :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-10.ttl: -------------------------------------------------------------------------------- 1 | # <= is not Turtle 2 | @prefix : . 3 | :s <= :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-pname-01.ttl: -------------------------------------------------------------------------------- 1 | # ~ must be escaped. 2 | @prefix : . 3 | :a~b :p :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-pname-03.ttl: -------------------------------------------------------------------------------- 1 | # No \u (x39 is "9") 2 | @prefix : . 3 | :a\u0039 :p :o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-str-esc-03.ttl: -------------------------------------------------------------------------------- 1 | "a\U00000020b" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-03.ttl: -------------------------------------------------------------------------------- 1 | "string"@en-uk . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-06.ttl: -------------------------------------------------------------------------------- 1 | 'string'@en-uk . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-08.ttl: -------------------------------------------------------------------------------- 1 | """abc 2 | def""" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-09.ttl: -------------------------------------------------------------------------------- 1 | '''abc 2 | def''' . 3 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_as_object.ttl: -------------------------------------------------------------------------------- 1 | [ ] . 2 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_as_subject.ttl: -------------------------------------------------------------------------------- 1 | [ ] . 2 | -------------------------------------------------------------------------------- /tests/turtle/comment_following_localName.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:o#comment 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_non_leading_extras.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:a·̀ͯ‿.⁀ . 3 | -------------------------------------------------------------------------------- /tests/turtle/prefix_with_non_leading_extras.ttl: -------------------------------------------------------------------------------- 1 | @prefix a·̀ͯ‿.⁀: . 2 | a·̀ͯ‿.⁀:s . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-18.nt: -------------------------------------------------------------------------------- 1 | "" . 2 | "" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-base-03.ttl: -------------------------------------------------------------------------------- 1 | # FULL STOP used after SPARQL BASE 2 | BASE . 3 |

. 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-05.ttl: -------------------------------------------------------------------------------- 1 | # N3 is...of 2 | @prefix : . 3 | 4 | :z is :p of :x . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-11.ttl: -------------------------------------------------------------------------------- 1 | # @forSome is not Turtle 2 | @prefix : . 3 | @forSome :x . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-12.ttl: -------------------------------------------------------------------------------- 1 | # @forAll is not Turtle 2 | @prefix : . 3 | @forAll :x . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-07.ttl: -------------------------------------------------------------------------------- 1 | """abc""def''ghi""" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-10.ttl: -------------------------------------------------------------------------------- 1 | """abc 2 | def"""@en . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-string-11.ttl: -------------------------------------------------------------------------------- 1 | '''abc 2 | def'''@en . 3 | -------------------------------------------------------------------------------- /tests/turtle/number_sign_following_PNAME_NS.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:\#numbersign 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/number_sign_following_localName.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:o\#numbersign 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-09.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-number-dot-in-anon.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :s 4 | :p [ 5 | :p1 27. 6 | ] . 7 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-06.ttl: -------------------------------------------------------------------------------- 1 | # Long literal with 4" 2 | @prefix : . 3 | :s :p """abc""""@en . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-07.ttl: -------------------------------------------------------------------------------- 1 | # Long literal with 4' 2 | @prefix : . 3 | :s :p '''abc''''@en . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-02.ttl: -------------------------------------------------------------------------------- 1 | # Turtle is not N3 2 | = . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-pname-esc-01.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :\~\.\-\!\$\&\'\(\)\*\+\,\;\=\/\?\#\@\_\%AA . 3 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_as_object.nt: -------------------------------------------------------------------------------- 1 | _:b1 . 2 | _:b1 . 3 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_as_subject.nt: -------------------------------------------------------------------------------- 1 | _:b1 . 2 | _:b1 . 3 | -------------------------------------------------------------------------------- /tests/turtle/labeled_blank_node_with_PN_CHARS_BASE_character_boundaries.ttl: -------------------------------------------------------------------------------- 1 | _:AZazÀÖØöø˿ͰͽͿ῿‌‍⁰↏Ⰰ⿯、퟿豈﷏ﷰ�𐀀󯿽 . 2 | -------------------------------------------------------------------------------- /tests/turtle/langtagged_LONG_with_subtag.ttl: -------------------------------------------------------------------------------- 1 | # Test long literal with lang tag 2 | @prefix : . 3 | :a :b """Cheers"""@en-UK . 4 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_non_leading_extras.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/repeated_semis_at_end.ttl: -------------------------------------------------------------------------------- 1 | ;; . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-15.ttl: -------------------------------------------------------------------------------- 1 | # Test long literal 2 | @prefix : . 3 | :a :b """a long 4 | literal 5 | with 6 | newlines""" . 7 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-esc-01.ttl: -------------------------------------------------------------------------------- 1 | # Bad string escape 2 | "a\zb" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-esc-02.ttl: -------------------------------------------------------------------------------- 1 | # Bad string escape 2 | "\uWXYZ" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-lang-01.ttl: -------------------------------------------------------------------------------- 1 | # Bad lang tag 2 | "string"@1 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-16.ttl: -------------------------------------------------------------------------------- 1 | # BNode as predicate 2 | [] . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-17.ttl: -------------------------------------------------------------------------------- 1 | # BNode as predicate 2 | _:a . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-ln-dots.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s.1 :p.1 :o.1 . 3 | :s..2 :p..2 :o..2. 4 | :3.s :3.p :3. 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-07.ttl: -------------------------------------------------------------------------------- 1 | # dash is a legal pname character 2 | @prefix x: . 3 | x:a-b-c x:p x:o . 4 | -------------------------------------------------------------------------------- /tests/turtle/prefixed_name_datatype.ttl: -------------------------------------------------------------------------------- 1 | @prefix xsd: . 2 | "1"^^xsd:integer . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-struct-01.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-struct-01.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-01.nt: -------------------------------------------------------------------------------- 1 | _:genid1 . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-05.ttl: -------------------------------------------------------------------------------- 1 | # Test empty [] operator; not allowed as predicate 2 | @prefix : . 3 | [] :a :b . 4 | :c :d [] . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-14.nt: -------------------------------------------------------------------------------- 1 | _:genid1 _:genid2 . 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-esc-03.ttl: -------------------------------------------------------------------------------- 1 | # Bad string escape 2 | "\U0000WXYZ" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-esc-04.ttl: -------------------------------------------------------------------------------- 1 | # Bad string escape 2 | "\U0000WXYZ" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-string-05.ttl: -------------------------------------------------------------------------------- 1 | # Long literal with missing end 2 | @prefix : . 3 | :s :p """abc 4 | def 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-14.ttl: -------------------------------------------------------------------------------- 1 | # Literal as subject 2 | "abc" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-15.ttl: -------------------------------------------------------------------------------- 1 | # Literal as predicate 2 | "abc" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bnode-10.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | :s1 :p :o . 4 | [ :p1 :o1 ; :p2 :o2 ] . 5 | :s2 :p :o . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-pname-esc-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s :p :0123\~\.\-\!\$\&\'\(\)\*\+\,\;\=\/\?\#\@\_\%AA123 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-08.ttl: -------------------------------------------------------------------------------- 1 | # underscore is a legal pname character 2 | @prefix x: . 3 | x:_ x:p_1 x:o . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-uri-01.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/prefix_reassigned_and_used.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | @prefix p: . 3 | p:s . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-25.ttl: -------------------------------------------------------------------------------- 1 | @prefix foo: . 2 | @prefix foo: . 3 | 4 | foo:blah foo:blah foo:blah . 5 | 6 | -------------------------------------------------------------------------------- /tests/turtle/nested_blankNodePropertyLists.ttl: -------------------------------------------------------------------------------- 1 | [ [ ] ; ]. 2 | -------------------------------------------------------------------------------- /tests/turtle/predicateObjectList_with_two_objectLists.ttl: -------------------------------------------------------------------------------- 1 | ; . 2 | -------------------------------------------------------------------------------- /tests/turtle/reserved_escaped_localName.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:\_\~\.\-\!\$\&\'\(\)\*\+\,\;\=\/\?\#\@\%00 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-05.nt: -------------------------------------------------------------------------------- 1 | _:genid1 . 2 | _:genid2 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-01.ttl: -------------------------------------------------------------------------------- 1 | # {} fomulae not in Turtle 2 | @prefix : . 3 | 4 | { :a :q :c . } :p :z . 5 | 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-bad-04.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-06.ttl: -------------------------------------------------------------------------------- 1 | # Test non empty [] operator; not allowed as predicate 2 | @prefix : . 3 | [ :a :b ] :c :d . 4 | :e :f [ :g :h ] . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-08.ttl: -------------------------------------------------------------------------------- 1 | # No DOT 2 | 3 | -------------------------------------------------------------------------------- /tests/turtle/objectList_with_two_objects.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-06.ttl: -------------------------------------------------------------------------------- 1 | # Turtle does not allow bnodes-as-predicates 2 | [] . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-07.ttl: -------------------------------------------------------------------------------- 1 | # Turtle does not allow bnodes-as-predicates 2 | _:p . 3 | -------------------------------------------------------------------------------- /tests/turtle/IRI_with_all_punctuation.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/IRI_with_all_punctuation.ttl: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_nfc_PN_CHARS_BASE_character_boundaries.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:AZazÀÖØöø˿ͰͽͿ῿‌‍⁰↏Ⰰ⿯、퟿﨎﷏ﷰ￯𐀀󯿽 . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-prefix-02.ttl: -------------------------------------------------------------------------------- 1 | # No prefix 2 | @prefix rdf: . 3 | rdf:type :C . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-04.ttl: -------------------------------------------------------------------------------- 1 | # Turtle does not allow literals-as-subjects 2 | "hello" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-05.ttl: -------------------------------------------------------------------------------- 1 | # Turtle does not allow literals-as-predicates 2 | "hello" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-09.ttl: -------------------------------------------------------------------------------- 1 | # Too many DOT 2 | . . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-11.ttl: -------------------------------------------------------------------------------- 1 | # Trailing ; 2 | ; 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-uri-02.ttl: -------------------------------------------------------------------------------- 1 | # x53 is capital S 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/nested_blankNodePropertyLists.nt: -------------------------------------------------------------------------------- 1 | _:b1 _:b2 . 2 | _:b2 . 3 | _:b1 . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-bad-02.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : hex 3C is < 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-bad-03.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : hex 3E is > 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-uri-01.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : space. 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-09.ttl: -------------------------------------------------------------------------------- 1 | # percents 2 | @prefix : . 3 | @prefix x: . 4 | :a%3E x:%25 :a%3Eb . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-uri-03.ttl: -------------------------------------------------------------------------------- 1 | # x53 is capital S 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/two_LITERAL_LONG2s.nt: -------------------------------------------------------------------------------- 1 | "first long literal" . 2 | "second long literal" . 3 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_assigned_nfc_PN_CHARS_BASE_character_boundaries.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:AZazÀÖØöø˿Ͱͽ΄῾‌‍⁰↉Ⰰ⿕、ퟻ﨎ﷇﷰ￯𐀀󠇯 . 3 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_assigned_nfc_bmp_PN_CHARS_BASE_character_boundaries.ttl: -------------------------------------------------------------------------------- 1 | @prefix p: . 2 | p:AZazÀÖØöø˿Ͱͽ΄῾‌‍⁰↉Ⰰ⿕、ퟻ﨎ﷇﷰ￯ . 3 | -------------------------------------------------------------------------------- /tests/turtle/predicateObjectList_with_two_objectLists.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-01.ttl: -------------------------------------------------------------------------------- 1 | # Turtle is not TriG 2 | { } 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-uri-02.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : bad escape 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-ln-colons.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | :s:1 :p:1 :o:1 . 3 | :s::2 :p::2 :o::2 . 4 | :3:s :3:p :3 . 5 | ::s ::p ::o . 6 | ::s: ::p: ::o: . 7 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_with_multiple_triples.ttl: -------------------------------------------------------------------------------- 1 | [ ; ] . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-LITERAL2_with_langtag_and_datatype.ttl: -------------------------------------------------------------------------------- 1 | "value"@en^^ . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-04.ttl: -------------------------------------------------------------------------------- 1 | # N3 paths 2 | @prefix : . 3 | @prefix ns: . 4 | 5 | :x^ns:p :p :z . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-uri-03.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : bad escape 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-datatypes-02.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix xsd: . 3 |

"123"^^xsd:string . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-bad-01.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : good escape, bad charcater 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/prefix_with_PN_CHARS_BASE_character_boundaries.ttl: -------------------------------------------------------------------------------- 1 | @prefix AZazÀÖØöø˿ͰͽͿ῿‌‍⁰↏Ⰰ⿯、퟿豈﷏ﷰ�𐀀󯿽: . 2 | AZazÀÖØöø˿ͰͽͿ῿‌‍⁰↏Ⰰ⿯、퟿豈﷏ﷰ�𐀀󯿽:o . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-uri-04.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : character escapes not allowed. 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-uri-05.ttl: -------------------------------------------------------------------------------- 1 | # Bad IRI : character escapes not allowed. 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL_with_UTF8_boundaries.nt: -------------------------------------------------------------------------------- 1 | "\u0080\u07FF\u0800\u0FFF\u1000\uCFFF\uD000\uD7FF\uE000\uFFFD\U00010000\U0003FFFD\U00040000\U000FFFFD\U00100000\U0010FFFD" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-prefix-06.ttl: -------------------------------------------------------------------------------- 1 | # colon is a legal pname character 2 | @prefix : . 3 | @prefix x: . 4 | :a:b:c x:d:e:f :::: . 5 | -------------------------------------------------------------------------------- /tests/turtle/two_LITERAL_LONG2s.ttl: -------------------------------------------------------------------------------- 1 | # Test long literal twice to ensure it does not over-quote 2 | @prefix : . 3 | :a :b """first long literal""" . 4 | :c :d """second long literal""" . 5 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_with_multiple_triples.nt: -------------------------------------------------------------------------------- 1 | _:b1 . 2 | _:b1 . 3 | _:b1 . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-n3-extras-03.ttl: -------------------------------------------------------------------------------- 1 | # N3 paths 2 | @prefix : . 3 | @prefix ns: . 4 | 5 | :x. 6 | ns:p. 7 | ns:q :p :z . 8 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-blank-label.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | _:0b :p :o . # Starts with digit 3 | _:_b :p :o . # Starts with underscore 4 | _:b.0 :p :o . # Contains dot, ends with digit 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-03.ttl: -------------------------------------------------------------------------------- 1 | # Turtle is not NQuads 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-22.nt: -------------------------------------------------------------------------------- 1 | "true"^^ . 2 | "false"^^ . 3 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/rychipman/easylex v0.0.0-20160129204217-49ee7767142f h1:L2/fBPABieQnQzfV40k2Zw7IcvZbt0CN5TgwUl8zDCs= 2 | github.com/rychipman/easylex v0.0.0-20160129204217-49ee7767142f/go.mod h1:MZ2GRTcqmve6EoSbErWgCR+Ash4p8Gc5esHe8MDErss= 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-02.ttl: -------------------------------------------------------------------------------- 1 | # Test @prefix and qnames 2 | @prefix : . 3 | @prefix a: . 4 | @prefix b: . 5 | :a :b :c . 6 | a:a a:b a:c . 7 | :a a:a b:a . 8 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-16.nt: -------------------------------------------------------------------------------- 1 | "\nthis \ris a \U00012451long\t\nliteral\uABCD\n" . 2 | "\tThis \uABCDis\r \U00012451another\n\none\n" . 3 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-uri-04.ttl: -------------------------------------------------------------------------------- 1 | # IRI with all chars in it. 2 | 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/LITERAL1_all_controls.nt: -------------------------------------------------------------------------------- 1 | "\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" . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-struct-02.ttl: -------------------------------------------------------------------------------- 1 | 2 | ; 3 | ; 4 | . 5 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_assigned_nfc_bmp_PN_CHARS_BASE_character_boundaries.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-eval-struct-02.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_nfc_PN_CHARS_BASE_character_boundaries.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/localName_with_assigned_nfc_PN_CHARS_BASE_character_boundaries.nt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-03.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-04.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/collection_object.nt: -------------------------------------------------------------------------------- 1 | _:el1 . 2 | _:el1 "1"^^ . 3 | _:el1 . 4 | -------------------------------------------------------------------------------- /tests/turtle/collection_subject.nt: -------------------------------------------------------------------------------- 1 | _:el1 "1"^^ . 2 | _:el1 . 3 | _:el1 . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-02.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-06.nt: -------------------------------------------------------------------------------- 1 | _:genid1 . 2 | _:genid1 . 3 | _:genid2 . 4 | _:genid2 . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-syntax-bad-struct-10.ttl: -------------------------------------------------------------------------------- 1 | # Too many DOT 2 | . . 3 | . 4 | -------------------------------------------------------------------------------- /tests/turtle/blankNodePropertyList_containing_collection.nt: -------------------------------------------------------------------------------- 1 | _:b1 _:el1 . 2 | _:el1 "1"^^ . 3 | _:el1 . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-12.nt: -------------------------------------------------------------------------------- 1 | "a" . 2 | "b" . 3 | "c" . 4 | "d" . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-19.nt: -------------------------------------------------------------------------------- 1 | "1.0"^^ . 2 | "1"^^ . 3 | "1.0e0"^^ . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-20.nt: -------------------------------------------------------------------------------- 1 | "-1.0"^^ . 2 | "-1"^^ . 3 | "-1.0e0"^^ . 4 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-11.ttl: -------------------------------------------------------------------------------- 1 | 000000 . 2 | 0 . 3 | 000001 . 4 | 2 . 5 | 4 . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-13.nt: -------------------------------------------------------------------------------- 1 | "1" . 2 | "2" . 3 | "def" . 4 | "678" . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-10.ttl: -------------------------------------------------------------------------------- 1 | # Test integer datatyped literals using an OWL cardinality constraint 2 | @prefix owl: . 3 | 4 | # based on examples in the OWL Reference 5 | 6 | _:hasParent a owl:ObjectProperty . 7 | 8 | [] a owl:Restriction ; 9 | owl:onProperty _:hasParent ; 10 | owl:maxCardinality 2 . 11 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-23.ttl: -------------------------------------------------------------------------------- 1 | # comment test 2 | @prefix : . 3 | :a :b :c . # end of line comment 4 | :d # ignore me 5 | :e # and me 6 | :f # and me 7 | . 8 | :g :h #ignore me 9 | :i, # and me 10 | :j . # and me 11 | 12 | :k :l :m ; #ignore me 13 | :n :o ; # and me 14 | :p :q . # and me 15 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-13.ttl: -------------------------------------------------------------------------------- 1 | # Tests for rdf:_ and other qnames starting with _ 2 | @prefix rdf: . 3 | @prefix ex: . 4 | @prefix : . 5 | 6 | ex:foo rdf:_1 "1" . 7 | ex:foo rdf:_2 "2" . 8 | ex:foo :_abc "def" . 9 | ex:foo :_345 "678" . 10 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-12.ttl: -------------------------------------------------------------------------------- 1 | # Tests for - and _ in names, qnames 2 | @prefix ex1: . 3 | @prefix ex-2: . 4 | @prefix ex3_: . 5 | @prefix ex4-: . 6 | 7 | ex1:foo-bar ex1:foo_bar "a" . 8 | ex-2:foo-bar ex-2:foo_bar "b" . 9 | ex3_:foo-bar ex3_:foo_bar "c" . 10 | ex4-:foo-bar ex4-:foo_bar "d" . 11 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-10.nt: -------------------------------------------------------------------------------- 1 | _:hasParent . 2 | _:genid1 . 3 | _:genid1 _:hasParent . 4 | _:genid1 "2"^^ . 5 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-08.nt: -------------------------------------------------------------------------------- 1 | _:genid1 "banana" . 2 | _:genid1 . 3 | _:genid2 "apple" . 4 | _:genid2 _:genid1 . 5 | _:genid2 . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-27.ttl: -------------------------------------------------------------------------------- 1 | # In-scope base URI is at this point 2 | . 3 | @base . 4 | # In-scope base URI is http://example.org/ns/ at this point 5 | . 6 | @base . 7 | # In-scope base URI is http://example.org/ns/foo/ at this point 8 | . 9 | @prefix : . 10 | :a4 :b4 :c4 . 11 | @prefix : . 12 | :a5 :b5 :c5 . 13 | -------------------------------------------------------------------------------- /tests/turtle/nested_collection.nt: -------------------------------------------------------------------------------- 1 | _:outerEl1 . 2 | _:outerEl1 _:innerEl1 . 3 | _:innerEl1 "1"^^ . 4 | _:innerEl1 . 5 | _:outerEl1 . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-27.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | . 5 | . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-16.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | ## \U00015678 is a not a legal codepoint 4 | ## :a :b """\nthis \ris a \U00015678long\t 5 | ## literal\uABCD 6 | ## """ . 7 | ## 8 | ## :d :e """\tThis \uABCDis\r \U00015678another\n 9 | ## one 10 | ## """ . 11 | 12 | # \U00015678 is a not a legal codepoint 13 | # \U00012451 in Cuneiform numeric ban 3 14 | :a :b """\nthis \ris a \U00012451long\t 15 | literal\uABCD 16 | """ . 17 | 18 | :d :e """\tThis \uABCDis\r \U00012451another\n 19 | one 20 | """ . 21 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-11.nt: -------------------------------------------------------------------------------- 1 | "000000"^^ . 2 | "0"^^ . 3 | "000001"^^ . 4 | "2"^^ . 5 | "4"^^ . 6 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-23.nt: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | . 5 | . 6 | . 7 | . 8 | -------------------------------------------------------------------------------- /tests/turtle/first.nt: -------------------------------------------------------------------------------- 1 | _:outerEl1 . 2 | _:outerEl1 _:innerEl1 . 3 | _:innerEl1 "1"^^ . 4 | _:innerEl1 . 5 | _:outerEl1 _:outerEl2 . 6 | _:outerEl2 "2"^^ . 7 | _:outerEl2 . 8 | -------------------------------------------------------------------------------- /tests/turtle/last.nt: -------------------------------------------------------------------------------- 1 | _:outerEl1 . 2 | _:outerEl1 "1"^^ . 3 | _:outerEl1 _:outerEl2 . 4 | _:outerEl2 _:innerEl1 . 5 | _:innerEl1 "2"^^ . 6 | _:innerEl1 . 7 | _:outerEl2 . 8 | -------------------------------------------------------------------------------- /lexer.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "github.com/rychipman/easylex" 5 | ) 6 | 7 | type lexer interface { 8 | NextToken() easylex.Token 9 | } 10 | 11 | type mockLexer struct { 12 | tokens []easylex.Token 13 | pos int 14 | } 15 | 16 | func newMockLexer(args ...easylex.Token) *mockLexer { 17 | return &mockLexer{ 18 | tokens: args, 19 | pos: 0, 20 | } 21 | } 22 | 23 | func (m *mockLexer) NextToken() easylex.Token { 24 | ret := m.tokens[m.pos] 25 | m.pos += 1 26 | return ret 27 | } 28 | 29 | type typeMockLexer struct { 30 | types []easylex.TokenType 31 | pos int 32 | } 33 | 34 | func newTypeMockLexer(args ...easylex.TokenType) *typeMockLexer { 35 | return &typeMockLexer{ 36 | types: args, 37 | pos: 0, 38 | } 39 | } 40 | 41 | func (m *typeMockLexer) NextToken() easylex.Token { 42 | typ := m.types[m.pos] 43 | m.pos += 1 44 | return easylex.Token{ 45 | typ, 46 | "n/a", 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /token.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "github.com/rychipman/easylex" 5 | ) 6 | 7 | const ( 8 | // tokens expressed as literal strings in http://www.w3.org/TR/turtle/#sec-grammar-grammar 9 | tokenAtPrefix easylex.TokenType = iota 10 | tokenAtBase 11 | tokenSPARQLPrefix 12 | tokenSPARQLBase 13 | tokenEndTriples 14 | tokenA // 5 15 | tokenPredicateListSeparator 16 | tokenObjectListSeparator 17 | tokenStartBlankNodePropertyList 18 | tokenEndBlankNodePropertyList 19 | tokenStartCollection // 10 20 | tokenEndCollection 21 | tokenLiteralDatatypeTag 22 | tokenTrue 23 | tokenFalse 24 | 25 | // terminal tokens from http://www.w3.org/TR/turtle/#terminals 26 | tokenIRIRef // 15 27 | tokenPNameNS 28 | tokenPNameLN 29 | tokenBlankNodeLabel 30 | tokenLangTag 31 | tokenInteger // 20 32 | tokenDecimal 33 | tokenDouble 34 | tokenExponent 35 | tokenStringLiteralQuote 36 | tokenStringLiteralSingleQuote // 25 37 | tokenStringLiteralLongQuote 38 | tokenStringLiteralLongSingleQuote 39 | tokenAnon 40 | ) 41 | -------------------------------------------------------------------------------- /rdf_test.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_unescapeUChar(t *testing.T) { 8 | tests := []struct { 9 | name string 10 | s string 11 | want string 12 | }{ 13 | { 14 | name: "on escapes", 15 | s: "simple", 16 | want: "simple", 17 | }, 18 | { 19 | name: "empty", 20 | s: "", 21 | want: "", 22 | }, 23 | { 24 | name: "single short escape", 25 | s: `ab\u0063de`, 26 | want: "abcde", 27 | }, 28 | { 29 | name: "single long escape", 30 | s: `ab\U00000063de`, 31 | want: "abcde", 32 | }, 33 | { 34 | name: "escaped short escape", 35 | s: `a \\user`, 36 | want: `a \\user`, 37 | }, 38 | { 39 | name: "escaped long escape", 40 | s: `a \\User`, 41 | want: `a \\User`, 42 | }, 43 | { 44 | name: "escaped escape before a short escape", 45 | s: `a \\\u0063lass`, 46 | want: `a \\class`, 47 | }, 48 | { 49 | name: "leading short escape", 50 | s: `\u0061bc`, 51 | want: "abc", 52 | }, 53 | { 54 | name: "leading escaped escape before a short escape", 55 | s: `\\\u0061bc`, 56 | want: `\\abc`, 57 | }, 58 | { 59 | name: "multiple escaped escapes", 60 | s: `a \\\\user`, 61 | want: `a \\\\user`, 62 | }, 63 | { 64 | name: "multiple short escapes", 65 | s: `an \u0061b\u0063 \\user`, 66 | want: `an abc \\user`, 67 | }, 68 | { 69 | name: "ending with escaped escape", 70 | s: `end\\u`, 71 | want: `end\\u`, 72 | }, 73 | } 74 | 75 | for _, tt := range tests { 76 | t.Run(tt.name, func(t *testing.T) { 77 | defer func() { 78 | if r := recover(); r != nil { 79 | t.Errorf("unescapeUChar(%s) = panic: %v", tt.s, r) 80 | } 81 | }() 82 | if got := unescapeUChar(tt.s); got != tt.want { 83 | t.Errorf("unescapeUChar(%s) = %v, want %v", tt.s, got, tt.want) 84 | } 85 | }) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-26.nt: -------------------------------------------------------------------------------- 1 | "2.345"^^ . 2 | "1"^^ . 3 | "1.0"^^ . 4 | "1."^^ . 5 | "1.000000000"^^ . 6 | "2.3"^^ . 7 | "2.234000005"^^ . 8 | "2.2340000005"^^ . 9 | "2.23400000005"^^ . 10 | "2.234000000005"^^ . 11 | "2.2340000000005"^^ . 12 | "2.23400000000005"^^ . 13 | "2.234000000000005"^^ . 14 | "2.2340000000000005"^^ . 15 | "2.23400000000000005"^^ . 16 | "2.234000000000000005"^^ . 17 | "2.2340000000000000005"^^ . 18 | "2.23400000000000000005"^^ . 19 | "2.234000000000000000005"^^ . 20 | "2.2340000000000000000005"^^ . 21 | "2.23400000000000000000005"^^ . 22 | "1.2345678901234567890123457890"^^ . 23 | -------------------------------------------------------------------------------- /tests/turtle/turtle-subm-26.ttl: -------------------------------------------------------------------------------- 1 | "2.345"^^ . 2 | "1"^^ . 3 | "1.0"^^ . 4 | "1."^^ . 5 | "1.000000000"^^ . 6 | "2.3"^^ . 7 | "2.234000005"^^ . 8 | "2.2340000005"^^ . 9 | "2.23400000005"^^ . 10 | "2.234000000005"^^ . 11 | "2.2340000000005"^^ . 12 | "2.23400000000005"^^ . 13 | "2.234000000000005"^^ . 14 | "2.2340000000000005"^^ . 15 | "2.23400000000000005"^^ . 16 | "2.234000000000000005"^^ . 17 | "2.2340000000000000005"^^ . 18 | "2.23400000000000000005"^^ . 19 | "2.234000000000000000005"^^ . 20 | "2.2340000000000000000005"^^ . 21 | "2.23400000000000000000005"^^ . 22 | "1.2345678901234567890123457890"^^ . 23 | -------------------------------------------------------------------------------- /tests/turtle/README: -------------------------------------------------------------------------------- 1 | This README is for the W3C RDF Working Group's Turtle test suite. 2 | This test suite contains four kinds of tests: 3 | 4 | 132 Evaluation (rdft:TestTurtleEval) - a pair of an input turtle 5 | file and reference ntriples file. 6 | 7 | 77 Positive syntax (rdft:TestTurtlePositiveSyntax) - an input turtle 8 | file with no syntax errors. 9 | 10 | 78 Negative syntax (rdft:TestTurtleNegativeSyntax) - an input turtle 11 | file with at least one syntax error. 12 | 13 | 4 Negative Evaluation (rdft:TestTurtleNegativeEval) - a pair of an 14 | input turtle file and reference ntriples file. These tests have the 15 | same properties as rdft:TestTurtleNegativeSyntax. 16 | 17 | The manifest.ttl file in this directory lists all of the tests in the 18 | RDF WG's Turtle test suite. Each test is one of the above tests. All 19 | tests have a name (mf:name) and an input (mf:action). The Evaluation 20 | tests have an expected result (mf:result). 21 | 22 | • An implementation passes an Evaluation test if it parses the input 23 | into a graph, parses the expecte result into another graph, and 24 | those two graphs are isomorphic (see 25 | ). 26 | 27 | • An implementation passes a positive syntax test if it parses the 28 | input. 29 | 30 | • An implementation passes a negative syntax test if it fails to parse 31 | the input. 32 | 33 | 34 | RELATIVE IRI RESOLUTION: 35 | 36 | The home of the test suite is . 37 | Per RFC 3986 section 5.1.3, the base IRI for parsing each file is the 38 | retrieval IRI for that file. For example, the tests turtle-subm-01 and 39 | turtle-subm-27 require relative IRI resolution against a base of 40 | and 41 | respectively. 42 | 43 | 44 | CHARACTER ENCODING: 45 | 46 | The Turtle language uses UTF-8 encoding. The following tests include 47 | non-ascii characters: 48 | localName_with_assigned_nfc_bmp_PN_CHARS_BASE_character_boundaries 49 | localName_with_assigned_nfc_PN_CHARS_BASE_character_boundaries * 50 | localName_with_nfc_PN_CHARS_BASE_character_boundaries * 51 | labeled_blank_node_with_PN_CHARS_BASE_character_boundaries * 52 | LITERAL1_with_UTF8_boundaries * 53 | LITERAL_LONG1_with_UTF8_boundaries * 54 | LITERAL2_with_UTF8_boundaries * 55 | LITERAL_LONG2_with_UTF8_boundaries * 56 | 57 | Those marked with a * include characters with codepoints greater than 58 | U+FFFD and are thus expressed as a pair of surrogate characters when 59 | represented in UCS2. 60 | 61 | 62 | See http://www.w3.org/2011/rdf-wg/wiki/Turtle_Test_Suite for more details. 63 | 64 | 65 | Eric Prud'hommeaux - 11 June 2013. 66 | -------------------------------------------------------------------------------- /matchers.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "github.com/rychipman/easylex" 5 | ) 6 | 7 | var ( 8 | matchPeriod = easylex.NewMatcher().AcceptRunes(".") 9 | matchComma = easylex.NewMatcher().AcceptRunes(",") 10 | matchSemicolon = easylex.NewMatcher().AcceptRunes(";") 11 | matchOpenBracket = easylex.NewMatcher().AcceptRunes("[") 12 | matchCloseBracket = easylex.NewMatcher().AcceptRunes("]") 13 | matchOpenParens = easylex.NewMatcher().AcceptRunes("(") 14 | matchCloseParens = easylex.NewMatcher().AcceptRunes(")") 15 | matchWhitespace = easylex.NewMatcher().AcceptRunes("\u0020\u0009\u000D\u000A") 16 | matchQuote = easylex.NewMatcher().AcceptRunes(`"`) 17 | matchSingleQuote = easylex.NewMatcher().AcceptRunes(`'`) 18 | matchLongQuote = easylex.NewMatcher().AcceptString(`"""`) 19 | matchLongSingleQuote = easylex.NewMatcher().AcceptString(`'''`) 20 | matchDoubleCaret = easylex.NewMatcher().AcceptString(`^^`) 21 | 22 | matchTrue = easylex.NewMatcher().AcceptString("true") 23 | matchFalse = easylex.NewMatcher().AcceptString("false") 24 | matchA = easylex.NewMatcher().AcceptRunes("a") 25 | matchSPARQLBase = easylex.NewMatcher().AcceptString("base").AcceptString("BASE") 26 | matchSPARQLPrefix = easylex.NewMatcher().AcceptString("prefix").AcceptString("PREFIX") 27 | 28 | matchEscapable = easylex.NewMatcher().AcceptRunes("_~.-!$&'()*+,;=/?#@%") 29 | matchHex = easylex.NewMatcher().AcceptRunes("0123456789abcdefABCDEF") 30 | matchDigits = easylex.NewMatcher().AcceptRunes("0123456789") 31 | matchAlphabet = easylex.NewMatcher().AcceptRunes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") 32 | matchAlphaNumeric = easylex.NewMatcher().AcceptRunes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") 33 | 34 | matchPNCharsBase = easylex.NewMatcher().AcceptRunes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").AcceptUnicodeRange(rune(0x00C0), rune(0x00D6)).AcceptUnicodeRange(rune(0x00D8), rune(0x00F6)).AcceptUnicodeRange(rune(0x00F8), rune(0x02FF)).AcceptUnicodeRange(rune(0x0370), rune(0x037D)).AcceptUnicodeRange(rune(0x037F), rune(0x1FFF)).AcceptUnicodeRange(rune(0x200C), rune(0x200D)).AcceptUnicodeRange(rune(0x2070), rune(0x218F)).AcceptUnicodeRange(rune(0x2C00), rune(0x2FEF)).AcceptUnicodeRange(rune(0x3001), rune(0xD7FF)).AcceptUnicodeRange(rune(0xF900), rune(0xFDCF)).AcceptUnicodeRange(rune(0xFDF0), rune(0xFFFD)).AcceptUnicodeRange(rune(0x10000), rune(0xEFFFF)) 35 | matchPNCharsU = easylex.NewMatcher().Union(matchPNCharsBase).AcceptRunes("_") 36 | matchPNChars = easylex.NewMatcher().Union(matchPNCharsU).Union(matchDigits).AcceptRunes("-\u00B7\u203F\u2040").AcceptUnicodeRange(rune(0x0300), rune(0x036F)) 37 | 38 | matchBareDecimalStart = easylex.NewMatcher().AcceptString(".0").AcceptString(".1").AcceptString(".2").AcceptString(".3").AcceptString(".4").AcceptString(".5").AcceptString(".6").AcceptString(".7").AcceptString(".8").AcceptString(".9") 39 | ) 40 | -------------------------------------------------------------------------------- /tests/turtle/LICENSE: -------------------------------------------------------------------------------- 1 | Summary 2 | ======= 3 | 4 | Distributed under both the W3C Test Suite License[1] and the W3C 3-clause BSD 5 | License[2]. To contribute to a W3C Test Suite, see the policies and contribution 6 | forms [3] 7 | 8 | 1. http://www.w3.org/Consortium/Legal/2008/04-testsuite-license 9 | 2. http://www.w3.org/Consortium/Legal/2008/03-bsd-license 10 | 3. http://www.w3.org/2004/10/27-testcases 11 | 12 | DISCLAIMER 13 | 14 | UNDER BOTH MUTUALLY EXCLUSIVE LICENSES, THIS DOCUMENT AND ALL DOCUMENTS, TESTS 15 | AND SOFTWARE THAT LINK THIS STATEMENT ARE PROVIDED "AS IS," AND COPYRIGHT 16 | HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, 17 | BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 18 | PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE 19 | SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT 20 | INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. 21 | COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR 22 | CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE 23 | OR IMPLEMENTATION OF THE CONTENTS THEREOF. 24 | 25 | 26 | W3C Test Suite License 27 | ====================== 28 | 29 | This document, Test Suites and other documents that link to this statement are 30 | provided by the copyright holders under the following license: By using and/or 31 | copying this document, or the W3C document from which this statement is linked, 32 | you (the licensee) agree that you have read, understood, and will comply with 33 | the following terms and conditions: 34 | 35 | Permission to copy, and distribute the contents of this document, or the W3C 36 | document from which this statement is linked, in any medium for any purpose and 37 | without fee or royalty is hereby granted, provided that you include the 38 | following on ALL copies of the document, or portions thereof, that you use: 39 | 40 | 1 A link or URL to the original W3C document. 41 | 42 | 2 The pre-existing copyright notice of the original author, or if it doesn't 43 | exist, a notice (hypertext is preferred, but a textual representation is 44 | permitted) of the form: "Copyright © [$date-of-document] World Wide Web 45 | Consortium, (Massachusetts Institute of Technology, European Research 46 | Consortium for Informatics and Mathematics, Keio University) and others. All 47 | Rights 48 | Reserved. http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html" 49 | 50 | 3 If it exists, the STATUS of the W3C document. 51 | 52 | 4 When space permits, inclusion of the full text of this NOTICE should be 53 | provided. We request that authorship attribution be provided in any software, 54 | documents, or other items or products that you create pursuant to the 55 | implementation of the contents of this document, or any portion thereof. 56 | 57 | 58 | No right to create modifications or derivatives of W3C documents is granted 59 | pursuant to this license. However, if additional requirements (documented in the 60 | Copyright FAQ) are satisfied, the right to create modifications or derivatives 61 | is sometimes granted by the W3C to individuals complying with those 62 | requirements. 63 | 64 | If a Test Suite distinguishes the test harness (or, framework for navigation) 65 | and the actual tests, permission is given to remove or alter the harness or 66 | navigation if the Test Suite in question allows to do so. The tests themselves 67 | shall NOT be changed in any way. 68 | 69 | The name and trademarks of W3C and other copyright holders may NOT be used in 70 | advertising or publicity pertaining to this document or other documents that 71 | link to this statement without specific, written prior permission. Title to 72 | copyright in this document will at all times remain with copyright 73 | holders. Permission is given to use the trademarked string W3C within claims of 74 | performance concerning W3C Specifications or features described therein, and 75 | there only, if the test suite so authorizes. 76 | 77 | THIS WORK IS PROVIDED BY W3C, MIT, ERCIM, KEIO UNIVERSITY, THE COPYRIGHT HOLDERS 78 | AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 79 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 80 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL W3C, MIT, ERCIM, KEIO 81 | UNIVERSITY, THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 82 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 83 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 84 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 85 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 86 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 87 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 88 | 89 | 90 | W3C 3-clause BSD License 91 | ======================== 92 | 93 | Redistribution and use in source and binary forms, with or without modification, 94 | are permitted provided that the following conditions are met: 95 | 96 | 1 Redistributions of works must retain the original copyright notice, this list 97 | of conditions and the following disclaimer. 98 | 99 | 2 Redistributions in binary form must reproduce the original copyright notice, 100 | this list of conditions and the following disclaimer in the documentation 101 | and/or other materials provided with the distribution. 102 | 103 | 3 Neither the name of the W3C nor the names of its contributors may be used to 104 | endorse or promote products derived from this work without specific prior 105 | written permission. 106 | 107 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 108 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 109 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 110 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 111 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 112 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 113 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 114 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 115 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 116 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 117 | 118 | -------------------------------------------------------------------------------- /isomorphism.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "crypto/sha1" 5 | "fmt" 6 | "sort" 7 | ) 8 | 9 | // algorithm: http://www.hpl.hp.com/techreports/2001/HPL-2001-293.pdf 10 | // also: http://blog.datagraph.org/2010/03/rdf-isomorphism 11 | 12 | type CanonicalGraph struct { 13 | graph *Graph 14 | nodes []Term 15 | bNodes []*BlankNode 16 | ungrounded map[*BlankNode]string 17 | grounded map[Term]string 18 | } 19 | 20 | func (g *Graph) Canonicalize() *CanonicalGraph { 21 | cg := &CanonicalGraph{ 22 | graph: g, 23 | nodes: g.NodesSorted(), 24 | ungrounded: make(map[*BlankNode]string), 25 | grounded: make(map[Term]string), 26 | } 27 | for _, n := range cg.nodes { 28 | if isBlankNode(n) { 29 | cg.bNodes = append(cg.bNodes, n.(*BlankNode)) 30 | } 31 | } 32 | return cg 33 | } 34 | 35 | func (cg1 *CanonicalGraph) IsomorphicTo(cg2 *CanonicalGraph) bool { 36 | // both graphs need same number of nodes 37 | if len(cg1.nodes) != len(cg2.nodes) { 38 | fmt.Println("Graphs not same size") 39 | return false 40 | } 41 | // make sure non-blank nodes match 42 | for i, n1 := range cg1.nodes { 43 | if !n1.Equals(cg2.nodes[i]) { 44 | fmt.Println("Graphs' non-blank nodes don't match") 45 | fmt.Printf("first: %+v\nsecond: %+v\n", cg1.nodes, cg2.nodes) 46 | return false 47 | } 48 | } 49 | // try to build a bijection between the graphs 50 | return cg1.BijectTo(cg2) 51 | } 52 | 53 | func (cg1 *CanonicalGraph) BijectTo(cg2 *CanonicalGraph) bool { 54 | // ground as many nodes as possible 55 | cg1.groundNodes() 56 | cg2.groundNodes() 57 | // ensure grounded nodes built at same rate 58 | if !cg1.verifyGrounded(cg2) { 59 | fmt.Println("verifyGrounded failed") 60 | return false 61 | } 62 | // map bnodes in cg1 to bnodes in cg2 63 | cg2UngroundedTmp := make(map[*BlankNode]string) 64 | for k, v := range cg2.ungrounded { 65 | cg2UngroundedTmp[k] = v 66 | } 67 | bijection := make(map[*BlankNode]*BlankNode) 68 | //fmt.Printf("ug1: %+v\nug2: %+v\n", cg1.ungrounded, cg2UngroundedTmp) 69 | for bn1, h1 := range cg1.ungrounded { 70 | for bn2, h2 := range cg2UngroundedTmp { 71 | if h2 == h1 { 72 | bijection[bn1] = bn2 73 | delete(cg2UngroundedTmp, bn2) 74 | } 75 | } 76 | } 77 | // if all nodes accounted for in mapping, success 78 | if cg1.validBijectionTo(bijection, cg2) { 79 | return true 80 | } 81 | 82 | // mark two ungrounded nodes with matching sigs as grounded and recurse 83 | for _, bn1 := range cg1.bNodes { 84 | if _, has := cg1.grounded[bn1]; has { 85 | fmt.Println("A") 86 | continue 87 | } 88 | for _, bn2 := range cg2.bNodes { 89 | if _, has := cg2.grounded[bn2]; has { 90 | fmt.Println("B") 91 | continue 92 | } 93 | if cg1.ungrounded[bn1] != cg2.ungrounded[bn2] { 94 | fmt.Println("C") 95 | continue 96 | } 97 | // try setting this pair as grounded 98 | hash := sha1.Sum([]byte(bn1.String())) 99 | cg1.grounded[bn1] = string(hash[:]) 100 | cg2.grounded[bn2] = string(hash[:]) 101 | fmt.Println("recursing") 102 | if cg1.BijectTo(cg2) { 103 | return true 104 | } 105 | // backtrack 106 | delete(cg1.grounded, bn1) 107 | delete(cg2.grounded, bn2) 108 | } 109 | } 110 | // if we have exhausted all signature matches, fail 111 | fmt.Println("signature matches exhausted") 112 | return false 113 | } 114 | 115 | func (cg1 *CanonicalGraph) validBijectionTo(bij map[*BlankNode]*BlankNode, cg2 *CanonicalGraph) bool { 116 | //fmt.Printf("bijmap: %+v\n", bij) 117 | nods1 := make([]Term, 0) 118 | nods2 := make([]Term, 0) 119 | cNods1 := make([]Term, 0) 120 | cNods2 := make([]Term, 0) 121 | for n1, n2 := range bij { 122 | nods1 = append(nods1, n1) 123 | nods2 = append(nods2, n2) 124 | } 125 | for _, n := range cg1.bNodes { 126 | cNods1 = append(cNods1, n) 127 | } 128 | for _, n := range cg2.bNodes { 129 | cNods2 = append(cNods2, n) 130 | } 131 | nodes1 := TermSlice(nods1) 132 | nodes2 := TermSlice(nods2) 133 | sort.Sort(nodes1) 134 | sort.Sort(nodes2) 135 | cNodes1 := TermSlice(cNods1) 136 | cNodes2 := TermSlice(cNods2) 137 | sort.Sort(cNodes1) 138 | sort.Sort(cNodes2) 139 | if len(nodes1) != len(cNodes1) || len(nodes2) != len(cNodes2) { 140 | fmt.Println("invalid bijection: lengths don't match") 141 | //fmt.Printf("%s\n%s\n%s\n%s\n", nodes1, cNodes1, nodes2, cNodes2) 142 | return false 143 | } 144 | for i := 0; i < len(nodes1); i++ { 145 | if nodes1[i] != cNodes1[i] { 146 | fmt.Println("invalid bijection: mismatched node") 147 | return false 148 | } 149 | if nodes2[i] != cNodes2[i] { 150 | fmt.Println("invalid bijection: mismatched node") 151 | return false 152 | } 153 | } 154 | return true 155 | } 156 | 157 | func (cg1 *CanonicalGraph) verifyGrounded(cg2 *CanonicalGraph) bool { 158 | for _, h1 := range cg1.grounded { 159 | found := false 160 | for _, h2 := range cg2.grounded { 161 | if h1 == h2 { 162 | found = true 163 | break 164 | } 165 | } 166 | if !found { 167 | return false 168 | } 169 | } 170 | for _, h2 := range cg2.grounded { 171 | found := false 172 | for _, h1 := range cg1.grounded { 173 | if h1 == h2 { 174 | found = true 175 | break 176 | } 177 | } 178 | if !found { 179 | return false 180 | } 181 | } 182 | return true 183 | } 184 | 185 | func (cg *CanonicalGraph) groundNodes() { 186 | //fmt.Printf("START\ngrounded: %+v\nungrounded: %+v\n", cg.grounded, cg.ungrounded) 187 | for { 188 | // note current num of grounded nodes 189 | startLen := len(cg.grounded) 190 | // mark nodes as grounded by their membership in triples 191 | for _, n := range cg.bNodes { 192 | if _, has := cg.grounded[n]; !has { 193 | fmt.Println("hashing a node") 194 | cg.hashNode(n) 195 | } 196 | } 197 | // TODO: do we need to ground nodes with unique signatures? 198 | // break if no new nodes have been grounded 199 | if len(cg.grounded) == startLen { 200 | break 201 | } 202 | } 203 | //fmt.Printf("grounded: %+v\nungrounded: %+v\nEND\n", cg.grounded, cg.ungrounded) 204 | } 205 | 206 | func (cg *CanonicalGraph) hashNode(bn *BlankNode) { 207 | tripleSignatures := make([]string, 0) 208 | grounded := true 209 | for trip := range cg.graph.IterTriples() { 210 | if trip.includes(bn) { 211 | tripleSignatures = append(tripleSignatures, cg.getHashString(trip, bn)) 212 | // if there are any other ungrounded blank nodes in this triple, 213 | // mark this blank node as ungrounded 214 | for term := range trip.IterNodes() { 215 | if isBlankNode(term) { 216 | bnod := term.(*BlankNode) 217 | _, present := cg.grounded[bnod] 218 | if !term.Equals(bn) && !present { 219 | grounded = false 220 | } 221 | } 222 | } 223 | } 224 | } 225 | sort.Strings(tripleSignatures) 226 | hash := sha1.Sum([]byte(fmt.Sprintf("%v", tripleSignatures))) 227 | if grounded { 228 | cg.grounded[bn] = string(hash[:]) 229 | } 230 | cg.ungrounded[bn] = string(hash[:]) 231 | } 232 | 233 | func (cg *CanonicalGraph) getHashString(t *Triple, n *BlankNode) string { 234 | str := "" 235 | for term := range t.IterNodes() { 236 | hash, grounded := cg.grounded[term] 237 | switch { 238 | case n == term: 239 | str += "itself" 240 | case grounded: 241 | str += hash 242 | case isBlankNode(n): 243 | str += "a blank node" 244 | default: 245 | str += n.String() 246 | } 247 | } 248 | return str 249 | } 250 | -------------------------------------------------------------------------------- /rdf.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strconv" 7 | "strings" 8 | "unicode/utf8" 9 | ) 10 | 11 | type Term interface { 12 | String() string 13 | Equals(Term) bool 14 | RawValue() string 15 | } 16 | 17 | // This must be a full (i.e. not relative IRI) 18 | type IRI struct { 19 | url string 20 | } 21 | 22 | func NewIRI(iri string) *IRI { 23 | return &IRI{ 24 | url: iri, 25 | } 26 | } 27 | 28 | func (i *IRI) String() string { 29 | if i == nil { 30 | return "" 31 | } 32 | return fmt.Sprintf("<%s>", i.url) 33 | } 34 | 35 | func (i *IRI) Equals(other Term) bool { 36 | switch other.(type) { 37 | case *IRI: 38 | break 39 | default: 40 | return false 41 | } 42 | return i.String() == other.String() 43 | } 44 | 45 | func (i *IRI) RawValue() string { 46 | return fmt.Sprintf("%s", i.url) 47 | } 48 | 49 | func newIRIFromString(s string) *IRI { 50 | url := iriRefToURL(s) 51 | return &IRI{url} 52 | } 53 | 54 | func iriRefToURL(s string) string { 55 | // strip <>, unescape, parse into url 56 | if strings.HasPrefix(s, "<") { 57 | s = s[1 : len(s)-1] 58 | } 59 | return unescapeUChar(s) 60 | } 61 | 62 | // see http://www.w3.org/TR/rdf11-concepts/#dfn-blank-node 63 | type BlankNode struct { 64 | Id int 65 | Label string 66 | } 67 | 68 | func NewBlankNode(label string) *BlankNode { 69 | return &BlankNode{ 70 | Label: label, 71 | } 72 | } 73 | 74 | func (b *BlankNode) String() string { 75 | return fmt.Sprintf("_:%s", b.Label) 76 | } 77 | 78 | func (b *BlankNode) Equals(other Term) bool { 79 | switch other.(type) { 80 | case *BlankNode: 81 | return true 82 | default: 83 | return false 84 | } 85 | panic("unreachable") 86 | } 87 | 88 | func (b *BlankNode) RawValue() string { 89 | return b.Label 90 | } 91 | 92 | func isBlankNode(t Term) bool { 93 | switch t.(type) { 94 | case *BlankNode: 95 | return true 96 | } 97 | return false 98 | } 99 | 100 | // see http://www.w3.org/TR/rdf11-concepts/#dfn-literal 101 | type Literal struct { 102 | LexicalForm string 103 | DatatypeIRI *IRI 104 | LanguageTag string 105 | } 106 | 107 | func NewLiteral(label string) *Literal { 108 | return &Literal{ 109 | LexicalForm: label, 110 | } 111 | } 112 | 113 | func NewLiteralWithDataType(label string, dtype *IRI) *Literal { 114 | return &Literal{ 115 | LexicalForm: label, 116 | DatatypeIRI: dtype, 117 | } 118 | } 119 | 120 | func NewLiteralWithLanguage(label string, lang string) *Literal { 121 | return &Literal{ 122 | LexicalForm: label, 123 | LanguageTag: lang, 124 | } 125 | } 126 | 127 | func (l *Literal) String() string { 128 | if l.LanguageTag != "" { 129 | return fmt.Sprintf("%q@%s", l.LexicalForm, l.LanguageTag) 130 | } 131 | return fmt.Sprintf("%q^^%s", l.LexicalForm, l.DatatypeIRI) 132 | } 133 | 134 | func (l *Literal) Equals(other Term) bool { 135 | switch other.(type) { 136 | case *Literal: 137 | break 138 | default: 139 | return false 140 | } 141 | otherLit := other.(*Literal) 142 | return l.LexicalForm == otherLit.LexicalForm && l.DatatypeIRI.Equals(otherLit.DatatypeIRI) && l.LanguageTag == otherLit.LanguageTag 143 | } 144 | 145 | func (l *Literal) RawValue() string { 146 | return l.LexicalForm 147 | } 148 | 149 | func lexicalForm(s string) string { 150 | var unquoted string 151 | if strings.HasPrefix(s, `"""`) || strings.HasPrefix(s, `'''`) { 152 | unquoted = s[3 : len(s)-3] 153 | } else { 154 | unquoted = s[1 : len(s)-1] 155 | } 156 | u := unescapeUChar(unquoted) 157 | ret := unescapeEChar(u) 158 | return ret 159 | } 160 | 161 | func unescapeEChar(s string) string { 162 | var replacements = []struct { 163 | old string 164 | new string 165 | }{ 166 | {`\t`, "\t"}, 167 | {`\b`, "\b"}, 168 | {`\n`, "\n"}, 169 | {`\r`, "\r"}, 170 | {`\f`, "\f"}, 171 | {`\"`, `"`}, 172 | {`\'`, `'`}, 173 | {`\\`, `\`}, 174 | } 175 | for _, r := range replacements { 176 | s = strings.Replace(s, r.old, r.new, -1) 177 | } 178 | return s 179 | } 180 | 181 | func getIndexOfEscape(s string, substr string) int { 182 | for { 183 | idx := strings.Index(s, substr) 184 | if idx < 0 { 185 | return idx 186 | } 187 | 188 | // search through runes backward from the index to ensure the escape isn't escaped 189 | var size int 190 | count := 1 191 | escapeRune := []rune(substr)[0] 192 | var r rune 193 | for i := idx; i > 0; i -= size { 194 | r, size = utf8.DecodeLastRuneInString(s[:i]) 195 | if r != escapeRune { 196 | break 197 | } 198 | count++ 199 | } 200 | 201 | // an odd number of escape characters indicates it's not escaped 202 | if count%2 == 1 { 203 | return idx 204 | } 205 | 206 | // skip that false match and check the rest of the string 207 | idx += len(substr) 208 | s = s[idx:] 209 | } 210 | } 211 | 212 | func unescapeUChar(s string) string { 213 | for { 214 | var start, hex, end string 215 | uIdx := getIndexOfEscape(s, `\u`) 216 | UIdx := getIndexOfEscape(s, `\U`) 217 | 218 | if uIdx >= 0 { 219 | start = s[:uIdx] 220 | if uIdx+6 > len(s) { 221 | hex = s[uIdx+2:] 222 | end = "" 223 | } else { 224 | hex = s[uIdx+2 : uIdx+6] 225 | end = s[uIdx+6:] 226 | } 227 | } else if UIdx >= 0 { 228 | start = s[:UIdx] 229 | if UIdx+10 > len(s) { 230 | hex = s[UIdx+2:] 231 | end = "" 232 | } else { 233 | hex = s[UIdx+2 : UIdx+10] 234 | end = s[UIdx+10:] 235 | } 236 | } else { 237 | break 238 | } 239 | num, err := strconv.ParseInt(hex, 16, 32) 240 | if err != nil { 241 | panic(err) // TODO: this shouldn't happen 242 | } 243 | s = fmt.Sprintf("%s%s%s", start, string(rune(num)), end) 244 | } 245 | return s 246 | } 247 | 248 | // see http://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple 249 | type Triple struct { 250 | Subject, Predicate, Object Term 251 | } 252 | 253 | func (t *Triple) String() string { 254 | return fmt.Sprintf("%s %s %s .", t.Subject, t.Predicate, t.Object) 255 | } 256 | 257 | func (t *Triple) includes(term Term) bool { 258 | for node := range t.IterNodes() { 259 | if node.Equals(term) { 260 | return true 261 | } 262 | } 263 | return false 264 | } 265 | 266 | func (t *Triple) IterNodes() <-chan Term { 267 | ch := make(chan Term, 3) 268 | ch <- t.Subject 269 | ch <- t.Predicate 270 | ch <- t.Object 271 | close(ch) 272 | return ch 273 | } 274 | 275 | // An RDF graph is a set of RDF triples 276 | type Graph struct { 277 | triples []*Triple 278 | uri *IRI 279 | } 280 | 281 | func (g *Graph) IsomorphicTo(other *Graph) bool { 282 | cg1 := g.Canonicalize() 283 | cg2 := other.Canonicalize() 284 | return cg1.IsomorphicTo(cg2) 285 | } 286 | 287 | func (g *Graph) String() string { 288 | str := "" 289 | i := -1 290 | for t := range g.IterTriples() { 291 | i += 1 292 | if i > 0 { 293 | str += "\n" 294 | } 295 | str = fmt.Sprintf("%s%s", str, t) 296 | } 297 | return str 298 | } 299 | 300 | func (g *Graph) IterTriples() <-chan *Triple { 301 | ch := make(chan *Triple) 302 | go func() { 303 | for _, trip := range g.triples { 304 | ch <- trip 305 | } 306 | close(ch) 307 | }() 308 | return ch 309 | } 310 | 311 | func (g *Graph) NodesSorted() []Term { 312 | set := make(map[string]Term) 313 | for t := range g.IterTriples() { 314 | for n := range t.IterNodes() { 315 | if _, has := set[n.String()]; !has { 316 | set[n.String()] = n 317 | } 318 | } 319 | } 320 | terms := make([]Term, 0) 321 | for _, t := range set { 322 | terms = append(terms, t) 323 | } 324 | termsSlice := TermSlice(terms) 325 | sort.Sort(termsSlice) 326 | fmt.Printf("nodes before sort: %+v\nafter: %+v\n", terms, termsSlice) 327 | return termsSlice 328 | } 329 | 330 | type TermSlice []Term 331 | 332 | func (ts TermSlice) Len() int { 333 | return len(ts) 334 | } 335 | 336 | func (ts TermSlice) Less(i, j int) bool { 337 | iNode := ts[i] 338 | jNode := ts[j] 339 | iPriority := 0 340 | jPriority := 0 341 | switch iNode.(type) { 342 | case *BlankNode: 343 | iPriority = 1 344 | case *Literal: 345 | iPriority = 2 346 | case *IRI: 347 | iPriority = 3 348 | } 349 | switch jNode.(type) { 350 | case *BlankNode: 351 | jPriority = 1 352 | case *Literal: 353 | jPriority = 2 354 | case *IRI: 355 | jPriority = 3 356 | } 357 | if iPriority > jPriority { 358 | return true 359 | } else if jPriority > iPriority { 360 | return false 361 | } 362 | return strings.Compare(iNode.String(), jNode.String()) > 0 363 | } 364 | 365 | func (ts TermSlice) Swap(i, j int) { 366 | iNode := ts[i] 367 | jNode := ts[j] 368 | ts[i] = jNode 369 | ts[j] = iNode 370 | } 371 | -------------------------------------------------------------------------------- /statefns.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/rychipman/easylex" 7 | ) 8 | 9 | const ( 10 | eof = -1 11 | ) 12 | 13 | func lexDocument(l *easylex.Lexer) easylex.StateFn { 14 | matchWhitespace.MatchRun(l) 15 | l.Ignore() 16 | switch l.Peek() { 17 | case easylex.EOF: 18 | l.Emit(easylex.TokenEOF) 19 | return nil 20 | case '#': 21 | return lexComment 22 | case '@': 23 | return lexAtStatement 24 | case '_': 25 | return lexBlankNodeLabel 26 | case '<': 27 | return lexIRIRef 28 | case '"', '\'': 29 | return lexRDFLiteral 30 | case '.': 31 | if matchBareDecimalStart.Peek(l) { 32 | return lexNumericLiteral 33 | } 34 | return lexPunctuation 35 | case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 36 | return lexNumericLiteral 37 | case '[': 38 | // anon 39 | l.Next() 40 | matchWhitespace.MatchRun(l) 41 | if matchCloseBracket.MatchOne(l) { 42 | l.Emit(tokenAnon) 43 | return lexDocument 44 | } 45 | l.Emit(tokenStartBlankNodePropertyList) 46 | return lexDocument 47 | case '^', ']', '(', ')', ';', ',': 48 | return lexPunctuation 49 | case 't', 'f', 'a', 'b', 'B', 'p', 'P': 50 | if matchTrue.MatchOne(l) { 51 | if isWhitespaceOrPunctuation(l.Peek()) { 52 | l.Emit(tokenTrue) 53 | return lexDocument 54 | } 55 | } 56 | if matchFalse.MatchOne(l) { 57 | if isWhitespaceOrPunctuation(l.Peek()) { 58 | l.Emit(tokenFalse) 59 | return lexDocument 60 | } 61 | } 62 | if matchA.MatchOne(l) { 63 | if isWhitespace(l.Peek()) { 64 | l.Emit(tokenA) 65 | return lexDocument 66 | } 67 | } 68 | if matchSPARQLBase.MatchOne(l) { 69 | if isWhitespace(l.Peek()) { 70 | l.Emit(tokenSPARQLBase) 71 | return lexDocument 72 | } 73 | } 74 | if matchSPARQLPrefix.MatchOne(l) { 75 | if isWhitespace(l.Peek()) { 76 | l.Emit(tokenSPARQLPrefix) 77 | return lexDocument 78 | } 79 | } 80 | fallthrough 81 | default: 82 | return lexPName 83 | } 84 | panic("unreachable") 85 | } 86 | 87 | func isWhitespace(r rune) bool { 88 | if strings.IndexRune("\n\r\t\v\f ", r) >= 0 { 89 | return true 90 | } 91 | return false 92 | } 93 | 94 | func isWhitespaceOrPunctuation(r rune) bool { 95 | if strings.IndexRune("\n\r\t\v\f.;, ", r) >= 0 { 96 | return true 97 | } 98 | return false 99 | } 100 | 101 | func lexComment(l *easylex.Lexer) easylex.StateFn { 102 | easylex.NewMatcher().AcceptRunes("#").AssertOne(l, "Expected '#' while lexing comment") 103 | easylex.NewMatcher().RejectRunes("\n").MatchRun(l) 104 | l.Ignore() 105 | return lexDocument 106 | } 107 | 108 | func lexAtStatement(l *easylex.Lexer) easylex.StateFn { 109 | easylex.NewMatcher().AcceptRunes("@").AssertOne(l, "Expected '@' while lexing AtStatement") 110 | if easylex.NewMatcher().AcceptString("prefix").MatchOne(l) { 111 | if isWhitespace(l.Peek()) { 112 | l.Emit(tokenAtPrefix) 113 | return lexDocument 114 | } 115 | } 116 | if easylex.NewMatcher().AcceptString("base").MatchOne(l) { 117 | if isWhitespace(l.Peek()) { 118 | l.Emit(tokenAtBase) 119 | return lexDocument 120 | } 121 | } 122 | matchAlphabet.AssertRun(l, "Expected alphabet while lexing AtStatement") 123 | for { 124 | hyphen := easylex.NewMatcher().AcceptRunes("-").MatchOne(l) 125 | alph := matchAlphaNumeric.MatchRun(l) 126 | if !hyphen && !alph { 127 | break 128 | } 129 | if hyphen != alph { 130 | // TODO: error 131 | } 132 | } 133 | l.Emit(tokenLangTag) 134 | return lexDocument 135 | } 136 | 137 | func lexBlankNodeLabel(l *easylex.Lexer) easylex.StateFn { 138 | easylex.NewMatcher().AcceptRunes("_").AssertOne(l, "Expected '_' while lexing bnode label") 139 | easylex.NewMatcher().AcceptRunes(":").AssertOne(l, "Expected ':' while lexing bnode label") 140 | easylex.NewMatcher().Union(matchPNCharsU).Union(matchDigits).AssertOne(l, "Expected pncharsu or digit while lexing bnode label") 141 | easylex.NewMatcher().Union(matchPNChars).AcceptRunes(".").MatchLookAheadRun(l, easylex.NewMatcher().Union(matchPNChars).AcceptRunes(".")) 142 | matchPNChars.MatchRun(l) 143 | l.Emit(tokenBlankNodeLabel) 144 | return lexDocument 145 | } 146 | 147 | func lexIRIRef(l *easylex.Lexer) easylex.StateFn { 148 | easylex.NewMatcher().AcceptRunes("<").AssertOne(l, "Expected '<' while lexing iriref") 149 | iriChars := easylex.NewMatcher().RejectRunes("<>\"{}|^`\\\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f\u0020") 150 | for { 151 | m1 := iriChars.MatchRun(l) 152 | if l.Peek() == '\\' { 153 | l.Next() 154 | if l.Peek() == 'u' { 155 | l.Next() 156 | for i := 0; i < 4; i += 1 { 157 | matchHex.AssertOne(l, "Expected hex digit while lexing iriref") 158 | } 159 | } else if l.Peek() == 'U' { 160 | l.Next() 161 | for i := 0; i < 8; i += 1 { 162 | matchHex.AssertOne(l, "Expected hex digit while lexing iriref") 163 | } 164 | } else { 165 | // TODO: error 166 | } 167 | } else if !m1 { 168 | break 169 | } 170 | } 171 | easylex.NewMatcher().AcceptRunes(">").AssertOne(l, "Expected '>' while lexing iriref") 172 | l.Emit(tokenIRIRef) 173 | return lexDocument 174 | } 175 | 176 | func lexRDFLiteral(l *easylex.Lexer) easylex.StateFn { 177 | if matchLongQuote.MatchOne(l) { 178 | for { 179 | if matchLongQuote.MatchOne(l) { 180 | break 181 | } 182 | q := matchQuote.MatchOne(l) 183 | q = matchQuote.MatchOne(l) || q 184 | ch := true 185 | if easylex.NewMatcher().RejectRunes(`"\`).MatchOne(l) { 186 | // do nothing 187 | } else if l.Peek() == '\\' { 188 | l.Next() 189 | switch l.Peek() { 190 | case 'u': 191 | l.Next() 192 | for i := 0; i < 4; i += 1 { 193 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 194 | } 195 | case 'U': 196 | l.Next() 197 | for i := 0; i < 8; i += 1 { 198 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 199 | } 200 | case 't', 'b', 'n', 'r', 'f', '"', '\'', '\\': 201 | l.Next() 202 | default: 203 | ch = false 204 | } 205 | } 206 | if q && !ch { 207 | // TODO: error 208 | } 209 | } 210 | l.Emit(tokenStringLiteralLongQuote) 211 | return lexDocument 212 | } 213 | if matchLongSingleQuote.MatchOne(l) { 214 | for { 215 | if matchLongSingleQuote.MatchOne(l) { 216 | break 217 | } 218 | q := matchSingleQuote.MatchOne(l) 219 | q = matchSingleQuote.MatchOne(l) || q 220 | ch := true 221 | if easylex.NewMatcher().RejectRunes(`'\`).MatchOne(l) { 222 | // do nothing 223 | } else if l.Peek() == '\\' { 224 | l.Next() 225 | switch l.Peek() { 226 | case 'u': 227 | l.Next() 228 | for i := 0; i < 4; i += 1 { 229 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 230 | } 231 | case 'U': 232 | l.Next() 233 | for i := 0; i < 8; i += 1 { 234 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 235 | } 236 | case 't', 'b', 'n', 'r', 'f', '"', '\'', '\\': 237 | l.Next() 238 | default: 239 | ch = false 240 | } 241 | } 242 | if !q && !ch { 243 | break 244 | } 245 | } 246 | l.Emit(tokenStringLiteralLongSingleQuote) 247 | return lexDocument 248 | } 249 | if matchQuote.MatchOne(l) { 250 | for { 251 | if easylex.NewMatcher().RejectRunes("\u0022\u005c\u000a\u000d").MatchOne(l) { 252 | // do nothing 253 | } else if l.Peek() == '\\' { 254 | l.Next() 255 | switch l.Peek() { 256 | case 'u': 257 | l.Next() 258 | for i := 0; i < 4; i += 1 { 259 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 260 | } 261 | case 'U': 262 | l.Next() 263 | for i := 0; i < 8; i += 1 { 264 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 265 | } 266 | case 't', 'b', 'n', 'r', 'f', '"', '\'', '\\': 267 | l.Next() 268 | default: 269 | break 270 | } 271 | } else { 272 | break 273 | } 274 | } 275 | matchQuote.AssertOne(l, "Expected '\"' while lexing RDF Literal") 276 | l.Emit(tokenStringLiteralQuote) 277 | return lexDocument 278 | } 279 | if matchSingleQuote.MatchOne(l) { 280 | for { 281 | if easylex.NewMatcher().RejectRunes("\u0027\u005c\u000a\u000d").MatchOne(l) { 282 | // do nothing 283 | } else if l.Peek() == '\\' { 284 | l.Next() 285 | switch l.Peek() { 286 | case 'u': 287 | l.Next() 288 | for i := 0; i < 4; i += 1 { 289 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 290 | } 291 | case 'U': 292 | l.Next() 293 | for i := 0; i < 8; i += 1 { 294 | matchHex.AssertOne(l, "Expected hex digit while lexing RDF Literal") 295 | } 296 | case 't', 'b', 'n', 'r', 'f', '"', '\'', '\\': 297 | l.Next() 298 | default: 299 | break 300 | } 301 | } else { 302 | break 303 | } 304 | } 305 | matchSingleQuote.AssertOne(l, "Expected \"'\" while lexing RDF Literal") 306 | l.Emit(tokenStringLiteralSingleQuote) 307 | return lexDocument 308 | } 309 | panic("unreachable") 310 | } 311 | 312 | func lexNumericLiteral(l *easylex.Lexer) easylex.StateFn { 313 | easylex.NewMatcher().AcceptRunes("+-").MatchOne(l) 314 | if matchDigits.MatchRun(l) { 315 | if easylex.NewMatcher().AcceptRunes("eE").MatchOne(l) { 316 | easylex.NewMatcher().AcceptRunes("+-").MatchOne(l) 317 | matchDigits.AssertRun(l, "Expected digits while lexing numeric literal") 318 | l.Emit(tokenDouble) 319 | return lexDocument 320 | } else if matchPeriod.MatchLookAhead(l, easylex.NewMatcher().AcceptRunes("0123456789eE")) { 321 | if matchDigits.MatchRun(l) { 322 | if isWhitespace(l.Peek()) { 323 | l.Emit(tokenDecimal) 324 | return lexDocument 325 | } 326 | } 327 | easylex.NewMatcher().AcceptRunes("eE").AssertOne(l, "Expected 'e' or 'E' while lexing numeric literal") 328 | easylex.NewMatcher().AcceptRunes("+-").MatchOne(l) 329 | matchDigits.AssertRun(l, "Expected digits while lexing numeric literal") 330 | l.Emit(tokenDouble) 331 | return lexDocument 332 | } else { 333 | l.Emit(tokenInteger) 334 | return lexDocument 335 | } 336 | } else { 337 | matchPeriod.AssertOne(l, "Expected '.' while lexing numeric literal") 338 | matchDigits.AssertRun(l, "Expected digits while lexing numeric literal") 339 | if easylex.NewMatcher().AcceptRunes("eE").MatchOne(l) { 340 | easylex.NewMatcher().AcceptRunes("+-").MatchOne(l) 341 | matchDigits.AssertRun(l, "Expected digits while lexing numeric literal") 342 | l.Emit(tokenDouble) 343 | return lexDocument 344 | } 345 | l.Emit(tokenDecimal) 346 | return lexDocument 347 | } 348 | } 349 | 350 | func lexPunctuation(l *easylex.Lexer) easylex.StateFn { 351 | // ^ ] ( ) ; , . 352 | if matchDoubleCaret.MatchOne(l) { 353 | l.Emit(tokenLiteralDatatypeTag) 354 | } else if matchCloseBracket.MatchOne(l) { 355 | l.Emit(tokenEndBlankNodePropertyList) 356 | } else if matchOpenParens.MatchOne(l) { 357 | l.Emit(tokenStartCollection) 358 | } else if matchCloseParens.MatchOne(l) { 359 | l.Emit(tokenEndCollection) 360 | } else if matchSemicolon.MatchOne(l) { 361 | l.Emit(tokenPredicateListSeparator) 362 | } else if matchComma.MatchOne(l) { 363 | l.Emit(tokenObjectListSeparator) 364 | } else if matchPeriod.MatchOne(l) { 365 | l.Emit(tokenEndTriples) 366 | } else { 367 | // TODO: error 368 | } 369 | return lexDocument 370 | } 371 | 372 | func lexPName(l *easylex.Lexer) easylex.StateFn { 373 | // accept PN_PREFIX 374 | matchPNCharsBase.MatchOne(l) 375 | for { 376 | period := matchPeriod.MatchRun(l) 377 | pnchars := matchPNChars.MatchRun(l) 378 | if !pnchars { 379 | if period { 380 | // TODO: error 381 | } 382 | break 383 | } 384 | } 385 | 386 | easylex.NewMatcher().AcceptRunes(":").AssertOne(l, "Expected ':' while lexing pname") 387 | // TODO: get exhaustive list of "end" chars 388 | // TODO: factor this out into a matcher 389 | if easylex.NewMatcher().AcceptRunes("\n\r\t\v\f ;,.#").Peek(l) { 390 | l.Emit(tokenPNameNS) 391 | return lexDocument 392 | } 393 | // accept PN_LOCAL 394 | if l.Peek() == '\\' { 395 | l.Next() 396 | matchEscapable.AssertOne(l, "Expected escapable while lexing pname") 397 | } else if l.Peek() == '%' { 398 | l.Next() 399 | matchHex.AssertOne(l, "Expected hex digit while lexing pname") 400 | matchHex.AssertOne(l, "Expected hex digit while lexing pname") 401 | } else { 402 | easylex.NewMatcher().AcceptRunes(":").Union(matchPNCharsU).Union(matchDigits).AssertOne(l, "Expected ':', pncharsu, or digits while lexing pname") 403 | } 404 | for { 405 | m := easylex.NewMatcher().Union(matchPNChars).AcceptRunes(".:").MatchLookAheadRun(l, easylex.NewMatcher().Union(matchPNChars).AcceptRunes(`.:\%`)) 406 | for { 407 | switch l.Peek() { 408 | case '\\': 409 | l.Next() 410 | matchEscapable.AssertOne(l, "Expected escapable while lexing pname") 411 | continue 412 | case '%': 413 | l.Next() 414 | matchHex.AssertOne(l, "Expected hex digit while lexing pname") 415 | matchHex.AssertOne(l, "Expected hex digit while lexing pname") 416 | continue 417 | } 418 | break 419 | } 420 | if !m { 421 | break 422 | } 423 | } 424 | easylex.NewMatcher().Union(matchPNChars).AcceptRunes(":").MatchRun(l) 425 | l.Emit(tokenPNameLN) 426 | return lexDocument 427 | } 428 | -------------------------------------------------------------------------------- /ttl_test.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "testing" 8 | ) 9 | 10 | func TestTurtlePositive(t *testing.T) { 11 | 12 | verbosity := 1 13 | 14 | for _, testName := range positiveParserTests { 15 | basePath := "./tests/turtle/" 16 | ttlFile := basePath + testName + ".ttl" 17 | ntFile := basePath + testName + ".nt" 18 | // ttlFd, err := os.Open(ttlFile) 19 | ttlFd, err := ioutil.ReadFile(ttlFile) 20 | if err != nil { 21 | t.Fatalf("Error reading file %s", ttlFile) 22 | } 23 | ttlReader := bytes.NewReader(ttlFd) 24 | ntFd, err := ioutil.ReadFile(ntFile) 25 | if err != nil { 26 | t.Fatalf("Error reading file %s", ntFile) 27 | } 28 | ntReader := bytes.NewReader(ntFd) 29 | if verbosity > 0 { 30 | fmt.Printf("\nStarting test %s\n", testName) 31 | } 32 | ttlGraph, err := NewParser("").Parse(ttlReader) 33 | if err != nil { 34 | t.Fatalf("Test %s failed. Error parsing %s\n(%s)", testName, ttlFile, err) 35 | } 36 | ntGraph, err := NewParser("").Parse(ntReader) 37 | if err != nil { 38 | t.Fatalf("Test %s failed. Error parsing %s\n(%s)", testName, ntFile, err) 39 | } 40 | if !ntGraph.IsomorphicTo(ttlGraph) { 41 | t.Fatalf("Test %s failed. Graphs not isomorphic.\nttl graph:\n%s\nnt graph:\n%s", testName, ttlGraph, ntGraph) 42 | } 43 | if verbosity > 0 { 44 | fmt.Printf("Test %s passed.\n", testName) 45 | } 46 | } 47 | } 48 | 49 | func TestTurtlePositiveNoIso(t *testing.T) { 50 | 51 | verbosity := 0 52 | 53 | for _, testName := range positiveParserTestsNoIso { 54 | basePath := "./tests/turtle/" 55 | ttlFile := basePath + testName + ".ttl" 56 | ttlBytes, err := ioutil.ReadFile(ttlFile) 57 | if err != nil { 58 | t.Fatalf("Error reading file %s", ttlFile) 59 | } 60 | if verbosity > 0 { 61 | fmt.Printf("\nStarting test %s\n", testName) 62 | } 63 | ttlReader := bytes.NewReader(ttlBytes) 64 | _, err = NewParser("").Parse(ttlReader) 65 | if err != nil { 66 | t.Fatalf("Test %s failed. Error parsing %s\n(%s)", testName, ttlFile, err) 67 | } 68 | if verbosity > 0 { 69 | fmt.Printf("Test %s passed.\n", testName) 70 | } 71 | } 72 | } 73 | 74 | func TestTurtleNegative(t *testing.T) { 75 | verbosity := 0 76 | for _, testName := range negativeParserTests { 77 | testFile := "./tests/turtle/" + testName 78 | b, err := ioutil.ReadFile(testFile) 79 | if err != nil { 80 | t.Fatalf("Error reading test file %s", testFile) 81 | } 82 | br := bytes.NewReader(b) 83 | if verbosity > 0 { 84 | fmt.Printf("\nStarting test %s\n", testName) 85 | } 86 | p := NewParser("") 87 | _, err = p.Parse(br) 88 | if err == nil { 89 | t.Fatalf("Test %s failed: %s", testName, err) 90 | } 91 | if verbosity > 0 { 92 | fmt.Printf("Test %s passed.\n", testName) 93 | } 94 | } 95 | } 96 | 97 | var negativeParserTests []string = []string{ 98 | // TODO: unicode escaped chars must conform to rules 99 | //"turtle-eval-bad-01.ttl", 100 | //"turtle-eval-bad-02.ttl", 101 | //"turtle-eval-bad-03.ttl", 102 | "turtle-eval-bad-04.ttl", 103 | "turtle-syntax-bad-base-01.ttl", 104 | "turtle-syntax-bad-base-02.ttl", 105 | "turtle-syntax-bad-base-03.ttl", 106 | "turtle-syntax-bad-blank-label-dot-end.ttl", 107 | // TODO: not failing bad string escapes 108 | //"turtle-syntax-bad-esc-01.ttl", 109 | // TODO: causing deadlock 110 | //"turtle-syntax-bad-esc-02.ttl", 111 | //"turtle-syntax-bad-esc-03.ttl", 112 | //"turtle-syntax-bad-esc-04.ttl", 113 | "turtle-syntax-bad-kw-01.ttl", 114 | "turtle-syntax-bad-kw-02.ttl", 115 | "turtle-syntax-bad-kw-03.ttl", 116 | "turtle-syntax-bad-kw-04.ttl", 117 | "turtle-syntax-bad-kw-05.ttl", 118 | "turtle-syntax-bad-lang-01.ttl", 119 | "turtle-syntax-bad-LITERAL2_with_langtag_and_datatype.ttl", 120 | "turtle-syntax-bad-ln-dash-start.ttl", 121 | "turtle-syntax-bad-ln-escape-start.ttl", 122 | "turtle-syntax-bad-ln-escape.ttl", 123 | "turtle-syntax-bad-missing-ns-dot-end.ttl", 124 | "turtle-syntax-bad-missing-ns-dot-start.ttl", 125 | "turtle-syntax-bad-n3-extras-01.ttl", 126 | "turtle-syntax-bad-n3-extras-02.ttl", 127 | "turtle-syntax-bad-n3-extras-03.ttl", 128 | // TODO: hangs 129 | //"turtle-syntax-bad-n3-extras-04.ttl", 130 | "turtle-syntax-bad-n3-extras-05.ttl", 131 | "turtle-syntax-bad-n3-extras-06.ttl", 132 | "turtle-syntax-bad-n3-extras-07.ttl", 133 | "turtle-syntax-bad-n3-extras-08.ttl", 134 | "turtle-syntax-bad-n3-extras-09.ttl", 135 | "turtle-syntax-bad-n3-extras-10.ttl", 136 | "turtle-syntax-bad-n3-extras-11.ttl", 137 | "turtle-syntax-bad-n3-extras-12.ttl", 138 | "turtle-syntax-bad-n3-extras-13.ttl", 139 | "turtle-syntax-bad-ns-dot-end.ttl", 140 | "turtle-syntax-bad-ns-dot-start.ttl", 141 | "turtle-syntax-bad-num-01.ttl", 142 | "turtle-syntax-bad-num-02.ttl", 143 | "turtle-syntax-bad-num-03.ttl", 144 | "turtle-syntax-bad-num-04.ttl", 145 | "turtle-syntax-bad-num-05.ttl", 146 | "turtle-syntax-bad-number-dot-in-anon.ttl", 147 | "turtle-syntax-bad-pname-01.ttl", 148 | "turtle-syntax-bad-pname-02.ttl", 149 | "turtle-syntax-bad-pname-03.ttl", 150 | "turtle-syntax-bad-prefix-01.ttl", 151 | "turtle-syntax-bad-prefix-02.ttl", 152 | "turtle-syntax-bad-prefix-03.ttl", 153 | "turtle-syntax-bad-prefix-04.ttl", 154 | "turtle-syntax-bad-prefix-05.ttl", 155 | "turtle-syntax-bad-string-01.ttl", 156 | "turtle-syntax-bad-string-02.ttl", 157 | // TODO: hangs 158 | //"turtle-syntax-bad-string-03.ttl", 159 | //"turtle-syntax-bad-string-04.ttl", 160 | //"turtle-syntax-bad-string-05.ttl", 161 | "turtle-syntax-bad-string-06.ttl", 162 | "turtle-syntax-bad-string-07.ttl", 163 | "turtle-syntax-bad-struct-01.ttl", 164 | "turtle-syntax-bad-struct-02.ttl", 165 | "turtle-syntax-bad-struct-03.ttl", 166 | "turtle-syntax-bad-struct-04.ttl", 167 | "turtle-syntax-bad-struct-05.ttl", 168 | "turtle-syntax-bad-struct-06.ttl", 169 | "turtle-syntax-bad-struct-07.ttl", 170 | "turtle-syntax-bad-struct-08.ttl", 171 | "turtle-syntax-bad-struct-09.ttl", 172 | "turtle-syntax-bad-struct-10.ttl", 173 | "turtle-syntax-bad-struct-11.ttl", 174 | "turtle-syntax-bad-struct-12.ttl", 175 | "turtle-syntax-bad-struct-13.ttl", 176 | "turtle-syntax-bad-struct-14.ttl", 177 | "turtle-syntax-bad-struct-15.ttl", 178 | "turtle-syntax-bad-struct-16.ttl", 179 | "turtle-syntax-bad-struct-17.ttl", 180 | "turtle-syntax-bad-uri-01.ttl", 181 | "turtle-syntax-bad-uri-02.ttl", 182 | // TODO: causes deadlock 183 | //"turtle-syntax-bad-uri-03.ttl", 184 | // TODO: char escapes not allowed in uri 185 | //"turtle-syntax-bad-uri-04.ttl", 186 | //"turtle-syntax-bad-uri-05.ttl", 187 | } 188 | 189 | var positiveParserTests []string = []string{ 190 | "bareword_a_predicate", 191 | "bareword_decimal", 192 | "bareword_double", 193 | "blankNodePropertyList_as_object", 194 | "blankNodePropertyList_as_subject", 195 | "blankNodePropertyList_containing_collection", 196 | "blankNodePropertyList_with_multiple_triples", 197 | "collection_object", 198 | "collection_subject", 199 | // TODO: ask andrei about this one 200 | //"empty_collection", 201 | "comment_following_PNAME_NS", 202 | "double_lower_case_e", 203 | // TODO: off-by-one in rdf:rest stuff 204 | //"first", 205 | //"last", 206 | "HYPHEN_MINUS_in_localName", 207 | "IRIREF_datatype", 208 | "IRI_with_all_punctuation", 209 | "labeled_blank_node_object", 210 | "labeled_blank_node_subject", 211 | "langtagged_non_LONG", 212 | "lantag_with_subtag", 213 | "LITERAL1_all_controls", 214 | "LITERAL1_all_punctuation", 215 | "LITERAL1_ascii_boundaries", 216 | "LITERAL1", 217 | "LITERAL2_ascii_boundaries", 218 | "literal_false", 219 | "LITERAL_LONG1_ascii_boundaries", 220 | "LITERAL_LONG1_with_1_squote", 221 | "LITERAL_LONG1_with_2_squotes", 222 | "LITERAL_LONG2_ascii_boundaries", 223 | "LITERAL_LONG2_with_1_squote", 224 | "LITERAL_LONG2_with_2_squotes", 225 | "literal_true", 226 | "literal_with_BACKSPACE", 227 | "literal_with_CARRIAGE_RETURN", 228 | "literal_with_CHARACTER_TABULATION", 229 | "literal_with_FORM_FEED", 230 | "literal_with_LINE_FEED", 231 | "literal_with_numeric_escape4", 232 | "literal_with_REVERSE_SOLIDUS", 233 | "localName_with_assigned_nfc_bmp_PN_CHARS_BASE_character_boundaries", 234 | "localName_with_assigned_nfc_PN_CHARS_BASE_character_boundaries", 235 | "localName_with_leading_digit", 236 | "localName_with_leading_underscore", 237 | "localName_with_nfc_PN_CHARS_BASE_character_boundaries", 238 | "localName_with_non_leading_extras", 239 | // TODO: proper unescaping 240 | //"manifest.ttl", 241 | "negative_numeric", 242 | // TODO: ended up with too many blank nodes 243 | //"nested_blankNodePropertyLists", 244 | "nested_collection", 245 | "numeric_with_leading_0", 246 | "objectList_with_two_objects", 247 | "predicateObjectList_with_two_objectLists", 248 | "turtle-eval-struct-02", 249 | "percent_escaped_localName", 250 | "positive_numeric", 251 | "prefix_reassigned_and_used", 252 | "repeated_semis_not_at_end", 253 | // TODO: automatic base of doc name 254 | //"turtle-subm-01", 255 | "turtle-eval-struct-01", 256 | // TODO: something wrong with IRI resolution 257 | //"langtagged_LONG_with_subtag", 258 | //"LITERAL_LONG2_with_REVERSE_SOLIDUS", 259 | //"localname_with_COLON", 260 | //"number_sign_following_localName", 261 | //"number_sign_following_PNAME_NS", 262 | //"reserved_escaped_localName", 263 | //"turtle-subm-02", 264 | //"turtle-subm-03", 265 | //"turtle-subm-04", 266 | //"turtle-subm-05", 267 | //"turtle-subm-06", 268 | //"turtle-subm-07", 269 | //"turtle-subm-08", 270 | //"turtle-subm-09", 271 | //"turtle-subm-10", 272 | //"turtle-subm-11", 273 | //"turtle-subm-12", 274 | //"turtle-subm-13", 275 | //"turtle-subm-14", 276 | //"turtle-subm-15", 277 | //"turtle-subm-16", 278 | //"turtle-subm-17", 279 | //"turtle-subm-18", 280 | //"turtle-subm-19", 281 | //"turtle-subm-20", 282 | //"turtle-subm-21", 283 | //"turtle-subm-22", 284 | //"turtle-subm-23", 285 | //"turtle-subm-24", 286 | //"turtle-subm-25", 287 | //"turtle-subm-26", 288 | //"turtle-subm-27", 289 | //"two_LITERAL_LONG2s", 290 | "underscore_in_localName", 291 | } 292 | 293 | var positiveParserTestsNoIso []string = []string{ 294 | "sole_blankNodePropertyList", 295 | "SPARQL_style_base", 296 | "SPARQL_style_prefix", 297 | "prefixed_IRI_object", 298 | "prefixed_IRI_predicate", 299 | "prefixed_name_datatype", 300 | "prefix_only_IRI", 301 | "prefix_with_non_leading_extras", 302 | "prefix_with_PN_CHARS_BASE_character_boundaries", 303 | "repeated_semis_at_end", 304 | "old_style_base", 305 | "old_style_prefix", 306 | "LITERAL_LONG2_with_UTF8_boundaries", 307 | "literal_with_escaped_BACKSPACE", 308 | "literal_with_escaped_CARRIAGE_RETURN", 309 | "literal_with_escaped_CHARACTER_TABULATION", 310 | "literal_with_escaped_FORM_FEED", 311 | "literal_with_escaped_LINE_FEED", 312 | "literal_with_numeric_escape8", 313 | "LITERAL1_with_UTF8_boundaries", 314 | "LITERAL2", 315 | "LITERAL2_with_UTF8_boundaries", 316 | "LITERAL_LONG1", 317 | "LITERAL_LONG1_with_UTF8_boundaries", 318 | "LITERAL_LONG2", 319 | "labeled_blank_node_with_leading_underscore", 320 | "labeled_blank_node_with_non_leading_extras", 321 | "labeled_blank_node_with_PN_CHARS_BASE_character_boundaries", 322 | "langtagged_LONG", 323 | "labeled_blank_node_with_leading_digit", 324 | "IRI_with_four_digit_numeric_escape", 325 | "IRI_with_eight_digit_numeric_escape", 326 | "IRI_subject", 327 | "default_namespace_IRI", 328 | "comment_following_localName", 329 | "bareword_integer", 330 | "anonymous_blank_node_object", 331 | "anonymous_blank_node_subject", 332 | "turtle-syntax-base-01", 333 | "turtle-syntax-base-02", 334 | "turtle-syntax-base-03", 335 | "turtle-syntax-base-04", 336 | "turtle-syntax-blank-label", 337 | "turtle-syntax-bnode-01", 338 | "turtle-syntax-bnode-02", 339 | "turtle-syntax-bnode-03", 340 | "turtle-syntax-bnode-04", 341 | "turtle-syntax-bnode-05", 342 | "turtle-syntax-bnode-06", 343 | "turtle-syntax-bnode-07", 344 | "turtle-syntax-bnode-08", 345 | "turtle-syntax-bnode-09", 346 | "turtle-syntax-bnode-10", 347 | "turtle-syntax-datatypes-01", 348 | "turtle-syntax-datatypes-02", 349 | "turtle-syntax-file-01", 350 | "turtle-syntax-file-02", 351 | "turtle-syntax-file-03", 352 | "turtle-syntax-kw-01", 353 | "turtle-syntax-kw-02", 354 | "turtle-syntax-kw-03", 355 | "turtle-syntax-lists-01", 356 | "turtle-syntax-lists-02", 357 | "turtle-syntax-lists-03", 358 | "turtle-syntax-lists-04", 359 | "turtle-syntax-lists-05", 360 | "turtle-syntax-ln-colons", 361 | "turtle-syntax-ln-dots", 362 | "turtle-syntax-ns-dots", 363 | "turtle-syntax-number-01", 364 | "turtle-syntax-number-02", 365 | "turtle-syntax-number-03", 366 | "turtle-syntax-number-04", 367 | "turtle-syntax-number-05", 368 | "turtle-syntax-number-06", 369 | "turtle-syntax-number-07", 370 | "turtle-syntax-number-08", 371 | "turtle-syntax-number-09", 372 | "turtle-syntax-number-10", 373 | "turtle-syntax-number-11", 374 | "turtle-syntax-pname-esc-01", 375 | "turtle-syntax-pname-esc-02", 376 | "turtle-syntax-pname-esc-03", 377 | "turtle-syntax-prefix-01", 378 | // this library will NOT allow mixed-case prefix declarations 379 | // "turtle-syntax-prefix-02", // <<< commented out 380 | "turtle-syntax-prefix-03", 381 | "turtle-syntax-prefix-04", 382 | "turtle-syntax-prefix-05", 383 | "turtle-syntax-prefix-06", 384 | "turtle-syntax-prefix-07", 385 | "turtle-syntax-prefix-08", 386 | "turtle-syntax-prefix-09", 387 | "turtle-syntax-str-esc-01", 388 | "turtle-syntax-str-esc-02", 389 | "turtle-syntax-str-esc-03", 390 | "turtle-syntax-string-01", 391 | "turtle-syntax-string-02", 392 | "turtle-syntax-string-03", 393 | "turtle-syntax-string-04", 394 | "turtle-syntax-string-05", 395 | "turtle-syntax-string-06", 396 | "turtle-syntax-string-07", 397 | "turtle-syntax-string-08", 398 | "turtle-syntax-string-09", 399 | "turtle-syntax-string-10", 400 | "turtle-syntax-string-11", 401 | "turtle-syntax-struct-01", 402 | "turtle-syntax-struct-02", 403 | "turtle-syntax-struct-03", 404 | "turtle-syntax-struct-04", 405 | "turtle-syntax-struct-05", 406 | "turtle-syntax-uri-01", 407 | "turtle-syntax-uri-02", 408 | "turtle-syntax-uri-03", 409 | "turtle-syntax-uri-04", 410 | } 411 | -------------------------------------------------------------------------------- /parser.go: -------------------------------------------------------------------------------- 1 | package gon3 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "net/url" 8 | "strings" 9 | 10 | "github.com/rychipman/easylex" 11 | ) 12 | 13 | type Parser struct { 14 | // target data structure 15 | Graph *Graph 16 | // parser state 17 | lex lexer 18 | nextTok chan easylex.Token 19 | baseURI *IRI 20 | namespaces map[string]*IRI 21 | bNodeLabels map[string]*BlankNode 22 | lastBlankNode int 23 | curSubject Term 24 | curPredicate Term 25 | } 26 | 27 | func NewParser(baseUri string) *Parser { 28 | // base, _ := url.Parse(baseUri) // TODO: properly initialize baseuri 29 | // initialize parser 30 | p := &Parser{ 31 | Graph: &Graph{}, // TODO: initialize 32 | nextTok: make(chan easylex.Token, 1), 33 | baseURI: NewIRI(baseUri), 34 | namespaces: map[string]*IRI{}, // TODO: probably don't need these map inits 35 | bNodeLabels: map[string]*BlankNode{}, 36 | lastBlankNode: -1, // TODO: make this initially nil 37 | } 38 | return p 39 | } 40 | 41 | func (p *Parser) Parse(input io.Reader) (*Graph, error) { 42 | var err error 43 | var done bool 44 | body, err := ioutil.ReadAll(input) 45 | if err != nil { 46 | return p.Graph, err 47 | } 48 | 49 | p.lex = easylex.Lex(string(body), lexDocument) 50 | 51 | for { // while the next token is not an EOF 52 | done, err = p.parseStatement() 53 | if done || err != nil { 54 | break 55 | } 56 | } 57 | return p.Graph, err 58 | } 59 | 60 | func (p *Parser) peek() easylex.Token { 61 | for { 62 | select { 63 | case t := <-p.nextTok: 64 | p.nextTok <- t 65 | return t 66 | default: 67 | p.nextTok <- p.lex.NextToken() 68 | } 69 | } 70 | } 71 | 72 | func (p *Parser) next() easylex.Token { 73 | for { 74 | select { 75 | case t := <-p.nextTok: 76 | return t 77 | default: 78 | p.nextTok <- p.lex.NextToken() 79 | } 80 | } 81 | } 82 | 83 | func (p *Parser) expect(typ easylex.TokenType) (easylex.Token, error) { 84 | tok := p.next() 85 | if tok.Typ != typ { 86 | return tok, fmt.Errorf("expected %v, got %s (type %v)", typ, tok.Val, tok.Typ) 87 | } 88 | return tok, nil 89 | } 90 | 91 | func (p *Parser) emitTriple(subj, pred, obj Term) { 92 | trip := &Triple{ 93 | Subject: subj, 94 | Predicate: pred, 95 | Object: obj, 96 | } 97 | p.Graph.triples = append(p.Graph.triples, trip) 98 | } 99 | 100 | func (p *Parser) blankNode(label string) *BlankNode { 101 | if label == "" { 102 | return p.newBlankNode() 103 | } else if node, present := p.bNodeLabels[label]; present { 104 | return node 105 | } 106 | newNode := p.newBlankNode() 107 | p.bNodeLabels[label] = newNode 108 | return newNode 109 | } 110 | 111 | func (p *Parser) newBlankNode() *BlankNode { 112 | id := p.lastBlankNode + 1 113 | label := fmt.Sprintf("a%d", id) 114 | b := &BlankNode{ 115 | Id: id, 116 | Label: label, 117 | } 118 | p.lastBlankNode = id 119 | return b 120 | } 121 | 122 | func (p *Parser) resolvePName(pname string) (*IRI, error) { 123 | strs := strings.Split(pname, ":") 124 | prefix := strs[0] 125 | name := strs[1] 126 | if iri, present := p.namespaces[prefix]; present { 127 | rel := iriRefToURL(name) 128 | merged, err := joinURL(iri.url, rel) 129 | // resolved := iri.url.ResolveReference(rel) // @@TODO: make sure this properly resolves weird things 130 | return &IRI{url: merged}, err 131 | } 132 | return nil, fmt.Errorf("Prefix %q not found in declared namespaces", prefix) 133 | } 134 | 135 | func (p *Parser) resolveIRI(iri string) (*IRI, error) { 136 | rel := iriRefToURL(iri) 137 | url, err := joinURL(p.baseURI.url, rel) 138 | return &IRI{url}, err 139 | } 140 | 141 | func (p *Parser) parseStatement() (bool, error) { 142 | tok := p.peek() 143 | switch tok.Typ { 144 | case easylex.TokenError: 145 | return false, fmt.Errorf("Received tokenError: %q", tok) 146 | case easylex.TokenEOF: 147 | return true, nil 148 | case tokenAtPrefix: 149 | err := p.parsePrefix() 150 | if err != nil { 151 | return false, err 152 | } 153 | case tokenAtBase: 154 | err := p.parseBase() 155 | if err != nil { 156 | return false, err 157 | } 158 | case tokenSPARQLBase: 159 | err := p.parseSPARQLBase() 160 | if err != nil { 161 | return false, err 162 | } 163 | case tokenSPARQLPrefix: 164 | err := p.parseSPARQLPrefix() 165 | if err != nil { 166 | return false, err 167 | } 168 | default: 169 | err := p.parseTriples() 170 | if err != nil { 171 | return false, err 172 | } 173 | } 174 | return false, nil 175 | } 176 | 177 | func (p *Parser) parsePrefix() error { 178 | _, err := p.expect(tokenAtPrefix) 179 | if err != nil { 180 | return err 181 | } 182 | pNameNS, err := p.expect(tokenPNameNS) 183 | if err != nil { 184 | return err 185 | } 186 | iriRef, err := p.expect(tokenIRIRef) 187 | if err != nil { 188 | return err 189 | } 190 | _, err = p.expect(tokenEndTriples) 191 | if err != nil { 192 | return err 193 | } 194 | // map a new namespace in parser state 195 | key := pNameNS.Val[:len(pNameNS.Val)-1] 196 | val := newIRIFromString(iriRef.Val) //@@@ 197 | p.namespaces[key] = val 198 | return err 199 | } 200 | 201 | func (p *Parser) parseBase() error { 202 | _, err := p.expect(tokenAtBase) 203 | if err != nil { 204 | return err 205 | } 206 | iriRef, err := p.expect(tokenIRIRef) 207 | if err != nil { 208 | return err 209 | } 210 | _, err = p.expect(tokenEndTriples) 211 | if err != nil { 212 | return err 213 | } 214 | // TODO: validate IRI? 215 | p.baseURI = newIRIFromString(iriRef.Val) 216 | return nil 217 | } 218 | 219 | func (p *Parser) parseSPARQLPrefix() error { 220 | _, err := p.expect(tokenSPARQLPrefix) 221 | if err != nil { 222 | return err 223 | } 224 | pNameNS, err := p.expect(tokenPNameNS) 225 | if err != nil { 226 | return err 227 | } 228 | iriRef, err := p.expect(tokenIRIRef) 229 | if err != nil { 230 | return err 231 | } 232 | // map a new namespace in parser state 233 | key := pNameNS.Val[:len(pNameNS.Val)-1] 234 | val := newIRIFromString(iriRef.Val) 235 | p.namespaces[key] = val 236 | return nil 237 | } 238 | 239 | func (p *Parser) parseSPARQLBase() error { 240 | _, err := p.expect(tokenSPARQLBase) 241 | if err != nil { 242 | return err 243 | } 244 | iriRef, err := p.expect(tokenIRIRef) 245 | if err != nil { 246 | return err 247 | } 248 | // TODO: validate IRI? 249 | p.baseURI = newIRIFromString(iriRef.Val) 250 | return nil 251 | } 252 | 253 | func (p *Parser) parseTriples() error { 254 | if p.peek().Typ == tokenStartBlankNodePropertyList { 255 | // if "blanknodepropertylist predicateobjectlist?" 256 | bNode, err := p.parseBlankNodePropertyList() 257 | if err != nil { 258 | return err 259 | } 260 | p.curSubject = bNode 261 | // parse a predicateobjectlist if we have one 262 | if p.peek().Typ != tokenEndTriples { 263 | err = p.parsePredicateObjectList() 264 | if err != nil { 265 | return err 266 | } 267 | } 268 | } else { 269 | // if "subject predicateobjectlist" 270 | err := p.parseSubject() 271 | if err != nil { 272 | return err 273 | } 274 | err = p.parsePredicateObjectList() 275 | if err != nil { 276 | return err 277 | } 278 | } 279 | _, err := p.expect(tokenEndTriples) 280 | if err != nil { 281 | return err 282 | } 283 | return nil 284 | } 285 | 286 | func (p *Parser) parseSubject() error { 287 | tok := p.peek() 288 | // expect a valid subject term, which is one of 289 | // iri|blanknode|collection 290 | switch tok.Typ { 291 | case tokenIRIRef: 292 | p.next() 293 | iri, err := p.resolveIRI(tok.Val) 294 | if err != nil { 295 | return err 296 | } 297 | p.curSubject = iri 298 | return nil 299 | case tokenPNameLN, tokenPNameNS: 300 | p.next() 301 | iri, err := p.resolvePName(tok.Val) 302 | p.curSubject = iri 303 | return err 304 | case tokenBlankNodeLabel: 305 | p.next() 306 | label := strings.Split(tok.Val, ":")[1] 307 | bNode := p.blankNode(label) 308 | p.curSubject = bNode 309 | return nil 310 | case tokenAnon: 311 | p.next() 312 | p.curSubject = p.blankNode("") 313 | return nil 314 | case tokenStartCollection: 315 | bNode, err := p.parseCollection() 316 | p.curSubject = bNode 317 | return err 318 | default: 319 | return fmt.Errorf("expected a subject, got %v (type %v)", tok, tok.Typ) 320 | } 321 | } 322 | 323 | func (p *Parser) parsePredicateObjectList() error { 324 | err := p.parsePredicate() 325 | if err != nil { 326 | return err 327 | } 328 | err = p.parseObjectList() 329 | if err != nil { 330 | return err 331 | } 332 | for p.peek().Typ == tokenPredicateListSeparator { 333 | _, err = p.expect(tokenPredicateListSeparator) 334 | if err != nil { 335 | return err 336 | } 337 | tok := p.peek() 338 | switch tok.Typ { 339 | case tokenA, tokenIRIRef, tokenPNameLN, tokenPNameNS: 340 | // if there is a predicate 341 | err = p.parsePredicate() 342 | if err != nil { 343 | return err 344 | } 345 | err = p.parseObjectList() 346 | if err != nil { 347 | return err 348 | } 349 | default: 350 | // done parsing predicateobjectlist 351 | } 352 | } 353 | return nil 354 | } 355 | 356 | func (p *Parser) parsePredicate() error { 357 | // expect token 'a' or an iri 358 | tok := p.next() 359 | switch tok.Typ { 360 | case tokenA: 361 | // TODO: remove magic string 362 | pred := newIRIFromString("") 363 | p.curPredicate = pred 364 | return nil 365 | case tokenIRIRef: 366 | iri, err := p.resolveIRI(tok.Val) 367 | if err != nil { 368 | return err 369 | } 370 | p.curPredicate = iri 371 | return nil 372 | case tokenPNameLN, tokenPNameNS: 373 | iri, err := p.resolvePName(tok.Val) 374 | p.curPredicate = iri 375 | return err 376 | default: 377 | return fmt.Errorf("expected predicate, got %v (type %v)", tok, tok.Typ) 378 | } 379 | } 380 | 381 | func (p *Parser) parseObjectList() error { 382 | err := p.parseObject() 383 | if err != nil { 384 | return err 385 | } 386 | for p.peek().Typ == tokenObjectListSeparator { 387 | // expect comma token 388 | _, err = p.expect(tokenObjectListSeparator) 389 | if err != nil { 390 | return err 391 | } 392 | err = p.parseObject() 393 | if err != nil { 394 | return err 395 | } 396 | } 397 | return nil 398 | } 399 | 400 | func (p *Parser) parseCollection() (*BlankNode, error) { 401 | savedSubject := p.curSubject 402 | savedPredicate := p.curPredicate 403 | _, err := p.expect(tokenStartCollection) 404 | if err != nil { 405 | return nil, err 406 | } 407 | 408 | // TODO: use consts 409 | rdfFirst := newIRIFromString("") 410 | rdfRest := newIRIFromString("") 411 | rdfNil := newIRIFromString("") 412 | 413 | bNode := p.blankNode("") 414 | p.curSubject = bNode 415 | p.curPredicate = rdfFirst 416 | next := p.peek() 417 | for next.Typ != tokenEndCollection { 418 | err := p.parseObject() 419 | if err != nil { 420 | return nil, err 421 | } 422 | next = p.peek() 423 | if next.Typ != tokenEndCollection { 424 | nextBNode := p.blankNode("") 425 | p.emitTriple(p.curSubject, rdfRest, nextBNode) 426 | p.curSubject = nextBNode 427 | } 428 | } 429 | 430 | _, err = p.expect(tokenEndCollection) 431 | if err != nil { 432 | return nil, err 433 | } 434 | p.emitTriple(p.curSubject, rdfRest, rdfNil) 435 | p.curSubject = savedSubject 436 | p.curPredicate = savedPredicate 437 | return bNode, nil 438 | } 439 | 440 | func (p *Parser) parseObject() error { 441 | // expect an object 442 | // where object = iri|blanknode|collection|blanknodepropertylist|literal 443 | tok := p.peek() 444 | switch tok.Typ { 445 | case tokenIRIRef: 446 | p.next() 447 | iri, err := p.resolveIRI(tok.Val) 448 | if err != nil { 449 | return err 450 | } 451 | p.emitTriple(p.curSubject, p.curPredicate, iri) 452 | return nil 453 | case tokenPNameLN, tokenPNameNS: 454 | p.next() 455 | iri, err := p.resolvePName(tok.Val) 456 | p.emitTriple(p.curSubject, p.curPredicate, iri) 457 | return err 458 | case tokenBlankNodeLabel: 459 | p.next() 460 | label := strings.Split(tok.Val, ":")[1] 461 | bNode := p.blankNode(label) 462 | p.emitTriple(p.curSubject, p.curPredicate, bNode) 463 | return nil 464 | case tokenAnon: 465 | p.next() 466 | bNode := p.blankNode("") 467 | p.emitTriple(p.curSubject, p.curPredicate, bNode) 468 | return nil 469 | case tokenStartCollection: 470 | bNode, err := p.parseCollection() 471 | p.emitTriple(p.curSubject, p.curPredicate, bNode) 472 | return err 473 | case tokenStartBlankNodePropertyList: 474 | bNode, err := p.parseBlankNodePropertyList() 475 | p.emitTriple(p.curSubject, p.curPredicate, bNode) 476 | return err 477 | case tokenInteger, tokenDecimal, tokenDouble, tokenTrue, tokenFalse, tokenStringLiteralQuote, tokenStringLiteralSingleQuote, tokenStringLiteralLongQuote, tokenStringLiteralLongSingleQuote: 478 | lit, err := p.parseLiteral() 479 | p.emitTriple(p.curSubject, p.curPredicate, lit) 480 | return err 481 | default: 482 | return fmt.Errorf("expected object, got %v (type %v)", tok, tok.Typ) 483 | } 484 | } 485 | 486 | func (p *Parser) parseBlankNodePropertyList() (*BlankNode, error) { 487 | savedSubject := p.curSubject 488 | savedPredicate := p.curPredicate 489 | // expect '[' token 490 | _, err := p.expect(tokenStartBlankNodePropertyList) 491 | if err != nil { 492 | return nil, err 493 | } 494 | bNode := p.blankNode("") 495 | p.curSubject = bNode 496 | err = p.parsePredicateObjectList() 497 | if err != nil { 498 | return nil, err 499 | } 500 | // expect ']' token 501 | _, err = p.expect(tokenEndBlankNodePropertyList) 502 | if err != nil { 503 | return nil, err 504 | } 505 | p.curSubject = savedSubject 506 | p.curPredicate = savedPredicate 507 | return bNode, nil 508 | } 509 | 510 | func (p *Parser) parseLiteral() (*Literal, error) { 511 | tok := p.peek() 512 | switch tok.Typ { 513 | case tokenInteger, tokenDecimal, tokenDouble: 514 | lit, err := p.parseNumericLiteral() 515 | return lit, err 516 | case tokenStringLiteralQuote, tokenStringLiteralSingleQuote, tokenStringLiteralLongQuote, tokenStringLiteralLongSingleQuote: 517 | lit, err := p.parseRDFLiteral() 518 | return lit, err 519 | case tokenTrue, tokenFalse: 520 | lit, err := p.parseBooleanLiteral() 521 | return lit, err 522 | default: 523 | return nil, fmt.Errorf("Expected a literal token, got %v", tok) 524 | } 525 | panic("unreachable") 526 | } 527 | 528 | func (p *Parser) parseNumericLiteral() (*Literal, error) { 529 | // TODO: replace these with consts 530 | xsdInteger := newIRIFromString("") 531 | xsdDecimal := newIRIFromString("") 532 | xsdDouble := newIRIFromString("") 533 | tok := p.next() 534 | switch tok.Typ { 535 | case tokenInteger: 536 | lit := &Literal{ 537 | tok.Val, 538 | xsdInteger, 539 | "", 540 | } 541 | return lit, nil 542 | case tokenDecimal: 543 | lit := &Literal{ 544 | tok.Val, 545 | xsdDecimal, 546 | "", 547 | } 548 | return lit, nil 549 | case tokenDouble: 550 | lit := &Literal{ 551 | tok.Val, 552 | xsdDouble, 553 | "", 554 | } 555 | return lit, nil 556 | default: 557 | return nil, fmt.Errorf("Expected a numeric literal token, got %s", tok) 558 | } 559 | } 560 | 561 | func (p *Parser) parseRDFLiteral() (*Literal, error) { 562 | tok := p.next() 563 | lit := &Literal{ 564 | LexicalForm: "", 565 | LanguageTag: "", 566 | } 567 | switch tok.Typ { 568 | case tokenStringLiteralQuote, tokenStringLiteralSingleQuote, tokenStringLiteralLongQuote, tokenStringLiteralLongSingleQuote: 569 | lit.LexicalForm = lexicalForm(tok.Val) 570 | default: 571 | return nil, fmt.Errorf("Expected a string literal token, got %s", tok) 572 | } 573 | if p.peek().Typ == tokenLangTag { 574 | langtag := p.next() 575 | lit.LanguageTag = langtag.Val[1:] 576 | // TODO: make this a const 577 | dIRI := newIRIFromString("") 578 | lit.DatatypeIRI = dIRI 579 | } else if p.peek().Typ == tokenLiteralDatatypeTag { 580 | p.next() 581 | tok := p.next() 582 | switch tok.Typ { 583 | case tokenIRIRef: 584 | iri, err := p.resolveIRI(tok.Val) 585 | if err != nil { 586 | return nil, err 587 | } 588 | lit.DatatypeIRI = iri 589 | case tokenPNameLN, tokenPNameNS: 590 | iri, err := p.resolvePName(tok.Val) 591 | if err != nil { 592 | return nil, err 593 | } 594 | lit.DatatypeIRI = iri 595 | default: 596 | return nil, fmt.Errorf("expected an IRI or PName, got %s (type %v)", tok.Val, tok.Typ) 597 | } 598 | } 599 | return lit, nil 600 | } 601 | 602 | func (p *Parser) parseBooleanLiteral() (*Literal, error) { 603 | // TODO: make this a const 604 | xsdBoolean := newIRIFromString("") 605 | tok := p.next() 606 | switch tok.Typ { 607 | case tokenTrue: 608 | lit := &Literal{ 609 | tok.Val, 610 | xsdBoolean, 611 | "", 612 | } 613 | return lit, nil 614 | case tokenFalse: 615 | lit := &Literal{ 616 | tok.Val, 617 | xsdBoolean, 618 | "", 619 | } 620 | return lit, nil 621 | default: 622 | return nil, fmt.Errorf("Expected a boolean literal token, got %s", tok) 623 | } 624 | } 625 | 626 | func joinURL(URI, p string) (string, error) { 627 | base, err := url.Parse(URI) 628 | if err != nil { 629 | return "", err 630 | } 631 | if len(p) > 0 { 632 | if strings.HasSuffix(URI, "#") { 633 | return base.String() + "#" + p, nil 634 | } 635 | ref, err := url.Parse(p) 636 | if err != nil { 637 | return "", err 638 | } 639 | base = base.ResolveReference(ref) 640 | } 641 | return base.String(), nil 642 | } 643 | --------------------------------------------------------------------------------