-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.go
81 lines (72 loc) · 1.57 KB
/
parser.go
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
package main
import (
"unicode"
)
type DatalogSyntax struct {
Expressions []ExpressionSyntax `@@*`
Query *AtomSyntax `"-" @@ "?"`
}
type ExpressionSyntax struct {
Head AtomSyntax `@@`
Body []NegatableAtomSyntax `( ":" "-" (@@ ","?)+ )? "."`
}
type NegatableAtomSyntax struct {
Negated string `("\\" "+")?`
Atom AtomSyntax `@@`
}
type AtomSyntax struct {
Predicate string `@Ident`
Terms []string `"(" (@Ident ","?)+ ")"`
}
func ConstructTerm(ts string) Term {
var termType string
if unicode.IsUpper(rune(ts[0])) {
termType = "VAR"
} else {
termType = "SYM"
}
return Term{
Type: termType,
Name: ts,
}
}
func ConstructAtom(as AtomSyntax) Atom {
terms := make([]Term, len(as.Terms))
for i, ts := range as.Terms {
terms[i] = ConstructTerm(ts)
}
return Atom{
PredicateSymbol: as.Predicate,
Terms: terms,
}
}
func ConstructProgram(ast DatalogSyntax) Program {
program := make([]Rule, len(ast.Expressions))
for i, expression := range ast.Expressions {
body := make([]Atom, len(expression.Body))
for j, bs := range expression.Body {
body[j] = ConstructAtom(bs.Atom)
}
program[i] = Rule{
Head: ConstructAtom(expression.Head),
Body: body,
}
}
return program
}
func ConstructQuery(ast DatalogSyntax) *Rule {
if ast.Query == nil {
return nil
}
atom := ConstructAtom(*ast.Query)
queryVars := make([]Term, 0)
for _, term := range atom.Terms {
if term.Type == "VAR" {
queryVars = append(queryVars, term)
}
}
return &Rule{
Head: Atom{QUERY_PREDICATE, queryVars},
Body: []Atom{atom},
}
}