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
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Grammar Well is a cross-platform compiler, parser, and/or interpreter. It originated as a port of the popular library [Nearley](https://github.com/kach/nearley) to TypeScript but has since evolved to include additional functionality, such as a built-in lexer and support for various parsing algorithms including LR0 and CKY. It also offers a range of quality of life features.
4
4
 
5
- Check out the Demo/Live Editor https://0x6563.github.io/grammar-well-editor
5
+ Check out the documentation at https://grammar-well.xyz/
6
6
 
7
7
  # Quick Start
8
8
  ### Install
@@ -13,585 +13,101 @@ Check out the Demo/Live Editor https://0x6563.github.io/grammar-well-editor
13
13
  ```Javascript
14
14
  import { Compile, Parse } from 'grammar-well';
15
15
 
16
- async function GrammarWellRunner(source, input) {
17
- function Evalr(source) {
18
- const module = { exports: null };
19
- eval(source);
20
- return module.exports;
21
- }
22
- const compiled = await Compile(source, { exportName: 'grammar' });
23
- return Parse(Evalr(compiled)(), input, { algorithm: 'earley' });
24
- }
25
-
26
-
27
- const source = `lexer: {{
28
- start: "json"
16
+ const source = `
17
+ import * from whitespace;
18
+
19
+ lexer {
20
+ start: "json"
21
+
22
+ [json]
23
+ - import whitespace
24
+ - when r:{-?(?:[0-9]|[1-9][0-9]+)(?:\.[0-9]+)?(?:[eE][-+]?[0-9]+)?\b} tag "number"
25
+ - when r:{"(?:\\["bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*"} tag "string"
26
+ - when "{" tag "{"
27
+ - when "}" tag "}"
28
+ - when "[" tag "["
29
+ - when "]" tag "]"
30
+ - when "," tag ","
31
+ - when ":" tag ":"
32
+ - when "true" tag "true"
33
+ - when "false" tag "false"
34
+ - when "null" tag "null"
29
35
 
30
- json ->
31
- - when: /\s+/ tag: "space"
32
- - when: /-?(?:[0-9]|[1-9][0-9]+)(?:\.[0-9]+)?(?:[eE][-+]?[0-9]+)?\b/ tag: "number"
33
- - when: /"(?:\\["bfnrt\/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*"/ tag: "string"
34
- - when: "{" tag: "{"
35
- - when: "}" tag: "}"
36
- - when: "[" tag: "["
37
- - when: "]" tag: "]"
38
- - when: "," tag: ","
39
- - when: ":" tag: ":"
40
- - when: "true" tag: "true"
41
- - when: "false" tag: "false"
42
- - when: "null" tag: "null"
43
- }}
44
-
45
- grammar: {{
46
- json -> _ (object | array) _ : {{ $1[0] }}
36
+ }
47
37
 
48
- object -> "{" _ "}" : {{ {} }}
49
- | "{" _ pair (_ "," _ pair)* _ "}" : \${ extractObject }
38
+ grammar {
39
+ start: "json"
50
40
 
51
- array -> "[" _ "]" : {{ [] }}
52
- | "[" _ value (_ "," _ value)* _ "]" : \${ extractArray }
41
+ [json]
42
+ | _ (object | array) _ => ( $1[0] )
53
43
 
54
- value : {{ $0 }} ->
55
- object
56
- | array
57
- | number
58
- | string
59
- | "true" : {{ true }}
60
- | "false" : {{ false }}
61
- | "null" : {{ null }}
44
+ [object]
45
+ | "{" _ "}" => ( {} )
46
+ | "{" _ pair (_ "," _ pair)* _ "}" => \${ extractObject }
62
47
 
63
- number -> $number : {{ parseFloat($0.value) }}
48
+ [array]
49
+ | "[" _ "]" => ( [] )
50
+ | "[" _ value (_ "," _ value)* _ "]" => \${ extractArray }
64
51
 
65
- string -> $string : {{ JSON.parse($0.value) }}
52
+ [value]
53
+ | object => ( $0 )
54
+ | array => ( $0 )
55
+ | number => ( $0 )
56
+ | string => ( $0 )
57
+ | "true" => ( true )
58
+ | "false" => ( false )
59
+ | "null" => ( null )
66
60
 
67
- pair -> key:k _ ":" _ value:v : {{ [$k, $v] }}
61
+ [number]
62
+ | <number> => ( parseFloat($0.value) )
68
63
 
69
- key -> string : {{ $0 }}
64
+ [string]
65
+ | <string> => ( JSON.parse($0.value) )
70
66
 
71
- _ -> $space? : {{ null }}
72
- }}
67
+ [pair]
68
+ | key@k _ ":" _ value@v => ( [$k, $v] )
73
69
 
74
- head: \${
70
+ [key]
71
+ | string => ( $0 )
75
72
 
76
- function extractPair(kv, output) {
77
- if(kv[0]) { output[kv[0]] = kv[1]; }
78
73
  }
79
74
 
80
- function extractObject({data}) {
81
- let output = {};
82
-
83
- extractPair(data[2], output);
84
-
85
- for (let i in data[3]) {
86
- extractPair(data[3][i][3], output);
75
+ on:import {
76
+ function extractPair(kv, output) {
77
+ if(kv[0]) { output[kv[0]] = kv[1]; }
87
78
  }
88
79
 
89
- return output;
90
- }
91
-
92
- function extractArray({data}) {
93
- let output = [data[2]];
80
+ function extractObject({data}) {
81
+ let output = {};
94
82
 
95
- for (let i in data[3]) {
96
- output.push(data[3][i][3]);
97
- }
98
-
99
- return output;
100
- }
101
- }
102
- `
83
+ extractPair(data[2], output);
103
84
 
104
- const input = `{"a":"string","b":true,"c":2}`
85
+ for (let i in data[3]) {
86
+ extractPair(data[3][i][3], output);
87
+ }
105
88
 
106
-
107
- console.log(await GrammarWellRunner(source, input))
108
- ```
109
-
110
- # Quick Guide
111
- Below is a quick guide highlighting some of the grammars features.
112
-
113
- # Terminology
114
- Thse are some terms you may find used around the documentation.
115
- #### Word
116
- A **word** refers to an alphanumeric string that matches `/[a-zA-Z_][a-zA-Z_\d]*/`
117
-
118
- #### Symbol
119
- A **Symbol** refers to **Terminals** and **Non Terminals** found in EBNF expressions.
120
-
121
- # Grammar Sections
122
- Grammar Well's grammar is broken into 4 sections **head**, **body**, **lexer**, and **grammar**
123
- .
124
- ## Head/Body
125
- Both the **head** and **body** section have the same syntax. These sections refer to literal javascript to embed in the compiled version of the grammar. The difference between the two is that **head** will be placed outside of the parse function and the **body** will be plaed within the parse function. This allows to have static variables that are persisted across executions, or not, depending on your use case.
126
-
127
- _example using both head and body to keep track the number of parses_
128
- ```
129
- head: ${
130
- let parses = 0;
131
-
132
- export function GetParseCount(){
133
- return parses;
89
+ return output;
134
90
  }
135
- }
136
-
137
- body :${
138
- parses++;
139
- }
140
- ```
141
-
142
-
143
- ## Lexer
144
- Grammar Well utilizes a stateful lexer, which is optional but highly recommended due to its significant assistance in constructing production rules for the grammar. The lexer configuration comprises two subsections: config and states. It is important to note that the configuration section must be placed at the top. **Currently**, the sole configuration option available is the optional setting start, which determines the initial lexer state to begin with.
145
-
146
- ```
147
- lexer: {{
148
- start: "root"
149
-
150
- root ->
151
- - import: string, ws
152
- - when: /\/(?:[^\/\\\r\n]|\\.)+\// tag: "REGEX" highlight: "regexp"
153
- - when: "{" tag: "CURLY_L" goto: body
154
-
155
- body->
156
- - import: string, ws
157
- - when: "}" tag: "CURLY_R" pop: 1
158
-
159
- string ->
160
- - when: /"(?:[^"\\\r\n]|\\.)*"/ tag: "T_STRING" highlight: "string"
161
-
162
- ws ->
163
- - when: /\s+/ tag: "T_WS"
164
- }}
165
- ```
166
- In the above example, we start with a state named `root` followed by `-` delimited list of rules. There are two type of rules _import_ rules and _token matching_ rules. Order is important.
167
-
168
- ### Import Rule
169
- ```
170
- - import: string, ws
171
- ```
172
- The first rule we see is in the example is an _import_ rule. The import rule expects a comma delimited list of states whose rules are to be imported in to this state. This is a convenient way of keeping your rules DRY.
173
-
174
- ### Token Matching Rule
175
- ```
176
- - when: /\/(?:[^\/\\\r\n]|\\.)+\// tag: "REGEX" highlight: "regexp"
177
- - when: "{" tag: "CURLY_L" goto: body
178
-
179
- ```
180
- This other rules we see in the example are _token matching_ rules. As the name implies, we declare what to match in the input stream. Below is a list of fields that are available.
181
-
182
- #### Fields
183
- - `when` [ _string | regex_] **required, exclusive with before** what to match in the input stream
184
- - `before` [_string | regex_] **required, exclusive with when** what to match but does not consume the input stream, should be used in conjunction with stack manipulation
185
- - `tag` [_comma delimited strings_] Applies tags to the matched token, these can be referenced in the grammar
186
- - `goto` [_word_] Moves to the defined state and adds the current state onto the stack
187
- - `pop` [_number|nothing_] Pops 1 or the number of states off the stack
188
- - `highlight` [_string_] This isn't used directly but can be used to help generate syntax highlighting.
189
- - `inset` [_number|nothing_] Adds the current state onto the stack 1 or the number of times defined.
190
-
191
- # Grammar
192
- The **grammar** section is heavily based on the EBNF notation with some additional syntax to help with generating output. If you aren't familiar with EBNF it would be good to start there before continuing.
193
-
194
- The basic syntax is a **Rule Name** followed by `->` and then a **Expression** (combinations of **Terminals** and **Non Terminals**). Multiple expressions can be declared for a rule by seperating them with a `|`. Depending on the parsing algorithm you choose there maybe additional constraints on the expression.
195
-
196
- _In this example.
197
- There are 4 Non Terminals; `Start`, `HelloGoodbye`, `Target`, and `__`.
198
- As well as 5 Terminals; `"Hello"`, `"Goodbye"`, `"World"`, `/[a-zA-Z]+/`, and `$ws`_
199
- ```
200
- Start -> HelloGoodbye __ Target
201
-
202
- HelloGoodbye -> "Hello"
203
- | "Goodbye"
204
-
205
- Target -> "World"
206
- | /[a-zA-Z]+/
207
-
208
- __ -> $ws
209
- ```
210
- ### Post Processors
211
- In addition to the standard anatomy of EBNF. Grammar Well supports **Post Processors**. **Post Processors** are used to either evaluate or transform a matched expression. They can follow a rule name but before the `->` seperator to apply to each expression as the default but overridable postprocessor. They can follow an expression to only apply to that segment.
212
-
213
- _In this example, you see two different types of post processors_
214
- ```
215
- Target : ${ ({data}) => data[0].value } ->
216
- "World"
217
- | /[a-zA-Z]+/ : {{ $0.value }}
218
- ```
219
-
220
- **JavaScript Literal** ` : ${ JavaScriptFunction }`
221
-
222
- The JavaScript Literal versions expects a JavaScript function.
223
-
224
- **JavaScript Template** ` : {{ JavaScriptFunctionBody }}`
225
-
226
- **Ordinal References**
227
-
228
- The Javascript Template version expects a function body and is provided a variable `data`. It will also do simple string replacements. For example any `$` followed by a number will be replaced with `data[number]`.
229
-
230
- _example displaying different syntax but equal functionality_
231
- ```
232
- Rule -> "Hello" : {{ $0.value }}
233
-
234
- Rule -> "Hello" : ${ ({data}) => data[0].value }
235
- ```
236
-
237
- **Aliased References**
238
-
239
- Keeping tracking of the ordinal index of your symbols in an expression can be tedious, so Grammar Well also provides aliasing. Any symbol in an expression can be suffixed with `:word`. That **word** can then be referenced in the template.
240
-
241
- _example displaying different syntax but equal functionality_
242
- ```
243
- Rule-> "Hello":hello : {{ $hello.value }}
244
-
245
- Rule-> "Hello" : ${ ({data}) => data[0].value }
246
- ```
247
-
248
91
 
92
+ function extractArray({data}) {
93
+ let output = [data[2]];
249
94
 
250
- ### Rule Name
251
- The name of a rule must be a **word** (regex: `/[a-zA-Z_][a-zA-Z_\d]+/`)
252
-
253
-
254
- ### Expression
255
- Besides having Terminals and Non Terminals. Each expression can also be followed by a **PostProcessor**.
256
-
257
- _example of a rule with 2 expressions with postprocessors for each_
258
- ```
259
- Target -> "World" : ${ (data) => data[0].value }
260
- | /[a-zA-Z]+/ : {{ $0.value }}
261
- ```
262
-
263
- ### Non Terminals
264
- **Non Terminals** are simple. They are **word**s that refer to another rule.
265
-
266
- ### Terminals
267
- There are three different types of terminals that Grammar Well supports:
268
-
269
- **Literals**
270
-
271
- Literals are double quoted strings that are case strings that are matched in the lexer stream. Optionaly strings can be modified to allow case insensitive matching by appending an `i` after the end quote.
272
-
273
- _example of having a case insensitive literal_
274
- ```
275
- Rule-> "Hello"i
276
- ```
277
- **Regular Expressions**
278
-
279
- Grammar Well is written in TypeScript, which leads two things.
280
- 1. The syntax for regex matches that of JavaScript.
281
- 2. It is limited to the capabilities of JavaScript's regex.
282
-
283
- ```
284
- Rule-> /[a-zA-Z]+/
285
- ```
286
-
287
- **Token Tags**
288
-
289
- If the lexer is used than you can refer to the tags defined by prefixing their name with an `$`
290
-
291
- ```
292
- Rule-> $token
293
- ```
294
-
295
- ### Grouping
296
- Symbols can be grouped with `()` seperating each option with a `|`
297
- ```
298
- Rule -> ("Hello" | "Goodbye")
299
- ```
300
- ### Modifiers
301
- EBNF modifiers like `?`,`*`, and `+` are all supported
302
- ```
303
- Whitespace -> " "*
304
- ```
305
- ### Aliasing
306
- As noted above in post processors alias allow named references to symbols to be used with in a template
307
- ```
308
- Rule-> "Hello":hello : {{ $hello.value }}
309
- ```
310
-
311
- # The Big Example
312
- _Grammar Well's Grammar File_
313
-
314
- ```
315
- lexer: {{
316
- start: "start"
317
-
318
- start ->
319
- - import: string, js, ws, comment, l_scolon, l_star
320
- - when: /lexer(?![a-zA-Z\d_])/ tag: "T_WORD" goto: lexer highlight: "type"
321
- - when: /grammar(?![a-zA-Z\d_])/ tag: "T_WORD" goto: grammar highlight: "type"
322
- - when: /config(?![a-zA-Z\d_])/ tag: "T_WORD" goto: config highlight: "type"
323
- - import: kv
324
- config ->
325
- - import: ws, l_colon
326
- - when: "{{" tag: "L_TEMPLATEL" set: config_inner
327
- config_inner ->
328
- - import: comment, kv
329
- - when: "}}" tag: "L_TEMPLATER" pop: 1
330
- grammar ->
331
- - import: ws, l_colon
332
- - when: "{{" tag: "L_TEMPLATEL" set: grammar_inner
333
- grammar_inner ->
334
- - import: comment, js, js_template, ws, regex, l_qmark, l_plus, l_star, kv, l_colon, l_comma, l_pipe, l_parenl, l_parenr, l_arrow, l_dsign, l_dash
335
- - when: "}}" tag: "L_TEMPLATER" pop: 1
336
- lexer ->
337
- - import: ws, l_colon
338
- - when: "{{" tag: "L_TEMPLATEL" set: lexer_inner
339
- lexer_inner ->
340
- - import: ws, comment, regex, l_comma, l_arrow, l_dash, kv, js
341
- - when: "}}" tag: "L_TEMPLATER" pop: 1
342
- js ->
343
- - when: "${" tag: "L_JSL" goto: js_wrap
344
- js_wrap ->
345
- default: "T_JSBODY"
346
- unmatched: "T_JSBODY"
347
- - import: jsignore
348
- - when: "{" tag: "T_JSBODY" goto: js_literal
349
- - when: "}" tag: "L_JSR" pop: 1
350
- js_literal ->
351
- default: "T_JSBODY"
352
- unmatched: "T_JSBODY"
353
- - import: jsignore
354
- - when: "{" tag: "T_JSBODY" goto: js_literal
355
- - when: "}" tag: "T_JSBODY" pop: 1
356
- js_template ->
357
- - when: "{{" tag: "L_TEMPLATEL" goto: js_template_inner
358
- js_template_inner ->
359
- default: "T_JSBODY"
360
- unmatched: "T_JSBODY"
361
- - import: jsignore
362
- - when: "{" tag: "T_JSBODY" goto: js_literal
363
- - when: "}}" tag: "L_TEMPLATER" pop: 1
364
- kv ->
365
- - import: string, ws, word, l_colon, integer
366
- jsignore ->
367
- - when: /"(?:[^"\\\r\n]|\\.)*"/ tag: "T_JSBODY"
368
- - when: /'(?:[^'\\\r\n]|\\.)*'/ tag: "T_JSBODY"
369
- - when: /`(?:[^`\\]|\\.)*`/ tag: "T_JSBODY"
370
- - when: /\/(?:[^\/\\\r\n]|\\.)+\/[gmiyu]*/ tag: "T_JSBODY"
371
- - when: /\/\/[^\n]*/ tag: "T_JSBODY"
372
- - when: /\/\*.*\*\// tag: "T_JSBODY"
373
- string ->
374
- - when: /"(?:[^"\\\r\n]|\\.)*"/ tag: "T_STRING" highlight: "string"
375
- string2 ->
376
- - when: /'(?:[^'\\\r\n]|\\.)*'/ tag: "T_STRING" highlight: "string"
377
- string3 ->
378
- - when: /`(?:[^`\\]|\\.)*`/ tag: "T_STRING" highlight: "string"
379
- regex ->
380
- - when: /\/(?:[^\/\\\r\n]|\\.)+\// tag: "T_REGEX" highlight: "regexp"
381
- integer ->
382
- - when: /\d+/ tag: "T_INTEGER" highlight: "number"
383
- word ->
384
- - when: /[a-zA-Z_][a-zA-Z_\d]*/ tag: "T_WORD"
385
- ws ->
386
- - when: /\s+/ tag: "T_WS"
387
- l_colon ->
388
- - when: ":" tag: "L_COLON" highlight: "keyword"
389
- l_scolon ->
390
- - when: ";" tag: "L_SCOLON"
391
- l_qmark ->
392
- - when: "?" tag: "L_QMARK"
393
- l_plus ->
394
- - when: "+" tag: "L_PLUS"
395
- l_star ->
396
- - when: "*" tag: "L_STAR"
397
- l_comma ->
398
- - when: "," tag: "L_COMMA"
399
- l_pipe ->
400
- - when: "|" tag: "L_PIPE" highlight: "keyword"
401
- l_parenl ->
402
- - when: "(" tag: "L_PARENL"
403
- l_parenr ->
404
- - when: ")" tag: "L_PARENR"
405
- l_templatel ->
406
- - when: "{{" tag: "L_TEMPLATEL"
407
- l_templater ->
408
- - when: "}}" tag: "L_TEMPLATER"
409
- l_arrow ->
410
- - when: "->" tag: "L_ARROW" highlight: "keyword"
411
- l_dsign ->
412
- - when: "$" tag: "L_DSIGN"
413
- l_dash ->
414
- - when: "-" tag: "L_DASH"
415
- comment ->
416
- - when: /\/\/[^\n]*/ tag: "T_COMMENT" highlight: "comment"
417
- commentmulti ->
418
- - when: /\/\*.*\*\// tag: "T_COMMENT" highlight: "comment"
419
-
420
- }}
421
-
422
- grammar: {{
423
-
424
- main ->
425
- _ section_list _ : {{ $1 }}
426
-
427
- section_list ->
428
- section : {{ [$0] }}
429
- | section T_WS section_list : {{ [$0].concat($2) }}
430
-
431
- section ->
432
- K_CONFIG _ L_COLON _ L_TEMPLATEL _ kv_list:list _ L_TEMPLATER : {{ { config: Object.assign(...$list) } }}
433
- | K_IMPORT _ L_STAR _ K_FROM __ T_WORD:import _ L_SCOLON : {{ { import: $import } }}
434
- | K_IMPORT _ L_STAR _ K_FROM __ T_STRING:import _ L_SCOLON : {{ { import: $import, path: true } }}
435
- | K_LEXER _ L_COLON _ L_TEMPLATEL _ lexer:lexer _ L_TEMPLATER : {{ { lexer: Object.assign(...$lexer) } }}
436
- | K_GRAMMAR _ L_COLON _ L_TEMPLATEL _ grammar:grammar _ L_TEMPLATER : {{ { grammar: $grammar } }}
437
- | K_BODY _ L_COLON _ T_JS:js : {{ { body: $js } }}
438
- | K_BODY _ L_COLON _ T_STRING:js : {{ { body: $js, path: true } }}
439
- | K_HEAD _ L_COLON _ T_JS:js : {{ { head: $js } }}
440
- | K_HEAD _ L_COLON _ T_STRING:js : {{ { head: $js, path: true } }}
441
-
442
- lexer ->
443
- kv_list _ state_list : {{ $0.concat({ states: $2 }) }}
444
- | state_list : {{ [{ states: $0 }] }}
445
-
446
- state_list ->
447
- state : {{ data }}
448
- | state _ state_list : {{ [$0].concat($2) }}
449
-
450
- state ->
451
- state_declare _ state_definition : {{ Object.assign({ name: $0 }, $2) }}
452
-
453
- state_declare ->
454
- T_WORD _ L_ARROW : {{ $0 }}
455
-
456
- state_definition ->
457
- kv_list _ token_list : {{ Object.assign(...$0, { rules: $2 }) }}
458
- | token_list : {{ { rules: $0 } }}
459
-
460
- token_list ->
461
- token : {{ data }}
462
- | token _ token_list : {{ [$0].concat($2) }}
463
-
464
- token ->
465
- L_DASH _ K_IMPORT _ L_COLON _ word_list : {{ { import: $6 } }}
466
- | L_DASH _ token_definition_list : {{ Object.assign(...$2) }}
467
-
468
- token_definition_list ->
469
- token_definition : {{ data }}
470
- | token_definition _ token_definition_list : {{ [$0].concat($2) }}
471
-
472
- token_definition ->
473
- K_TAG _ L_COLON _ string_list : {{ { tag: $4 } }}
474
- | K_WHEN _ L_COLON _ T_STRING : {{ { when: $4 } }}
475
- | K_WHEN _ L_COLON _ T_REGEX : {{ { when: $4 } }}
476
- | K_POP : {{ { pop: 1 } }}
477
- | K_POP _ L_COLON _ T_INTEGER : {{ { pop: parseInt($4) } }}
478
- | K_POP _ L_COLON _ K_ALL : {{ { pop: "all" } }}
479
- | K_HIGHLIGHT _ L_COLON _ T_STRING : {{ { highlight: $4 } }}
480
- | K_INSET : {{ { inset: 1 } }}
481
- | K_INSET _ L_COLON _ T_INTEGER : {{ { inset: parseInt($4) } }}
482
- | K_SET _ L_COLON _ T_WORD : {{ { set: $4 } }}
483
- | K_GOTO _ L_COLON _ T_WORD : {{ { goto: $4 } }}
484
- | K_TYPE _ L_COLON _ T_STRING : {{ { type: $4 } }}
485
-
486
- grammar ->
487
- kv_list _ grammar_rule_list : {{ { config: Object.assign(...$0), rules: $2 } }}
488
- | grammar_rule_list : {{ { rules: $0 } }}
489
-
490
- grammar_rule_list ->
491
- grammar_rule : {{ [$0] }}
492
- | grammar_rule _ grammar_rule_list : {{ [$0].concat($2) }}
493
-
494
- grammar_rule ->
495
- T_WORD _ L_ARROW _ expression_list : {{ { name: $0, expressions: $4 } }}
496
- | T_WORD __ L_COLON _ T_JS:js _ L_ARROW _ expression_list:expressions : {{ { name: $0, expressions: $expressions, postprocess: $js } }}
497
- | T_WORD __ L_COLON _ T_GRAMMAR_TEMPLATE:template _ L_ARROW _ expression_list:expressions : {{ { name: $0, expressions: $expressions, postprocess: $template } }}
498
-
499
- expression_list ->
500
- expression
501
- | expression_list _ L_PIPE _ expression : {{ $0.concat([$4]) }}
502
-
503
- expression ->
504
- expression_symbol_list : {{ { symbols: $0 } }}
505
- | expression_symbol_list __ L_COLON _ T_JS:js : {{ { symbols: $0, postprocess: $js } }}
506
- | expression_symbol_list __ L_COLON _ T_GRAMMAR_TEMPLATE:template : {{ { symbols: $0, postprocess: $template } }}
507
-
508
- expression_symbol_list ->
509
- expression_symbol
510
- | expression_symbol_list T_WS expression_symbol : {{ $0.concat([$2]) }}
511
-
512
-
513
- expression_symbol ->
514
- expression_symbol_match : {{ $0 }}
515
- | expression_symbol_match L_COLON T_WORD : {{ { ...$0, alias: $2 } }}
516
- | expression_symbol_match expression_repeater : {{ { expression: $0, repeat: $1 } }}
517
- | expression_symbol_match expression_repeater L_COLON T_WORD : {{ { expression: $0, repeat: $1, alias: $4 } }}
518
-
519
-
520
- expression_symbol_match ->
521
- T_WORD : {{ { rule: $0 } }}
522
- | T_STRING "i"? : {{ { literal: $0, insensitive: !!$1 } }}
523
- | L_DSIGN T_WORD : {{ { token: $1} }}
524
- | L_DSIGN T_STRING : {{ { token: $1} }}
525
- | T_REGEX : {{ $0 }}
526
- | L_PARENL _ expression_list _ L_PARENR : {{ { subexpression: $2 } }}
527
- | T_JS : {{ $0 }}
528
-
529
- expression_repeater : {{ $0[0].value }} ->
530
- L_QMARK
531
- | L_PLUS
532
- | L_STAR
533
-
534
- kv_list ->
535
- kv : {{ data }}
536
- | kv _ kv_list : {{ [$0].concat($2) }}
537
-
538
- kv ->
539
- T_WORD _ L_COLON _ ( T_WORD| T_STRING| T_INTEGER | T_JS | T_GRAMMAR_TEMPLATE) : {{ { [$0]: $4[0] } }}
540
-
541
- string_list ->
542
- T_STRING : {{ [$0] }}
543
- | T_STRING _ L_COMMA _ string_list : {{ [$0].concat($4) }}
544
-
545
- word_list ->
546
- T_WORD : {{ [$0] }}
547
- | T_WORD _ L_COMMA _ word_list : {{ [$0].concat($4) }}
548
-
549
- _ ->
550
- ( T_WS | T_COMMENT )* : {{ null }}
551
-
552
- __ ->
553
- ( T_WS | T_COMMENT )+ : {{ null }}
554
-
555
- L_COLON -> $L_COLON
556
- L_SCOLON -> $L_SCOLON
557
- L_QMARK -> $L_QMARK
558
- L_PLUS -> $L_PLUS
559
- L_STAR -> $L_STAR
560
- L_COMMA -> $L_COMMA
561
- L_PIPE -> $L_PIPE
562
- L_PARENL -> $L_PARENL
563
- L_PARENR -> $L_PARENR
564
- L_TEMPLATEL -> $L_TEMPLATEL
565
- L_TEMPLATER -> $L_TEMPLATER
566
- L_ARROW -> $L_ARROW
567
- L_DSIGN -> $L_DSIGN
568
- L_DASH -> $L_DASH
569
-
570
- K_ALL -> "all"
571
- K_TAG -> "tag"
572
- K_FROM -> "from"
573
- K_TYPE -> "type"
574
- K_WHEN -> "when"
575
- K_POP -> "pop"
576
- K_HIGHLIGHT -> "highlight"
577
- K_INSET -> "inset"
578
- K_SET -> "set"
579
- K_GOTO -> "goto"
580
- K_CONFIG -> "config"
581
- K_LEXER -> "lexer"
582
- K_GRAMMAR -> "grammar"
583
- K_IMPORT -> "import"
584
- K_BODY -> "body"
585
- K_HEAD -> "head"
586
-
587
- T_JS -> $L_JSL $T_JSBODY* $L_JSR : {{ { js: $1.map(v=>v.value).join('') } }}
588
- T_GRAMMAR_TEMPLATE -> $L_TEMPLATEL _ $T_JSBODY* _ $L_TEMPLATER : {{ { template: $2.map(v=>v.value).join('').trim() } }}
589
- T_STRING -> $T_STRING : {{ JSON.parse($0.value) }}
590
- T_WORD -> $T_WORD : {{ $0.value }}
591
- T_REGEX -> $T_REGEX /[gmiuy]/* : {{ { regex: $0.value.replace(/\\\\\//g,'/').slice(1,-1), flags: $1.map(v=>v.value).join('').trim() } }}
592
- T_COMMENT -> $T_COMMENT
593
- T_INTEGER -> $T_INTEGER : {{ $0.value }}
594
- T_WS -> $T_WS : {{ null }}
595
- }}
95
+ for (let i in data[3]) {
96
+ output.push(data[3][i][3]);
97
+ }
596
98
 
99
+ return output;
100
+ }
101
+ }`
102
+
103
+ const javascriptsource = await Generate(source, {
104
+ output: {
105
+ name: 'grammar',
106
+ format: 'typescript',
107
+ artifacts: {
108
+ lexer: true,
109
+ grammar: true
110
+ }
111
+ }
112
+ });
597
113
  ```
@@ -0,0 +1,7 @@
1
+ import { JavaScriptGenerator } from "../stringify/javascript.js";
2
+ export declare class BasicGrammarTable {
3
+ private generator;
4
+ constructor(generator: JavaScriptGenerator);
5
+ stringify(depth?: number): string;
6
+ private stringifyGrammarRules;
7
+ }