rip-lang 3.0.1 → 3.0.2
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.
- package/docs/dist/rip.browser.js +30 -5
- package/docs/dist/rip.browser.min.js +120 -120
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/package.json +1 -1
- package/src/grammar/grammar.rip +1 -1
- package/src/grammar/solar.rip +1 -1
- package/src/lexer.js +24 -6
|
Binary file
|
package/package.json
CHANGED
package/src/grammar/grammar.rip
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Each rule maps a pattern of tokens/types to an s-expression action.
|
|
7
7
|
#
|
|
8
8
|
# Action format:
|
|
9
|
-
# - Numbers (1, 2, 3
|
|
9
|
+
# - Numbers (1, 2, ...3) reference matched symbols by position
|
|
10
10
|
# - ...N spreads the array at position N
|
|
11
11
|
# - String literals become s-expression nodes: '["if", 2, 3]'
|
|
12
12
|
# - Default action (no action given) returns position 1
|
package/src/grammar/solar.rip
CHANGED
|
@@ -53,7 +53,7 @@ class Item
|
|
|
53
53
|
|
|
54
54
|
# LR State: A set of items with transitions to other states
|
|
55
55
|
class State
|
|
56
|
-
constructor: (items
|
|
56
|
+
constructor: (...items) ->
|
|
57
57
|
@id = null # state number (assigned later)
|
|
58
58
|
@items = new Set(items) # kernel and closure items
|
|
59
59
|
@transitions = new Map # symbol → next state
|
package/src/lexer.js
CHANGED
|
@@ -1076,6 +1076,8 @@ export class Lexer {
|
|
|
1076
1076
|
else if (SHIFT.has(val)) tag = 'SHIFT';
|
|
1077
1077
|
// Spaced ? → SPACE? (ternary)
|
|
1078
1078
|
else if (val === '?' && prev?.spaced) tag = 'SPACE?';
|
|
1079
|
+
// ?[ and ?( without dot → treat as optional chaining (?.)
|
|
1080
|
+
else if (val === '?' && (this.chunk[1] === '[' || this.chunk[1] === '(')) tag = '?.';
|
|
1079
1081
|
// Call/index context (ES6 optional chaining only)
|
|
1080
1082
|
else if (prev) {
|
|
1081
1083
|
if (val === '(' && !prev.spaced && CALLABLE.has(prev[0])) {
|
|
@@ -1190,15 +1192,11 @@ export class Lexer {
|
|
|
1190
1192
|
let starter = null;
|
|
1191
1193
|
let indent = null;
|
|
1192
1194
|
let outdent = null;
|
|
1193
|
-
let bodyStart = null;
|
|
1194
|
-
|
|
1195
1195
|
let condition = (token, i) => {
|
|
1196
1196
|
return token[1] !== ';' && SINGLE_CLOSERS.has(token[0]) &&
|
|
1197
1197
|
!(token[0] === 'TERMINATOR' && EXPRESSION_CLOSE.has(this.tokens[i + 1]?.[0])) &&
|
|
1198
1198
|
!(token[0] === 'ELSE' && starter !== 'THEN') ||
|
|
1199
|
-
token[0] === ',' && (starter === '->' || starter === '=>') &&
|
|
1200
|
-
!(bodyStart != null && IMPLICIT_FUNC.has(this.tokens[bodyStart]?.[0]) && this.tokens[bodyStart]?.spaced &&
|
|
1201
|
-
(IMPLICIT_CALL.has(this.tokens[bodyStart + 1]?.[0]) || (this.tokens[bodyStart + 1]?.[0] === '...' && IMPLICIT_CALL.has(this.tokens[bodyStart + 2]?.[0])))) ||
|
|
1199
|
+
token[0] === ',' && (starter === '->' || starter === '=>') && !this.commaInImplicitCall(i) ||
|
|
1202
1200
|
CALL_CLOSERS.has(token[0]) && (this.tokens[i - 1]?.newLine || this.tokens[i - 1]?.[0] === 'OUTDENT');
|
|
1203
1201
|
};
|
|
1204
1202
|
|
|
@@ -1240,7 +1238,6 @@ export class Lexer {
|
|
|
1240
1238
|
if (SINGLE_LINERS.has(tag) && this.tokens[i + 1]?.[0] !== 'INDENT' &&
|
|
1241
1239
|
!(tag === 'ELSE' && this.tokens[i + 1]?.[0] === 'IF')) {
|
|
1242
1240
|
starter = tag;
|
|
1243
|
-
bodyStart = i + 2;
|
|
1244
1241
|
[indent, outdent] = this.makeIndentation();
|
|
1245
1242
|
if (tag === 'THEN') indent.fromThen = true;
|
|
1246
1243
|
tokens.splice(i + 1, 0, indent);
|
|
@@ -1501,6 +1498,27 @@ export class Lexer {
|
|
|
1501
1498
|
}
|
|
1502
1499
|
}
|
|
1503
1500
|
|
|
1501
|
+
// Scan backward from comma to see if it's inside an implicit function call
|
|
1502
|
+
commaInImplicitCall(i) {
|
|
1503
|
+
let levels = 0;
|
|
1504
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
1505
|
+
let tag = this.tokens[j][0];
|
|
1506
|
+
if (EXPRESSION_END.has(tag)) { levels++; continue; }
|
|
1507
|
+
if (EXPRESSION_START.has(tag)) {
|
|
1508
|
+
if (tag === 'INDENT') return false;
|
|
1509
|
+
levels--;
|
|
1510
|
+
if (levels < 0) return false;
|
|
1511
|
+
continue;
|
|
1512
|
+
}
|
|
1513
|
+
if (levels > 0) continue;
|
|
1514
|
+
if (IMPLICIT_FUNC.has(tag) && this.tokens[j].spaced) {
|
|
1515
|
+
let nt = this.tokens[j + 1]?.[0];
|
|
1516
|
+
return IMPLICIT_CALL.has(nt) || (nt === '...' && IMPLICIT_CALL.has(this.tokens[j + 2]?.[0]));
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1504
1522
|
looksObjectish(j) {
|
|
1505
1523
|
if (!this.tokens[j]) return false;
|
|
1506
1524
|
if (this.tokens[j]?.[0] === '@' && this.tokens[j + 2]?.[0] === ':') return true;
|