aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorpukkamustard <pukkamustard@posteo.net>2021-05-10 16:05:20 +0200
committerpukkamustard <pukkamustard@posteo.net>2021-05-20 10:45:33 +0200
commitd9006ccd093f8890dc950fa7416b44c09d1350b7 (patch)
treeeac1dd12cdcccce09926ffb1ff0d65d9d8b95497 /test
parentff6b06ec2295e35a9f2e6e029a06fdea927ed883 (diff)
Rdf_datalog.Parser: Parser for Datalog
This allows the Datalog engine to be used without constructing complicated OCaml terms. Clauses can now simply be written in usual Datalog syntax. See test/datalog/main.ml for an example.
Diffstat (limited to 'test')
-rw-r--r--test/datalog/dune13
-rw-r--r--test/datalog/main.ml36
-rw-r--r--test/datalog/parser.ml116
3 files changed, 165 insertions, 0 deletions
diff --git a/test/datalog/dune b/test/datalog/dune
new file mode 100644
index 0000000..1ca70ed
--- /dev/null
+++ b/test/datalog/dune
@@ -0,0 +1,13 @@
+(executables
+ (names parser main)
+ (libraries rdf_datalog
+ rdf_alcotest
+ angstrom alcotest))
+
+(rule
+ (alias runtest)
+ (action (run ./main.exe)))
+
+(rule
+ (alias runtest)
+ (action (run ./parser.exe)))
diff --git a/test/datalog/main.ml b/test/datalog/main.ml
new file mode 100644
index 0000000..ad6e295
--- /dev/null
+++ b/test/datalog/main.ml
@@ -0,0 +1,36 @@
+(*
+ * SPDX-FileCopyrightText: 2021 petites singularit├ęs <ps-dream@lesoiseaux.io>
+ * SPDX-FileCopyrightText: 2021 pukkamustard <pukkamustard@posteo.netq>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ *)
+
+module Parser = Rdf_datalog.Parser
+module Term = Rdf_datalog.Term
+module Literal = Rdf_datalog.Literal
+module Clause = Rdf_datalog.Clause
+module Theory = Rdf_datalog.Theory
+
+let example =
+ {example|
+
+ edge("a", "b").
+ edge("b", "c").
+ edge("c", "d").
+
+ path(?a,?b) :- edge(?a,?b).
+ path(?a,?c) :- edge(?a,?b), path(?b,?c).
+|example}
+
+let parse p string =
+ Angstrom.parse_string
+ ~consume:Angstrom.Consume.All
+ p string
+ |> Result.get_ok
+
+let parse_theory = parse Parser.theory
+let parse_query = parse Parser.query
+
+let () =
+ Format.printf "%a" (Fmt.list Literal.pp) @@
+ Theory.prove (parse_theory example) (parse_query {q|path(?a,?b)?|q})
diff --git a/test/datalog/parser.ml b/test/datalog/parser.ml
new file mode 100644
index 0000000..7c100dc
--- /dev/null
+++ b/test/datalog/parser.ml
@@ -0,0 +1,116 @@
+(*
+ * SPDX-FileCopyrightText: 2021 petites singularit├ęs <ps-dream@lesoiseaux.io>
+ * SPDX-FileCopyrightText: 2021 pukkamustard <pukkamustard@posteo.netq>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ *)
+
+module Parser = Rdf_datalog.Parser
+module Term = Rdf_datalog.Term
+module Literal = Rdf_datalog.Literal
+module Clause = Rdf_datalog.Clause
+
+open Alcotest
+
+let parse p =
+ Angstrom.parse_string
+ ~consume:Angstrom.Consume.All
+ p
+
+let xsd_string_test_case =
+ test_case "xsd_string" `Quick
+ (fun () ->
+ check (result Rdf_alcotest.literal string)
+ "can parse"
+ (parse Parser.xsd_string "\"Hello World\"")
+ (Result.ok @@ Rdf.Literal.make "Hello World" @@ Rdf.Namespace.xsd "string")
+ )
+
+let iri_test_case =
+ test_case "iri" `Quick
+ (fun () ->
+ check (result Rdf_alcotest.iri string)
+ "can parse"
+ (parse Parser.iri "<http://example.com>")
+ (Result.ok @@ Rdf.Iri.of_string "http://example.com")
+ )
+
+let variable_test_case =
+ test_case "variable" `Quick
+ (fun () -> check (result string string)
+ "can parse"
+ (parse Parser.variable "?abc")
+ (Result.ok @@ "abc"))
+
+let term_testable =
+ testable Term.pp Term.equal
+
+let term_test_case =
+ let cases =
+ ["?abc", Term.variable "abc";
+ "?a", Term.variable "a";
+ "<http://example.com>", "http://example.com" |> Rdf.Iri.of_string |> Rdf.Term.of_iri |> Term.constant;
+ "\"blups\"", Rdf.Literal.make "blups" (Rdf.Namespace.xsd "string") |> Rdf.Term.of_literal |> Term.constant;
+ ] in
+
+ test_case "term" `Quick
+ (fun () ->
+ List.iter
+ (fun (enc, v) ->
+ check (result term_testable string)
+ "can parse"
+ (parse Parser.term enc)
+ (Result.ok v))
+ cases)
+
+let literal_testable =
+ testable Literal.pp Literal.equal
+
+let literal_test_case =
+ let cases = [
+ "p(?a,?b)", Literal.make "p" [Term.variable "a"; Term.variable "b"];
+ "graph(?a,<http://example.com>)", Literal.make "graph" [Term.variable "a";
+ "http://example.com" |> Rdf.Iri.of_string |> Rdf.Term.of_iri |> Term.constant]
+ ] in
+ test_case "literal" `Quick
+ (fun () ->
+ List.iter
+ (fun (enc, v) ->
+ check (result literal_testable string)
+ "can parse"
+ (parse Parser.literal enc)
+ (Result.ok v))
+ cases)
+
+let clause_testable =
+ testable Clause.pp Clause.equal
+
+let clause_test_case =
+ let cases = [
+ "p(?a, ?b).", Literal.make "p" [Term.variable "a"; Term.variable "b"] |> Clause.fact;
+ "p(?a, ?b) :- q(?a,?b).", Clause.make
+ (Literal.make "p" [Term.variable "a"; Term.variable "b"])
+ [(Literal.make "q" [Term.variable "a"; Term.variable "b"])] ;
+ ] in
+ test_case "clause" `Quick
+ (fun () ->
+ List.iter
+ (fun (enc, v) ->
+ check (result clause_testable string)
+ "can parse"
+ (parse Parser.clause enc)
+ (Result.ok v))
+ cases)
+
+let () =
+ Alcotest.run "Rdf_datalog.Parser"
+ [
+ "Basic parsers", [
+ xsd_string_test_case;
+ iri_test_case;
+ variable_test_case;
+ term_test_case;
+ literal_test_case;
+ clause_test_case;
+ ]
+ ]