-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathparse.js
100 lines (76 loc) · 2.68 KB
/
parse.js
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
91
92
93
94
95
96
97
98
99
100
// Rule ::= [Compound Compounds]
// Compounds ::= , Compound Compounds | empty
//
// Structure ::= Variable | Compound
// Variable ::= string | symbol
// Compound ::= [Atom Structures]
// Structure ::= , Structure Structures | empty
// Atom ::= string | number
var Parsec = require("parsecjs");
var debug = Parsec.debug();
//////////
// Atom //
//////////
var atom = debug(Parsec.then(Parsec.Spaces, Parsec.choice([
Parsec.Number,
Parsec.DoubleQuotedString,
Parsec.regexp(/^[a-z][_0-9A-Za-z]*/)])), "atom");
///////////////
// Structure //
///////////////
var structures = [];
var structure = debug(Parsec.choice(structures), "structure");
//////////////
// Variable //
//////////////
var variable = debug(Parsec.then(Parsec.Spaces, Parsec.regexp(/^[_A-Z][_0-9A-Za-z]*/)), "variable");
structures.push(variable);
//////////////
// Compound //
//////////////
var compound = debug(Parsec.bind(atom,
(functor) => Parsec.choice([
Parsec.then(Parsec.keyword("("), Parsec.bind(Parsec.separate(structure, Parsec.keyword(",")),
(arguments) => Parsec.then(Parsec.keyword(")"), Parsec.return([functor].concat(arguments))))),
Parsec.return([functor])])), "compound");
structures.push(compound);
/////////////////////////////////////////////////////
// List (syntactic sugar for nested calls to cons) //
/////////////////////////////////////////////////////
var desugar = (elements) => (tail) => {
var result = tail;
for (var i=elements.length-1; i>=0; i--)
result = ["cons", elements[i], result];
return result;
}
var tail = debug(Parsec.choice([
Parsec.then(Parsec.keyword("]"), Parsec.return(["nil"])),
Parsec.then(Parsec.keyword("|"), Parsec.bind(structure,
(tail) => Parsec.then(Parsec.keyword("]"), Parsec.return(tail))))]), "tail")
var list = debug(Parsec.then(Parsec.keyword("["), Parsec.bind(Parsec.separate(structure, Parsec.keyword(",")),
(elements) => Parsec.lift(tail, desugar(elements)))), "list");
structures.push(list);
//////////
// Rule //
//////////
var body = debug(Parsec.choice([
Parsec.then(Parsec.keyword("."), Parsec.return([])),
Parsec.then(Parsec.keyword(":-"), Parsec.bind(Parsec.separate(compound, Parsec.keyword(",")),
(compounds) => Parsec.then(Parsec.keyword("."), Parsec.return(compounds))))]), "body");
var rule = debug(Parsec.bind(compound,
(head) => Parsec.lift(body, Array.prototype.concat.bind([head]))), "rule");
///////////////
// Top level //
///////////////
var rules = debug(Parsec.many(rule), "rules");
var parsers = {
variable: variable,
atom: atom,
compound: compound,
structure: structure,
rule: rule,
rules: rules,
prolog: rules,
query: compound
};
module.exports = (label, input) => Parsec.run(parsers[label], input);