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
|
@@ -43,6 +43,23 @@ let NodeSort = function (NodeSort) {
|
|
|
43
43
|
TerpEvt["HandledComponentNode"] = "handled-component-node";
|
|
44
44
|
return TerpEvt;
|
|
45
45
|
})({});
|
|
46
|
+
let ParseErrorCode = function (ParseErrorCode) {
|
|
47
|
+
ParseErrorCode[ParseErrorCode["UNCLOSED_BRACE"] = 9001] = "UNCLOSED_BRACE";
|
|
48
|
+
ParseErrorCode[ParseErrorCode["UNCLOSED_STRING"] = 9002] = "UNCLOSED_STRING";
|
|
49
|
+
ParseErrorCode[ParseErrorCode["UNCLOSED_STATIC_INS"] = 9003] = "UNCLOSED_STATIC_INS";
|
|
50
|
+
ParseErrorCode[ParseErrorCode["INCONSISTENT_INDENT"] = 9004] = "INCONSISTENT_INDENT";
|
|
51
|
+
ParseErrorCode[ParseErrorCode["INDENT_MISMATCH"] = 9005] = "INDENT_MISMATCH";
|
|
52
|
+
ParseErrorCode[ParseErrorCode["MISSING_ASSIGN"] = 9006] = "MISSING_ASSIGN";
|
|
53
|
+
ParseErrorCode[ParseErrorCode["INVALID_TAG_NAME"] = 9007] = "INVALID_TAG_NAME";
|
|
54
|
+
ParseErrorCode[ParseErrorCode["ELSE_WITHOUT_IF"] = 9008] = "ELSE_WITHOUT_IF";
|
|
55
|
+
ParseErrorCode[ParseErrorCode["EMPTY_IF_BODY"] = 9009] = "EMPTY_IF_BODY";
|
|
56
|
+
ParseErrorCode[ParseErrorCode["EMPTY_FOR_BODY"] = 9010] = "EMPTY_FOR_BODY";
|
|
57
|
+
ParseErrorCode[ParseErrorCode["MISSING_FOR_COLLECTION"] = 9011] = "MISSING_FOR_COLLECTION";
|
|
58
|
+
ParseErrorCode[ParseErrorCode["MISSING_FOR_SEMICOLON"] = 9012] = "MISSING_FOR_SEMICOLON";
|
|
59
|
+
ParseErrorCode[ParseErrorCode["MISSING_FOR_ITEM"] = 9013] = "MISSING_FOR_ITEM";
|
|
60
|
+
ParseErrorCode[ParseErrorCode["PIPE_IN_WRONG_CONTEXT"] = 9014] = "PIPE_IN_WRONG_CONTEXT";
|
|
61
|
+
return ParseErrorCode;
|
|
62
|
+
}({});
|
|
46
63
|
class ParseSyntaxError extends SyntaxError {
|
|
47
64
|
constructor(code, message, loc) {
|
|
48
65
|
super(message);
|
|
@@ -169,7 +186,7 @@ class Tokenizer {
|
|
|
169
186
|
const expLen = this.dentStack[i];
|
|
170
187
|
if (currLen === expLen) break;
|
|
171
188
|
if (currLen > expLen) {
|
|
172
|
-
throw
|
|
189
|
+
throw new ParseSyntaxError(ParseErrorCode.INCONSISTENT_INDENT, '缩进大小不统一', this.emptyLoc());
|
|
173
190
|
}
|
|
174
191
|
if (this.shorterThanBaseDentEof()) {
|
|
175
192
|
break;
|
|
@@ -394,7 +411,7 @@ class Tokenizer {
|
|
|
394
411
|
while (1) {
|
|
395
412
|
nextC = this.code[this.i + 1];
|
|
396
413
|
if (nextC === undefined) {
|
|
397
|
-
this.throwUnclosed(
|
|
414
|
+
this.throwUnclosed(ParseErrorCode.UNCLOSED_STATIC_INS, '未闭合的 "${...}"', startOffset, startLine, startCol);
|
|
398
415
|
}
|
|
399
416
|
value += nextC;
|
|
400
417
|
this.next();
|
|
@@ -423,7 +440,7 @@ class Tokenizer {
|
|
|
423
440
|
while (1) {
|
|
424
441
|
const char = this.code[this.i];
|
|
425
442
|
if (char === undefined) {
|
|
426
|
-
this.throwUnclosed(
|
|
443
|
+
this.throwUnclosed(ParseErrorCode.UNCLOSED_BRACE, '未闭合的 "{"', startOffset, startLine, startCol);
|
|
427
444
|
}
|
|
428
445
|
const nextChar = this.code[this.i + 1];
|
|
429
446
|
if (inComment === 'single' && char === '\n') {
|
|
@@ -512,6 +529,18 @@ class Tokenizer {
|
|
|
512
529
|
isEmptyLine
|
|
513
530
|
};
|
|
514
531
|
}
|
|
532
|
+
emptyLoc() {
|
|
533
|
+
const pos = this.getCurrentPos();
|
|
534
|
+
return {
|
|
535
|
+
start: pos,
|
|
536
|
+
end: {
|
|
537
|
+
offset: pos.offset + 1,
|
|
538
|
+
line: pos.line,
|
|
539
|
+
column: pos.column + 1
|
|
540
|
+
},
|
|
541
|
+
source: ' '
|
|
542
|
+
};
|
|
543
|
+
}
|
|
515
544
|
dent() {
|
|
516
545
|
const _this$getDentValue2 = this.getDentValue(),
|
|
517
546
|
value = _this$getDentValue2.value,
|
|
@@ -538,7 +567,7 @@ class Tokenizer {
|
|
|
538
567
|
const expLen = this.dentStack[i];
|
|
539
568
|
if (currLen === expLen) break;
|
|
540
569
|
if (currLen > expLen) {
|
|
541
|
-
throw
|
|
570
|
+
throw new ParseSyntaxError(ParseErrorCode.INCONSISTENT_INDENT, '缩进大小不统一', this.emptyLoc());
|
|
542
571
|
}
|
|
543
572
|
if (this.shorterThanBaseDentEof()) {
|
|
544
573
|
return;
|
|
@@ -616,7 +645,7 @@ class Tokenizer {
|
|
|
616
645
|
while (1) {
|
|
617
646
|
nextC = this.code[this.i + 1];
|
|
618
647
|
if (nextC === undefined) {
|
|
619
|
-
this.throwUnclosed(
|
|
648
|
+
this.throwUnclosed(ParseErrorCode.UNCLOSED_STRING, '未闭合的字符串字面量', startOffset, startLine, startCol);
|
|
620
649
|
}
|
|
621
650
|
const memoCount = continuousBackslashCount;
|
|
622
651
|
if (nextC === '\\') {
|
|
@@ -937,18 +966,6 @@ class Compiler {
|
|
|
937
966
|
loc
|
|
938
967
|
});
|
|
939
968
|
}
|
|
940
|
-
emptyLoc() {
|
|
941
|
-
const pos = this.tokenizer.getCurrentPos();
|
|
942
|
-
return {
|
|
943
|
-
start: pos,
|
|
944
|
-
end: {
|
|
945
|
-
offset: pos.offset + 1,
|
|
946
|
-
line: pos.line,
|
|
947
|
-
column: pos.column + 1
|
|
948
|
-
},
|
|
949
|
-
source: ' '
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
969
|
parseProgram() {
|
|
953
970
|
const body = [];
|
|
954
971
|
try {
|
|
@@ -962,10 +979,8 @@ class Compiler {
|
|
|
962
979
|
} catch (error) {
|
|
963
980
|
if (error instanceof ParseSyntaxError) {
|
|
964
981
|
this.addError(error.code, error.message, error.loc);
|
|
965
|
-
} else
|
|
966
|
-
|
|
967
|
-
const code = knownCodes.includes(error.message) ? error.message : 'INCONSISTENT_INDENT';
|
|
968
|
-
this.addError(code, error.message, this.emptyLoc());
|
|
982
|
+
} else {
|
|
983
|
+
this.addError(error.toString(), '未知错误', this.tokenizer.emptyLoc());
|
|
969
984
|
}
|
|
970
985
|
}
|
|
971
986
|
return {
|
|
@@ -1005,7 +1020,7 @@ class Compiler {
|
|
|
1005
1020
|
templateNode(siblings) {
|
|
1006
1021
|
const token = this.tokenizer.token;
|
|
1007
1022
|
if (token.type & TokenType.Pipe) {
|
|
1008
|
-
this.addError(
|
|
1023
|
+
this.addError(ParseErrorCode.PIPE_IN_WRONG_CONTEXT, '"|" 只能出现在元素属性扩展行中', token.loc ?? this.tokenizer.emptyLoc());
|
|
1009
1024
|
this.tokenizer.nextToken();
|
|
1010
1025
|
return null;
|
|
1011
1026
|
}
|
|
@@ -1013,12 +1028,13 @@ class Compiler {
|
|
|
1013
1028
|
_this$tokenizer$_hook2 = _slicedToArray(_this$tokenizer$_hook, 2),
|
|
1014
1029
|
hookType = _this$tokenizer$_hook2[0],
|
|
1015
1030
|
value = _this$tokenizer$_hook2[1];
|
|
1016
|
-
|
|
1017
|
-
|
|
1031
|
+
const isElseOrFail = value === 'else' || value === 'fail';
|
|
1032
|
+
if (value === 'if' || isElseOrFail) {
|
|
1033
|
+
if (isElseOrFail) {
|
|
1018
1034
|
const lastSibling = siblings[siblings.length - 1];
|
|
1019
1035
|
const lastType = lastSibling?.type;
|
|
1020
1036
|
if (lastType !== NodeType.If && lastType !== NodeType.Else && lastType !== NodeType.Fail) {
|
|
1021
|
-
this.addError(
|
|
1037
|
+
this.addError(ParseErrorCode.ELSE_WITHOUT_IF, `"${value}" 前必须有 "if" 或 "else" 节点`, token.loc ?? this.tokenizer.emptyLoc());
|
|
1022
1038
|
}
|
|
1023
1039
|
}
|
|
1024
1040
|
return this.parseConditionalNode();
|
|
@@ -1046,7 +1062,7 @@ class Compiler {
|
|
|
1046
1062
|
parseElementNode(node) {
|
|
1047
1063
|
const tagToken = this.tokenizer.token;
|
|
1048
1064
|
if (!(tagToken.type & TokenType.Identifier)) {
|
|
1049
|
-
this.addError(
|
|
1065
|
+
this.addError(ParseErrorCode.INVALID_TAG_NAME, `无效的标签名,期望标识符但得到 "${tagToken.value}"`, tagToken.loc ?? this.tokenizer.emptyLoc());
|
|
1050
1066
|
while (!(this.tokenizer.token.type & TokenType.NewLine) && !this.tokenizer.isEof()) {
|
|
1051
1067
|
this.tokenizer.nextToken();
|
|
1052
1068
|
}
|
|
@@ -1077,15 +1093,15 @@ class Compiler {
|
|
|
1077
1093
|
return node;
|
|
1078
1094
|
}
|
|
1079
1095
|
parseLoopNode(node) {
|
|
1080
|
-
const forLoc = this.tokenizer.token.loc ?? this.emptyLoc();
|
|
1096
|
+
const forLoc = this.tokenizer.token.loc ?? this.tokenizer.emptyLoc();
|
|
1081
1097
|
this.tokenizer.nextToken();
|
|
1082
1098
|
const collection = this.parsePropertyValue();
|
|
1083
1099
|
if (!collection.value && collection.value !== 0) {
|
|
1084
|
-
this.addError(
|
|
1100
|
+
this.addError(ParseErrorCode.MISSING_FOR_COLLECTION, '"for" 缺少集合表达式', forLoc);
|
|
1085
1101
|
}
|
|
1086
1102
|
const semicolonToken = this.tokenizer.nextToken();
|
|
1087
1103
|
if (!(semicolonToken.type & TokenType.Semicolon)) {
|
|
1088
|
-
this.addError(
|
|
1104
|
+
this.addError(ParseErrorCode.MISSING_FOR_SEMICOLON, '"for" 语法:for <集合>; <item> [index][; key],缺少第一个 ";"', semicolonToken.loc ?? this.tokenizer.emptyLoc());
|
|
1089
1105
|
}
|
|
1090
1106
|
const itemToken = this.tokenizer.nextToken();
|
|
1091
1107
|
const isDestruct = itemToken.type === TokenType.InsertionExp;
|
|
@@ -1094,7 +1110,7 @@ class Compiler {
|
|
|
1094
1110
|
}
|
|
1095
1111
|
const item = this.parsePropertyValue();
|
|
1096
1112
|
if (!item.value && item.value !== 0) {
|
|
1097
|
-
this.addError(
|
|
1113
|
+
this.addError(ParseErrorCode.MISSING_FOR_ITEM, '"for" 缺少 item 变量名', itemToken.loc ?? this.tokenizer.emptyLoc());
|
|
1098
1114
|
}
|
|
1099
1115
|
let char = this.tokenizer.peekChar(),
|
|
1100
1116
|
key,
|
|
@@ -1159,7 +1175,7 @@ class Compiler {
|
|
|
1159
1175
|
node.value = this.parsePropertyValue();
|
|
1160
1176
|
this.tokenizer.nextToken();
|
|
1161
1177
|
} else {
|
|
1162
|
-
this.addError(
|
|
1178
|
+
this.addError(ParseErrorCode.MISSING_ASSIGN, `属性 "${node.key.key}" 缺少 "=" 赋值符号`, node.key.loc ?? this.tokenizer.emptyLoc());
|
|
1163
1179
|
}
|
|
1164
1180
|
node.loc.start = node.key.loc.start;
|
|
1165
1181
|
node.loc.end = node.value ? node.value.loc.end : node.key.loc.end;
|