yukigo-prolog-parser 0.1.3 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.json +7 -7
- package/CHANGELOG.md +41 -13
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/parser/grammar.cjs +193 -0
- package/dist/parser/grammar.cjs.map +1 -0
- package/dist/parser/grammar.d.cts +16 -0
- package/dist/parser/lexer.d.ts +1 -0
- package/dist/parser/lexer.js +2 -0
- package/dist/parser/lexer.js.map +1 -1
- package/dist/std.js +131 -131
- package/package.json +6 -13
- package/src/index.ts +93 -82
- package/src/parser/{grammar.ts → grammar.cjs} +114 -155
- package/src/parser/grammar.d.ts +3 -0
- package/src/parser/grammar.ne +224 -223
- package/src/parser/lexer.ts +42 -40
- package/src/std.ts +131 -131
- package/tests/parser.spec.ts +1083 -1084
- package/tests/tests.spec.ts +82 -82
- package/tsconfig.json +26 -26
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/parser/grammar.d.ts +0 -28
- package/dist/parser/grammar.js +0 -189
- package/dist/parser/grammar.js.map +0 -1
package/dist/std.js
CHANGED
|
@@ -1,133 +1,133 @@
|
|
|
1
|
-
export const stdCode = `
|
|
2
|
-
% between(+Low, +High, ?Value)
|
|
3
|
-
% True if Low =< Value =< High (assuming integers)
|
|
4
|
-
between(Low, High, Low) :- Low =< High.
|
|
5
|
-
between(Low, High, Value) :-
|
|
6
|
-
Low < High,
|
|
7
|
-
NextLow is Low + 1,
|
|
8
|
-
between(NextLow, High, Value).
|
|
9
|
-
|
|
10
|
-
% union(+List1, +List2, -Union)
|
|
11
|
-
% Union of two lists without duplicates (order not preserved)
|
|
12
|
-
union([], L, L).
|
|
13
|
-
union([H|T], L2, Union) :-
|
|
14
|
-
( member(H, L2)
|
|
15
|
-
-> union(T, L2, Union)
|
|
16
|
-
; Union = [H|Rest],
|
|
17
|
-
union(T, L2, Rest)
|
|
18
|
-
).
|
|
19
|
-
|
|
20
|
-
% intersection(+List1, +List2, -Intersection)
|
|
21
|
-
intersection([], _, []).
|
|
22
|
-
intersection([H|T], L2, [H|Rest]) :-
|
|
23
|
-
member(H, L2),
|
|
24
|
-
!,
|
|
25
|
-
intersection(T, L2, Rest).
|
|
26
|
-
intersection([_|T], L2, Rest) :-
|
|
27
|
-
intersection(T, L2, Rest).
|
|
28
|
-
|
|
29
|
-
% max_member(-Max, +List)
|
|
30
|
-
max_member(Max, [Max]) :- !.
|
|
31
|
-
max_member(Max, [H|T]) :-
|
|
32
|
-
max_member(M, T),
|
|
33
|
-
( H > M
|
|
34
|
-
-> Max = H
|
|
35
|
-
; Max = M
|
|
36
|
-
).
|
|
37
|
-
|
|
38
|
-
% min_member(-Min, +List)
|
|
39
|
-
min_member(Min, [Min]) :- !.
|
|
40
|
-
min_member(Min, [H|T]) :-
|
|
41
|
-
min_member(M, T),
|
|
42
|
-
( H < M
|
|
43
|
-
-> Min = H
|
|
44
|
-
; Min = M
|
|
45
|
-
).
|
|
46
|
-
|
|
47
|
-
% sumlist(+List, -Sum)
|
|
48
|
-
sumlist([], 0).
|
|
49
|
-
sumlist([H|T], Sum) :-
|
|
50
|
-
sumlist(T, RestSum),
|
|
51
|
-
Sum is H + RestSum.
|
|
52
|
-
|
|
53
|
-
% length(?List, ?Length)
|
|
54
|
-
length([], 0).
|
|
55
|
-
length([_|Tail], N) :-
|
|
56
|
-
length(Tail, M),
|
|
57
|
-
N is M + 1.
|
|
58
|
-
|
|
59
|
-
% flatten(+NestedList, -FlatList)
|
|
60
|
-
flatten([], []).
|
|
61
|
-
flatten([H|T], Flat) :-
|
|
62
|
-
!,
|
|
63
|
-
flatten(H, FlatH),
|
|
64
|
-
flatten(T, FlatT),
|
|
65
|
-
append(FlatH, FlatT, Flat).
|
|
66
|
-
flatten(X, [X]).
|
|
67
|
-
|
|
68
|
-
% reverse(+List, -Reversed)
|
|
69
|
-
reverse(List, Reversed) :-
|
|
70
|
-
reverse_acc(List, [], Reversed).
|
|
71
|
-
|
|
72
|
-
reverse_acc([], Acc, Acc).
|
|
73
|
-
reverse_acc([H|T], Acc, Reversed) :-
|
|
74
|
-
reverse_acc(T, [H|Acc], Reversed).
|
|
75
|
-
|
|
76
|
-
% list_to_set(+List, -Set)
|
|
77
|
-
% Removes duplicates, keeps first occurrence
|
|
78
|
-
list_to_set([], []).
|
|
79
|
-
list_to_set([H|T], [H|Rest]) :-
|
|
80
|
-
exclude(==(H), T, T1),
|
|
81
|
-
list_to_set(T1, Rest).
|
|
82
|
-
|
|
83
|
-
==(H, T) :-
|
|
84
|
-
H == T.
|
|
85
|
-
|
|
86
|
-
% nth0(?Index, ?List, ?Elem)
|
|
87
|
-
% Index starts at 0
|
|
88
|
-
nth0(0, [H|_], H).
|
|
89
|
-
nth0(N, [_|T], Elem) :-
|
|
90
|
-
N > 0,
|
|
91
|
-
N1 is N - 1,
|
|
92
|
-
nth0(N1, T, Elem).
|
|
93
|
-
|
|
94
|
-
% nth1(?Index, ?List, ?Elem)
|
|
95
|
-
% Index starts at 1
|
|
96
|
-
nth1(1, [H|_], H).
|
|
97
|
-
nth1(N, [_|T], Elem) :-
|
|
98
|
-
N > 1,
|
|
99
|
-
N1 is N - 1,
|
|
100
|
-
nth1(N1, T, Elem).
|
|
101
|
-
|
|
102
|
-
% append/3 (needed for flatten and union)
|
|
103
|
-
append([], L, L).
|
|
104
|
-
append([H|T], L, [H|R]) :-
|
|
105
|
-
append(T, L, R).
|
|
106
|
-
|
|
107
|
-
% member/2 (needed for many predicates)
|
|
108
|
-
member(H, [H|_]).
|
|
109
|
-
member(H, [_|T]) :-
|
|
110
|
-
member(H, T).
|
|
111
|
-
|
|
112
|
-
% exclude(+Pred, +List, -Filtered)
|
|
113
|
-
% Removes elements satisfying Pred
|
|
114
|
-
exclude(_, [], []).
|
|
115
|
-
exclude(Pred, [H|T], Rest) :-
|
|
116
|
-
( call(Pred, H)
|
|
117
|
-
-> exclude(Pred, T, Rest)
|
|
118
|
-
; Rest = [H|Rest2],
|
|
119
|
-
exclude(Pred, T, Rest2)
|
|
120
|
-
).
|
|
121
|
-
|
|
122
|
-
% Arithmetic predicates
|
|
123
|
-
abs(X, Y) :- Y is abs(X).
|
|
124
|
-
round(X, Y) :- Y is round(X).
|
|
125
|
-
sqrt(X, Y) :- Y is sqrt(X).
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
max_list([X], X).
|
|
129
|
-
max_list([H|T], Max) :-
|
|
130
|
-
max_list(T, MaxTail),
|
|
131
|
-
Max is max(H, MaxTail).
|
|
1
|
+
export const stdCode = `
|
|
2
|
+
% between(+Low, +High, ?Value)
|
|
3
|
+
% True if Low =< Value =< High (assuming integers)
|
|
4
|
+
between(Low, High, Low) :- Low =< High.
|
|
5
|
+
between(Low, High, Value) :-
|
|
6
|
+
Low < High,
|
|
7
|
+
NextLow is Low + 1,
|
|
8
|
+
between(NextLow, High, Value).
|
|
9
|
+
|
|
10
|
+
% union(+List1, +List2, -Union)
|
|
11
|
+
% Union of two lists without duplicates (order not preserved)
|
|
12
|
+
union([], L, L).
|
|
13
|
+
union([H|T], L2, Union) :-
|
|
14
|
+
( member(H, L2)
|
|
15
|
+
-> union(T, L2, Union)
|
|
16
|
+
; Union = [H|Rest],
|
|
17
|
+
union(T, L2, Rest)
|
|
18
|
+
).
|
|
19
|
+
|
|
20
|
+
% intersection(+List1, +List2, -Intersection)
|
|
21
|
+
intersection([], _, []).
|
|
22
|
+
intersection([H|T], L2, [H|Rest]) :-
|
|
23
|
+
member(H, L2),
|
|
24
|
+
!,
|
|
25
|
+
intersection(T, L2, Rest).
|
|
26
|
+
intersection([_|T], L2, Rest) :-
|
|
27
|
+
intersection(T, L2, Rest).
|
|
28
|
+
|
|
29
|
+
% max_member(-Max, +List)
|
|
30
|
+
max_member(Max, [Max]) :- !.
|
|
31
|
+
max_member(Max, [H|T]) :-
|
|
32
|
+
max_member(M, T),
|
|
33
|
+
( H > M
|
|
34
|
+
-> Max = H
|
|
35
|
+
; Max = M
|
|
36
|
+
).
|
|
37
|
+
|
|
38
|
+
% min_member(-Min, +List)
|
|
39
|
+
min_member(Min, [Min]) :- !.
|
|
40
|
+
min_member(Min, [H|T]) :-
|
|
41
|
+
min_member(M, T),
|
|
42
|
+
( H < M
|
|
43
|
+
-> Min = H
|
|
44
|
+
; Min = M
|
|
45
|
+
).
|
|
46
|
+
|
|
47
|
+
% sumlist(+List, -Sum)
|
|
48
|
+
sumlist([], 0).
|
|
49
|
+
sumlist([H|T], Sum) :-
|
|
50
|
+
sumlist(T, RestSum),
|
|
51
|
+
Sum is H + RestSum.
|
|
52
|
+
|
|
53
|
+
% length(?List, ?Length)
|
|
54
|
+
length([], 0).
|
|
55
|
+
length([_|Tail], N) :-
|
|
56
|
+
length(Tail, M),
|
|
57
|
+
N is M + 1.
|
|
58
|
+
|
|
59
|
+
% flatten(+NestedList, -FlatList)
|
|
60
|
+
flatten([], []).
|
|
61
|
+
flatten([H|T], Flat) :-
|
|
62
|
+
!,
|
|
63
|
+
flatten(H, FlatH),
|
|
64
|
+
flatten(T, FlatT),
|
|
65
|
+
append(FlatH, FlatT, Flat).
|
|
66
|
+
flatten(X, [X]).
|
|
67
|
+
|
|
68
|
+
% reverse(+List, -Reversed)
|
|
69
|
+
reverse(List, Reversed) :-
|
|
70
|
+
reverse_acc(List, [], Reversed).
|
|
71
|
+
|
|
72
|
+
reverse_acc([], Acc, Acc).
|
|
73
|
+
reverse_acc([H|T], Acc, Reversed) :-
|
|
74
|
+
reverse_acc(T, [H|Acc], Reversed).
|
|
75
|
+
|
|
76
|
+
% list_to_set(+List, -Set)
|
|
77
|
+
% Removes duplicates, keeps first occurrence
|
|
78
|
+
list_to_set([], []).
|
|
79
|
+
list_to_set([H|T], [H|Rest]) :-
|
|
80
|
+
exclude(==(H), T, T1),
|
|
81
|
+
list_to_set(T1, Rest).
|
|
82
|
+
|
|
83
|
+
==(H, T) :-
|
|
84
|
+
H == T.
|
|
85
|
+
|
|
86
|
+
% nth0(?Index, ?List, ?Elem)
|
|
87
|
+
% Index starts at 0
|
|
88
|
+
nth0(0, [H|_], H).
|
|
89
|
+
nth0(N, [_|T], Elem) :-
|
|
90
|
+
N > 0,
|
|
91
|
+
N1 is N - 1,
|
|
92
|
+
nth0(N1, T, Elem).
|
|
93
|
+
|
|
94
|
+
% nth1(?Index, ?List, ?Elem)
|
|
95
|
+
% Index starts at 1
|
|
96
|
+
nth1(1, [H|_], H).
|
|
97
|
+
nth1(N, [_|T], Elem) :-
|
|
98
|
+
N > 1,
|
|
99
|
+
N1 is N - 1,
|
|
100
|
+
nth1(N1, T, Elem).
|
|
101
|
+
|
|
102
|
+
% append/3 (needed for flatten and union)
|
|
103
|
+
append([], L, L).
|
|
104
|
+
append([H|T], L, [H|R]) :-
|
|
105
|
+
append(T, L, R).
|
|
106
|
+
|
|
107
|
+
% member/2 (needed for many predicates)
|
|
108
|
+
member(H, [H|_]).
|
|
109
|
+
member(H, [_|T]) :-
|
|
110
|
+
member(H, T).
|
|
111
|
+
|
|
112
|
+
% exclude(+Pred, +List, -Filtered)
|
|
113
|
+
% Removes elements satisfying Pred
|
|
114
|
+
exclude(_, [], []).
|
|
115
|
+
exclude(Pred, [H|T], Rest) :-
|
|
116
|
+
( call(Pred, H)
|
|
117
|
+
-> exclude(Pred, T, Rest)
|
|
118
|
+
; Rest = [H|Rest2],
|
|
119
|
+
exclude(Pred, T, Rest2)
|
|
120
|
+
).
|
|
121
|
+
|
|
122
|
+
% Arithmetic predicates
|
|
123
|
+
abs(X, Y) :- Y is abs(X).
|
|
124
|
+
round(X, Y) :- Y is round(X).
|
|
125
|
+
sqrt(X, Y) :- Y is sqrt(X).
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
max_list([X], X).
|
|
129
|
+
max_list([H|T], Max) :-
|
|
130
|
+
max_list(T, MaxTail),
|
|
131
|
+
Max is max(H, MaxTail).
|
|
132
132
|
`;
|
|
133
133
|
//# sourceMappingURL=std.js.map
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yukigo-prolog-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build": "nearleyc ./src/parser/grammar.ne -o ./src/parser/grammar.
|
|
9
|
+
"build": "nearleyc ./src/parser/grammar.ne -o ./src/parser/grammar.cjs && tsc",
|
|
10
10
|
"test": "mocha --import=tsx"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [],
|
|
@@ -17,23 +17,16 @@
|
|
|
17
17
|
"moo-ignore": "^2.5.3",
|
|
18
18
|
"nearley": "^2.20.1"
|
|
19
19
|
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/moo": "^0.5.10"
|
|
22
|
+
},
|
|
20
23
|
"exports": {
|
|
21
24
|
".": {
|
|
22
25
|
"import": "./dist/index.js",
|
|
23
26
|
"types": "./dist/index.d.ts"
|
|
24
27
|
}
|
|
25
28
|
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@types/chai": "^5.2.2",
|
|
28
|
-
"@types/mocha": "^10.0.10",
|
|
29
|
-
"@types/moo": "^0.5.10",
|
|
30
|
-
"@types/node": "^24.10.0",
|
|
31
|
-
"chai": "^6.2.0",
|
|
32
|
-
"mocha": "^11.7.1",
|
|
33
|
-
"tsx": "^4.20.6",
|
|
34
|
-
"typescript": "^5.9.2"
|
|
35
|
-
},
|
|
36
29
|
"peerDependencies": {
|
|
37
|
-
"yukigo-ast": "^0.
|
|
30
|
+
"yukigo-ast": "^0.3.0"
|
|
38
31
|
}
|
|
39
32
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,82 +1,93 @@
|
|
|
1
|
-
import { AST, Expression, Rule, YukigoParser } from "yukigo-ast";
|
|
2
|
-
import nearley from "nearley";
|
|
3
|
-
import grammar from "./parser/grammar.
|
|
4
|
-
import { Token } from "moo";
|
|
5
|
-
import { stdCode } from "./std.js";
|
|
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
|
-
public
|
|
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
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
1
|
+
import { AST, Expression, Rule, YukigoParser } from "yukigo-ast";
|
|
2
|
+
import nearley from "nearley";
|
|
3
|
+
import grammar from "./parser/grammar.cjs";
|
|
4
|
+
import { Token } from "moo";
|
|
5
|
+
import { stdCode } from "./std.js";
|
|
6
|
+
|
|
7
|
+
interface NearleyError {
|
|
8
|
+
token?: any;
|
|
9
|
+
offset?: number;
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class UnexpectedToken extends Error {
|
|
14
|
+
constructor(token: Token) {
|
|
15
|
+
super(
|
|
16
|
+
`Parser: Unexpected '${token.type}' token '${token.value}' at line ${token.line} col ${token.col}.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class AmbiguityError extends Error {
|
|
21
|
+
constructor(amountAST: number) {
|
|
22
|
+
super(
|
|
23
|
+
`Parser: Too much ambiguity. ${amountAST} ASTs parsed. Output not generated.`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type HaskellConfig = {
|
|
29
|
+
typecheck: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export class YukigoPrologParser implements YukigoParser {
|
|
33
|
+
public errors: string[] = [];
|
|
34
|
+
private std: AST;
|
|
35
|
+
constructor(std: string = stdCode) {
|
|
36
|
+
this.errors = [];
|
|
37
|
+
this.std = this.feedParser(std);
|
|
38
|
+
}
|
|
39
|
+
public parse(code: string): AST {
|
|
40
|
+
const result = this.feedParser(code);
|
|
41
|
+
const ast = groupRuleDeclarations(this.std.concat(result));
|
|
42
|
+
return ast;
|
|
43
|
+
}
|
|
44
|
+
public parseExpression(code: string): Expression {
|
|
45
|
+
const expr = this.feedParser(code)[0];
|
|
46
|
+
return expr;
|
|
47
|
+
}
|
|
48
|
+
private feedParser(code: string): any {
|
|
49
|
+
const parser = new nearley.Parser(
|
|
50
|
+
nearley.Grammar.fromCompiled(grammar as any)
|
|
51
|
+
);
|
|
52
|
+
try {
|
|
53
|
+
parser.feed(code);
|
|
54
|
+
parser.finish();
|
|
55
|
+
} catch (e: unknown) {
|
|
56
|
+
const error = e as NearleyError; // Assert the shape
|
|
57
|
+
if (error.token) {
|
|
58
|
+
throw new UnexpectedToken(error.token);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
const { results } = parser;
|
|
63
|
+
if (results.length > 1) throw new AmbiguityError(results.length);
|
|
64
|
+
if (results.length == 0) return [];
|
|
65
|
+
return results[0];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function groupRuleDeclarations(ast: AST): AST {
|
|
70
|
+
const groups: Record<string, Rule[]> = {};
|
|
71
|
+
const others: AST = [];
|
|
72
|
+
|
|
73
|
+
for (const node of ast) {
|
|
74
|
+
if (node instanceof Rule) {
|
|
75
|
+
const name = node.identifier.value;
|
|
76
|
+
if (!groups[name]) {
|
|
77
|
+
groups[name] = [];
|
|
78
|
+
}
|
|
79
|
+
groups[name].push(node);
|
|
80
|
+
} else {
|
|
81
|
+
others.push(node);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Merge equations for each rule
|
|
86
|
+
const ruleGroups: Rule[] = Object.values(groups).map((rules) => {
|
|
87
|
+
const identifier = rules[0].identifier;
|
|
88
|
+
const allEquations = rules.flatMap((r) => r.equations);
|
|
89
|
+
return new Rule(identifier, allEquations, identifier.loc);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return [...others, ...ruleGroups];
|
|
93
|
+
}
|