grammar-well 1.3.3 → 2.0.0

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 (261) 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/json.d.ts +183 -0
  12. package/build/generator/builtin/json.js +124 -0
  13. package/build/generator/builtin/json.js.map +1 -0
  14. package/build/generator/builtin/registry.json +1 -0
  15. package/build/generator/builtin/whitespace.d.ts +61 -0
  16. package/build/generator/builtin/whitespace.js +37 -0
  17. package/build/generator/builtin/whitespace.js.map +1 -0
  18. package/build/generator/generator.d.ts +38 -0
  19. package/build/generator/generator.js +368 -0
  20. package/build/generator/generator.js.map +1 -0
  21. package/build/generator/grammars/index.d.ts +2 -0
  22. package/build/generator/grammars/index.js +3 -0
  23. package/build/generator/grammars/index.js.map +1 -0
  24. package/build/generator/grammars/v1.d.ts +1190 -0
  25. package/build/generator/grammars/v1.js +614 -0
  26. package/build/generator/grammars/v1.js.map +1 -0
  27. package/build/generator/grammars/v2.d.ts +1367 -0
  28. package/build/generator/grammars/v2.js +695 -0
  29. package/build/generator/grammars/v2.js.map +1 -0
  30. package/build/generator/import-resolvers/auto.d.ts +2 -0
  31. package/build/generator/import-resolvers/auto.js +11 -0
  32. package/build/generator/import-resolvers/auto.js.map +1 -0
  33. package/build/generator/import-resolvers/browser.d.ts +7 -0
  34. package/build/generator/import-resolvers/browser.js +13 -0
  35. package/build/generator/import-resolvers/browser.js.map +1 -0
  36. package/build/generator/import-resolvers/default.d.ts +2 -0
  37. package/build/generator/import-resolvers/default.js +11 -0
  38. package/build/generator/import-resolvers/default.js.map +1 -0
  39. package/build/generator/import-resolvers/filesystem.d.ts +7 -0
  40. package/build/generator/import-resolvers/filesystem.js +15 -0
  41. package/build/generator/import-resolvers/filesystem.js.map +1 -0
  42. package/build/generator/index.d.ts +3 -0
  43. package/build/generator/index.js +4 -0
  44. package/build/generator/index.js.map +1 -0
  45. package/build/generator/state.d.ts +28 -0
  46. package/build/generator/state.js +73 -0
  47. package/build/generator/state.js.map +1 -0
  48. package/build/generator/stringify/common.d.ts +22 -0
  49. package/build/generator/stringify/common.js +83 -0
  50. package/build/generator/stringify/common.js.map +1 -0
  51. package/build/generator/stringify/exports/javascript.d.ts +3 -0
  52. package/build/generator/stringify/exports/javascript.js +26 -0
  53. package/build/generator/stringify/exports/javascript.js.map +1 -0
  54. package/build/generator/stringify/exports/json.d.ts +2 -0
  55. package/build/generator/stringify/exports/json.js +4 -0
  56. package/build/generator/stringify/exports/json.js.map +1 -0
  57. package/build/generator/stringify/exports/registry.d.ts +20 -0
  58. package/build/generator/stringify/exports/registry.js +17 -0
  59. package/build/generator/stringify/exports/registry.js.map +1 -0
  60. package/build/generator/stringify/exports/typescript.d.ts +2 -0
  61. package/build/generator/stringify/exports/typescript.js +16 -0
  62. package/build/generator/stringify/exports/typescript.js.map +1 -0
  63. package/build/generator/stringify/grammar/v2.d.ts +20 -0
  64. package/build/generator/stringify/grammar/v2.js +211 -0
  65. package/build/generator/stringify/grammar/v2.js.map +1 -0
  66. package/build/generator/stringify/javascript.d.ts +13 -0
  67. package/build/generator/stringify/javascript.js +83 -0
  68. package/build/generator/stringify/javascript.js.map +1 -0
  69. package/build/index.d.ts +7 -6
  70. package/build/index.js +7 -24
  71. package/build/index.js.map +1 -1
  72. package/build/lexers/character-lexer.d.ts +2 -2
  73. package/build/lexers/character-lexer.js +1 -5
  74. package/build/lexers/character-lexer.js.map +1 -1
  75. package/build/lexers/stateful-lexer.d.ts +12 -17
  76. package/build/lexers/stateful-lexer.js +38 -186
  77. package/build/lexers/stateful-lexer.js.map +1 -1
  78. package/build/lexers/token-buffer.d.ts +8 -8
  79. package/build/lexers/token-buffer.js +1 -5
  80. package/build/lexers/token-buffer.js.map +1 -1
  81. package/build/parser/algorithms/cyk.d.ts +6 -6
  82. package/build/parser/algorithms/cyk.js +10 -13
  83. package/build/parser/algorithms/cyk.js.map +1 -1
  84. package/build/parser/algorithms/earley.d.ts +7 -7
  85. package/build/parser/algorithms/earley.js +7 -11
  86. package/build/parser/algorithms/earley.js.map +1 -1
  87. package/build/parser/algorithms/lrk/algorithm.d.ts +3 -3
  88. package/build/parser/algorithms/lrk/algorithm.js +10 -13
  89. package/build/parser/algorithms/lrk/algorithm.js.map +1 -1
  90. package/build/parser/algorithms/lrk/bimap.js +1 -5
  91. package/build/parser/algorithms/lrk/bimap.js.map +1 -1
  92. package/build/parser/algorithms/lrk/canonical-collection.d.ts +7 -7
  93. package/build/parser/algorithms/lrk/canonical-collection.js +11 -15
  94. package/build/parser/algorithms/lrk/canonical-collection.js.map +1 -1
  95. package/build/parser/algorithms/lrk/closure.d.ts +3 -3
  96. package/build/parser/algorithms/lrk/closure.js +3 -7
  97. package/build/parser/algorithms/lrk/closure.js.map +1 -1
  98. package/build/parser/algorithms/lrk/stack.d.ts +6 -6
  99. package/build/parser/algorithms/lrk/stack.js +1 -5
  100. package/build/parser/algorithms/lrk/stack.js.map +1 -1
  101. package/build/parser/algorithms/lrk/state.d.ts +5 -5
  102. package/build/parser/algorithms/lrk/state.js +1 -2
  103. package/build/parser/parse.d.ts +10 -0
  104. package/build/parser/parse.js +34 -0
  105. package/build/parser/parse.js.map +1 -0
  106. package/build/parser/parser.d.ts +6 -17
  107. package/build/parser/parser.js +26 -42
  108. package/build/parser/parser.js.map +1 -1
  109. package/build/tsconfig.tsbuildinfo +1 -0
  110. package/build/typings/ast.d.ts +134 -0
  111. package/build/typings/ast.js +3 -0
  112. package/build/typings/ast.js.map +1 -0
  113. package/build/typings/common.d.ts +4 -0
  114. package/build/typings/common.js +2 -0
  115. package/build/typings/common.js.map +1 -0
  116. package/build/typings/generator.d.ts +58 -0
  117. package/build/typings/generator.js +3 -0
  118. package/build/typings/generator.js.map +1 -0
  119. package/build/typings/index.d.ts +43 -0
  120. package/build/typings/index.js +5 -0
  121. package/build/typings/index.js.map +1 -0
  122. package/build/typings/runtime.d.ts +70 -0
  123. package/build/typings/runtime.js +2 -0
  124. package/build/typings/runtime.js.map +1 -0
  125. package/build/utility/format.d.ts +1 -0
  126. package/build/utility/format.js +12 -0
  127. package/build/utility/format.js.map +1 -0
  128. package/build/utility/formatter.d.ts +1 -0
  129. package/build/utility/formatter.js +12 -0
  130. package/build/utility/formatter.js.map +1 -0
  131. package/build/utility/general.d.ts +1 -1
  132. package/build/utility/general.js +5 -13
  133. package/build/utility/general.js.map +1 -1
  134. package/build/utility/index.d.ts +4 -1
  135. package/build/utility/index.js +4 -17
  136. package/build/utility/index.js.map +1 -1
  137. package/build/utility/lint.d.ts +2 -2
  138. package/build/utility/lint.js +2 -6
  139. package/build/utility/lint.js.map +1 -1
  140. package/build/utility/migrate.d.ts +1 -0
  141. package/build/utility/migrate.js +10 -0
  142. package/build/utility/migrate.js.map +1 -0
  143. package/build/utility/monarch.d.ts +2 -2
  144. package/build/utility/monarch.js +33 -38
  145. package/build/utility/monarch.js.map +1 -1
  146. package/build/utility/parsing.d.ts +6 -0
  147. package/build/utility/parsing.js +26 -0
  148. package/build/utility/parsing.js.map +1 -0
  149. package/build/utility/text-format.d.ts +6 -6
  150. package/build/utility/text-format.js +2 -6
  151. package/build/utility/text-format.js.map +1 -1
  152. package/package.json +17 -24
  153. package/src/generator/artifacts/basic.ts +26 -0
  154. package/src/generator/artifacts/lexer.ts +228 -0
  155. package/src/{compiler/generator → generator}/artifacts/lr.ts +25 -24
  156. package/src/generator/builtin/character.well +7 -0
  157. package/src/generator/builtin/json.well +85 -0
  158. package/src/generator/builtin/number.well +21 -0
  159. package/src/generator/builtin/registry.json +1 -0
  160. package/src/generator/builtin/string.well +54 -0
  161. package/src/generator/builtin/whitespace.well +16 -0
  162. package/src/generator/generator.ts +401 -0
  163. package/src/generator/grammars/index.ts +2 -0
  164. package/src/generator/grammars/v1.ts +620 -0
  165. package/src/generator/grammars/v1.well +422 -0
  166. package/src/generator/grammars/v2.ts +701 -0
  167. package/src/generator/grammars/v2.well +413 -0
  168. package/src/generator/import-resolvers/auto.ts +12 -0
  169. package/src/generator/import-resolvers/browser.ts +13 -0
  170. package/src/generator/import-resolvers/filesystem.ts +18 -0
  171. package/src/generator/index.ts +3 -0
  172. package/src/generator/state.ts +89 -0
  173. package/src/generator/stringify/common.ts +90 -0
  174. package/src/generator/stringify/exports/javascript.ts +29 -0
  175. package/src/generator/stringify/exports/json.ts +5 -0
  176. package/src/generator/stringify/exports/registry.ts +20 -0
  177. package/src/generator/stringify/exports/typescript.ts +17 -0
  178. package/src/generator/stringify/grammar/v2.ts +223 -0
  179. package/src/generator/stringify/javascript.ts +94 -0
  180. package/src/index.ts +7 -6
  181. package/src/lexers/character-lexer.ts +2 -2
  182. package/src/lexers/stateful-lexer.ts +46 -203
  183. package/src/lexers/token-buffer.ts +3 -3
  184. package/src/parser/algorithms/cyk.ts +13 -12
  185. package/src/parser/algorithms/earley.ts +10 -10
  186. package/src/parser/algorithms/lrk/algorithm.ts +8 -7
  187. package/src/parser/algorithms/lrk/canonical-collection.ts +14 -14
  188. package/src/parser/algorithms/lrk/closure.ts +6 -6
  189. package/src/parser/algorithms/lrk/stack.ts +6 -6
  190. package/src/parser/algorithms/lrk/state.ts +5 -5
  191. package/src/parser/parse.ts +45 -0
  192. package/src/typings/ast.ts +148 -0
  193. package/src/typings/common.ts +2 -0
  194. package/src/typings/generator.ts +62 -0
  195. package/src/typings/index.ts +38 -0
  196. package/src/typings/runtime.ts +82 -0
  197. package/src/utility/format.ts +12 -0
  198. package/src/utility/general.ts +1 -2
  199. package/src/utility/index.ts +4 -1
  200. package/src/utility/lint.ts +5 -5
  201. package/src/utility/monarch.ts +34 -34
  202. package/src/utility/parsing.ts +30 -0
  203. package/src/utility/text-format.ts +7 -7
  204. package/.eslintrc.cjs +0 -14
  205. package/bootstrap.ts +0 -45
  206. package/build/compiler/builtin.json +0 -1
  207. package/build/compiler/compiler.d.ts +0 -50
  208. package/build/compiler/compiler.js +0 -249
  209. package/build/compiler/compiler.js.map +0 -1
  210. package/build/compiler/generator/artifacts/lr.js.map +0 -1
  211. package/build/compiler/generator/artifacts/standard.d.ts +0 -7
  212. package/build/compiler/generator/artifacts/standard.js +0 -28
  213. package/build/compiler/generator/artifacts/standard.js.map +0 -1
  214. package/build/compiler/generator/generator.d.ts +0 -24
  215. package/build/compiler/generator/generator.js +0 -217
  216. package/build/compiler/generator/generator.js.map +0 -1
  217. package/build/compiler/gwell.d.ts +0 -1112
  218. package/build/compiler/gwell.js +0 -576
  219. package/build/compiler/gwell.js.map +0 -1
  220. package/build/compiler/import-resolver.d.ts +0 -15
  221. package/build/compiler/import-resolver.js +0 -37
  222. package/build/compiler/import-resolver.js.map +0 -1
  223. package/build/compiler/index.d.ts +0 -2
  224. package/build/compiler/index.js +0 -19
  225. package/build/compiler/index.js.map +0 -1
  226. package/build/compiler/outputs/javascript.d.ts +0 -3
  227. package/build/compiler/outputs/javascript.js +0 -29
  228. package/build/compiler/outputs/javascript.js.map +0 -1
  229. package/build/compiler/outputs/json.d.ts +0 -2
  230. package/build/compiler/outputs/json.js +0 -8
  231. package/build/compiler/outputs/json.js.map +0 -1
  232. package/build/compiler/outputs/typescript.d.ts +0 -2
  233. package/build/compiler/outputs/typescript.js +0 -21
  234. package/build/compiler/outputs/typescript.js.map +0 -1
  235. package/build/parser/algorithms/lr.d.ts +0 -7
  236. package/build/parser/algorithms/lr.js +0 -108
  237. package/build/parser/algorithms/lr.js.map +0 -5
  238. package/build/parser/algorithms/lr0.d.ts +0 -7
  239. package/build/parser/algorithms/lr0.js +0 -156
  240. package/build/parser/algorithms/lr0.js.map +0 -1
  241. package/build/typings.d.ts +0 -226
  242. package/build/typings.js +0 -3
  243. package/build/typings.js.map +0 -1
  244. package/src/compiler/builtin/json.gwell +0 -74
  245. package/src/compiler/builtin/number.gwell +0 -20
  246. package/src/compiler/builtin/string.gwell +0 -48
  247. package/src/compiler/builtin/whitespace.gwell +0 -10
  248. package/src/compiler/builtin.json +0 -1
  249. package/src/compiler/compiler.ts +0 -265
  250. package/src/compiler/generator/artifacts/standard.ts +0 -26
  251. package/src/compiler/generator/generator.ts +0 -237
  252. package/src/compiler/gwell.gwell +0 -294
  253. package/src/compiler/gwell.js +0 -578
  254. package/src/compiler/import-resolver.ts +0 -36
  255. package/src/compiler/index.ts +0 -2
  256. package/src/compiler/outputs/javascript.ts +0 -27
  257. package/src/compiler/outputs/json.ts +0 -5
  258. package/src/compiler/outputs/typescript.ts +0 -18
  259. package/src/parser/parser.ts +0 -77
  260. package/src/typings.ts +0 -248
  261. package/testing.ts +0 -18
@@ -0,0 +1,17 @@
1
+ import { JavaScriptGenerator } from "../javascript.js";
2
+
3
+ export function TypescriptFormat(generator: JavaScriptGenerator) {
4
+ const exportName = generator.name();
5
+ return `// Generated automatically by Grammar-Well, version ${generator.state.version}
6
+ // https://github.com/0x6563/grammar-well
7
+ // @ts-nocheck
8
+
9
+ ${generator.lifecycle('import')}
10
+
11
+ class ${exportName} {
12
+ artifacts = ${generator.artifacts(1)}
13
+ constructor(){${generator.lifecycle('new')}}
14
+ }
15
+
16
+ export default ${exportName};`;
17
+ }
@@ -0,0 +1,223 @@
1
+ import { ASTConfig, ASTDirectives, ASTGrammar, ASTGrammarProduction, ASTGrammarSymbol, ASTImport, ASTLexer, ASTLexerState, ASTLexerStateImportRule, ASTLexerStateMatchRule, ASTLexerStateNonMatchRule, GeneratorGrammarSymbol } from "../../../typings/index.js";
2
+
3
+ export class V2GrammarString {
4
+ source: string = '';
5
+ append(directives: ASTDirectives | (ASTDirectives[])) {
6
+ directives = Array.isArray(directives) ? directives : [directives];
7
+ for (const directive of directives) {
8
+ if ("lifecycle" in directive) {
9
+ this.appendSection("on:" + directive.lifecycle, directive.js.js.trim());
10
+ } else if ("import" in directive) {
11
+ this.appendImportDirective(directive);
12
+ } else if ("config" in directive) {
13
+ this.appendConfigDirective(directive);
14
+ } else if ("grammar" in directive) {
15
+ this.appendGrammarDirective(directive);
16
+ } else if ("lexer" in directive) {
17
+ this.appendLexerDirective(directive);
18
+ }
19
+ }
20
+ }
21
+
22
+ appendImportDirective(directive: ASTImport) {
23
+ this.source += `import * from ${directive.path ? JSON.stringify(directive.import) : directive.import};\n`;
24
+ }
25
+
26
+ appendConfigDirective(directive: ASTConfig) {
27
+ this.appendSection('config', this.formatKV(directive.config, 1));
28
+ }
29
+
30
+ appendGrammarDirective(directive: ASTGrammar) {
31
+ let body = '';
32
+ if (directive.grammar.config) {
33
+ body += this.formatKV(directive.grammar.config, 1);
34
+ }
35
+ if (directive.grammar.rules) {
36
+ for (const rule of directive.grammar.rules) {
37
+ body += this.formatGrammarRule(rule);
38
+ }
39
+ }
40
+ this.appendSection('grammar', body);
41
+ }
42
+
43
+ formatGrammarRule(rule: ASTGrammarProduction) {
44
+ let body = '\n' + this.indent(1, `[${rule.name}]`);
45
+ if (rule.postprocess) {
46
+ body += ` ${this.formatPostProcess(rule.postprocess)}`;
47
+ }
48
+ for (const exp of rule.expressions) {
49
+ body += '\n' + this.indent(2, '| ') + this.formatSymbols(exp.symbols as any);
50
+ if (exp.postprocess) {
51
+ body += ` ${this.formatPostProcess(exp.postprocess)}`;
52
+ }
53
+ }
54
+ body += '\n';
55
+ return body;
56
+ }
57
+
58
+ formatSymbols(exp: GeneratorGrammarSymbol[]) {
59
+ return exp.map(v => this.formatSymbol(v) + (v.alias ? "@" + v.alias : '')).join(' ');
60
+ }
61
+
62
+ formatSymbol(exp: ASTGrammarSymbol | GeneratorGrammarSymbol | string) {
63
+ if (typeof exp == 'string') {
64
+ return JSON.stringify(exp);
65
+ }
66
+ if ('subexpression' in exp) {
67
+ return `(${exp.subexpression.map(v => this.formatSymbols(v.symbols as any)).join(' | ')})`;
68
+ }
69
+ if ('rule' in exp) {
70
+ return exp.rule;
71
+ }
72
+ if ('literal' in exp) {
73
+ return (exp.insensitive ? '\\i ' : '') + JSON.stringify(exp.literal);
74
+ }
75
+ if ('regex' in exp) {
76
+ let { regex, flags } = exp;
77
+ return `r${flags || ''}:{${regex}}`;
78
+ }
79
+ if ('token' in exp) {
80
+ return `<${exp.token}>`;
81
+ }
82
+ if ('expression' in exp) {
83
+ return this.formatSymbol(exp.expression) + (exp.repeat || '');
84
+ }
85
+ }
86
+
87
+ formatPostProcess(postProcess: ASTGrammarProduction['postprocess']) {
88
+
89
+ // if ('builtin' in postProcess) {
90
+ // return postProcess;
91
+ // }
92
+ if ('js' in postProcess) {
93
+ return `=> \${ ${postProcess.js} }`;
94
+ }
95
+ if ('template' in postProcess) {
96
+ const prefix = postProcess.template.slice(0, 1);
97
+ const suffix = postProcess.template.slice(-1);
98
+ return `=> ${prefix} ${postProcess.template.slice(1, -1).trim()} ${suffix}`;
99
+ }
100
+ }
101
+
102
+ appendLexerDirective(directive: ASTLexer) {
103
+ let body = '';
104
+ if (directive.lexer.start) {
105
+ body += this.formatKV({ start: directive.lexer.start }, 1);
106
+ }
107
+ if (directive.lexer.states) {
108
+ for (const { state, name } of directive.lexer.states) {
109
+ if ('span' in state) {
110
+ body += '\n' + this.indent(1, `[${name}] span {\n`);
111
+ const stateOpen = state.span.find(v => v.name == 'start');
112
+ const stateBody = state.span.find(v => v.name == 'span');
113
+ const stateClose = state.span.find(v => v.name == 'stop');
114
+ if (state.config) {
115
+ body += this.formatKV(state.config, 2);
116
+ }
117
+ if (stateOpen) {
118
+ body += this.formatLexerState('start', stateOpen.state, 2);
119
+ }
120
+ if (stateBody) {
121
+ body += this.formatLexerState('span', stateBody.state, 2);
122
+ }
123
+ if (stateClose) {
124
+ body += this.formatLexerState('stop', stateClose.state, 2);
125
+ }
126
+ body += '\n' + this.indent(1, `}\n`);
127
+ } else {
128
+ body += this.formatLexerState(name, state, 1)
129
+ }
130
+ }
131
+ }
132
+
133
+ this.appendSection('lexer', body);
134
+ }
135
+
136
+ formatLexerState(name: string, state: ASTLexerState, depth: number = 0) {
137
+ let body = '\n' + this.indent(depth, `[${name}]\n`);
138
+ if (state.default) {
139
+ body += this.indent(depth + 1, 'default: ' + this.formatLexerStateRule(state.default) + ';\n');
140
+ }
141
+ if (state.unmatched) {
142
+ body += this.indent(depth + 1, 'unmatched: ' + this.formatLexerStateRule(state.unmatched) + ';\n');
143
+ }
144
+ for (const rule of state.rules) {
145
+ if ('span' in rule)
146
+ continue;
147
+ body += this.indent(depth + 1, '- ' + this.formatLexerStateRule(rule) + '\n');
148
+ }
149
+ return body;
150
+ }
151
+
152
+ formatLexerStateRule(rule: ASTLexerStateMatchRule | ASTLexerStateNonMatchRule | ASTLexerStateImportRule) {
153
+ let body = '';
154
+ if ('import' in rule) {
155
+ body += 'import ' + rule.import.join(', ');
156
+ } else {
157
+ if (rule.before) {
158
+ body += 'before ' + this.formatSymbol((rule as ASTLexerStateMatchRule).when);
159
+ } else if (rule.skip) {
160
+ body += 'skip ' + this.formatSymbol((rule as ASTLexerStateMatchRule).when);
161
+ } else if ('when' in rule) {
162
+ body += 'when ' + this.formatSymbol(rule.when as any);
163
+ }
164
+
165
+ if (typeof rule.type != 'undefined') {
166
+ body += ` type ${JSON.stringify(rule.type)}`;
167
+ }
168
+ if (typeof rule.tag != 'undefined') {
169
+ body += ` tag ${rule.tag.map(v => JSON.stringify(v)).join(', ')}`;
170
+ }
171
+ if (typeof rule.open != 'undefined') {
172
+ body += ` open ${JSON.stringify(rule.open)}`;
173
+ }
174
+ if (typeof rule.close != 'undefined') {
175
+ body += ` close ${JSON.stringify(rule.close)}`;
176
+ }
177
+ if (typeof rule.highlight != 'undefined') {
178
+ body += ` highlight ${JSON.stringify(rule.highlight)}`;
179
+ }
180
+ if (typeof rule.unembed != 'undefined') {
181
+ body += ` unembed`;
182
+ }
183
+ if (typeof rule.embed != 'undefined') {
184
+ body += ` embed`;
185
+ }
186
+ if (typeof rule.pop != 'undefined') {
187
+ body += ` pop` + (rule.pop == 'all' || rule.pop > 1 ? ' ' + rule.pop : '');
188
+ }
189
+ if (typeof rule.inset != 'undefined') {
190
+ body += ` inset` + (rule.inset > 1 ? ' ' + rule.inset : '');
191
+ }
192
+ if (typeof rule.goto != 'undefined') {
193
+ body += ` goto ${rule.goto}`;
194
+ }
195
+ if (typeof rule.set != 'undefined') {
196
+ body += ` set ${rule.set}`;
197
+ }
198
+ if ("stay" in rule && rule.stay) {
199
+ body += ` stay`;
200
+ }
201
+ }
202
+ return body.trim();
203
+ }
204
+
205
+ formatKV(obj: { [key: string]: any }, depth: number = 0) {
206
+ let body = '';
207
+ for (const key in obj) {
208
+ body += this.indent(depth, `${key}: ${JSON.stringify(obj[key])}\n`);
209
+ }
210
+ return body;
211
+ }
212
+
213
+ appendSection(label: string, body: string) {
214
+ if (this.source) {
215
+ this.source += '\n';
216
+ }
217
+ this.source += `${label} {\n${body}\n}\n`;
218
+ }
219
+
220
+ indent(depth: number = 0, content: string) {
221
+ return `\t`.repeat(depth) + content;
222
+ }
223
+ }
@@ -0,0 +1,94 @@
1
+ import { Dictionary, GeneratorOutputOptions, GeneratorGrammarProductionRule } from "../../typings/index.js";
2
+ import { BasicGrammarTable } from "../artifacts/basic.js";
3
+ import { LexerArtifact } from "../artifacts/lexer.js";
4
+ import { LRParseTableBuilder } from "../artifacts/lr.js";
5
+ import { GeneratorState } from "../state.js";
6
+ import { CommonGenerator } from "./common.js";
7
+
8
+ const PostProcessors = {
9
+ "join": "({data}) => data.join('')",
10
+ "concat": "({data}) => data[0].concat([data[1]])",
11
+ "null": "() => null",
12
+ "first": "({data}) => data[0]"
13
+ };
14
+
15
+ export class JavaScriptGenerator {
16
+
17
+ constructor(public state: GeneratorState, public options: GeneratorOutputOptions) { }
18
+
19
+ name() {
20
+ return this.options.name || 'GWLanguage';
21
+ }
22
+
23
+ lifecycle(lifecycle: string) {
24
+ if (this.options.noscript)
25
+ return '';
26
+ return this.state.lifecycle[lifecycle] || '';
27
+ }
28
+
29
+ artifacts(depth: number = 0) {
30
+ let output: { [key: string]: string } = {};
31
+ const artifacts = this.options.artifacts || { grammar: true, lexer: true };
32
+
33
+ if (artifacts && artifacts.lr) {
34
+ const table = new LRParseTableBuilder(this);
35
+ output.lr = CommonGenerator.JSON({
36
+ k: "0",
37
+ table: table.stringify(depth + 2)
38
+ }, depth + 1);
39
+ }
40
+
41
+ if ('lexer' in this.state && artifacts.lexer) {
42
+ const l = new LexerArtifact(this.state.lexer);
43
+ output.lexer = l.output(depth + 1);
44
+ }
45
+
46
+ if (artifacts.grammar) {
47
+ const basic = new BasicGrammarTable(this);
48
+ output.grammar = basic.stringify(depth + 1);
49
+ }
50
+
51
+ return CommonGenerator.JSON(output, depth);
52
+ }
53
+
54
+ postProcess(postprocess: GeneratorGrammarProductionRule['postprocess'], alias: Dictionary<number>) {
55
+ postprocess = this.state.grammar.config.postprocessorOverride || postprocess || this.state.grammar.config.postprocessorDefault;
56
+ if (!postprocess)
57
+ return null;
58
+ if ('builtin' in postprocess)
59
+ return PostProcessors[postprocess.builtin];
60
+ if (this.options.noscript)
61
+ return;
62
+ if (typeof postprocess == 'string')
63
+ return postprocess;
64
+ if ('js' in postprocess)
65
+ return postprocess.js;
66
+ if ('template' in postprocess)
67
+ return this.templatePostProcess(postprocess.template, alias);
68
+ }
69
+
70
+ grammarRule(rule: GeneratorGrammarProductionRule) {
71
+ const symbols = [];
72
+ const alias = {};
73
+ for (let i = 0; i < rule.symbols.length; i++) {
74
+ symbols.push(CommonGenerator.SerializeSymbol(rule.symbols[i]));
75
+ if (rule.symbols[i].alias) {
76
+ alias[rule.symbols[i].alias] = i;
77
+ }
78
+ }
79
+
80
+ return CommonGenerator.JSON({
81
+ name: JSON.stringify(rule.name),
82
+ symbols: CommonGenerator.JSON(symbols, -1),
83
+ postprocess: this.postProcess(rule.postprocess, alias)
84
+ }, -1);
85
+ }
86
+
87
+ private templatePostProcess(templateBody: string, alias: { [key: string]: number }) {
88
+ for (const key in alias) {
89
+ templateBody = templateBody.replace(new RegExp('(?:\\$)' + key + '(?![a-zA-Z\\d\\$_])'), `data[${alias[key]}]`);
90
+ }
91
+ return "({data}) => { return " + templateBody.replace(/\$(\d+)/g, "data[$1]") + "; }";
92
+ }
93
+
94
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
- export * from './compiler/compiler';
2
- export * from './compiler/import-resolver';
3
- export * from './parser/parser';
4
- export * from './typings'
5
- export { StatefulLexer } from './lexers/stateful-lexer';
6
- export * from './utility/monarch';
1
+ export * from './generator/generator.js';
2
+ export * from './generator/import-resolvers/auto.js';
3
+ export { StatefulLexer } from './lexers/stateful-lexer.js';
4
+ export * from './parser/parse.js';
5
+ export * from './utility/parsing.js';
6
+ export * from './typings/index.js';
7
+ export * from './utility/index.js';
@@ -1,6 +1,6 @@
1
- import { Lexer } from "../typings";
1
+ import { RuntimeLexer } from "../typings/index.js";
2
2
 
3
- export class CharacterLexer implements Lexer {
3
+ export class CharacterLexer implements RuntimeLexer {
4
4
  private buffer: string | any[] = '';
5
5
 
6
6
  private $indexOffset = 0;
@@ -1,8 +1,8 @@
1
- import { CompiledStateDefinition, LexerStateMatchRule, ResolvedStateDefinition, LexerStateDefinition, LexerConfig, Lexer } from "../typings";
1
+ import { RuntimeLexerStateMatchRule, ASTLexerStateNonMatchRule, RuntimeLexer, RuntimeLexerConfig, StatefulLexerStateDefinition } from "../typings/index.js";
2
2
 
3
- export class StatefulLexer implements Lexer {
3
+ export class StatefulLexer implements RuntimeLexer {
4
4
  private start: string;
5
- private states: { [key: string]: CompiledStateDefinition } = Object.create(null);
5
+ private states: { [key: string]: StatefulLexerStateDefinition } = Object.create(null);
6
6
  private buffer: string;
7
7
  private stack: string[];
8
8
  private index: number;
@@ -10,20 +10,13 @@ export class StatefulLexer implements Lexer {
10
10
  private column: number;
11
11
  private prefetched?: RegExpExecArray;
12
12
  private current: string;
13
- private unmatched: LexerStateMatchRule;
14
- private rules: LexerStateMatchRule[];
13
+ private unmatched: ASTLexerStateNonMatchRule;
14
+ private rules: RuntimeLexerStateMatchRule[];
15
15
  private regexp: RegExp;
16
16
  private tags = new Map<string[], Set<string>>();
17
17
 
18
- constructor({ states, start }: LexerConfig) {
19
- ResolveStates(states, start);
20
- for (const key in states) {
21
- this.states[key] = {
22
- regexp: CompileRegExp(states[key] as ResolvedStateDefinition),
23
- rules: states[key].rules as LexerStateMatchRule[],
24
- unmatched: states[key].unmatched ? { type: states[key].unmatched } as LexerStateMatchRule : null
25
- };
26
- }
18
+ constructor({ states, start }: RuntimeLexerConfig) {
19
+ this.states = states;
27
20
  this.start = start;
28
21
  this.buffer = '';
29
22
  this.stack = [];
@@ -50,16 +43,31 @@ export class StatefulLexer implements Lexer {
50
43
  }
51
44
  }
52
45
 
53
- next() {
54
- const next = this.matchNext();
46
+ next(skipped: boolean = false) {
47
+ const next = this.matchNext(skipped);
55
48
  if (!next) {
56
49
  return
57
50
  }
58
51
  const { rule, text, index } = next;
59
52
  if (!rule) {
60
- throw new Error(`No matching rule for ${text}`);
53
+ throw new Error(`No matching rule for ${text.split(/\n|\r\n/).slice(0, 3).join('\n')}`);
54
+ }
55
+ const token = {
56
+ type: rule.type,
57
+ highlight: rule.highlight,
58
+ open: rule.open,
59
+ close: rule.close,
60
+ tag: this.getTags(rule.tag),
61
+ value: text,
62
+ text: text,
63
+ offset: index,
64
+ line: this.line,
65
+ lines: 0,
66
+ column: this.column,
67
+ state: this.current
61
68
  }
62
- const token = this.createToken(rule, text, index)
69
+ this.adjustPosition(text);
70
+ token.lines = this.line - token.line;
63
71
  this.adjustStack(rule);
64
72
  return token;
65
73
  }
@@ -71,7 +79,7 @@ export class StatefulLexer implements Lexer {
71
79
  this.current = current;
72
80
  this.rules = info.rules;
73
81
  this.unmatched = info.unmatched;
74
- this.regexp = info.regexp;
82
+ this.regexp = info.regex;
75
83
  }
76
84
 
77
85
  private pop() {
@@ -83,14 +91,14 @@ export class StatefulLexer implements Lexer {
83
91
  this.set(state)
84
92
  }
85
93
 
86
- private matchNext() {
94
+ private matchNext(skipped: boolean = false) {
87
95
  if (this.index === this.buffer.length) {
88
96
  return;
89
97
  }
90
98
 
91
99
  const { index, buffer } = this;
92
100
  let text;
93
- let rule: LexerStateMatchRule;
101
+ let rule: RuntimeLexerStateMatchRule | ASTLexerStateNonMatchRule;
94
102
  let match;
95
103
 
96
104
  this.regexp.lastIndex = index;
@@ -111,6 +119,10 @@ export class StatefulLexer implements Lexer {
111
119
  rule = this.getGroup(match);
112
120
  text = match[0];
113
121
  if (rule.before) {
122
+ this.adjustStack(rule);
123
+ return this.matchNext(skipped);
124
+ } else if (rule.skip && !skipped) {
125
+ this.adjustPosition(text);
114
126
  this.adjustStack(rule);
115
127
  return this.matchNext();
116
128
  }
@@ -119,33 +131,6 @@ export class StatefulLexer implements Lexer {
119
131
  return { index, rule, text }
120
132
  }
121
133
 
122
- private createToken(rule: LexerStateMatchRule, text: string, offset: number) {
123
- const token = {
124
- type: rule.type,
125
- highlight: rule.highlight,
126
- open: rule.open,
127
- close: rule.close,
128
- tag: this.getTags(rule.tag),
129
- value: text,
130
- text: text,
131
- offset: offset,
132
- line: this.line,
133
- lines: 0,
134
- column: this.column,
135
- state: this.current
136
- }
137
- for (let i = 0; i < text.length; i++) {
138
- this.column++;
139
- if (text[i] == '\n') {
140
- token.lines++;
141
- this.column = 1;
142
- }
143
- }
144
- this.index += text.length;
145
- this.line += token.lines;
146
- return token;
147
- }
148
-
149
134
  private getTags(tags?: string[]) {
150
135
  if (!tags)
151
136
  return undefined;
@@ -154,7 +139,18 @@ export class StatefulLexer implements Lexer {
154
139
  return this.tags.get(tags);
155
140
  }
156
141
 
157
- private adjustStack(rule: LexerStateMatchRule) {
142
+ private adjustPosition(text: string) {
143
+ this.index += text.length;
144
+ for (let i = 0; i < text.length; i++) {
145
+ this.column++;
146
+ if (text[i] == '\n') {
147
+ this.line++;
148
+ this.column = 1;
149
+ }
150
+ }
151
+ }
152
+
153
+ private adjustStack(rule: RuntimeLexerStateMatchRule) {
158
154
  if (rule.pop) {
159
155
  let i = rule.pop === 'all' ? this.stack.length : rule.pop;
160
156
  while (i-- > 0) {
@@ -177,7 +173,7 @@ export class StatefulLexer implements Lexer {
177
173
  }
178
174
  }
179
175
 
180
- private getGroup(match): LexerStateMatchRule {
176
+ private getGroup(match): RuntimeLexerStateMatchRule {
181
177
  for (let i = 0; i < this.rules.length; i++) {
182
178
  if (match[i + 1] !== undefined) {
183
179
  return this.rules[i];
@@ -185,157 +181,4 @@ export class StatefulLexer implements Lexer {
185
181
  }
186
182
  throw new Error('Cannot find token type for matched text')
187
183
  }
188
- }
189
-
190
- class RegexLib {
191
-
192
- static IsRegex(o: any) {
193
- return o instanceof RegExp;
194
- }
195
-
196
- static Escape(s: string) {
197
- return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
198
- }
199
-
200
- static HasGroups(s: string) {
201
- return (new RegExp('|' + s)).exec('').length > 1;
202
- }
203
-
204
- static Capture(source: string) {
205
- return '(' + source + ')';
206
- }
207
-
208
- static Join(regexps: string[]) {
209
- if (!regexps.length)
210
- return '(?!)';
211
- const source = regexps.map((s) => `(?:${s})`).join('|');
212
- return `(?:${source})`;
213
- }
214
-
215
- static Source(search: string | RegExp) {
216
- if (typeof search === 'string') {
217
- return `(?:${RegexLib.Escape(search)})`;
218
- }
219
- if (RegexLib.IsRegex(search)) {
220
- return search.source;
221
- }
222
- throw new Error('Not a pattern: ' + search)
223
- }
224
-
225
- }
226
-
227
- function CompileRegExp(state: ResolvedStateDefinition): RegExp {
228
- const rules = [];
229
- const subexpressions = [];
230
-
231
- let isUnicode = null;
232
- let isCI = null;
233
- for (const options of state.rules) {
234
- if (RegexLib.IsRegex(options.when)) {
235
- const when = options.when as RegExp;
236
- if (isUnicode === null) {
237
- isUnicode = when.unicode
238
- } else if (isUnicode !== when.unicode && !state.unmatched) {
239
- throw new Error(`Inconsistent Regex Flag /u in state: ${state.name}`);
240
- }
241
- if (isCI === null) {
242
- isCI = when.ignoreCase
243
- } else if (isCI !== when.ignoreCase) {
244
- throw new Error(`Inconsistent Regex Flag /i in state: ${state.name}`);
245
- }
246
- } else {
247
- if (isCI == null) {
248
- isCI = false;
249
- } else if (isCI != false) {
250
- throw new Error(`Inconsistent Regex Flag /i in state: ${state.name}`);
251
- }
252
- }
253
-
254
- rules.push(options);
255
- const pat = RegexLib.Source(options.when);
256
- const regexp = new RegExp(pat)
257
- if (regexp.test("")) {
258
- throw new Error("RegExp matches empty string: " + regexp)
259
- }
260
-
261
- if (RegexLib.HasGroups(pat)) {
262
- throw new Error("RegExp has capture groups: " + regexp + "\nUse (?: … ) instead")
263
- }
264
-
265
- subexpressions.push(RegexLib.Capture(pat))
266
- }
267
-
268
- let flags = !state.unmatched ? 'ym' : 'gm';
269
- if (isUnicode === true)
270
- flags += "u"
271
- if (isCI === true)
272
- flags += "i"
273
- return new RegExp(RegexLib.Join(subexpressions), flags);
274
- }
275
-
276
- export function ResolveStates(states: { [key: string]: LexerStateDefinition }, start: string) {
277
- const resolved = new Set<string>();
278
- const resolving = new Set<string>();
279
- const chain = new Set<string>();
280
-
281
- ResolveRuleImports(start, states, resolved, resolving, chain);
282
- for (const key in states) {
283
- if (!resolved.has(key)) {
284
- delete states[key];
285
- }
286
- }
287
- return states;
288
- }
289
-
290
- function ResolveRuleImports(name: string, states: { [key: string]: LexerStateDefinition }, resolved: Set<string>, resolving: Set<string>, chain: Set<string>) {
291
- if (chain.has(name))
292
- throw new Error(`Can not resolve circular import of ${name}`);
293
- if (!states[name])
294
- throw new Error(`Can not import unknown state ${name}`);
295
- if (resolved.has(name) || resolving.has(name))
296
- return;
297
- const state = states[name];
298
- const rules = new UniqueRules();
299
- chain.add(name);
300
- resolving.add(name);
301
- for (let i = 0; i < state.rules.length; i++) {
302
- const rule = state.rules[i];
303
- if ("import" in rule) {
304
- for (const ref of rule.import) {
305
- ResolveRuleImports(ref, states, resolved, resolving, chain);
306
- rules.push(...states[ref].rules as LexerStateMatchRule[]);
307
- }
308
- } else {
309
- rules.push(rule);
310
- if ("set" in rule && !resolving.has(rule.set)) {
311
- ResolveRuleImports(rule.set, states, resolved, resolving, new Set());
312
- }
313
- if ("goto" in rule && !resolving.has(rule.goto)) {
314
- ResolveRuleImports(rule.goto, states, resolved, resolving, new Set());
315
- }
316
- }
317
- }
318
- state.rules = rules.rules;
319
- chain.delete(name);
320
- resolved.add(name);
321
- }
322
-
323
- class UniqueRules {
324
- private regexps = new Set<string>();
325
- private strings = new Set<string>();
326
- rules: LexerStateMatchRule[] = [];
327
-
328
- push(...rules: LexerStateMatchRule[]) {
329
- for (const rule of rules) {
330
- if (RegexLib.IsRegex(rule.when)) {
331
- if (!this.regexps.has((rule.when as RegExp).source)) {
332
- this.rules.push(rule);
333
- }
334
- } else {
335
- if (!this.strings.has(rule.when as string)) {
336
- this.rules.push(rule);
337
- }
338
- }
339
- }
340
- }
341
184
  }