bobe 0.0.34 → 0.0.36
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 +146 -34
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.compiler.cjs.js +146 -34
- package/dist/bobe.compiler.cjs.js.map +1 -1
- package/dist/bobe.compiler.esm.js +146 -35
- package/dist/bobe.compiler.esm.js.map +1 -1
- package/dist/bobe.esm.js +146 -35
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.umd.js +146 -34
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -146,11 +146,11 @@ declare enum FakeType {
|
|
|
146
146
|
}
|
|
147
147
|
type NodeSortBit = number;
|
|
148
148
|
type BaseType = string | number | boolean | undefined | null;
|
|
149
|
-
|
|
149
|
+
type SourceLocation = {
|
|
150
150
|
start: Position;
|
|
151
151
|
end: Position;
|
|
152
152
|
source: string;
|
|
153
|
-
}
|
|
153
|
+
};
|
|
154
154
|
interface Position {
|
|
155
155
|
line: number;
|
|
156
156
|
column: number;
|
|
@@ -174,6 +174,18 @@ type TerpConf = Partial<Pick<Interpreter, 'createNode' | 'setProp' | 'insertAfte
|
|
|
174
174
|
type CustomRenderConf = Pick<TerpConf, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib'>;
|
|
175
175
|
type Hook = (props: HookProps) => any;
|
|
176
176
|
type HookType = 'dynamic' | 'static';
|
|
177
|
+
type ParseErrorCode = 'UNCLOSED_BRACE' | 'UNCLOSED_STRING' | 'UNCLOSED_STATIC_INS' | 'INCONSISTENT_INDENT' | 'INDENT_MISMATCH' | 'MISSING_ASSIGN' | 'INVALID_TAG_NAME' | 'ELSE_WITHOUT_IF' | 'EMPTY_IF_BODY' | 'EMPTY_FOR_BODY' | 'MISSING_FOR_COLLECTION' | 'MISSING_FOR_SEMICOLON' | 'MISSING_FOR_ITEM' | 'PIPE_IN_WRONG_CONTEXT';
|
|
178
|
+
type ParseError = {
|
|
179
|
+
code: ParseErrorCode;
|
|
180
|
+
message: string;
|
|
181
|
+
loc: SourceLocation;
|
|
182
|
+
};
|
|
183
|
+
/** tokenizer 抛出的带位置信息的语法错误 */
|
|
184
|
+
declare class ParseSyntaxError extends SyntaxError {
|
|
185
|
+
code: ParseErrorCode;
|
|
186
|
+
loc: SourceLocation;
|
|
187
|
+
constructor(code: ParseErrorCode, message: string, loc: SourceLocation);
|
|
188
|
+
}
|
|
177
189
|
type ProgramCtx = {
|
|
178
190
|
stack: MultiTypeStack<any>;
|
|
179
191
|
prevSibling: any;
|
|
@@ -271,6 +283,9 @@ declare class Tokenizer {
|
|
|
271
283
|
constructor(hook: Hook, useDedentAsEof: boolean);
|
|
272
284
|
private next;
|
|
273
285
|
getCurrentPos(): Position;
|
|
286
|
+
/** 构造从当前扫描起始位置到模板结尾的 SourceLocation,用于未闭合错误 */
|
|
287
|
+
private unclosedLoc;
|
|
288
|
+
private throwUnclosed;
|
|
274
289
|
resume(_snapshot: ReturnType<Tokenizer['snapshot']>): void;
|
|
275
290
|
snapshot(keys?: (keyof Tokenizer)[]): Partial<Tokenizer>;
|
|
276
291
|
skip(): string;
|
|
@@ -383,7 +398,7 @@ interface LoopNode extends BaseNode {
|
|
|
383
398
|
}
|
|
384
399
|
interface ComponentNode extends BaseNode {
|
|
385
400
|
type: NodeType.Component;
|
|
386
|
-
componentName:
|
|
401
|
+
componentName: PropertyValue;
|
|
387
402
|
props: Property[];
|
|
388
403
|
children?: TemplateNode[];
|
|
389
404
|
}
|
|
@@ -395,7 +410,10 @@ interface FragmentNode extends BaseNode {
|
|
|
395
410
|
declare class Compiler {
|
|
396
411
|
tokenizer: Tokenizer;
|
|
397
412
|
hooks: ParseHooks;
|
|
413
|
+
errors: ParseError[];
|
|
398
414
|
constructor(tokenizer: Tokenizer, hooks?: ParseHooks);
|
|
415
|
+
private addError;
|
|
416
|
+
private emptyLoc;
|
|
399
417
|
/**
|
|
400
418
|
* 编译程序入口,生成AST
|
|
401
419
|
*/
|
|
@@ -438,6 +456,10 @@ declare class Compiler {
|
|
|
438
456
|
* 根据值类型创建属性值节点
|
|
439
457
|
*/
|
|
440
458
|
parsePropertyValue(node?: PropertyValue): PropertyValue;
|
|
459
|
+
/**
|
|
460
|
+
* 根据值类型创建名称
|
|
461
|
+
*/
|
|
462
|
+
parseName(node?: PropertyValue): PropertyValue;
|
|
441
463
|
}
|
|
442
464
|
type PickParseProps<T> = {
|
|
443
465
|
[K in keyof T as K extends `parse${string}` ? K : never]: T[K];
|
|
@@ -454,5 +476,5 @@ type ParseHooks = Partial<{
|
|
|
454
476
|
declare function bobe(fragments: TemplateStringsArray, ...values: any[]): BobeUI;
|
|
455
477
|
declare function customRender(option: CustomRenderConf): <T>(Ctor: typeof Store, root: any) => (ComponentNode$1 | Store)[];
|
|
456
478
|
|
|
457
|
-
export { Compiler, NodeType, Tokenizer, bobe, customRender };
|
|
458
|
-
export type { ASTNodeType, BaseNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, InterpolationNode, LoopNode, Program, Property, PropertyKeyNode, PropertyValue, StaticValue, TemplateNode, TextNode };
|
|
479
|
+
export { Compiler, NodeType, ParseSyntaxError, Tokenizer, bobe, customRender };
|
|
480
|
+
export type { ASTNodeType, BaseNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, InterpolationNode, LoopNode, ParseError, ParseErrorCode, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
|
package/dist/index.umd.js
CHANGED
|
@@ -44,6 +44,13 @@
|
|
|
44
44
|
TerpEvt["HandledComponentNode"] = "handled-component-node";
|
|
45
45
|
return TerpEvt;
|
|
46
46
|
})({});
|
|
47
|
+
class ParseSyntaxError extends SyntaxError {
|
|
48
|
+
constructor(code, message, loc) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.code = code;
|
|
51
|
+
this.loc = loc;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
47
54
|
|
|
48
55
|
class Tokenizer {
|
|
49
56
|
TabSize = 2;
|
|
@@ -82,6 +89,25 @@
|
|
|
82
89
|
column: this.column
|
|
83
90
|
};
|
|
84
91
|
}
|
|
92
|
+
unclosedLoc(startOffset, startLine, startCol) {
|
|
93
|
+
const end = this.code.length - 1;
|
|
94
|
+
return {
|
|
95
|
+
start: {
|
|
96
|
+
offset: startOffset,
|
|
97
|
+
line: startLine,
|
|
98
|
+
column: startCol
|
|
99
|
+
},
|
|
100
|
+
end: {
|
|
101
|
+
offset: end,
|
|
102
|
+
line: this.line,
|
|
103
|
+
column: this.column
|
|
104
|
+
},
|
|
105
|
+
source: this.code.slice(startOffset, end)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
throwUnclosed(code, message, startOffset, startLine, startCol) {
|
|
109
|
+
throw new ParseSyntaxError(code, message, this.unclosedLoc(startOffset, startLine, startCol));
|
|
110
|
+
}
|
|
85
111
|
resume(_snapshot) {
|
|
86
112
|
this.token = undefined;
|
|
87
113
|
this.needIndent = false;
|
|
@@ -250,8 +276,7 @@
|
|
|
250
276
|
}
|
|
251
277
|
return this.token;
|
|
252
278
|
} catch (error) {
|
|
253
|
-
|
|
254
|
-
return this.token;
|
|
279
|
+
throw error;
|
|
255
280
|
} finally {
|
|
256
281
|
this.handledTokens.push(this.token);
|
|
257
282
|
}
|
|
@@ -314,6 +339,9 @@
|
|
|
314
339
|
this.setToken(TokenType.Pipe, '|');
|
|
315
340
|
}
|
|
316
341
|
staticIns() {
|
|
342
|
+
const startOffset = this.preI,
|
|
343
|
+
startLine = this.line,
|
|
344
|
+
startCol = this.preCol;
|
|
317
345
|
let nextC = this.code[this.i + 1];
|
|
318
346
|
if (nextC !== '{') {
|
|
319
347
|
return false;
|
|
@@ -323,6 +351,9 @@
|
|
|
323
351
|
let innerBrace = 0;
|
|
324
352
|
while (1) {
|
|
325
353
|
nextC = this.code[this.i + 1];
|
|
354
|
+
if (nextC === undefined) {
|
|
355
|
+
this.throwUnclosed('UNCLOSED_STATIC_INS', '未闭合的 "${...}"', startOffset, startLine, startCol);
|
|
356
|
+
}
|
|
326
357
|
value += nextC;
|
|
327
358
|
this.next();
|
|
328
359
|
if (nextC === '{') {
|
|
@@ -339,6 +370,9 @@
|
|
|
339
370
|
return true;
|
|
340
371
|
}
|
|
341
372
|
brace() {
|
|
373
|
+
const startOffset = this.preI,
|
|
374
|
+
startLine = this.line,
|
|
375
|
+
startCol = this.preCol;
|
|
342
376
|
let inComment,
|
|
343
377
|
inString,
|
|
344
378
|
count = 0,
|
|
@@ -346,6 +380,9 @@
|
|
|
346
380
|
backslashCount = 0;
|
|
347
381
|
while (1) {
|
|
348
382
|
const char = this.code[this.i];
|
|
383
|
+
if (char === undefined) {
|
|
384
|
+
this.throwUnclosed('UNCLOSED_BRACE', '未闭合的 "{"', startOffset, startLine, startCol);
|
|
385
|
+
}
|
|
349
386
|
const nextChar = this.code[this.i + 1];
|
|
350
387
|
if (inComment === 'single' && char === '\n') {
|
|
351
388
|
inComment = null;
|
|
@@ -528,11 +565,17 @@
|
|
|
528
565
|
this.setToken(TokenType.Identifier, realValue);
|
|
529
566
|
}
|
|
530
567
|
str(char) {
|
|
568
|
+
const startOffset = this.preI,
|
|
569
|
+
startLine = this.line,
|
|
570
|
+
startCol = this.preCol;
|
|
531
571
|
let value = '';
|
|
532
572
|
let nextC;
|
|
533
573
|
let continuousBackslashCount = 0;
|
|
534
574
|
while (1) {
|
|
535
575
|
nextC = this.code[this.i + 1];
|
|
576
|
+
if (nextC === undefined) {
|
|
577
|
+
this.throwUnclosed('UNCLOSED_STRING', '未闭合的字符串字面量', startOffset, startLine, startCol);
|
|
578
|
+
}
|
|
536
579
|
const memoCount = continuousBackslashCount;
|
|
537
580
|
if (nextC === '\\') {
|
|
538
581
|
continuousBackslashCount++;
|
|
@@ -600,24 +643,6 @@
|
|
|
600
643
|
}
|
|
601
644
|
}
|
|
602
645
|
|
|
603
|
-
var NodeType = function (NodeType) {
|
|
604
|
-
NodeType["Element"] = "Element";
|
|
605
|
-
NodeType["Text"] = "Text";
|
|
606
|
-
NodeType["Interpolation"] = "Interpolation";
|
|
607
|
-
NodeType["Property"] = "Property";
|
|
608
|
-
NodeType["PropertyKey"] = "PropertyKey";
|
|
609
|
-
NodeType["StaticValue"] = "StaticValue";
|
|
610
|
-
NodeType["DynamicValue"] = "DynamicValue";
|
|
611
|
-
NodeType["Program"] = "Program";
|
|
612
|
-
NodeType["If"] = "If";
|
|
613
|
-
NodeType["Else"] = "Else";
|
|
614
|
-
NodeType["Fail"] = "Fail";
|
|
615
|
-
NodeType["For"] = "For";
|
|
616
|
-
NodeType["Component"] = "Component";
|
|
617
|
-
NodeType["Fragment"] = "Fragment";
|
|
618
|
-
return NodeType;
|
|
619
|
-
}(NodeType || {});
|
|
620
|
-
|
|
621
646
|
function _applyDecs2311(e, t, n, r, o, i) {
|
|
622
647
|
var a,
|
|
623
648
|
c,
|
|
@@ -834,24 +859,71 @@
|
|
|
834
859
|
}
|
|
835
860
|
}
|
|
836
861
|
|
|
862
|
+
var NodeType = function (NodeType) {
|
|
863
|
+
NodeType["Element"] = "Element";
|
|
864
|
+
NodeType["Text"] = "Text";
|
|
865
|
+
NodeType["Interpolation"] = "Interpolation";
|
|
866
|
+
NodeType["Property"] = "Property";
|
|
867
|
+
NodeType["PropertyKey"] = "PropertyKey";
|
|
868
|
+
NodeType["StaticValue"] = "StaticValue";
|
|
869
|
+
NodeType["DynamicValue"] = "DynamicValue";
|
|
870
|
+
NodeType["Program"] = "Program";
|
|
871
|
+
NodeType["If"] = "If";
|
|
872
|
+
NodeType["Else"] = "Else";
|
|
873
|
+
NodeType["Fail"] = "Fail";
|
|
874
|
+
NodeType["For"] = "For";
|
|
875
|
+
NodeType["Component"] = "Component";
|
|
876
|
+
NodeType["Fragment"] = "Fragment";
|
|
877
|
+
return NodeType;
|
|
878
|
+
}(NodeType || {});
|
|
879
|
+
|
|
837
880
|
let _initProto;
|
|
838
881
|
class Compiler {
|
|
839
882
|
static {
|
|
840
|
-
var _applyDecs$e = _slicedToArray(_applyDecs2311(this, [], [[NodeHook, 2, "parseProgram"], [[NodeHook, NodeLoc], 2, "parseComponentNode"], [[NodeHook, NodeLoc], 2, "parseElementNode"], [[NodeHook, NodeLoc], 2, "parseConditionalNode"], [[NodeHook, NodeLoc], 2, "parseLoopNode"], [NodeHook, 2, "parseProperty"], [[NodeHook, TokenLoc], 2, "parsePropertyKey"], [[NodeHook, TokenLoc], 2, "parsePropertyValue"]]).e, 1);
|
|
883
|
+
var _applyDecs$e = _slicedToArray(_applyDecs2311(this, [], [[NodeHook, 2, "parseProgram"], [[NodeHook, NodeLoc], 2, "parseComponentNode"], [[NodeHook, NodeLoc], 2, "parseElementNode"], [[NodeHook, NodeLoc], 2, "parseConditionalNode"], [[NodeHook, NodeLoc], 2, "parseLoopNode"], [NodeHook, 2, "parseProperty"], [[NodeHook, TokenLoc], 2, "parsePropertyKey"], [[NodeHook, TokenLoc], 2, "parsePropertyValue"], [[NodeHook, TokenLoc], 2, "parseName"]]).e, 1);
|
|
841
884
|
_initProto = _applyDecs$e[0];
|
|
842
885
|
}
|
|
886
|
+
errors = (_initProto(this), []);
|
|
843
887
|
constructor(tokenizer, hooks = {}) {
|
|
844
888
|
this.tokenizer = tokenizer;
|
|
845
889
|
this.hooks = hooks;
|
|
846
|
-
|
|
890
|
+
}
|
|
891
|
+
addError(code, message, loc) {
|
|
892
|
+
this.errors.push({
|
|
893
|
+
code,
|
|
894
|
+
message,
|
|
895
|
+
loc
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
emptyLoc() {
|
|
899
|
+
const pos = this.tokenizer.getCurrentPos();
|
|
900
|
+
return {
|
|
901
|
+
start: pos,
|
|
902
|
+
end: {
|
|
903
|
+
offset: pos.offset + 1,
|
|
904
|
+
line: pos.line,
|
|
905
|
+
column: pos.column + 1
|
|
906
|
+
},
|
|
907
|
+
source: ' '
|
|
908
|
+
};
|
|
847
909
|
}
|
|
848
910
|
parseProgram() {
|
|
849
|
-
this.tokenizer.nextToken();
|
|
850
911
|
const body = [];
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
912
|
+
try {
|
|
913
|
+
this.tokenizer.nextToken();
|
|
914
|
+
while (!this.tokenizer.isEof()) {
|
|
915
|
+
const node = this.templateNode(body);
|
|
916
|
+
if (node) {
|
|
917
|
+
body.push(node);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
} catch (error) {
|
|
921
|
+
if (error instanceof ParseSyntaxError) {
|
|
922
|
+
this.addError(error.code, error.message, error.loc);
|
|
923
|
+
} else if (error instanceof SyntaxError) {
|
|
924
|
+
const knownCodes = ['INCONSISTENT_INDENT', 'INDENT_MISMATCH'];
|
|
925
|
+
const code = knownCodes.includes(error.message) ? error.message : 'INCONSISTENT_INDENT';
|
|
926
|
+
this.addError(code, error.message, this.emptyLoc());
|
|
855
927
|
}
|
|
856
928
|
}
|
|
857
929
|
return {
|
|
@@ -877,7 +949,7 @@
|
|
|
877
949
|
if (this.tokenizer.token.type & TokenType.Indent) {
|
|
878
950
|
this.tokenizer.nextToken();
|
|
879
951
|
while (!(this.tokenizer.token.type & TokenType.Dedent) && !this.tokenizer.isEof()) {
|
|
880
|
-
const child = this.templateNode();
|
|
952
|
+
const child = this.templateNode(children);
|
|
881
953
|
if (child) {
|
|
882
954
|
children.push(child);
|
|
883
955
|
}
|
|
@@ -888,13 +960,25 @@
|
|
|
888
960
|
}
|
|
889
961
|
return children;
|
|
890
962
|
}
|
|
891
|
-
templateNode() {
|
|
892
|
-
this.tokenizer.token;
|
|
963
|
+
templateNode(siblings) {
|
|
964
|
+
const token = this.tokenizer.token;
|
|
965
|
+
if (token.type & TokenType.Pipe) {
|
|
966
|
+
this.addError('PIPE_IN_WRONG_CONTEXT', '"|" 只能出现在元素属性扩展行中', token.loc ?? this.emptyLoc());
|
|
967
|
+
this.tokenizer.nextToken();
|
|
968
|
+
return null;
|
|
969
|
+
}
|
|
893
970
|
const _this$tokenizer$_hook = this.tokenizer._hook({}),
|
|
894
971
|
_this$tokenizer$_hook2 = _slicedToArray(_this$tokenizer$_hook, 2),
|
|
895
972
|
hookType = _this$tokenizer$_hook2[0],
|
|
896
973
|
value = _this$tokenizer$_hook2[1];
|
|
897
974
|
if (value === 'if' || value === 'else' || value === 'fail') {
|
|
975
|
+
if (value === 'else' || value === 'fail') {
|
|
976
|
+
const lastSibling = siblings[siblings.length - 1];
|
|
977
|
+
const lastType = lastSibling?.type;
|
|
978
|
+
if (lastType !== NodeType.If && lastType !== NodeType.Else && lastType !== NodeType.Fail) {
|
|
979
|
+
this.addError('ELSE_WITHOUT_IF', `"${value}" 前必须有 "if" 或 "else" 节点`, token.loc ?? this.emptyLoc());
|
|
980
|
+
}
|
|
981
|
+
}
|
|
898
982
|
return this.parseConditionalNode();
|
|
899
983
|
}
|
|
900
984
|
if (value === 'for') {
|
|
@@ -906,12 +990,11 @@
|
|
|
906
990
|
return this.parseElementNode();
|
|
907
991
|
}
|
|
908
992
|
parseComponentNode(node) {
|
|
909
|
-
const
|
|
910
|
-
const tagName = tagToken.value;
|
|
993
|
+
const name = this.parseName();
|
|
911
994
|
this.tokenizer.nextToken();
|
|
912
995
|
const props = this.headerLineAndExtensions();
|
|
913
996
|
node.type = NodeType.Component;
|
|
914
|
-
node.componentName =
|
|
997
|
+
node.componentName = name;
|
|
915
998
|
node.props = props;
|
|
916
999
|
this.hooks.parseComponentNode?.propsAdded?.call(this, node);
|
|
917
1000
|
const children = this.handleChildren();
|
|
@@ -920,6 +1003,13 @@
|
|
|
920
1003
|
}
|
|
921
1004
|
parseElementNode(node) {
|
|
922
1005
|
const tagToken = this.tokenizer.token;
|
|
1006
|
+
if (!(tagToken.type & TokenType.Identifier)) {
|
|
1007
|
+
this.addError('INVALID_TAG_NAME', `无效的标签名,期望标识符但得到 "${tagToken.value}"`, tagToken.loc ?? this.emptyLoc());
|
|
1008
|
+
while (!(this.tokenizer.token.type & TokenType.NewLine) && !this.tokenizer.isEof()) {
|
|
1009
|
+
this.tokenizer.nextToken();
|
|
1010
|
+
}
|
|
1011
|
+
return null;
|
|
1012
|
+
}
|
|
923
1013
|
const tagName = tagToken.value;
|
|
924
1014
|
this.tokenizer.nextToken();
|
|
925
1015
|
const props = this.headerLineAndExtensions();
|
|
@@ -945,15 +1035,25 @@
|
|
|
945
1035
|
return node;
|
|
946
1036
|
}
|
|
947
1037
|
parseLoopNode(node) {
|
|
1038
|
+
const forLoc = this.tokenizer.token.loc ?? this.emptyLoc();
|
|
948
1039
|
this.tokenizer.nextToken();
|
|
949
1040
|
const collection = this.parsePropertyValue();
|
|
950
|
-
|
|
1041
|
+
if (!collection.value && collection.value !== 0) {
|
|
1042
|
+
this.addError('MISSING_FOR_COLLECTION', '"for" 缺少集合表达式', forLoc);
|
|
1043
|
+
}
|
|
1044
|
+
const semicolonToken = this.tokenizer.nextToken();
|
|
1045
|
+
if (!(semicolonToken.type & TokenType.Semicolon)) {
|
|
1046
|
+
this.addError('MISSING_FOR_SEMICOLON', '"for" 语法:for <集合>; <item> [index][; key],缺少第一个 ";"', semicolonToken.loc ?? this.emptyLoc());
|
|
1047
|
+
}
|
|
951
1048
|
const itemToken = this.tokenizer.nextToken();
|
|
952
1049
|
const isDestruct = itemToken.type === TokenType.InsertionExp;
|
|
953
1050
|
if (isDestruct) {
|
|
954
1051
|
itemToken.value = '{' + itemToken.value + '}';
|
|
955
1052
|
}
|
|
956
1053
|
const item = this.parsePropertyValue();
|
|
1054
|
+
if (!item.value && item.value !== 0) {
|
|
1055
|
+
this.addError('MISSING_FOR_ITEM', '"for" 缺少 item 变量名', itemToken.loc ?? this.emptyLoc());
|
|
1056
|
+
}
|
|
957
1057
|
let char = this.tokenizer.peekChar(),
|
|
958
1058
|
key,
|
|
959
1059
|
index;
|
|
@@ -1016,6 +1116,8 @@
|
|
|
1016
1116
|
this.tokenizer.nextToken();
|
|
1017
1117
|
node.value = this.parsePropertyValue();
|
|
1018
1118
|
this.tokenizer.nextToken();
|
|
1119
|
+
} else {
|
|
1120
|
+
this.addError('MISSING_ASSIGN', `属性 "${node.key.key}" 缺少 "=" 赋值符号`, node.key.loc ?? this.emptyLoc());
|
|
1019
1121
|
}
|
|
1020
1122
|
node.loc.start = node.key.loc.start;
|
|
1021
1123
|
node.loc.end = node.value ? node.value.loc.end : node.key.loc.end;
|
|
@@ -1036,6 +1138,15 @@
|
|
|
1036
1138
|
node.value = value;
|
|
1037
1139
|
return node;
|
|
1038
1140
|
}
|
|
1141
|
+
parseName(node) {
|
|
1142
|
+
const _this$tokenizer$_hook5 = this.tokenizer._hook({}),
|
|
1143
|
+
_this$tokenizer$_hook6 = _slicedToArray(_this$tokenizer$_hook5, 2),
|
|
1144
|
+
hookType = _this$tokenizer$_hook6[0],
|
|
1145
|
+
value = _this$tokenizer$_hook6[1];
|
|
1146
|
+
node.type = hookType === 'dynamic' ? NodeType.DynamicValue : NodeType.StaticValue;
|
|
1147
|
+
node.value = value;
|
|
1148
|
+
return node;
|
|
1149
|
+
}
|
|
1039
1150
|
}
|
|
1040
1151
|
function NodeLoc(target, context) {
|
|
1041
1152
|
return function (_node) {
|
|
@@ -2006,6 +2117,7 @@
|
|
|
2006
2117
|
|
|
2007
2118
|
exports.Compiler = Compiler;
|
|
2008
2119
|
exports.NodeType = NodeType;
|
|
2120
|
+
exports.ParseSyntaxError = ParseSyntaxError;
|
|
2009
2121
|
exports.Tokenizer = Tokenizer;
|
|
2010
2122
|
exports.bobe = bobe;
|
|
2011
2123
|
exports.customRender = customRender;
|