-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparserBuilder.js
121 lines (92 loc) · 3.44 KB
/
parserBuilder.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
function labelToFunctionName(actionLabel) {
return actionLabel
.split('_')
.map((current, index) => (index == 0)
? current.toLowerCase()
: current.charAt(0).toUpperCase() + current.slice(1).toLowerCase())
.join('');
}
function convertTextIntoAction(rawAction, actions) {
const [actionName, rawActionName, actionParameters] = (rawAction instanceof Array)
? [labelToFunctionName(rawAction[0]), rawAction[0], rawAction.slice(1)]
: [labelToFunctionName(rawAction), rawAction, []];
if (!actions.hasOwnProperty(actionName)) {
throw new Error(`Unknown action: '${actionName}' (raw: ${rawActionName})`);
}
return actions[actionName].apply(null, actionParameters);
}
function parseParameters(parameter, actions) {
if (parameter instanceof Array) {
return parameter.map(currentAction => convertTextIntoAction(currentAction, actions));
} else if (parameter instanceof Object) {
const result = {};
for (const key in parameter) {
if (!parameter.hasOwnProperty(key)) {
continue;
}
result[key] = parseParameters(parameter[key], actions);
}
return result;
}
return parameter;
}
function* preProcessing(states, preParsers) {
for (const state of states) {
if (state.hasOwnProperty('pre_parser')) {
const preParserName = labelToFunctionName(state['pre_parser']);
if (!preParsers.hasOwnProperty(preParserName)) {
throw new Error(`Unknown preParsers: '${preParserName}' (raw: '${state['pre_parser']}')`);
}
yield* state['pre_states'].map(preParsers[preParserName]);
} else {
yield state;
}
}
}
function parser(statesArray, states, actions, preParsers) {
return Array.from(preProcessing(statesArray, preParsers))
.reduce((previous, current) => {
if (!current.hasOwnProperty('type')) {
throw new Error(`Missing type attribute! (raw: ${JSON.stringify(current)})`);
}
if (!current.hasOwnProperty('name')) {
throw new Error(`Missing name attribute! (raw: ${JSON.stringify(current)})`);
}
const stateName = labelToFunctionName(current.type);
if (!states.hasOwnProperty(stateName)) {
throw new Error(`Unknown state: '${stateName}' (raw: '${current.type}')`);
}
previous[current.name] = states[stateName].call(null, parseParameters(current, actions));
return previous;
}, {});
}
class ParserBuilder {
constructor() {
this.additionalStates = null;
this.additionalActions = null;
this.preParsers = null;
}
addCustomStates(states) {
this.additionalStates = states;
return this;
}
addCustomActions(actions) {
this.additionalActions = actions;
return this;
}
addPreParsers(preParsers) {
this.preParsers = preParsers;
return this;
}
parse(jsonStatesArray) {
const originalActions = require('./actions');
const originalStates = require('./states');
return parser(
jsonStatesArray,
{ ...originalStates, ...(this.additionalStates || {}) },
{ ...originalActions, ...(this.additionalActions || {}) },
this.preParsers || {}
);
}
}
module.exports = ParserBuilder;