grammar-well 2.0.6 → 2.1.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 (56) hide show
  1. package/build/generator/generator.js +4 -1
  2. package/build/generator/generator.js.map +1 -1
  3. package/build/generator/grammars/v1.d.ts +1 -0
  4. package/build/generator/grammars/v1.js +1 -0
  5. package/build/generator/grammars/v1.js.map +1 -1
  6. package/build/generator/grammars/v2.d.ts +10 -2
  7. package/build/generator/grammars/v2.js +4 -1
  8. package/build/generator/grammars/v2.js.map +1 -1
  9. package/build/generator/state.d.ts +7 -5
  10. package/build/generator/state.js +5 -2
  11. package/build/generator/state.js.map +1 -1
  12. package/build/generator/stringify/exports/javascript.js +3 -2
  13. package/build/generator/stringify/exports/javascript.js.map +1 -1
  14. package/build/generator/stringify/exports/typescript.js +3 -2
  15. package/build/generator/stringify/exports/typescript.js.map +1 -1
  16. package/build/generator/stringify/grammar/v2.d.ts +4 -0
  17. package/build/generator/stringify/grammar/v2.js +14 -5
  18. package/build/generator/stringify/grammar/v2.js.map +1 -1
  19. package/build/generator/stringify/javascript.d.ts +1 -0
  20. package/build/generator/stringify/javascript.js +23 -2
  21. package/build/generator/stringify/javascript.js.map +1 -1
  22. package/build/lexers/character-lexer.d.ts +1 -0
  23. package/build/lexers/character-lexer.js +2 -1
  24. package/build/lexers/character-lexer.js.map +1 -1
  25. package/build/lexers/stateful-lexer.d.ts +1 -0
  26. package/build/lexers/stateful-lexer.js +2 -1
  27. package/build/lexers/stateful-lexer.js.map +1 -1
  28. package/build/lexers/token-buffer.d.ts +2 -1
  29. package/build/lexers/token-buffer.js +7 -2
  30. package/build/lexers/token-buffer.js.map +1 -1
  31. package/build/parser/algorithms/earley.js +14 -1
  32. package/build/parser/algorithms/earley.js.map +1 -1
  33. package/build/parser/parse.js +8 -7
  34. package/build/parser/parse.js.map +1 -1
  35. package/build/typings/ast.d.ts +1 -1
  36. package/build/typings/runtime.d.ts +4 -0
  37. package/build/version.json +1 -1
  38. package/package.json +1 -1
  39. package/src/generator/generator.ts +4 -1
  40. package/src/generator/grammars/v1.ts +2 -1
  41. package/src/generator/grammars/v2.ts +5 -2
  42. package/src/generator/grammars/v2.well +2 -0
  43. package/src/generator/state.ts +11 -5
  44. package/src/generator/stringify/exports/javascript.ts +3 -2
  45. package/src/generator/stringify/exports/typescript.ts +3 -2
  46. package/src/generator/stringify/grammar/v2.ts +17 -5
  47. package/src/generator/stringify/javascript.ts +24 -2
  48. package/src/lexers/character-lexer.ts +2 -1
  49. package/src/lexers/stateful-lexer.ts +2 -1
  50. package/src/lexers/token-buffer.ts +5 -2
  51. package/src/parser/algorithms/earley.ts +18 -3
  52. package/src/parser/parse.ts +8 -7
  53. package/src/typings/ast.ts +1 -1
  54. package/src/typings/generator.ts +1 -1
  55. package/src/typings/runtime.ts +3 -1
  56. package/src/version.json +1 -1
@@ -4,8 +4,9 @@ export class GeneratorState {
4
4
  grammar?: GeneratorStateGrammar;
5
5
  lexer?: GeneratorLexerConfig;
6
6
  lifecycle: {
7
- import?: string;
8
- new?: string;
7
+ import?: string[];
8
+ new?: string[];
9
+ token?: string[];
9
10
  } = {}
10
11
 
11
12
  config = {};
@@ -72,9 +73,14 @@ export class GeneratorState {
72
73
  }
73
74
  }
74
75
 
75
- addLifecycle(lifecycle: string, literal: string) {
76
- this.lifecycle[lifecycle] = this.lifecycle[lifecycle] || '';
77
- this.lifecycle[lifecycle] += literal;
76
+ addLifecycle(lifecycle: string, literal: string | string[]) {
77
+ this.lifecycle[lifecycle] = this.lifecycle[lifecycle] || [];
78
+
79
+ if (typeof literal == 'string')
80
+ this.lifecycle[lifecycle].push(literal);
81
+
82
+ if (Array.isArray(literal))
83
+ this.lifecycle[lifecycle].push(...literal);
78
84
  }
79
85
 
80
86
  export() {
@@ -20,10 +20,11 @@ function Generate(generator: JavaScriptGenerator) {
20
20
  return `// Generated automatically by Grammar-Well, version ${generator.state.version}
21
21
  // https://github.com/0x6563/grammar-well
22
22
 
23
- ${generator.lifecycle('import')}
23
+ ${generator.lifecycle('import').join('')}
24
24
 
25
25
  class ${exportName} {
26
+ state = {};
26
27
  artifacts = ${generator.artifacts(1)}
27
- constructor(){${generator.lifecycle('new')}}
28
+ constructor(){${generator.lifecycle('new').join('')}}
28
29
  }`;
29
30
  }
@@ -6,11 +6,12 @@ export function TypescriptFormat(generator: JavaScriptGenerator) {
6
6
  // https://github.com/0x6563/grammar-well
7
7
  // @ts-nocheck
8
8
 
9
- ${generator.lifecycle('import')}
9
+ ${generator.lifecycle('import').join('')}
10
10
 
11
11
  class ${exportName} {
12
+ state = {};
12
13
  artifacts = ${generator.artifacts(1)}
13
- constructor(){${generator.lifecycle('new')}}
14
+ constructor(){${generator.lifecycle('new').join('')}}
14
15
  }
15
16
 
16
17
  export default ${exportName};`;
@@ -6,7 +6,11 @@ export class V2GrammarString {
6
6
  directives = Array.isArray(directives) ? directives : [directives];
7
7
  for (const directive of directives) {
8
8
  if ("lifecycle" in directive) {
9
- this.appendSection("on:" + directive.lifecycle, directive.js.js.trim());
9
+ if ('js' in directive.js)
10
+ this.appendSection("on:" + directive.lifecycle, directive.js.js.trim());
11
+ else if ('template' in directive.js)
12
+ this.appendSource("on:" + directive.lifecycle + this.formatTemplate(directive.js));
13
+
10
14
  } else if ("import" in directive) {
11
15
  this.appendImportDirective(directive);
12
16
  } else if ("config" in directive) {
@@ -93,12 +97,16 @@ export class V2GrammarString {
93
97
  return `=> \${ ${postProcess.js} }`;
94
98
  }
95
99
  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}`;
100
+ return this.formatTemplate(postProcess)
99
101
  }
100
102
  }
101
103
 
104
+ formatTemplate(postProcess: { template: string }) {
105
+ const prefix = postProcess.template.slice(0, 1);
106
+ const suffix = postProcess.template.slice(-1);
107
+ return `=> ${prefix} ${postProcess.template.slice(1, -1).trim()} ${suffix}`;
108
+ }
109
+
102
110
  appendLexerDirective(directive: ASTLexer) {
103
111
  let body = '';
104
112
  if (directive.lexer.start) {
@@ -211,10 +219,14 @@ export class V2GrammarString {
211
219
  }
212
220
 
213
221
  appendSection(label: string, body: string) {
222
+ this.appendSource(`${label} {\n${body}\n}\n`)
223
+ }
224
+
225
+ appendSource(source) {
214
226
  if (this.source) {
215
227
  this.source += '\n';
216
228
  }
217
- this.source += `${label} {\n${body}\n}\n`;
229
+ this.source += source;
218
230
  }
219
231
 
220
232
  indent(depth: number = 0, content: string) {
@@ -22,8 +22,8 @@ export class JavaScriptGenerator {
22
22
 
23
23
  lifecycle(lifecycle: string) {
24
24
  if (this.options.noscript)
25
- return '';
26
- return this.state.lifecycle[lifecycle] || '';
25
+ return [];
26
+ return this.state.lifecycle[lifecycle] || [];
27
27
  }
28
28
 
29
29
  artifacts(depth: number = 0) {
@@ -48,9 +48,31 @@ export class JavaScriptGenerator {
48
48
  output.grammar = basic.stringify(depth + 1);
49
49
  }
50
50
 
51
+ const onToken = this.lifecycle('token');
52
+ if (onToken.length) {
53
+ output.tokenProcessor = `() => {`
54
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 1)}return (token) => {`
55
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 2)}const processors = [`;
56
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 3)}${onToken.map(v => `({ token, state }) => ${v}`).join(',' + CommonGenerator.SmartIndent(depth + 3))}`
57
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 2)}];`
58
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 2)}for (const processor of processors) {`
59
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 3)}token = processor({ token, state: this.state })`
60
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 2)}}`
61
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 2)}return token;`
62
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth + 1)}}`
63
+ output.tokenProcessor += `${CommonGenerator.SmartIndent(depth)}}`;
64
+ }
51
65
  return CommonGenerator.JSON(output, depth);
52
66
  }
53
67
 
68
+ f(token) {
69
+ const processors = [({ token, state }) => token]
70
+ for (const processor of processors) {
71
+ token = processor({ token, state: this.state })
72
+ }
73
+ return token;
74
+ }
75
+
54
76
  postProcess(postprocess: GeneratorGrammarProductionRule['postprocess'], alias: Dictionary<number>) {
55
77
  postprocess = this.state.grammar.config.postprocessorOverride || postprocess || this.state.grammar.config.postprocessorDefault;
56
78
  if (!postprocess)
@@ -28,7 +28,8 @@ export class CharacterLexer implements RuntimeLexer {
28
28
  value,
29
29
  offset: this.index,
30
30
  line: this.line,
31
- column: this.column
31
+ column: this.column,
32
+ custom: {}
32
33
  };
33
34
  }
34
35
  }
@@ -64,7 +64,8 @@ export class StatefulLexer implements RuntimeLexer {
64
64
  line: this.line,
65
65
  lines: 0,
66
66
  column: this.column,
67
- state: this.current
67
+ state: this.current,
68
+ custom: {},
68
69
  }
69
70
  this.adjustPosition(text);
70
71
  token.lines = this.line - token.line;
@@ -15,7 +15,7 @@ export class TokenBuffer {
15
15
  return { historyIndex: this.$historyIndex, offset: this.offset };
16
16
  }
17
17
 
18
- constructor(public lexer: RuntimeLexer) { }
18
+ constructor(public lexer: RuntimeLexer, private tokenProcessor?: (token: RuntimeLexerToken) => RuntimeLexerToken) { }
19
19
 
20
20
  reset(buffer: string) {
21
21
  this.lexer.feed(buffer);
@@ -77,8 +77,11 @@ export class TokenBuffer {
77
77
  this.queued = '';
78
78
  token = this.lexer.next();
79
79
  }
80
- if (token)
80
+ if (token) {
81
+ if (this.tokenProcessor)
82
+ token = this.tokenProcessor(token);
81
83
  this.history.push(token);
84
+ }
82
85
  return token;
83
86
  }
84
87
 
@@ -1,4 +1,4 @@
1
- import { Dictionary, RuntimeGrammarProductionRule, RuntimeParserClass } from "../../typings/index.js";
1
+ import { Dictionary, RuntimeGrammarProductionRule, RuntimeLexerToken, RuntimeParserClass } from "../../typings/index.js";
2
2
  import { TokenBuffer } from "../../lexers/token-buffer.js";
3
3
  import { TextFormatter } from "../../utility/text-format.js";
4
4
  import { ParserUtility } from "../../utility/parsing.js";
@@ -58,9 +58,22 @@ export function Earley(language: RuntimeParserClass & { tokens: TokenBuffer }, o
58
58
  results.push(data);
59
59
  }
60
60
  }
61
+ const clone = results.length > 1;
62
+ for (let i = 0; i < results.length; i++) {
63
+ results[i] = PostProcess(results[i], clone);
64
+ }
61
65
  return { results, info: { table } };
62
66
  }
63
67
 
68
+ function PostProcess(ast: PreAST | RuntimeLexerToken, clone?: boolean) {
69
+ if (!Array.isArray(ast))
70
+ return clone ? { ...ast } : ast;
71
+ const data = [];
72
+ for (let i = 0; i < ast[1].length; i++) {
73
+ data[i] = PostProcess(ast[1][i], clone);
74
+ }
75
+ return ParserUtility.PostProcess(ast[0], data, ast[2]);
76
+ }
64
77
 
65
78
  class Column {
66
79
  data: any;
@@ -170,7 +183,7 @@ class State {
170
183
 
171
184
 
172
185
  finish() {
173
- this.data = ParserUtility.PostProcess(this.rule, this.data, { reference: this.reference, dot: this.dot });
186
+ this.data = [this.rule, this.data, { reference: this.reference, dot: this.dot }];
174
187
  }
175
188
 
176
189
  protected build() {
@@ -190,4 +203,6 @@ interface StateToken {
190
203
  token: any,
191
204
  isToken: boolean,
192
205
  reference: number
193
- }
206
+ }
207
+
208
+ type PreAST = [RuntimeGrammarProductionRule, (RuntimeLexerToken | PreAST)[], { reference: number, dot: number }];
@@ -29,13 +29,14 @@ export function Parse(
29
29
  return results == 'full' ? result : result.results[0];
30
30
  }
31
31
 
32
- function GetTokenizer({ lexer }: RuntimeParserClass['artifacts']) {
33
- if (!lexer) {
34
- return new TokenBuffer(new CharacterLexer());
35
- } else if ("feed" in lexer && typeof lexer.feed == 'function') {
36
- return new TokenBuffer(lexer);
37
- } else if ('states' in lexer) {
38
- return new TokenBuffer(new StatefulLexer(lexer));
32
+ function GetTokenizer(artifacts: RuntimeParserClass['artifacts']) {
33
+ const tokenProcessor = artifacts?.tokenProcessor ? artifacts.tokenProcessor() : null;
34
+ if (!artifacts.lexer) {
35
+ return new TokenBuffer(new CharacterLexer(), tokenProcessor);
36
+ } else if ("feed" in artifacts.lexer && typeof artifacts.lexer.feed == 'function') {
37
+ return new TokenBuffer(artifacts.lexer, tokenProcessor);
38
+ } else if ('states' in artifacts.lexer) {
39
+ return new TokenBuffer(new StatefulLexer(artifacts.lexer), tokenProcessor);
39
40
  }
40
41
  }
41
42
 
@@ -5,7 +5,7 @@ export type AST = ASTDirectives[];
5
5
  export type ASTJavascriptLifecycleLiteral = {
6
6
  lifecycle: string;
7
7
  path?: boolean;
8
- js: ASTJavaScriptLiteral;
8
+ js: ASTJavaScriptLiteral | ASTJavaScriptTemplate;
9
9
  }
10
10
  export type ASTJavaScriptLiteral = { js: string }
11
11
  export type ASTJavaScriptTemplate = { template: string }
@@ -41,7 +41,7 @@ export interface GeneratorStateGrammar {
41
41
  };
42
42
 
43
43
  export interface GeneratorLexerConfig {
44
- start?: string
44
+ start?: string;
45
45
  states: Dictionary<GeneratorLexerState>;
46
46
  }
47
47
 
@@ -1,5 +1,5 @@
1
1
  import { LRState } from "./index.js";
2
- import { ASTGrammarSymbolLiteral, ASTGrammarSymbolToken, ASTLexerStateMatchRule, ASTLexerStateNonMatchRule } from "./ast.js";
2
+ import { ASTGrammarSymbolLiteral, ASTGrammarSymbolToken, ASTLexerStateNonMatchRule } from "./ast.js";
3
3
  import { Dictionary } from "./common.js";
4
4
 
5
5
  export interface RuntimeParserClass {
@@ -13,6 +13,7 @@ export interface RuntimeParserClass {
13
13
  k: number;
14
14
  table: Dictionary<LRState>;
15
15
  }
16
+ tokenProcessor: () => ((token: RuntimeLexerToken) => RuntimeLexerToken) | undefined
16
17
  }
17
18
  new();
18
19
  }
@@ -60,6 +61,7 @@ export interface RuntimeLexerToken {
60
61
  offset: number;
61
62
  line: number;
62
63
  column: number;
64
+ custom?: { [key: string]: any }
63
65
  }
64
66
 
65
67
 
package/src/version.json CHANGED
@@ -1 +1 @@
1
- {"version":"2.0.6"}
1
+ {"version":"2.1.0"}