-
Notifications
You must be signed in to change notification settings - Fork 4
/
chevrotain.mjs
113 lines (102 loc) · 2.9 KB
/
chevrotain.mjs
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
import { createToken, Lexer, EmbeddedActionsParser } from "chevrotain";
const nameKey = createToken({ name: "nameKey", pattern: /name/ });
const classKey = createToken({ name: "classKey", pattern: /class/ });
const irandKey = createToken({ name: "irandKey", pattern: /item_randomness/ });
const colon = createToken({ name: "colon", pattern: /:/ });
const whiteSpace = createToken({
name: "WhiteSpace",
pattern: /\s+/,
group: Lexer.SKIPPED,
});
const nameString = createToken({ name: "nameString", pattern: /[a-zA-Z]+/ });
const classString = createToken({
name: "classString",
pattern: /human|dwarf|wizard/i,
});
const irandString = createToken({
name: "randString",
pattern: /very low|low|medium|high|very high/i,
});
const allTokens = [
nameKey,
classKey,
classString,
irandKey,
irandString,
whiteSpace,
colon,
nameString,
];
const lexer = new Lexer(allTokens);
class ConfigParser extends EmbeddedActionsParser {
constructor() {
super(allTokens);
const $ = this;
$.RULE("config", () => {
return $.SUBRULE($.configKeys);
});
$.RULE("configKeys", () => {
let obj = {};
$.MANY(() => {
$.OR([
{
ALT: () => {
obj.name = $.SUBRULE($.characterName);
},
},
{
ALT: () => {
obj.class = $.SUBRULE($.characterClass);
},
},
{
ALT: () => {
obj.item_randomness = $.SUBRULE($.itemRandomness);
},
},
]);
});
return obj;
});
$.RULE("characterName", () => {
$.CONSUME(nameKey);
$.CONSUME(colon);
let name = $.CONSUME(nameString).image;
return name;
});
$.RULE("characterClass", () => {
$.CONSUME(classKey);
$.CONSUME(colon);
let cls = $.CONSUME(classString).image.toLowerCase();
return cls;
});
$.RULE("itemRandomness", () => {
$.CONSUME(irandKey);
$.CONSUME(colon);
let temp = $.CONSUME(irandString).image.toLowerCase();
let bounds = {
"very low": [0.05, 0.2],
low: [0.2, 0.4],
medium: [0.4, 0.6],
high: [0.6, 0.8],
"very high": [0.8, 1],
}[temp];
let rand = Math.random();
return $.ACTION(() => bounds[0] + (bounds[1] - bounds[0]) * rand);
});
// very important to call this after all the rules have been defined.
// otherwise the parser may not work correctly as it will lack information
// derived during the self analysis phase.
this.performSelfAnalysis();
}
}
const parser = new ConfigParser();
// wrapping it all together
const lexResult = lexer.tokenize(
"name: Rincewind\nclass: Wizard\nitem_randomness: very high\n",
);
// setting a new input will RESET the parser instance's state.
parser.input = lexResult.tokens;
// any top level rule may be used as an entry point
const value = parser.config();
console.log(value);