Skip to content

Commit 5e5a50e

Browse files
committed
Early whiteblock body termination
Addresses wcjohnson/lightscript#39
1 parent 3099b20 commit 5e5a50e

File tree

18 files changed

+866
-47
lines changed

18 files changed

+866
-47
lines changed

src/parser/statement.js

+2-29
Original file line numberDiff line numberDiff line change
@@ -630,19 +630,7 @@ pp.parseLabeledStatement = function (node, maybeName, expr) {
630630

631631
pp.parseExpressionStatement = function (node, expr) {
632632
node.expression = expr;
633-
if (this.hasPlugin("lightscript")) {
634-
// for array comprehensions.
635-
// TODO: cleanup / think of a better way of doing this.
636-
this.match(tt.bracketR) ||
637-
this.match(tt.braceR) ||
638-
this.match(tt.parenR) ||
639-
this.match(tt._else) ||
640-
this.match(tt._elif) ||
641-
this.match(tt.colon) ||
642-
this.semicolon();
643-
} else {
644-
this.semicolon();
645-
}
633+
this.semicolon();
646634
return this.finishNode(node, "ExpressionStatement");
647635
};
648636

@@ -674,17 +662,7 @@ pp.parseBlockBody = function (node, allowDirectives, topLevel, end) {
674662
let oldStrict;
675663
let octalPosition;
676664

677-
const oldInWhiteBlock = this.state.inWhiteBlock;
678-
const oldWhiteBlockIndentLevel = this.state.whiteBlockIndentLevel;
679-
680-
let isEnd;
681-
if (this.hasPlugin("lightscript") && typeof end === "number") {
682-
this.state.inWhiteBlock = true;
683-
this.state.whiteBlockIndentLevel = end;
684-
isEnd = () => this.state.indentLevel <= end || this.match(tt.eof);
685-
} else {
686-
isEnd = () => this.eat(end);
687-
}
665+
const isEnd = () => this.eat(end);
688666

689667
while (!isEnd()) {
690668
if (!parsedNonDirective && this.state.containsOctal && !octalPosition) {
@@ -713,11 +691,6 @@ pp.parseBlockBody = function (node, allowDirectives, topLevel, end) {
713691
node.body.push(stmt);
714692
}
715693

716-
if (this.hasPlugin("lightscript")) {
717-
this.state.inWhiteBlock = oldInWhiteBlock;
718-
this.state.whiteBlockIndentLevel = oldWhiteBlockIndentLevel;
719-
}
720-
721694
if (oldStrict === false) {
722695
this.setStrict(false);
723696
}

src/parser/util.js

+6-17
Original file line numberDiff line numberDiff line change
@@ -63,23 +63,12 @@ pp.isLineBreak = function () {
6363
// Test whether a semicolon can be inserted at the current position.
6464

6565
pp.canInsertSemicolon = function () {
66-
return this.match(tt.eof) ||
67-
this.match(tt.braceR) ||
68-
this.isLineBreak() ||
69-
(this.hasPlugin("lightscript") && (
70-
// LSC oneline statement ASI cases
71-
// Allow if x: throw y else: throw z
72-
this.match(tt._else) ||
73-
this.match(tt._elif) ||
74-
// Allow (-> throw new Error)()
75-
this.match(tt.parenR) ||
76-
// Allow [-> throw new Error]
77-
this.match(tt.bracketR) ||
78-
// Technically it is legal to insert a ; after a ;.
79-
// Allows -> throw new Error; f()
80-
this.state.tokens[this.state.tokens.length - 1].type === tt.semi
81-
)) ||
82-
(this.hasPlugin("seqExprRequiresParen") && this.match(tt.comma));
66+
return this.match(tt.eof)
67+
|| this.match(tt.braceR)
68+
|| this.isLineBreak()
69+
|| this.state.tokens[this.state.tokens.length - 1].type === tt.semi
70+
|| (this.match(tt.comma) && this.hasPlugin("seqExprRequiresParen"))
71+
|| (this.hasPlugin("lightscript") && this.matchesWhiteBlockASIToken());
8372
};
8473

8574
// TODO

src/plugins/lightscript.js

+65-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,70 @@ pp.expectParenFreeBlockStart = function (node) {
120120
}
121121
};
122122

123+
pp.matchesWhiteBlockASIToken = function() {
124+
return (
125+
(this.match(tt.comma) && this.hasPlugin("seqExprRequiresParen")) ||
126+
this.match(tt.parenR) ||
127+
this.match(tt.bracketR) ||
128+
this.match(tt.braceR) ||
129+
this.match(tt._else) ||
130+
this.match(tt._elif) ||
131+
this.match(tt.colon) ||
132+
this.match(tt.eof)
133+
);
134+
};
135+
136+
// c/p statement.js parseBlockBody
137+
pp.parseWhiteBlockBody = function (node, allowDirectives, topLevel, whiteBlockIndentLevel) {
138+
node.body = [];
139+
node.directives = [];
140+
141+
let parsedNonDirective = false;
142+
let oldStrict;
143+
let octalPosition;
144+
145+
const oldInWhiteBlock = this.state.inWhiteBlock;
146+
const oldWhiteBlockIndentLevel = this.state.whiteBlockIndentLevel;
147+
this.state.inWhiteBlock = true;
148+
this.state.whiteBlockIndentLevel = whiteBlockIndentLevel;
149+
150+
const isEnd = () => this.state.indentLevel <= whiteBlockIndentLevel || this.matchesWhiteBlockASIToken();
151+
152+
while (!isEnd()) {
153+
if (!parsedNonDirective && this.state.containsOctal && !octalPosition) {
154+
octalPosition = this.state.octalPosition;
155+
}
156+
157+
const stmt = this.parseStatement(true, topLevel);
158+
159+
if (allowDirectives && !parsedNonDirective && this.isValidDirective(stmt)) {
160+
const directive = this.stmtToDirective(stmt);
161+
node.directives.push(directive);
162+
163+
if (oldStrict === undefined && directive.value.value === "use strict") {
164+
oldStrict = this.state.strict;
165+
this.setStrict(true);
166+
167+
if (octalPosition) {
168+
this.raise(octalPosition, "Octal literal in strict mode");
169+
}
170+
}
171+
172+
continue;
173+
}
174+
175+
parsedNonDirective = true;
176+
node.body.push(stmt);
177+
}
178+
179+
this.state.inWhiteBlock = oldInWhiteBlock;
180+
this.state.whiteBlockIndentLevel = oldWhiteBlockIndentLevel;
181+
182+
if (oldStrict === false) {
183+
this.setStrict(false);
184+
}
185+
};
186+
123187
pp.parseInlineWhiteBlock = function(node) {
124188
if (this.state.type.startsExpr) return this.parseMaybeAssign();
125189
// oneline statement case
@@ -130,7 +194,7 @@ pp.parseInlineWhiteBlock = function(node) {
130194
};
131195

132196
pp.parseMultilineWhiteBlock = function(node, indentLevel) {
133-
this.parseBlockBody(node, false, false, indentLevel);
197+
this.parseWhiteBlockBody(node, false, false, indentLevel);
134198
if (!node.body.length) {
135199
this.unexpected(node.start, "Expected an Indent or Statement");
136200
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"throws": "Unexpected token (1:10)"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"throws": "Unexpected token (1:20)"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[->
2+
a, b]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
{
2+
"type": "File",
3+
"start": 0,
4+
"end": 11,
5+
"loc": {
6+
"start": {
7+
"line": 1,
8+
"column": 0
9+
},
10+
"end": {
11+
"line": 2,
12+
"column": 7
13+
}
14+
},
15+
"program": {
16+
"type": "Program",
17+
"start": 0,
18+
"end": 11,
19+
"loc": {
20+
"start": {
21+
"line": 1,
22+
"column": 0
23+
},
24+
"end": {
25+
"line": 2,
26+
"column": 7
27+
}
28+
},
29+
"sourceType": "script",
30+
"body": [
31+
{
32+
"type": "ExpressionStatement",
33+
"start": 0,
34+
"end": 11,
35+
"loc": {
36+
"start": {
37+
"line": 1,
38+
"column": 0
39+
},
40+
"end": {
41+
"line": 2,
42+
"column": 7
43+
}
44+
},
45+
"expression": {
46+
"type": "ArrayExpression",
47+
"start": 0,
48+
"end": 11,
49+
"loc": {
50+
"start": {
51+
"line": 1,
52+
"column": 0
53+
},
54+
"end": {
55+
"line": 2,
56+
"column": 7
57+
}
58+
},
59+
"elements": [
60+
{
61+
"type": "ArrowFunctionExpression",
62+
"start": 1,
63+
"end": 7,
64+
"loc": {
65+
"start": {
66+
"line": 1,
67+
"column": 1
68+
},
69+
"end": {
70+
"line": 2,
71+
"column": 3
72+
}
73+
},
74+
"id": null,
75+
"generator": false,
76+
"expression": false,
77+
"async": false,
78+
"params": [],
79+
"skinny": true,
80+
"body": {
81+
"type": "BlockStatement",
82+
"start": 1,
83+
"end": 7,
84+
"loc": {
85+
"start": {
86+
"line": 1,
87+
"column": 1
88+
},
89+
"end": {
90+
"line": 2,
91+
"column": 3
92+
}
93+
},
94+
"body": [
95+
{
96+
"type": "ExpressionStatement",
97+
"start": 6,
98+
"end": 7,
99+
"loc": {
100+
"start": {
101+
"line": 2,
102+
"column": 2
103+
},
104+
"end": {
105+
"line": 2,
106+
"column": 3
107+
}
108+
},
109+
"expression": {
110+
"type": "Identifier",
111+
"start": 6,
112+
"end": 7,
113+
"loc": {
114+
"start": {
115+
"line": 2,
116+
"column": 2
117+
},
118+
"end": {
119+
"line": 2,
120+
"column": 3
121+
},
122+
"identifierName": "a"
123+
},
124+
"name": "a"
125+
}
126+
}
127+
],
128+
"directives": [],
129+
"extra": {
130+
"curly": false
131+
}
132+
}
133+
},
134+
{
135+
"type": "Identifier",
136+
"start": 9,
137+
"end": 10,
138+
"loc": {
139+
"start": {
140+
"line": 2,
141+
"column": 5
142+
},
143+
"end": {
144+
"line": 2,
145+
"column": 6
146+
},
147+
"identifierName": "b"
148+
},
149+
"name": "b"
150+
}
151+
]
152+
}
153+
}
154+
],
155+
"directives": []
156+
}
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a! b() ->
2+
c, d

0 commit comments

Comments
 (0)