forked from threatgrid/naga
-
Notifications
You must be signed in to change notification settings - Fork 2
/
pabu.clj
90 lines (76 loc) · 2.73 KB
/
pabu.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
(ns ^{:doc "Implements Pabu, which is a Prolog-like language for Naga.
Parses code and returns Naga rules."
:author "Paula Gearon"}
naga.lang.pabu
(:require [naga.schema.structs :as structs :refer [Axiom Program Triple]]
[naga.lang.parser :as parser]
[naga.rules :as r]
[naga.util :as u]
[schema.core :as s])
(:import [java.io InputStream]
[naga.schema.structs Rule]
[clojure.lang Var]))
;; TODO: Multi-arity not yet supported
(def Args
[(s/one s/Any "entity")
(s/optional s/Any "value")])
(def AxiomAST
{:type (s/eq :axiom)
:axiom [(s/one s/Keyword "Property")
(s/one Args "args")]})
(s/defn triplets :- [Triple]
"Converts raw parsed predicate information into a seq of triples"
[[property [s o :as args]]]
(case (count args)
0 [[s :rdf/type :owl/thing]]
1 [[s :rdf/type property]]
2 [[s property o]]
(throw (ex-info "Multi-arity predicates not yet supported"))))
(s/defn triplet :- Triple
"Converts raw parsed predicate information into a single triple"
[raw]
(first (triplets raw)))
(defn structure
"Converts the AST for a structure into either a seq of triplets or predicates.
Types are intentionally loose, since it's either a pair or a list."
[ast-data]
(if (vector? ast-data)
(let [[p args] ast-data]
(if-let [f (and (keyword? p) (u/get-fn-reference p))]
[(with-meta (cons f args) (meta args))]
(triplets ast-data)))
[ast-data]))
(s/defn ast->axiom :- Axiom
"Converts the axiom structure returned from the parser"
[{axiom :axiom :as axiom-ast} :- AxiomAST]
(triplet axiom))
(def VK "Either a Variable or a Keyword" (s/cond-pre s/Keyword s/Symbol))
(def PatternPredicate [(s/one VK "property")
(s/one Args "arguments")])
(def ExpressionPredicate (s/pred list?))
(def Predicate (s/cond-pre ExpressionPredicate PatternPredicate))
(def RuleAST
{:type (s/eq :rule)
:head [[(s/one VK "property")
(s/one Args "arguments")]]
:body [Predicate]})
(s/defn ast->rule :- Rule
"Converts the rule structure returned from the parser"
[{:keys [head body] :as rule-ast} :- RuleAST]
(r/rule (map triplet head)
(mapcat structure body)
(-> head ffirst name gensym name)))
(s/defn read-str :- {:rules [Rule]
:axioms [Axiom]}
"Reads a string"
[s :- s/Str]
(let [program-ast (parser/parse s)
axioms (filter (comp (partial = :axiom) :type) program-ast)
rules (filter (comp (partial = :rule) :type) program-ast)]
{:rules (map ast->rule rules)
:axioms (map ast->axiom axioms)}))
(s/defn read-stream :- Program
"Reads a input stream"
[in :- InputStream]
(let [text (slurp in)]
(read-str text)))