bobe 0.0.36 → 0.0.37
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/dist/bobe.cjs.js +47 -31
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.compiler.cjs.js +47 -31
- package/dist/bobe.compiler.cjs.js.map +1 -1
- package/dist/bobe.compiler.esm.js +47 -31
- package/dist/bobe.compiler.esm.js.map +1 -1
- package/dist/bobe.esm.js +47 -31
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +19 -4
- package/dist/index.umd.js +47 -31
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/bobe.esm.js
CHANGED
|
@@ -42,6 +42,23 @@ let NodeSort = function (NodeSort) {
|
|
|
42
42
|
TerpEvt["HandledComponentNode"] = "handled-component-node";
|
|
43
43
|
return TerpEvt;
|
|
44
44
|
})({});
|
|
45
|
+
let ParseErrorCode = function (ParseErrorCode) {
|
|
46
|
+
ParseErrorCode[ParseErrorCode["UNCLOSED_BRACE"] = 9001] = "UNCLOSED_BRACE";
|
|
47
|
+
ParseErrorCode[ParseErrorCode["UNCLOSED_STRING"] = 9002] = "UNCLOSED_STRING";
|
|
48
|
+
ParseErrorCode[ParseErrorCode["UNCLOSED_STATIC_INS"] = 9003] = "UNCLOSED_STATIC_INS";
|
|
49
|
+
ParseErrorCode[ParseErrorCode["INCONSISTENT_INDENT"] = 9004] = "INCONSISTENT_INDENT";
|
|
50
|
+
ParseErrorCode[ParseErrorCode["INDENT_MISMATCH"] = 9005] = "INDENT_MISMATCH";
|
|
51
|
+
ParseErrorCode[ParseErrorCode["MISSING_ASSIGN"] = 9006] = "MISSING_ASSIGN";
|
|
52
|
+
ParseErrorCode[ParseErrorCode["INVALID_TAG_NAME"] = 9007] = "INVALID_TAG_NAME";
|
|
53
|
+
ParseErrorCode[ParseErrorCode["ELSE_WITHOUT_IF"] = 9008] = "ELSE_WITHOUT_IF";
|
|
54
|
+
ParseErrorCode[ParseErrorCode["EMPTY_IF_BODY"] = 9009] = "EMPTY_IF_BODY";
|
|
55
|
+
ParseErrorCode[ParseErrorCode["EMPTY_FOR_BODY"] = 9010] = "EMPTY_FOR_BODY";
|
|
56
|
+
ParseErrorCode[ParseErrorCode["MISSING_FOR_COLLECTION"] = 9011] = "MISSING_FOR_COLLECTION";
|
|
57
|
+
ParseErrorCode[ParseErrorCode["MISSING_FOR_SEMICOLON"] = 9012] = "MISSING_FOR_SEMICOLON";
|
|
58
|
+
ParseErrorCode[ParseErrorCode["MISSING_FOR_ITEM"] = 9013] = "MISSING_FOR_ITEM";
|
|
59
|
+
ParseErrorCode[ParseErrorCode["PIPE_IN_WRONG_CONTEXT"] = 9014] = "PIPE_IN_WRONG_CONTEXT";
|
|
60
|
+
return ParseErrorCode;
|
|
61
|
+
}({});
|
|
45
62
|
class ParseSyntaxError extends SyntaxError {
|
|
46
63
|
constructor(code, message, loc) {
|
|
47
64
|
super(message);
|
|
@@ -159,7 +176,7 @@ class Tokenizer {
|
|
|
159
176
|
const expLen = this.dentStack[i];
|
|
160
177
|
if (currLen === expLen) break;
|
|
161
178
|
if (currLen > expLen) {
|
|
162
|
-
throw
|
|
179
|
+
throw new ParseSyntaxError(ParseErrorCode.INCONSISTENT_INDENT, '缩进大小不统一', this.emptyLoc());
|
|
163
180
|
}
|
|
164
181
|
if (this.shorterThanBaseDentEof()) {
|
|
165
182
|
break;
|
|
@@ -350,7 +367,7 @@ class Tokenizer {
|
|
|
350
367
|
while (1) {
|
|
351
368
|
nextC = this.code[this.i + 1];
|
|
352
369
|
if (nextC === undefined) {
|
|
353
|
-
this.throwUnclosed(
|
|
370
|
+
this.throwUnclosed(ParseErrorCode.UNCLOSED_STATIC_INS, '未闭合的 "${...}"', startOffset, startLine, startCol);
|
|
354
371
|
}
|
|
355
372
|
value += nextC;
|
|
356
373
|
this.next();
|
|
@@ -379,7 +396,7 @@ class Tokenizer {
|
|
|
379
396
|
while (1) {
|
|
380
397
|
const char = this.code[this.i];
|
|
381
398
|
if (char === undefined) {
|
|
382
|
-
this.throwUnclosed(
|
|
399
|
+
this.throwUnclosed(ParseErrorCode.UNCLOSED_BRACE, '未闭合的 "{"', startOffset, startLine, startCol);
|
|
383
400
|
}
|
|
384
401
|
const nextChar = this.code[this.i + 1];
|
|
385
402
|
if (inComment === 'single' && char === '\n') {
|
|
@@ -468,6 +485,18 @@ class Tokenizer {
|
|
|
468
485
|
isEmptyLine
|
|
469
486
|
};
|
|
470
487
|
}
|
|
488
|
+
emptyLoc() {
|
|
489
|
+
const pos = this.getCurrentPos();
|
|
490
|
+
return {
|
|
491
|
+
start: pos,
|
|
492
|
+
end: {
|
|
493
|
+
offset: pos.offset + 1,
|
|
494
|
+
line: pos.line,
|
|
495
|
+
column: pos.column + 1
|
|
496
|
+
},
|
|
497
|
+
source: ' '
|
|
498
|
+
};
|
|
499
|
+
}
|
|
471
500
|
dent() {
|
|
472
501
|
const _this$getDentValue2 = this.getDentValue(),
|
|
473
502
|
value = _this$getDentValue2.value,
|
|
@@ -494,7 +523,7 @@ class Tokenizer {
|
|
|
494
523
|
const expLen = this.dentStack[i];
|
|
495
524
|
if (currLen === expLen) break;
|
|
496
525
|
if (currLen > expLen) {
|
|
497
|
-
throw
|
|
526
|
+
throw new ParseSyntaxError(ParseErrorCode.INCONSISTENT_INDENT, '缩进大小不统一', this.emptyLoc());
|
|
498
527
|
}
|
|
499
528
|
if (this.shorterThanBaseDentEof()) {
|
|
500
529
|
return;
|
|
@@ -572,7 +601,7 @@ class Tokenizer {
|
|
|
572
601
|
while (1) {
|
|
573
602
|
nextC = this.code[this.i + 1];
|
|
574
603
|
if (nextC === undefined) {
|
|
575
|
-
this.throwUnclosed(
|
|
604
|
+
this.throwUnclosed(ParseErrorCode.UNCLOSED_STRING, '未闭合的字符串字面量', startOffset, startLine, startCol);
|
|
576
605
|
}
|
|
577
606
|
const memoCount = continuousBackslashCount;
|
|
578
607
|
if (nextC === '\\') {
|
|
@@ -893,18 +922,6 @@ class Compiler {
|
|
|
893
922
|
loc
|
|
894
923
|
});
|
|
895
924
|
}
|
|
896
|
-
emptyLoc() {
|
|
897
|
-
const pos = this.tokenizer.getCurrentPos();
|
|
898
|
-
return {
|
|
899
|
-
start: pos,
|
|
900
|
-
end: {
|
|
901
|
-
offset: pos.offset + 1,
|
|
902
|
-
line: pos.line,
|
|
903
|
-
column: pos.column + 1
|
|
904
|
-
},
|
|
905
|
-
source: ' '
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
925
|
parseProgram() {
|
|
909
926
|
const body = [];
|
|
910
927
|
try {
|
|
@@ -918,10 +935,8 @@ class Compiler {
|
|
|
918
935
|
} catch (error) {
|
|
919
936
|
if (error instanceof ParseSyntaxError) {
|
|
920
937
|
this.addError(error.code, error.message, error.loc);
|
|
921
|
-
} else
|
|
922
|
-
|
|
923
|
-
const code = knownCodes.includes(error.message) ? error.message : 'INCONSISTENT_INDENT';
|
|
924
|
-
this.addError(code, error.message, this.emptyLoc());
|
|
938
|
+
} else {
|
|
939
|
+
this.addError(error.toString(), '未知错误', this.tokenizer.emptyLoc());
|
|
925
940
|
}
|
|
926
941
|
}
|
|
927
942
|
return {
|
|
@@ -961,7 +976,7 @@ class Compiler {
|
|
|
961
976
|
templateNode(siblings) {
|
|
962
977
|
const token = this.tokenizer.token;
|
|
963
978
|
if (token.type & TokenType.Pipe) {
|
|
964
|
-
this.addError(
|
|
979
|
+
this.addError(ParseErrorCode.PIPE_IN_WRONG_CONTEXT, '"|" 只能出现在元素属性扩展行中', token.loc ?? this.tokenizer.emptyLoc());
|
|
965
980
|
this.tokenizer.nextToken();
|
|
966
981
|
return null;
|
|
967
982
|
}
|
|
@@ -969,12 +984,13 @@ class Compiler {
|
|
|
969
984
|
_this$tokenizer$_hook2 = _slicedToArray(_this$tokenizer$_hook, 2),
|
|
970
985
|
hookType = _this$tokenizer$_hook2[0],
|
|
971
986
|
value = _this$tokenizer$_hook2[1];
|
|
972
|
-
|
|
973
|
-
|
|
987
|
+
const isElseOrFail = value === 'else' || value === 'fail';
|
|
988
|
+
if (value === 'if' || isElseOrFail) {
|
|
989
|
+
if (isElseOrFail) {
|
|
974
990
|
const lastSibling = siblings[siblings.length - 1];
|
|
975
991
|
const lastType = lastSibling?.type;
|
|
976
992
|
if (lastType !== NodeType.If && lastType !== NodeType.Else && lastType !== NodeType.Fail) {
|
|
977
|
-
this.addError(
|
|
993
|
+
this.addError(ParseErrorCode.ELSE_WITHOUT_IF, `"${value}" 前必须有 "if" 或 "else" 节点`, token.loc ?? this.tokenizer.emptyLoc());
|
|
978
994
|
}
|
|
979
995
|
}
|
|
980
996
|
return this.parseConditionalNode();
|
|
@@ -1002,7 +1018,7 @@ class Compiler {
|
|
|
1002
1018
|
parseElementNode(node) {
|
|
1003
1019
|
const tagToken = this.tokenizer.token;
|
|
1004
1020
|
if (!(tagToken.type & TokenType.Identifier)) {
|
|
1005
|
-
this.addError(
|
|
1021
|
+
this.addError(ParseErrorCode.INVALID_TAG_NAME, `无效的标签名,期望标识符但得到 "${tagToken.value}"`, tagToken.loc ?? this.tokenizer.emptyLoc());
|
|
1006
1022
|
while (!(this.tokenizer.token.type & TokenType.NewLine) && !this.tokenizer.isEof()) {
|
|
1007
1023
|
this.tokenizer.nextToken();
|
|
1008
1024
|
}
|
|
@@ -1033,15 +1049,15 @@ class Compiler {
|
|
|
1033
1049
|
return node;
|
|
1034
1050
|
}
|
|
1035
1051
|
parseLoopNode(node) {
|
|
1036
|
-
const forLoc = this.tokenizer.token.loc ?? this.emptyLoc();
|
|
1052
|
+
const forLoc = this.tokenizer.token.loc ?? this.tokenizer.emptyLoc();
|
|
1037
1053
|
this.tokenizer.nextToken();
|
|
1038
1054
|
const collection = this.parsePropertyValue();
|
|
1039
1055
|
if (!collection.value && collection.value !== 0) {
|
|
1040
|
-
this.addError(
|
|
1056
|
+
this.addError(ParseErrorCode.MISSING_FOR_COLLECTION, '"for" 缺少集合表达式', forLoc);
|
|
1041
1057
|
}
|
|
1042
1058
|
const semicolonToken = this.tokenizer.nextToken();
|
|
1043
1059
|
if (!(semicolonToken.type & TokenType.Semicolon)) {
|
|
1044
|
-
this.addError(
|
|
1060
|
+
this.addError(ParseErrorCode.MISSING_FOR_SEMICOLON, '"for" 语法:for <集合>; <item> [index][; key],缺少第一个 ";"', semicolonToken.loc ?? this.tokenizer.emptyLoc());
|
|
1045
1061
|
}
|
|
1046
1062
|
const itemToken = this.tokenizer.nextToken();
|
|
1047
1063
|
const isDestruct = itemToken.type === TokenType.InsertionExp;
|
|
@@ -1050,7 +1066,7 @@ class Compiler {
|
|
|
1050
1066
|
}
|
|
1051
1067
|
const item = this.parsePropertyValue();
|
|
1052
1068
|
if (!item.value && item.value !== 0) {
|
|
1053
|
-
this.addError(
|
|
1069
|
+
this.addError(ParseErrorCode.MISSING_FOR_ITEM, '"for" 缺少 item 变量名', itemToken.loc ?? this.tokenizer.emptyLoc());
|
|
1054
1070
|
}
|
|
1055
1071
|
let char = this.tokenizer.peekChar(),
|
|
1056
1072
|
key,
|
|
@@ -1115,7 +1131,7 @@ class Compiler {
|
|
|
1115
1131
|
node.value = this.parsePropertyValue();
|
|
1116
1132
|
this.tokenizer.nextToken();
|
|
1117
1133
|
} else {
|
|
1118
|
-
this.addError(
|
|
1134
|
+
this.addError(ParseErrorCode.MISSING_ASSIGN, `属性 "${node.key.key}" 缺少 "=" 赋值符号`, node.key.loc ?? this.tokenizer.emptyLoc());
|
|
1119
1135
|
}
|
|
1120
1136
|
node.loc.start = node.key.loc.start;
|
|
1121
1137
|
node.loc.end = node.value ? node.value.loc.end : node.key.loc.end;
|