Skip to content

Commit b153e7b

Browse files
committed
support dynamic token values
1 parent 7d6c56c commit b153e7b

11 files changed

+70
-15
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ test/coverage.html
2626
coverage
2727

2828
package-lock.json
29+
yarn.lock

grammar.js

+3-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

grammar.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

grammar.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,16 @@ function grammar(jsonic: Jsonic) {
108108
{ b: 1, g: 'val,json,more' },
109109
])
110110

111-
.bc((rule: Rule) => {
111+
.bc((rule: Rule, ctx: Context) => {
112112
// console.log('VAL BC A', rule.node, rule.o0.val, rule.os, rule.child.node)
113113

114114
// NOTE: val can be undefined when there is no value at all
115115
// (eg. empty string, thus no matched opening token)
116116
rule.node =
117117
undefined === rule.node ?
118118
undefined === rule.child.node ?
119-
(0 === rule.os ? undefined : rule.o0.val) :
119+
// (0 === rule.os ? undefined : rule.o0.val) :
120+
(0 === rule.os ? undefined : rule.o0.resolveVal(rule, ctx)) :
120121
rule.child.node :
121122
rule.node
122123

lexer.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ declare class TokenImpl implements Token {
2626
err?: string;
2727
why?: string;
2828
constructor(name: string, tin: Tin, val: any, src: string, pnt: Point, use?: any, why?: string);
29+
resolveVal(rule: Rule, ctx: Context): any;
2930
bad(err: string, details?: any): Token;
3031
toString(): string;
3132
[INSPECT](): string;

lexer.js

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lexer.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lexer.ts

+9
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ class TokenImpl implements Token {
114114
this.len = null == src ? 0 : src.length
115115
}
116116

117+
118+
resolveVal(rule: Rule, ctx: Context): any {
119+
let out = 'function' === typeof this.val ?
120+
(this.val as any)(rule, ctx) :
121+
this.val
122+
return out
123+
}
124+
125+
117126
bad(err: string, details?: any): Token {
118127
this.err = err
119128
if (null != details) {

test/custom.test.js

+36-1
Original file line numberDiff line numberDiff line change
@@ -302,18 +302,53 @@ describe('custom', function () {
302302

303303

304304
it('parser-value', () => {
305-
let b = ''
305+
function Car() {this.m = true}
306+
let c0 = new Car()
307+
expect(c0 instanceof Car).toEqual(true)
308+
309+
let o0 = {x:1}
310+
let f1 = ()=>'F1'
311+
306312
let j = Jsonic.make({
307313
value: {
308314
map: {
309315
foo: {val:'FOO'},
310316
bar: {val:'BAR'},
317+
zed: {val:123},
318+
qaz: {val:false},
319+
obj: {val:o0},
320+
321+
// This won't work - cloning removes constructor
322+
car: {val:c0},
323+
324+
// Functions build values dynamically, or prevent cloning
325+
fun: {val:()=>'f0'},
326+
high: {val:()=>f1},
327+
ferry: {val:()=>new Car()},
311328
}
312329
}
313330
})
314331

315332
expect(j('foo')).toEqual('FOO')
316333
expect(j('bar')).toEqual('BAR')
334+
expect(j('zed')).toEqual(123)
335+
expect(j('qaz')).toEqual(false)
336+
337+
// Options get copied, so `obj` should remain {x:1}
338+
o0.x = 2
339+
expect(j('obj')).toEqual({x:1})
340+
341+
// Instance properties are copied, but not constructor
342+
expect(j('car')).toEqual({m:true})
343+
expect(j('car') instanceof Car ).toEqual(false)
344+
345+
expect(j('fun')).toEqual('f0')
346+
expect(j('high')).toEqual(f1)
347+
348+
// constructor is protected
349+
expect(j('ferry')).toEqual({m:true})
350+
expect(j('ferry') instanceof Car).toEqual(true)
351+
317352
})
318353

319354

types.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ export interface Token {
340340
err?: string;
341341
why?: string;
342342
bad(err: string, details?: any): Token;
343+
resolveVal(rule: Rule, ctx: Context): any;
343344
}
344345
export interface AltSpec {
345346
s?: (Tin | Tin[] | null | undefined)[] | null;

types.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,12 @@ export interface Rule {
227227
parent: Rule // The parent rule, that pushed this rule onto the stack.
228228
prev: Rule // The previous sibling rule, that issued an `r` command.
229229

230-
// open: Token[] // The tokens than matched in the open state.
231-
// close: Token[] // The tokens than matched in the close state.
232-
os: number
233-
o0: Token
234-
o1: Token
235-
cs: number
236-
c0: Token
237-
c1: Token
230+
os: number // Number of open state tokens (# 'opens').
231+
o0: Token // First open state token.
232+
o1: Token // Second open state token.
233+
cs: number // Number of close state tokens (# 'closes').
234+
c0: Token // First close state token.
235+
c1: Token // Second close state token.
238236

239237
n: Counters // Named counter values.
240238
d: number // The current stack depth.
@@ -457,6 +455,8 @@ export interface Token {
457455

458456
// Convert into an error Token.
459457
bad(err: string, details?: any): Token
458+
459+
resolveVal(rule: Rule, ctx: Context): any
460460
}
461461

462462

0 commit comments

Comments
 (0)