@bablr/language-en-json 0.4.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.
@@ -0,0 +1,209 @@
1
+ import { i } from '@bablr/boot/shorthand.macro';
2
+ import { triviaEnhancer } from '@bablr/helpers/trivia';
3
+ import * as productions from '@bablr/helpers/productions';
4
+ import { buildString, buildBoolean } from '@bablr/agast-vm-helpers';
5
+ import { Node, CoveredBy, AllowEmpty, InjectFrom, Attributes } from '@bablr/helpers/decorators';
6
+ import * as Space from '@bablr/language-en-blank-space';
7
+
8
+ export const dependencies = { Space };
9
+
10
+ export const canonicalURL = 'https://github.com/bablr-lang/language-en-json';
11
+
12
+ export const escapables = new Map(
13
+ Object.entries({
14
+ b: '\b',
15
+ f: '\f',
16
+ n: '\n',
17
+ r: '\r',
18
+ t: '\t',
19
+ '\\': '\\',
20
+ '/': '/',
21
+ }),
22
+ );
23
+
24
+ export const grammar = triviaEnhancer(
25
+ {
26
+ triviaIsAllowed: (s) => s.span === 'Bare',
27
+ *eatMatchTrivia() {
28
+ if (yield i`match(/[ \n\r\t]/)`) {
29
+ yield i`eat(<#*Space:Space>)`;
30
+ }
31
+ },
32
+ },
33
+ class JSONGrammar {
34
+ *[Symbol.for('@bablr/fragment')]() {
35
+ yield i`eat(<> 'root')`;
36
+ }
37
+
38
+ @CoveredBy('Element')
39
+ *Expression() {
40
+ yield i`eat(<Any> null [
41
+ <Array '['>
42
+ <Object '{'>
43
+ <String '"'>
44
+ <Number /-?\d/ span='Number'>
45
+ <Null 'null'>
46
+ <Boolean /true|false/>
47
+ ])`;
48
+ }
49
+
50
+ @CoveredBy('Expression')
51
+ @Node
52
+ *Array() {
53
+ yield i`eat(<~*Punctuator '[' balanced=']'> 'openToken')`;
54
+ yield i`eat(<List> 'elements[]' {
55
+ element: <Expression>
56
+ separator: <~*Punctuator ','>
57
+ allowTrailingSeparator: false
58
+ })`;
59
+ yield i`eat(<~*Punctuator ']' balancer> 'closeToken')`;
60
+ }
61
+
62
+ @CoveredBy('Expression')
63
+ @Node
64
+ *Object() {
65
+ yield i`eat(<~*Punctuator '{' balanced='}'> 'openToken')`;
66
+ yield i`eat(<List> 'properties[]' {
67
+ element: <Property>
68
+ separator: <~*Punctuator ','>
69
+ allowTrailingSeparator: false
70
+ })`;
71
+ yield i`eat(<~*Punctuator '}' balancer> 'closeToken')`;
72
+ }
73
+
74
+ @Node
75
+ *Property() {
76
+ yield i`eat(<String> 'key')`;
77
+ yield i`eat(<~*Punctuator ':'> 'sigilToken')`;
78
+ yield i`eat(<Expression> 'value')`;
79
+ }
80
+
81
+ @CoveredBy('Language')
82
+ @Node
83
+ *String() {
84
+ yield i`eat(<~*Punctuator '"' balanced='"' balancedSpan='String'> 'openToken')`;
85
+ yield i`eat(<*StringContent> 'content')`;
86
+ yield i`eat(<~*Punctuator '"' balancer> 'closeToken')`;
87
+ }
88
+
89
+ @AllowEmpty
90
+ @Node
91
+ *StringContent() {
92
+ let esc, lit;
93
+ do {
94
+ esc = (yield i`match('\\')`) && (yield i`eat(<@EscapeSequence>)`);
95
+ lit = yield i`eatMatch(/[^\r\n\\"]+/)`;
96
+ } while (esc || lit);
97
+ }
98
+
99
+ @Attributes(['cooked'])
100
+ @Node
101
+ *EscapeSequence({ state: { span }, ctx }) {
102
+ if (!span.startsWith('String')) {
103
+ yield i`fail()`;
104
+ }
105
+
106
+ yield i`eat(<~*Punctuator '\\'> 'sigilToken')`;
107
+
108
+ let match, cooked;
109
+
110
+ if ((match = yield i`match(/[\\/bfnrt"]/)`)) {
111
+ const match_ = ctx.sourceTextFor(match);
112
+ yield i`eat(<~*Keyword ${buildString(match_)}> 'value')`;
113
+ cooked = escapables.get(match_) || match_;
114
+ } else if (yield i`match('u')`) {
115
+ const codeNode = yield i`eat(<EscapeCode> 'value')`;
116
+ cooked = parseInt(
117
+ ctx
118
+ .getProperty(codeNode, 'digits')
119
+ .map((digit) => ctx.sourceTextFor(digit))
120
+ .join(''),
121
+ 16,
122
+ );
123
+ } else {
124
+ yield i`fail()`;
125
+ }
126
+
127
+ yield i`bindAttribute(cooked ${buildString(cooked.toString(10))})`;
128
+ }
129
+
130
+ @Node
131
+ *EscapeCode() {
132
+ yield i`eat(<~*Keyword 'u'> 'typeToken')`;
133
+ yield i`eat(<Digits> 'digits[]')`;
134
+ }
135
+
136
+ @CoveredBy('Expression')
137
+ @Node
138
+ *Number() {
139
+ yield i`eat(<Integer> 'wholePart' { noDoubleZero: true matchSign: '-' })`;
140
+
141
+ let fs = yield i`eatMatch(<~*Punctuator '.'> 'fractionalSeparatorToken')`;
142
+
143
+ if (fs) {
144
+ yield i`eat(<Integer> 'fractionalPart')`;
145
+ } else {
146
+ yield i`eat(null 'fractionalPart')`;
147
+ }
148
+
149
+ let es = yield i`eatMatch(<~*Punctuator /[eE]/> 'exponentSeparatorToken')`;
150
+
151
+ if (es) {
152
+ yield i`eat(<Integer> 'exponentPart' { matchSign: /[+-]/ })`;
153
+ } else {
154
+ yield i`eat(null 'exponentPart')`;
155
+ }
156
+ }
157
+
158
+ @Node
159
+ *Integer({ value: props, ctx }) {
160
+ const { matchSign = null, noDoubleZero = false } = (props && ctx.unbox(props)) || {};
161
+
162
+ if (matchSign) {
163
+ yield i`eatMatch(<~*Punctuator ${matchSign}> 'signToken')`;
164
+ } else {
165
+ yield i`eat(null 'signToken')`;
166
+ }
167
+
168
+ yield i`eat(<*UnsignedInteger noDoubleZero=${buildBoolean(noDoubleZero)}> 'value')`;
169
+ }
170
+
171
+ @Node
172
+ *UnsignedInteger({ value: props, ctx }) {
173
+ const { noDoubleZero = false } = (props && ctx.unbox(props)) || {};
174
+
175
+ let [firstDigit] = ctx.ownTerminalsFor(yield i`eat(/\d/)`);
176
+
177
+ if (!noDoubleZero || firstDigit.value !== '0') {
178
+ yield i`eatMatch(/\d+/)`;
179
+ }
180
+ }
181
+
182
+ @CoveredBy('Expression')
183
+ @Node
184
+ *Boolean() {
185
+ yield i`eat(<~*Keyword /true|false/> 'sigilToken')`;
186
+ }
187
+
188
+ @CoveredBy('Expression')
189
+ @Node
190
+ *Null() {
191
+ yield i`eat(<~*Keyword 'null'> 'sigilToken')`;
192
+ }
193
+
194
+ @Node
195
+ @InjectFrom(productions)
196
+ *Keyword() {}
197
+
198
+ @Node
199
+ @InjectFrom(productions)
200
+ *Punctuator() {}
201
+
202
+ @AllowEmpty
203
+ @InjectFrom(productions)
204
+ *List() {}
205
+
206
+ @InjectFrom(productions)
207
+ *Any() {}
208
+ },
209
+ );
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@bablr/language-en-json",
3
+ "version": "0.4.0",
4
+ "description": "A BABLR language for JSON",
5
+ "engines": {
6
+ "node": ">=12.0.0"
7
+ },
8
+ "type": "module",
9
+ "exports": {
10
+ ".": "./lib/grammar.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "files": [
14
+ "lib/**/*.js"
15
+ ],
16
+ "scripts": {
17
+ "build": "macrome build",
18
+ "watch": "macrome watch",
19
+ "clean": "macrome clean",
20
+ "test": "mocha"
21
+ },
22
+ "sideEffects": false,
23
+ "dependencies": {
24
+ "@bablr/agast-vm-helpers": "0.2.0",
25
+ "@bablr/boot": "0.3.0",
26
+ "@bablr/helpers": "0.17.0",
27
+ "@bablr/language-en-blank-space": "0.2.0",
28
+ "@babel/runtime": "^7.22.15"
29
+ },
30
+ "devDependencies": {
31
+ "@bablr/agast-helpers": "0.2.0",
32
+ "@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#49f5952efed27f94ee9b94340eb1563c440bf64e",
33
+ "@bablr/macrome": "0.1.3",
34
+ "@bablr/macrome-generator-bablr": "0.3.1",
35
+ "@qnighy/dedent": "0.1.1",
36
+ "bablr": "0.3.0",
37
+ "enhanced-resolve": "^5.12.0",
38
+ "eslint": "^7.32.0",
39
+ "eslint-import-resolver-enhanced-resolve": "^1.0.5",
40
+ "eslint-plugin-import": "^2.27.5",
41
+ "expect": "29.7.0",
42
+ "iter-tools-es": "^7.5.3",
43
+ "mocha": "10.4.0",
44
+ "prettier": "^2.0.5"
45
+ },
46
+ "keywords": [
47
+ "bablr-language",
48
+ "grammar",
49
+ "english",
50
+ "json"
51
+ ],
52
+ "repository": "git@github.com:bablr-lang/language-en-json.git",
53
+ "homepage": "https://github.com/bablr-lang/language-en-json",
54
+ "author": "Conrad Buck <conartist6@gmail.com>",
55
+ "license": "MIT"
56
+ }