diff --git a/src/riscript.js b/src/riscript.js index f13d752..a6aa27c 100644 --- a/src/riscript.js +++ b/src/riscript.js @@ -563,7 +563,7 @@ class RiScript { EndingBreak: /\r?\n$/, NonGateAtSigns: /([^}])@(?!{)/, AnySymbol: new RegExp(`[${anysym}]`), - ParenthesizedWeights: /\(\s*(\d+)\s*\)/g, // TODO: change for negative weights + ParenthesizedWeights: /\(\s*(-?\d+)\s*\)/g, MultiLineComments: /\/\*[^]*?(\r?\n)?\//g, SingleLineComments: /\/\/[^\n]+(\r?\n|$)/g, MarkdownLinks: /\[([^\]]+)\]\(([^)"]+)(?: \"([^\"]+)\")?\)/g, diff --git a/src/tokens.js b/src/tokens.js index 94cb659..deb1262 100644 --- a/src/tokens.js +++ b/src/tokens.js @@ -58,7 +58,7 @@ function getTokens(v2Compatible) { const Symbol = createToken({ name: "Symbol", pattern: new RegExp(`(${Escaped.DYNAMIC}|${Escaped.STATIC}[A-Za-z_0-9])[A-Za-z_0-9]*(\\(\\))?`) }); const Transform = createToken({ name: "Transform", pattern: /\.[A-Za-z_0-9][A-Za-z_0-9]*(\(\))?/ }); const Entity = createToken({ name: "Entity", pattern: ENTITY_PATTERN }); - const Weight = createToken({ name: "Weight", pattern: new RegExp(`\\s*${Escaped.OPEN_WEIGHT}\\d+${Escaped.CLOSE_WEIGHT}\\s*`) }); // TODO: change for negative weights + const Weight = createToken({ name: "Weight", pattern: new RegExp(`\\s*${Escaped.OPEN_WEIGHT}-?\\d+${Escaped.CLOSE_WEIGHT}\\s*`) }); const PendingGate = createToken({ name: "PendingGate", pattern: PENDING_GATE_PATTERN }); const Raw = createToken({ name: "Raw", pattern: new RegExp(`[^${Escaped.SPECIAL}]+`) }); @@ -100,13 +100,13 @@ function bracketMatch(text, startOffset) { charCode = text.charCodeAt(endOffset); } - // No match, must return null xsto conform with the RegExp.prototype.exec signature + // No match, must return null to conform with the RegExp.prototype.exec if (endOffset === startOffset) { if (dbug) console.log(`"${text.substring(startOffset, endOffset)}" -> null3`); return null; } else { let matchedString = text.substring(startOffset, endOffset); - // according to the RegExp.prototype.exec API the first item in the returned array must be the whole matched string. + // according to RegExp.prototype.exec API first item in the returned array must be the whole matched string if (dbug) console.log(' returned -> ', [matchedString]); return [matchedString]; } diff --git a/test/dist/riscript.tests.js b/test/dist/riscript.tests.js index 2144325..58756a4 100644 --- a/test/dist/riscript.tests.js +++ b/test/dist/riscript.tests.js @@ -393,17 +393,17 @@ describe(title, function() { expect(/(man|boy):(man|boy)/.test(res)).true; }); it("Repeat choices with randomSeed", function() { - if (!("randomSeed" in riscript.RiTa)) - return; - const seed = Math.random() * Number.MAX_SAFE_INTEGER; - const script = "$a=[1|2|3|4|5|6]\n$a"; - riscript.RiTa.randomSeed(seed); - let b; - const a = riscript.evaluate(script); - for (let i = 0; i < 5; i++) { + if ("randomSeed" in riscript.RiTa) { + const seed = Math.random() * Number.MAX_SAFE_INTEGER; + const script = "$a=[1|2|3|4|5|6]\n$a"; riscript.RiTa.randomSeed(seed); - b = riscript.evaluate(script); - expect(a).eq(b); + let b; + const a = riscript.evaluate(script); + for (let i = 0; i < 5; i++) { + riscript.RiTa.randomSeed(seed); + b = riscript.evaluate(script); + expect(a).eq(b); + } } }); it("Selects non-weighted choices evenly", function() { diff --git a/test/riscript.tests.js b/test/riscript.tests.js index 17c74a2..6a7a61c 100644 --- a/test/riscript.tests.js +++ b/test/riscript.tests.js @@ -328,7 +328,7 @@ describe(title, function () { it('Handles boolean gate logic', function () { // reject if no valid conditions expect(riscript.evaluate('$a=2\n[ @{$a: {}} hello]')).eq(''); - + // simple AND expect(riscript.evaluate('$a=2\n[ @{$a: {@gt: 3}} hello]')).eq(''); expect(riscript.evaluate('$a=4\n[ @{$a: {@gt: 3}} hello]')).eq('hello'); @@ -375,7 +375,7 @@ describe(title, function () { }); it('Extract operands from gate with object operands', function () { - const obj = { $a: 3, '@or': [{ $b: {'@lt': 30 } }, { $c: /^p*/ }] }; + const obj = { $a: 3, '@or': [{ $b: { '@lt': 30 } }, { $c: /^p*/ }] }; const query = new RiScript.Query(riscript, obj); const operands = query.operands(riscript, obj); expect(operands).eql(['a', 'c', 'b']); @@ -389,8 +389,8 @@ describe(title, function () { }); it('Calls test on RiQuery', function () { - const obj = { $a: 3, '@or': [{ $b: {'@lt': 30 } }, { $c: /^p*/ }] }; - const query = new RiScript.Query(riscript, obj); + const obj = { $a: 3, '@or': [{ $b: { '@lt': 30 } }, { $c: /^p*/ }] }; + const query = new RiScript.Query(riscript, obj); const res = query.test({ a: 3, b: 10 }); expect(res).true; }); @@ -519,17 +519,18 @@ describe(title, function () { }); it('Repeat choices with randomSeed', function () { - if (!('randomSeed' in riscript.RiTa)) return; - const seed = Math.random() * Number.MAX_SAFE_INTEGER; - const script = '$a=[1|2|3|4|5|6]\n$a'; - riscript.RiTa.randomSeed(seed); // TODO: How to handle with no RiTa ? - let b; - const a = riscript.evaluate(script); - for (let i = 0; i < 5; i++) { + if ('randomSeed' in riscript.RiTa) { + const seed = Math.random() * Number.MAX_SAFE_INTEGER; + const script = '$a=[1|2|3|4|5|6]\n$a'; riscript.RiTa.randomSeed(seed); // TODO: How to handle with no RiTa ? - b = riscript.evaluate(script); - // console.log(i + ') ', a, b); - expect(a).eq(b); + let b; + const a = riscript.evaluate(script); + for (let i = 0; i < 5; i++) { + riscript.RiTa.randomSeed(seed); // TODO: How to handle with no RiTa ? + b = riscript.evaluate(script); + // console.log(i + ') ', a, b); + expect(a).eq(b); + } } }); @@ -1175,7 +1176,8 @@ describe(title, function () { expect(riscript.evaluate('$.uppercase()')).eq(''); expect(riscript.evaluate('$.capB()', ctx)).eq('B'); expect(riscript.evaluate('$.uppercase', 0)).eq(''); - expect(riscript.evaluate('[].capB', ctx)).eq('B'); }); + expect(riscript.evaluate('[].capB', ctx)).eq('B'); + }); it('Resolves transforms containing riscript', function () { let ctx;