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