grammar-well 1.3.3 → 2.0.1

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.
Files changed (246) hide show
  1. package/README.md +76 -560
  2. package/build/generator/artifacts/basic.d.ts +7 -0
  3. package/build/generator/artifacts/basic.js +24 -0
  4. package/build/generator/artifacts/basic.js.map +1 -0
  5. package/build/generator/artifacts/lexer.d.ts +13 -0
  6. package/build/generator/artifacts/lexer.js +204 -0
  7. package/build/generator/artifacts/lexer.js.map +1 -0
  8. package/build/{compiler/generator → generator}/artifacts/lr.d.ts +14 -14
  9. package/build/{compiler/generator → generator}/artifacts/lr.js +18 -22
  10. package/build/generator/artifacts/lr.js.map +1 -0
  11. package/build/generator/builtin/registry.json +1 -0
  12. package/build/generator/generator.d.ts +38 -0
  13. package/build/generator/generator.js +368 -0
  14. package/build/generator/generator.js.map +1 -0
  15. package/build/generator/grammars/index.d.ts +2 -0
  16. package/build/generator/grammars/index.js +3 -0
  17. package/build/generator/grammars/index.js.map +1 -0
  18. package/build/generator/grammars/v1.d.ts +1190 -0
  19. package/build/generator/grammars/v1.js +614 -0
  20. package/build/generator/grammars/v1.js.map +1 -0
  21. package/build/generator/grammars/v2.d.ts +1367 -0
  22. package/build/generator/grammars/v2.js +695 -0
  23. package/build/generator/grammars/v2.js.map +1 -0
  24. package/build/generator/import-resolvers/auto.d.ts +2 -0
  25. package/build/generator/import-resolvers/auto.js +11 -0
  26. package/build/generator/import-resolvers/auto.js.map +1 -0
  27. package/build/generator/import-resolvers/browser.d.ts +7 -0
  28. package/build/generator/import-resolvers/browser.js +13 -0
  29. package/build/generator/import-resolvers/browser.js.map +1 -0
  30. package/build/generator/import-resolvers/filesystem.d.ts +7 -0
  31. package/build/generator/import-resolvers/filesystem.js +15 -0
  32. package/build/generator/import-resolvers/filesystem.js.map +1 -0
  33. package/build/generator/index.d.ts +3 -0
  34. package/build/generator/index.js +4 -0
  35. package/build/generator/index.js.map +1 -0
  36. package/build/generator/state.d.ts +28 -0
  37. package/build/generator/state.js +73 -0
  38. package/build/generator/state.js.map +1 -0
  39. package/build/generator/stringify/common.d.ts +22 -0
  40. package/build/generator/stringify/common.js +83 -0
  41. package/build/generator/stringify/common.js.map +1 -0
  42. package/build/generator/stringify/exports/javascript.d.ts +3 -0
  43. package/build/generator/stringify/exports/javascript.js +26 -0
  44. package/build/generator/stringify/exports/javascript.js.map +1 -0
  45. package/build/generator/stringify/exports/json.d.ts +2 -0
  46. package/build/generator/stringify/exports/json.js +4 -0
  47. package/build/generator/stringify/exports/json.js.map +1 -0
  48. package/build/generator/stringify/exports/registry.d.ts +20 -0
  49. package/build/generator/stringify/exports/registry.js +17 -0
  50. package/build/generator/stringify/exports/registry.js.map +1 -0
  51. package/build/generator/stringify/exports/typescript.d.ts +2 -0
  52. package/build/generator/stringify/exports/typescript.js +16 -0
  53. package/build/generator/stringify/exports/typescript.js.map +1 -0
  54. package/build/generator/stringify/grammar/v2.d.ts +20 -0
  55. package/build/generator/stringify/grammar/v2.js +211 -0
  56. package/build/generator/stringify/grammar/v2.js.map +1 -0
  57. package/build/generator/stringify/javascript.d.ts +13 -0
  58. package/build/generator/stringify/javascript.js +83 -0
  59. package/build/generator/stringify/javascript.js.map +1 -0
  60. package/build/index.d.ts +7 -6
  61. package/build/index.js +7 -24
  62. package/build/index.js.map +1 -1
  63. package/build/lexers/character-lexer.d.ts +2 -2
  64. package/build/lexers/character-lexer.js +1 -5
  65. package/build/lexers/character-lexer.js.map +1 -1
  66. package/build/lexers/stateful-lexer.d.ts +12 -17
  67. package/build/lexers/stateful-lexer.js +38 -186
  68. package/build/lexers/stateful-lexer.js.map +1 -1
  69. package/build/lexers/token-buffer.d.ts +8 -8
  70. package/build/lexers/token-buffer.js +1 -5
  71. package/build/lexers/token-buffer.js.map +1 -1
  72. package/build/parser/algorithms/cyk.d.ts +6 -6
  73. package/build/parser/algorithms/cyk.js +10 -13
  74. package/build/parser/algorithms/cyk.js.map +1 -1
  75. package/build/parser/algorithms/earley.d.ts +7 -7
  76. package/build/parser/algorithms/earley.js +7 -11
  77. package/build/parser/algorithms/earley.js.map +1 -1
  78. package/build/parser/algorithms/lrk/algorithm.d.ts +3 -3
  79. package/build/parser/algorithms/lrk/algorithm.js +10 -13
  80. package/build/parser/algorithms/lrk/algorithm.js.map +1 -1
  81. package/build/parser/algorithms/lrk/bimap.js +1 -5
  82. package/build/parser/algorithms/lrk/bimap.js.map +1 -1
  83. package/build/parser/algorithms/lrk/canonical-collection.d.ts +7 -7
  84. package/build/parser/algorithms/lrk/canonical-collection.js +11 -15
  85. package/build/parser/algorithms/lrk/canonical-collection.js.map +1 -1
  86. package/build/parser/algorithms/lrk/closure.d.ts +3 -3
  87. package/build/parser/algorithms/lrk/closure.js +3 -7
  88. package/build/parser/algorithms/lrk/closure.js.map +1 -1
  89. package/build/parser/algorithms/lrk/stack.d.ts +6 -6
  90. package/build/parser/algorithms/lrk/stack.js +1 -5
  91. package/build/parser/algorithms/lrk/stack.js.map +1 -1
  92. package/build/parser/algorithms/lrk/state.d.ts +5 -5
  93. package/build/parser/algorithms/lrk/state.js +1 -2
  94. package/build/parser/parse.d.ts +10 -0
  95. package/build/parser/parse.js +34 -0
  96. package/build/parser/parse.js.map +1 -0
  97. package/build/tsconfig.tsbuildinfo +1 -0
  98. package/build/typings/ast.d.ts +134 -0
  99. package/build/typings/ast.js +3 -0
  100. package/build/typings/ast.js.map +1 -0
  101. package/build/typings/common.d.ts +4 -0
  102. package/build/typings/common.js +2 -0
  103. package/build/typings/common.js.map +1 -0
  104. package/build/typings/generator.d.ts +58 -0
  105. package/build/typings/generator.js +3 -0
  106. package/build/typings/generator.js.map +1 -0
  107. package/build/typings/index.d.ts +43 -0
  108. package/build/typings/index.js +5 -0
  109. package/build/typings/index.js.map +1 -0
  110. package/build/typings/runtime.d.ts +70 -0
  111. package/build/typings/runtime.js +2 -0
  112. package/build/typings/runtime.js.map +1 -0
  113. package/build/utility/format.d.ts +1 -0
  114. package/build/utility/format.js +12 -0
  115. package/build/utility/format.js.map +1 -0
  116. package/build/utility/general.d.ts +1 -1
  117. package/build/utility/general.js +5 -13
  118. package/build/utility/general.js.map +1 -1
  119. package/build/utility/index.d.ts +4 -1
  120. package/build/utility/index.js +4 -17
  121. package/build/utility/index.js.map +1 -1
  122. package/build/utility/lint.d.ts +2 -2
  123. package/build/utility/lint.js +2 -6
  124. package/build/utility/lint.js.map +1 -1
  125. package/build/utility/monarch.d.ts +2 -2
  126. package/build/utility/monarch.js +33 -38
  127. package/build/utility/monarch.js.map +1 -1
  128. package/build/utility/parsing.d.ts +6 -0
  129. package/build/utility/parsing.js +26 -0
  130. package/build/utility/parsing.js.map +1 -0
  131. package/build/utility/text-format.d.ts +6 -6
  132. package/build/utility/text-format.js +2 -6
  133. package/build/utility/text-format.js.map +1 -1
  134. package/package.json +17 -24
  135. package/src/generator/artifacts/basic.ts +26 -0
  136. package/src/generator/artifacts/lexer.ts +228 -0
  137. package/src/{compiler/generator → generator}/artifacts/lr.ts +25 -24
  138. package/src/generator/builtin/character.well +7 -0
  139. package/src/generator/builtin/json.well +85 -0
  140. package/src/generator/builtin/number.well +21 -0
  141. package/src/generator/builtin/registry.json +1 -0
  142. package/src/generator/builtin/string.well +54 -0
  143. package/src/generator/builtin/whitespace.well +16 -0
  144. package/src/generator/generator.ts +401 -0
  145. package/src/generator/grammars/index.ts +2 -0
  146. package/src/generator/grammars/v1.ts +620 -0
  147. package/src/generator/grammars/v1.well +422 -0
  148. package/src/generator/grammars/v2.ts +701 -0
  149. package/src/generator/grammars/v2.well +413 -0
  150. package/src/generator/import-resolvers/auto.ts +12 -0
  151. package/src/generator/import-resolvers/browser.ts +13 -0
  152. package/src/generator/import-resolvers/filesystem.ts +18 -0
  153. package/src/generator/index.ts +3 -0
  154. package/src/generator/state.ts +89 -0
  155. package/src/generator/stringify/common.ts +90 -0
  156. package/src/generator/stringify/exports/javascript.ts +29 -0
  157. package/src/generator/stringify/exports/json.ts +5 -0
  158. package/src/generator/stringify/exports/registry.ts +20 -0
  159. package/src/generator/stringify/exports/typescript.ts +17 -0
  160. package/src/generator/stringify/grammar/v2.ts +223 -0
  161. package/src/generator/stringify/javascript.ts +94 -0
  162. package/src/index.ts +7 -6
  163. package/src/lexers/character-lexer.ts +2 -2
  164. package/src/lexers/stateful-lexer.ts +46 -203
  165. package/src/lexers/token-buffer.ts +3 -3
  166. package/src/parser/algorithms/cyk.ts +13 -12
  167. package/src/parser/algorithms/earley.ts +10 -10
  168. package/src/parser/algorithms/lrk/algorithm.ts +8 -7
  169. package/src/parser/algorithms/lrk/canonical-collection.ts +14 -14
  170. package/src/parser/algorithms/lrk/closure.ts +6 -6
  171. package/src/parser/algorithms/lrk/stack.ts +6 -6
  172. package/src/parser/algorithms/lrk/state.ts +5 -5
  173. package/src/parser/parse.ts +45 -0
  174. package/src/typings/ast.ts +148 -0
  175. package/src/typings/common.ts +2 -0
  176. package/src/typings/generator.ts +62 -0
  177. package/src/typings/index.ts +38 -0
  178. package/src/typings/runtime.ts +82 -0
  179. package/src/utility/format.ts +12 -0
  180. package/src/utility/general.ts +1 -2
  181. package/src/utility/index.ts +4 -1
  182. package/src/utility/lint.ts +5 -5
  183. package/src/utility/monarch.ts +34 -34
  184. package/src/utility/parsing.ts +30 -0
  185. package/src/utility/text-format.ts +7 -7
  186. package/.eslintrc.cjs +0 -14
  187. package/bootstrap.ts +0 -45
  188. package/build/compiler/builtin.json +0 -1
  189. package/build/compiler/compiler.d.ts +0 -50
  190. package/build/compiler/compiler.js +0 -249
  191. package/build/compiler/compiler.js.map +0 -1
  192. package/build/compiler/generator/artifacts/lr.js.map +0 -1
  193. package/build/compiler/generator/artifacts/standard.d.ts +0 -7
  194. package/build/compiler/generator/artifacts/standard.js +0 -28
  195. package/build/compiler/generator/artifacts/standard.js.map +0 -1
  196. package/build/compiler/generator/generator.d.ts +0 -24
  197. package/build/compiler/generator/generator.js +0 -217
  198. package/build/compiler/generator/generator.js.map +0 -1
  199. package/build/compiler/gwell.d.ts +0 -1112
  200. package/build/compiler/gwell.js +0 -576
  201. package/build/compiler/gwell.js.map +0 -1
  202. package/build/compiler/import-resolver.d.ts +0 -15
  203. package/build/compiler/import-resolver.js +0 -37
  204. package/build/compiler/import-resolver.js.map +0 -1
  205. package/build/compiler/index.d.ts +0 -2
  206. package/build/compiler/index.js +0 -19
  207. package/build/compiler/index.js.map +0 -1
  208. package/build/compiler/outputs/javascript.d.ts +0 -3
  209. package/build/compiler/outputs/javascript.js +0 -29
  210. package/build/compiler/outputs/javascript.js.map +0 -1
  211. package/build/compiler/outputs/json.d.ts +0 -2
  212. package/build/compiler/outputs/json.js +0 -8
  213. package/build/compiler/outputs/json.js.map +0 -1
  214. package/build/compiler/outputs/typescript.d.ts +0 -2
  215. package/build/compiler/outputs/typescript.js +0 -21
  216. package/build/compiler/outputs/typescript.js.map +0 -1
  217. package/build/parser/algorithms/lr.d.ts +0 -7
  218. package/build/parser/algorithms/lr.js +0 -108
  219. package/build/parser/algorithms/lr.js.map +0 -5
  220. package/build/parser/algorithms/lr0.d.ts +0 -7
  221. package/build/parser/algorithms/lr0.js +0 -156
  222. package/build/parser/algorithms/lr0.js.map +0 -1
  223. package/build/parser/parser.d.ts +0 -26
  224. package/build/parser/parser.js +0 -74
  225. package/build/parser/parser.js.map +0 -1
  226. package/build/typings.d.ts +0 -226
  227. package/build/typings.js +0 -3
  228. package/build/typings.js.map +0 -1
  229. package/src/compiler/builtin/json.gwell +0 -74
  230. package/src/compiler/builtin/number.gwell +0 -20
  231. package/src/compiler/builtin/string.gwell +0 -48
  232. package/src/compiler/builtin/whitespace.gwell +0 -10
  233. package/src/compiler/builtin.json +0 -1
  234. package/src/compiler/compiler.ts +0 -265
  235. package/src/compiler/generator/artifacts/standard.ts +0 -26
  236. package/src/compiler/generator/generator.ts +0 -237
  237. package/src/compiler/gwell.gwell +0 -294
  238. package/src/compiler/gwell.js +0 -578
  239. package/src/compiler/import-resolver.ts +0 -36
  240. package/src/compiler/index.ts +0 -2
  241. package/src/compiler/outputs/javascript.ts +0 -27
  242. package/src/compiler/outputs/json.ts +0 -5
  243. package/src/compiler/outputs/typescript.ts +0 -18
  244. package/src/parser/parser.ts +0 -77
  245. package/src/typings.ts +0 -248
  246. package/testing.ts +0 -18
@@ -0,0 +1,228 @@
1
+ import { ASTGrammarSymbolRegex, ASTLexerStateImportRule, ASTLexerStateMatchRule, ASTLexerStateNonMatchRule, Dictionary, GeneratorLexerConfig, GeneratorLexerState } from "../../typings/index.js";
2
+ import { CommonGenerator } from "../stringify/common.js";
3
+
4
+ export class LexerArtifact {
5
+ private resolved = new Set<string>();
6
+ private resolving = new Set<string>();
7
+
8
+ constructor(private lexer: GeneratorLexerConfig) { }
9
+
10
+ output(depth: number = 0) {
11
+ if (!this.lexer)
12
+ return null;
13
+
14
+ if (typeof this.lexer === 'string')
15
+ return this.lexer;
16
+
17
+ return CommonGenerator.JSON({
18
+ start: JSON.stringify(this.lexer.start),
19
+ states: this.lexerConfigStates(this.lexer.states, depth + 1)
20
+ }, depth);
21
+ }
22
+
23
+ private lexerConfigStates(states: Dictionary<GeneratorLexerState>, depth: number) {
24
+ this.resolveStates(this.lexer.start);
25
+ const map = {};
26
+ for (const key in states) {
27
+ const state = states[key];
28
+ map[key] = CommonGenerator.JSON({
29
+ unmatched: state.unmatched ? this.lexerConfigStateRule(state.unmatched) : null,
30
+ rules: this.lexerConfigStateRules(state.rules, depth + 2),
31
+ regex: CompileRegExp(key, state as unknown as any)
32
+ }, depth + 1);
33
+ }
34
+
35
+ return CommonGenerator.JSON(map, depth);
36
+ }
37
+
38
+ private lexerConfigStateRules(rules: (ASTLexerStateImportRule | ASTLexerStateMatchRule)[], depth: number) {
39
+ const ary = rules.map(rule => {
40
+ if ('import' in rule)
41
+ return CommonGenerator.JSON({ import: JSON.stringify(rule.import) }, -1)
42
+ return this.lexerConfigStateRule(rule as ASTLexerStateMatchRule)
43
+ });
44
+ return CommonGenerator.JSON(ary, depth);
45
+ }
46
+
47
+ private lexerConfigStateRule(rule: ASTLexerStateMatchRule | ASTLexerStateNonMatchRule) {
48
+ return CommonGenerator.JSON({
49
+ when: 'when' in rule ? CommonGenerator.SerializeSymbol(rule.when as any) : null,
50
+ before: JSON.stringify(rule.before),
51
+ skip: JSON.stringify(rule.skip),
52
+
53
+ type: JSON.stringify(rule.type),
54
+ tag: JSON.stringify(rule.tag),
55
+ open: JSON.stringify(rule.open),
56
+ close: JSON.stringify(rule.close),
57
+ highlight: JSON.stringify(rule.highlight),
58
+
59
+ pop: JSON.stringify(rule.pop),
60
+ set: JSON.stringify(rule.set),
61
+ inset: JSON.stringify(rule.inset),
62
+ goto: JSON.stringify(rule.goto),
63
+ }, -1);
64
+ }
65
+
66
+ private resolveStates(start: string) {
67
+ this.resolved = new Set<string>();
68
+ this.resolving = new Set<string>();
69
+ this.resolveRuleImports(start, new Set());
70
+ for (const key in this.lexer.states) {
71
+ if (!this.resolved.has(key)) {
72
+ delete this.lexer.states[key];
73
+ }
74
+ }
75
+ }
76
+
77
+ private resolveRuleImports(name: string, chain: Set<string>) {
78
+ if (chain.has(name))
79
+ throw new Error(`Can not resolve circular import of ${name}`);
80
+ if (!this.lexer.states[name])
81
+ throw new Error(`Can not import unknown state ${name}`);
82
+ if (this.resolved.has(name) || this.resolving.has(name))
83
+ return;
84
+ const state = this.lexer.states[name];
85
+ const rules = new UniqueRules();
86
+ chain.add(name);
87
+ this.resolving.add(name);
88
+ for (let i = 0; i < state.rules.length; i++) {
89
+ const rule = state.rules[i];
90
+ if ("import" in rule) {
91
+ for (const ref of rule.import) {
92
+ this.resolveRuleImports(ref, chain);
93
+ rules.push(...this.lexer.states[ref].rules as ASTLexerStateMatchRule[]);
94
+ }
95
+ } else {
96
+ rules.push(rule);
97
+ if (rule.set && !this.resolving.has(rule.set)) {
98
+ this.resolveRuleImports(rule.set, new Set());
99
+ }
100
+ if (rule.goto && !this.resolving.has(rule.goto)) {
101
+ this.resolveRuleImports(rule.goto, new Set());
102
+ }
103
+ }
104
+ }
105
+ state.rules = rules.rules;
106
+ chain.delete(name);
107
+ this.resolved.add(name);
108
+ }
109
+ }
110
+
111
+ class UniqueRules {
112
+ private regexps = new Set<string>();
113
+ private strings = new Set<string>();
114
+ rules: ASTLexerStateMatchRule[] = [];
115
+
116
+ push(...rules: (ASTLexerStateMatchRule)[]) {
117
+ for (const rule of rules) {
118
+ if (typeof rule.when === 'object') {
119
+ if (!this.regexps.has(rule.when.regex)) {
120
+ this.regexps.add(rule.when.regex);
121
+ this.rules.push(rule);
122
+ }
123
+ } else {
124
+ if (!this.strings.has(rule.when as string)) {
125
+ this.strings.add(rule.when);
126
+ this.rules.push(rule);
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+
134
+ function CompileRegExp(name: string, state: { unmatched?: ASTLexerStateNonMatchRule, rules: ASTLexerStateMatchRule[] }): string {
135
+ const rules = [];
136
+ const subexpressions = [];
137
+
138
+ let isUnicode = null;
139
+ let isCI = null;
140
+ for (const options of state.rules) {
141
+ if (RegexLib.IsRegex(options.when)) {
142
+ const { flags } = options.when as ASTGrammarSymbolRegex;
143
+ const u = flags.includes('u');
144
+ const i = flags.includes('i');
145
+
146
+ if (isUnicode === null) {
147
+ isUnicode = u;
148
+ } else if (isUnicode !== u && !state.unmatched) {
149
+ throw new Error(`Inconsistent Regex Flag /u in state: ${name}`);
150
+ }
151
+
152
+ if (isCI === null) {
153
+ isCI = i;
154
+ } else if (isCI !== i) {
155
+ throw new Error(`Inconsistent Regex Flag /i in state: ${name}`);
156
+ }
157
+
158
+ } else {
159
+ if (!isCI) {
160
+ isCI = false;
161
+ } else if (isCI) {
162
+ throw new Error(`Inconsistent Regex Flag /i in state: ${name}`);
163
+ }
164
+ }
165
+
166
+ rules.push(options);
167
+ const pat = RegexLib.Source(options.when);
168
+ const regexp = new RegExp(pat)
169
+ if (regexp.test("")) {
170
+ throw new Error("RegExp matches empty string: " + regexp);
171
+ }
172
+
173
+ if (RegexLib.HasGroups(pat)) {
174
+ throw new Error("RegExp has capture groups: " + regexp + "\nUse (?: … ) instead");
175
+ }
176
+
177
+ subexpressions.push(RegexLib.Capture(pat))
178
+ }
179
+
180
+ let flags = !state.unmatched ? 'ym' : 'gm';
181
+ if (isUnicode === true)
182
+ flags += "u"
183
+ if (isCI === true)
184
+ flags += "i"
185
+ return `/${new RegExp(RegexLib.Join(subexpressions)).source}/${flags}`;
186
+ }
187
+
188
+
189
+ class RegexLib {
190
+
191
+ static IsRegex(o: any) {
192
+ return typeof o == 'object' && 'regex' in o;
193
+ }
194
+
195
+ static Escape(s: string) {
196
+ return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
197
+ }
198
+
199
+ static HasGroups(s: string) {
200
+ return (new RegExp('|' + s)).exec('').length > 1;
201
+ }
202
+
203
+ static Capture(source: string) {
204
+ return '(' + source + ')';
205
+ }
206
+
207
+ static Join(regexps: string[]) {
208
+ if (!regexps.length)
209
+ return '(?!)';
210
+ const source = regexps.map((s) => `(?:${s})`).join('|');
211
+ return `(?:${source})`;
212
+ }
213
+
214
+ static Source(search: string | ASTGrammarSymbolRegex) {
215
+ if (typeof search === 'string') {
216
+ return `(?:${RegexLib.Escape(search)})`;
217
+ }
218
+ try {
219
+ if (RegexLib.IsRegex(search)) {
220
+ return search.regex;
221
+ }
222
+ throw new Error('Not a pattern: ' + search)
223
+ } catch (error) {
224
+ throw error;
225
+ }
226
+ }
227
+
228
+ }
@@ -1,14 +1,15 @@
1
- import { Generator } from "../generator";
2
- import { Dictionary, GeneratorGrammarRule, GeneratorGrammarSymbol, GrammarTypeRule } from "../../../typings";
3
- import { Collection, GeneratorSymbolCollection } from "../../../utility/general";
1
+ import { ASTGrammarSymbolNonTerminal, Dictionary, GeneratorGrammarProductionRule, GeneratorGrammarSymbol } from "../../typings/index.js";
2
+ import { Collection, GeneratorSymbolCollection } from "../../utility/general.js";
3
+ import { CommonGenerator } from "../stringify/common.js";
4
+ import { JavaScriptGenerator } from "../stringify/javascript.js";
4
5
 
5
6
 
6
7
  export class LRParseTableBuilder {
7
- rules: Collection<GeneratorGrammarRule> = new Collection();
8
+ rules: Collection<GeneratorGrammarProductionRule> = new Collection();
8
9
  table: Dictionary<StateBuilder> = Object.create(null)
9
10
  symbols: GeneratorSymbolCollection = new GeneratorSymbolCollection();
10
11
 
11
- constructor(public generator: Generator) {
12
+ constructor(public generator: JavaScriptGenerator) {
12
13
  const augmented = { name: Symbol() as unknown as string, symbols: [{ rule: generator.state.grammar.start }] }
13
14
  generator.state.grammar.rules[augmented.name] = [augmented];
14
15
  this.addState([{ rule: augmented, dot: 0 }]);
@@ -27,7 +28,7 @@ export class LRParseTableBuilder {
27
28
  state.queue = {};
28
29
  }
29
30
 
30
- encodeRule(rule: GeneratorGrammarRule, dot: number) {
31
+ encodeRule(rule: GeneratorGrammarProductionRule, dot: number) {
31
32
  return this.rules.encode(rule) + '.' + dot;
32
33
  }
33
34
 
@@ -35,26 +36,26 @@ export class LRParseTableBuilder {
35
36
  return Array.from(new Set(seed)).map(v => this.encodeRule(v.rule, v.dot)).sort().join()
36
37
  }
37
38
 
38
- serialize(depth: number = 0) {
39
+ stringify(depth: number = 0) {
39
40
  const map = {};
40
41
  for (const key in this.table) {
41
- map[key] = this.serializeState(this.table[key].serialize(), depth + 1);
42
+ map[key] = this.stringifyState(this.table[key].export(), depth + 1);
42
43
  }
43
44
 
44
- return Generator.Pretty(map, depth)
45
+ return CommonGenerator.JSON(map, depth)
45
46
  }
46
47
 
47
- serializeState(state: State, depth: number = 0) {
48
- return Generator.Pretty({
49
- actions: state.actions.map(v => this.serializeNext(v, depth + 1)),
50
- goto: Generator.Pretty(state.goto, depth + 1),
51
- reduce: state.reduce ? this.generator.serializeGrammarRule(state.reduce) : null,
48
+ stringifyState(state: State, depth: number = 0) {
49
+ return CommonGenerator.JSON({
50
+ actions: state.actions.map(v => this.stringifyNext(v, depth + 1)),
51
+ goto: CommonGenerator.JSON(state.goto, depth + 1),
52
+ reduce: state.reduce ? this.generator.grammarRule(state.reduce) : null,
52
53
  isFinal: state.isFinal ? 'true' : 'false'
53
54
  }, depth);
54
55
  }
55
- serializeNext(next: Next, depth: number) {
56
- return Generator.Pretty({
57
- symbol: Generator.SerializeSymbol(next.symbol),
56
+ stringifyNext(next: Next, depth: number) {
57
+ return CommonGenerator.JSON({
58
+ symbol: CommonGenerator.SerializeSymbol(next.symbol),
58
59
  next: JSON.stringify(next.next)
59
60
  }, -1);
60
61
  }
@@ -71,7 +72,7 @@ class StateBuilder {
71
72
  queue: { [key: string]: StateItem[] } = {};
72
73
  actions: Map<GeneratorGrammarSymbol, string> = new Map();
73
74
  goto: Map<GeneratorGrammarSymbol, string> = new Map();
74
- reduce?: GeneratorGrammarRule;
75
+ reduce?: GeneratorGrammarProductionRule;
75
76
 
76
77
  constructor(private collection: LRParseTableBuilder, items: StateItem[]) {
77
78
  const visited = new Set<GeneratorGrammarSymbol>();
@@ -98,7 +99,7 @@ class StateBuilder {
98
99
  }
99
100
  }
100
101
 
101
- private closure(rule: GeneratorGrammarRule, dot: number, visited: Set<GeneratorGrammarSymbol>) {
102
+ private closure(rule: GeneratorGrammarProductionRule, dot: number, visited: Set<GeneratorGrammarSymbol>) {
102
103
  const isFinal = rule.symbols.length == dot;
103
104
  this.isFinal = isFinal || this.isFinal;
104
105
  const symbol = rule.symbols[dot];
@@ -109,13 +110,13 @@ class StateBuilder {
109
110
  visited.add(symbol);
110
111
  const stateItem = { rule, dot: dot + 1 };
111
112
 
112
- if (Generator.SymbolIsTerminal(symbol)) {
113
+ if (CommonGenerator.SymbolIsTerminal(symbol)) {
113
114
  const id = this.collection.symbols.encode(symbol);
114
115
  this.outputs.action[id] = this.outputs.action[id] || [];
115
116
  this.outputs.action[id].push(stateItem);
116
117
  } else {
117
118
  const id = this.collection.symbols.encode(symbol);
118
- const name = typeof symbol === 'string' ? symbol : (symbol as GrammarTypeRule).rule;
119
+ const name = typeof symbol === 'string' ? symbol : (symbol as ASTGrammarSymbolNonTerminal).rule;
119
120
  this.outputs.goto[id] = this.outputs.goto[id] || [];
120
121
  this.outputs.goto[id].push(stateItem);
121
122
  for (const rule of this.collection.generator.state.grammar.rules[name]) {
@@ -124,7 +125,7 @@ class StateBuilder {
124
125
  }
125
126
  }
126
127
 
127
- serialize(): State {
128
+ export(): State {
128
129
  const actions: Next[] = [];
129
130
  const goto: { [key: string]: string } = {}
130
131
  for (const [symbol, next] of this.actions) {
@@ -141,13 +142,13 @@ class StateBuilder {
141
142
  interface State {
142
143
  actions: Next[];
143
144
  goto: { [key: string]: string };
144
- reduce: GeneratorGrammarRule;
145
+ reduce: GeneratorGrammarProductionRule;
145
146
  isFinal: boolean;
146
147
  }
147
148
 
148
149
  type Next = { symbol: GeneratorGrammarSymbol, next: string };
149
150
 
150
- type StateItem = { rule: GeneratorGrammarRule, dot: number };
151
+ type StateItem = { rule: GeneratorGrammarProductionRule, dot: number };
151
152
 
152
153
  interface StateOut {
153
154
  action: Dictionary<StateItem[]>;
@@ -0,0 +1,7 @@
1
+ lexer {
2
+ start: "character"
3
+
4
+ [character]
5
+ - when r:{.}
6
+
7
+ }
@@ -0,0 +1,85 @@
1
+ import * from whitespace;
2
+
3
+ lexer {
4
+ start: "json"
5
+
6
+ [json]
7
+ - import whitespace
8
+ - when r:{-?(?:[0-9]|[1-9][0-9]+)(?:\.[0-9]+)?(?:[eE][-+]?[0-9]+)?\b} tag "number"
9
+ - when r:{"(?:\\["bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*"} tag "string"
10
+ - when "{" tag "{"
11
+ - when "}" tag "}"
12
+ - when "[" tag "["
13
+ - when "]" tag "]"
14
+ - when "," tag ","
15
+ - when ":" tag ":"
16
+ - when "true" tag "true"
17
+ - when "false" tag "false"
18
+ - when "null" tag "null"
19
+
20
+ }
21
+
22
+ grammar {
23
+ start: "json"
24
+
25
+ [json]
26
+ | _ (object | array) _ => ( $1[0] )
27
+
28
+ [object]
29
+ | "{" _ "}" => ( {} )
30
+ | "{" _ pair (_ "," _ pair)* _ "}" => ${ extractObject }
31
+
32
+ [array]
33
+ | "[" _ "]" => ( [] )
34
+ | "[" _ value (_ "," _ value)* _ "]" => ${ extractArray }
35
+
36
+ [value]
37
+ | object => ( $0 )
38
+ | array => ( $0 )
39
+ | number => ( $0 )
40
+ | string => ( $0 )
41
+ | "true" => ( true )
42
+ | "false" => ( false )
43
+ | "null" => ( null )
44
+
45
+ [number]
46
+ | <number> => ( parseFloat($0.value) )
47
+
48
+ [string]
49
+ | <string> => ( JSON.parse($0.value) )
50
+
51
+ [pair]
52
+ | key@k _ ":" _ value@v => ( [$k, $v] )
53
+
54
+ [key]
55
+ | string => ( $0 )
56
+
57
+ }
58
+
59
+ on:import {
60
+ function extractPair(kv, output) {
61
+ if(kv[0]) { output[kv[0]] = kv[1]; }
62
+ }
63
+
64
+ function extractObject({data}) {
65
+ let output = {};
66
+
67
+ extractPair(data[2], output);
68
+
69
+ for (let i in data[3]) {
70
+ extractPair(data[3][i][3], output);
71
+ }
72
+
73
+ return output;
74
+ }
75
+
76
+ function extractArray({data}) {
77
+ let output = [data[2]];
78
+
79
+ for (let i in data[3]) {
80
+ output.push(data[3][i][3]);
81
+ }
82
+
83
+ return output;
84
+ }
85
+ }
@@ -0,0 +1,21 @@
1
+ grammar {
2
+
3
+ [unsigned_int]
4
+ | r:{[0-9]}+ => ( parseInt($0.join("")) )
5
+
6
+ [int]
7
+ | ("-" | "+")? r:{[0-9]}+ => ( $0 ? parseInt($0[0]+$1.join("")) : parseInt($1.join("")) )
8
+
9
+ [unsigned_decimal]
10
+ | r:{[0-9]}+ ("." r:{[0-9]}+)? => ( parseFloat($0.join("") + ($1 ? "."+$1[1].join("") : "")) )
11
+
12
+ [decimal]
13
+ | "-"? r:{[0-9]}+ ("." r:{[0-9]}+)? => ( parseFloat( ($0 || "") + $1.join("") +($2 ? "."+$2[1].join("") : "")) )
14
+
15
+ [percentage]
16
+ | decimal "%" => ( $0/100 )
17
+
18
+ [jsonfloat]
19
+ | "-"? r:{[0-9]}+ ("." r:{[0-9]}+)? (r:{[eE]} r:{[+-]}? r:{[0-9]}+)? => ( parseFloat( ($0 || "") + $1.join("") + ($2 ? "."+$2[1].join("") : "") + ($3 ? "e" + ($3[1] || "+") + $3[2].join("") : "")) )
20
+
21
+ }
@@ -0,0 +1 @@
1
+ {"character":"lexer {\n\tstart: \"character\"\n\n\t[character]\n\t\t- when r:{.}\n\n}\n","json":"import * from whitespace;\n\nlexer {\n\tstart: \"json\"\n\n\t[json]\n\t\t- import whitespace\n\t\t- when r:{-?(?:[0-9]|[1-9][0-9]+)(?:\\.[0-9]+)?(?:[eE][-+]?[0-9]+)?\\b} tag \"number\"\n\t\t- when r:{\"(?:\\\\[\"bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\"\\\\])*\"} tag \"string\"\n\t\t- when \"{\" tag \"{\"\n\t\t- when \"}\" tag \"}\"\n\t\t- when \"[\" tag \"[\"\n\t\t- when \"]\" tag \"]\"\n\t\t- when \",\" tag \",\"\n\t\t- when \":\" tag \":\"\n\t\t- when \"true\" tag \"true\"\n\t\t- when \"false\" tag \"false\"\n\t\t- when \"null\" tag \"null\"\n\n}\n\ngrammar {\n\tstart: \"json\"\n\n\t[json]\n\t\t| _ (object | array) _ => ( $1[0] )\n\n\t[object]\n\t\t| \"{\" _ \"}\" => ( {} )\n\t\t| \"{\" _ pair (_ \",\" _ pair)* _ \"}\" => ${ extractObject }\n\n\t[array]\n\t\t| \"[\" _ \"]\" => ( [] )\n\t\t| \"[\" _ value (_ \",\" _ value)* _ \"]\" => ${ extractArray }\n\n\t[value]\n\t\t| object => ( $0 )\n\t\t| array => ( $0 )\n\t\t| number => ( $0 )\n\t\t| string => ( $0 )\n\t\t| \"true\" => ( true )\n\t\t| \"false\" => ( false )\n\t\t| \"null\" => ( null )\n\n\t[number]\n\t\t| <number> => ( parseFloat($0.value) )\n\n\t[string]\n\t\t| <string> => ( JSON.parse($0.value) )\n\n\t[pair]\n\t\t| key@k _ \":\" _ value@v => ( [$k, $v] )\n\n\t[key]\n\t\t| string => ( $0 )\n\n}\n\non:import {\nfunction extractPair(kv, output) {\n if(kv[0]) { output[kv[0]] = kv[1]; }\n }\n\n function extractObject({data}) {\n let output = {};\n\n extractPair(data[2], output);\n\n for (let i in data[3]) {\n extractPair(data[3][i][3], output);\n }\n\n return output;\n }\n\n function extractArray({data}) {\n let output = [data[2]];\n\n for (let i in data[3]) {\n output.push(data[3][i][3]);\n }\n\n return output;\n }\n}\n","number":"grammar {\n\n\t[unsigned_int]\n\t\t| r:{[0-9]}+ => ( parseInt($0.join(\"\")) )\n\n\t[int]\n\t\t| (\"-\" | \"+\")? r:{[0-9]}+ => ( $0 ? parseInt($0[0]+$1.join(\"\")) : parseInt($1.join(\"\")) )\n\n\t[unsigned_decimal]\n\t\t| r:{[0-9]}+ (\".\" r:{[0-9]}+)? => ( parseFloat($0.join(\"\") + ($1 ? \".\"+$1[1].join(\"\") : \"\")) )\n\n\t[decimal]\n\t\t| \"-\"? r:{[0-9]}+ (\".\" r:{[0-9]}+)? => ( parseFloat( ($0 || \"\") + $1.join(\"\") +($2 ? \".\"+$2[1].join(\"\") : \"\")) )\n\n\t[percentage]\n\t\t| decimal \"%\" => ( $0/100 )\n\n\t[jsonfloat]\n\t\t| \"-\"? r:{[0-9]}+ (\".\" r:{[0-9]}+)? (r:{[eE]} r:{[+-]}? r:{[0-9]}+)? => ( parseFloat( ($0 || \"\") + $1.join(\"\") + ($2 ? \".\"+$2[1].join(\"\") : \"\") + ($3 ? \"e\" + ($3[1] || \"+\") + $3[2].join(\"\") : \"\")) )\n\n}\n","string":"lexer {\n\n\t[string]\n\t\t- import singleQuoteString, doubleQuoteString\n\n\t[doubleQuoteString]\n\t\t- when \"\\\"\" tag \"dquote\" highlight \"string\" goto doubleQuoteStringEnd\n\n\t[singleQuoteString]\n\t\t- when \"'\" tag \"squote\" highlight \"string\" goto singleQuoteStringEnd\n\n\t[doubleQuoteStringEnd]\n\t\t- when r:{\\\\[\\\\/bnrft]} tag \"escaped\" highlight \"constant\"\n\t\t- when r:{\\\\\"} tag \"quoteEscape\"\n\t\t- when r:{\\\\u[A-Fa-f\\d]{4}} tag \"escaped\" highlight \"constant\"\n\t\t- when r:{\\\\.} tag \"badEscape\"\n\t\t- when r:{[^\"\\\\]+} tag \"string\" highlight \"string\"\n\t\t- when \"\\\"\" tag \"dquote\" highlight \"string\" pop\n\n\t[singleQuoteStringEnd]\n\t\t- when r:{\\\\[\\\\/bnrft]} tag \"escaped\"\n\t\t- when r:{\\\\'} tag \"quoteEscape\"\n\t\t- when r:{\\\\u[A-Fa-f\\d]{4}} tag \"escaped\"\n\t\t- when r:{\\\\.} tag \"badEscape\"\n\t\t- when r:{[^'\\\\]+} tag \"string\" highlight \"string\"\n\t\t- when \"'\" tag \"squote\" highlight \"string\" pop\n\n}\n\ngrammar {\n\n\t[string] => ( $0 )\n\t\t| singleQuoteString\n\t\t| doubleQuoteString\n\n\t[doubleQuoteString]\n\t\t| <dquote> stringInner <dquote> => ( $1 )\n\t\t| <dquote> <dquote> => ( '' )\n\n\t[singleQuoteString]\n\t\t| <squote> stringInner <squote> => ( $1 )\n\t\t| <squote> <squote> => ( '' )\n\n\t[stringInner]\n\t\t| stringEscape => ( $0 )\n\t\t| <string> => ( $0.value )\n\t\t| stringInner stringEscape => ( $0 + $1 )\n\t\t| stringInner <string> => ( $0 + $1.value )\n\n\t[stringEscape]\n\t\t| <escaped> => ( JSON.parse('\"' + $0.value + '\"') )\n\t\t| <quoteEscape> => ( $0.value[1] )\n\n}\n","whitespace":"lexer {\n\n\t[whitespace]\n\t\t- when r:{\\s+} tag \"whitespace\"\n\n}\n\ngrammar {\n\n\t[_]\n\t\t| <whitespace>? => ( null )\n\n\t[__]\n\t\t| <whitespace>+ => ( null )\n\n}\n"}
@@ -0,0 +1,54 @@
1
+ lexer {
2
+
3
+ [string]
4
+ - import singleQuoteString, doubleQuoteString
5
+
6
+ [doubleQuoteString]
7
+ - when "\"" tag "dquote" highlight "string" goto doubleQuoteStringEnd
8
+
9
+ [singleQuoteString]
10
+ - when "'" tag "squote" highlight "string" goto singleQuoteStringEnd
11
+
12
+ [doubleQuoteStringEnd]
13
+ - when r:{\\[\\/bnrft]} tag "escaped" highlight "constant"
14
+ - when r:{\\"} tag "quoteEscape"
15
+ - when r:{\\u[A-Fa-f\d]{4}} tag "escaped" highlight "constant"
16
+ - when r:{\\.} tag "badEscape"
17
+ - when r:{[^"\\]+} tag "string" highlight "string"
18
+ - when "\"" tag "dquote" highlight "string" pop
19
+
20
+ [singleQuoteStringEnd]
21
+ - when r:{\\[\\/bnrft]} tag "escaped"
22
+ - when r:{\\'} tag "quoteEscape"
23
+ - when r:{\\u[A-Fa-f\d]{4}} tag "escaped"
24
+ - when r:{\\.} tag "badEscape"
25
+ - when r:{[^'\\]+} tag "string" highlight "string"
26
+ - when "'" tag "squote" highlight "string" pop
27
+
28
+ }
29
+
30
+ grammar {
31
+
32
+ [string] => ( $0 )
33
+ | singleQuoteString
34
+ | doubleQuoteString
35
+
36
+ [doubleQuoteString]
37
+ | <dquote> stringInner <dquote> => ( $1 )
38
+ | <dquote> <dquote> => ( '' )
39
+
40
+ [singleQuoteString]
41
+ | <squote> stringInner <squote> => ( $1 )
42
+ | <squote> <squote> => ( '' )
43
+
44
+ [stringInner]
45
+ | stringEscape => ( $0 )
46
+ | <string> => ( $0.value )
47
+ | stringInner stringEscape => ( $0 + $1 )
48
+ | stringInner <string> => ( $0 + $1.value )
49
+
50
+ [stringEscape]
51
+ | <escaped> => ( JSON.parse('"' + $0.value + '"') )
52
+ | <quoteEscape> => ( $0.value[1] )
53
+
54
+ }
@@ -0,0 +1,16 @@
1
+ lexer {
2
+
3
+ [whitespace]
4
+ - when r:{\s+} tag "whitespace"
5
+
6
+ }
7
+
8
+ grammar {
9
+
10
+ [_]
11
+ | <whitespace>? => ( null )
12
+
13
+ [__]
14
+ | <whitespace>+ => ( null )
15
+
16
+ }