Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c9b169f

Browse files
Add support for labeled statements to the parser/AST
This is a prerequisite for supporting labeled breaks/continues. Clearly unusable labels, such as `x: let foo = 1;` report an error by default, similar to TS's behavior.
1 parent 40850fe commit c9b169f

File tree

3 files changed

+68
-18
lines changed

3 files changed

+68
-18
lines changed

‎src/ast.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -440,9 +440,10 @@ export abstract class Node {
440440

441441
static createBlockStatement(
442442
statements: Statement[],
443+
label: IdentifierExpression | null,
443444
range: Range
444445
): BlockStatement {
445-
return new BlockStatement(statements, range);
446+
return new BlockStatement(statements, label,range);
446447
}
447448

448449
static createBreakStatement(
@@ -475,9 +476,10 @@ export abstract class Node {
475476
static createDoStatement(
476477
body: Statement,
477478
condition: Expression,
479+
label: IdentifierExpression | null,
478480
range: Range
479481
): DoStatement {
480-
return new DoStatement(body, condition, range);
482+
return new DoStatement(body, condition, label,range);
481483
}
482484

483485
static createEmptyStatement(
@@ -607,18 +609,20 @@ export abstract class Node {
607609
condition: Expression | null,
608610
incrementor: Expression | null,
609611
body: Statement,
612+
label: IdentifierExpression | null,
610613
range: Range
611614
): ForStatement {
612-
return new ForStatement(initializer, condition, incrementor, body, range);
615+
return new ForStatement(initializer, condition, incrementor, body, label,range);
613616
}
614617

615618
static createForOfStatement(
616619
variable: Statement,
617620
iterable: Expression,
618621
body: Statement,
622+
label: IdentifierExpression | null,
619623
range: Range
620624
): ForOfStatement {
621-
return new ForOfStatement(variable, iterable, body, range);
625+
return new ForOfStatement(variable, iterable, body, label,range);
622626
}
623627

624628
static createFunctionDeclaration(
@@ -753,9 +757,10 @@ export abstract class Node {
753757
static createWhileStatement(
754758
condition: Expression,
755759
statement: Statement,
760+
label: IdentifierExpression | null,
756761
range: Range
757762
): WhileStatement {
758-
return new WhileStatement(condition, statement, range);
763+
return new WhileStatement(condition, statement, label,range);
759764
}
760765

761766
/** Tests if this node is a literal of the specified kind. */
@@ -1788,6 +1793,8 @@ export class BlockStatement extends Statement {
17881793
constructor(
17891794
/** Contained statements. */
17901795
public statements: Statement[],
1796+
/** Label, if any. */
1797+
public label: IdentifierExpression | null,
17911798
/** Source range. */
17921799
range: Range
17931800
) {
@@ -1858,6 +1865,8 @@ export class DoStatement extends Statement {
18581865
public body: Statement,
18591866
/** Condition when to repeat. */
18601867
public condition: Expression,
1868+
/** Label, if any. */
1869+
public label: IdentifierExpression | null,
18611870
/** Source range. */
18621871
range: Range
18631872
) {
@@ -2022,6 +2031,8 @@ export class ForStatement extends Statement {
20222031
public incrementor: Expression | null,
20232032
/** Body statement being looped over. */
20242033
public body: Statement,
2034+
/** Label, if any. */
2035+
public label: IdentifierExpression | null,
20252036
/** Source range. */
20262037
range: Range
20272038
) {
@@ -2038,6 +2049,8 @@ export class ForOfStatement extends Statement {
20382049
public iterable: Expression,
20392050
/** Body statement being looped over. */
20402051
public body: Statement,
2052+
/** Label, if any. */
2053+
public label: IdentifierExpression | null,
20412054
/** Source range. */
20422055
range: Range
20432056
) {
@@ -2382,6 +2395,8 @@ export class WhileStatement extends Statement {
23822395
public condition: Expression,
23832396
/** Body statement being looped over. */
23842397
public body: Statement,
2398+
/** Label, if any. */
2399+
public label: IdentifierExpression | null,
23852400
/** Source range. */
23862401
range: Range
23872402
) {

‎src/diagnosticMessages.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
"A class may only extend another class.": 1311,
126126
"A parameter property cannot be declared using a rest parameter.": 1317,
127127
"A default export can only be used in a module.": 1319,
128+
"A label is not allowed here.": 1344,
128129
"An expression of type '{0}' cannot be tested for truthiness.": 1345,
129130
"An identifier or keyword cannot immediately follow a numeric literal.": 1351,
130131

‎src/parser.ts

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,7 +2899,34 @@ export class Parser extends DiagnosticEmitter {
28992899

29002900
let state = tn.mark();
29012901
let token = tn.next();
2902+
let label: IdentifierExpression | null = null;
29022903
let statement: Statement | null = null;
2904+
2905+
// Detect labeled statements
2906+
if (token == Token.Identifier) {
2907+
const preIdentifierState = tn.mark();
2908+
const identifier = tn.readIdentifier();
2909+
const range = tn.range();
2910+
2911+
if (tn.skip(Token.Colon)) {
2912+
label = Node.createIdentifierExpression(identifier, range);
2913+
token = tn.next();
2914+
2915+
switch (token) {
2916+
case Token.For:
2917+
case Token.While:
2918+
case Token.Do:
2919+
case Token.OpenBrace:
2920+
// Do nothing
2921+
break;
2922+
default:
2923+
this.error(DiagnosticCode.A_label_is_not_allowed_here, range);
2924+
}
2925+
} else {
2926+
tn.reset(preIdentifierState);
2927+
}
2928+
}
2929+
29032930
switch (token) {
29042931
case Token.Break: {
29052932
statement = this.parseBreak(tn);
@@ -2914,11 +2941,11 @@ export class Parser extends DiagnosticEmitter {
29142941
break;
29152942
}
29162943
case Token.Do: {
2917-
statement = this.parseDoStatement(tn);
2944+
statement = this.parseDoStatement(tn,label);
29182945
break;
29192946
}
29202947
case Token.For: {
2921-
statement = this.parseForStatement(tn);
2948+
statement = this.parseForStatement(tn,label);
29222949
break;
29232950
}
29242951
case Token.If: {
@@ -2934,7 +2961,7 @@ export class Parser extends DiagnosticEmitter {
29342961
break;
29352962
}
29362963
case Token.OpenBrace: {
2937-
statement = this.parseBlockStatement(tn, topLevel);
2964+
statement = this.parseBlockStatement(tn, topLevel,label);
29382965
break;
29392966
}
29402967
case Token.Return: {
@@ -2967,7 +2994,7 @@ export class Parser extends DiagnosticEmitter {
29672994
break;
29682995
}
29692996
case Token.While: {
2970-
statement = this.parseWhileStatement(tn);
2997+
statement = this.parseWhileStatement(tn,label);
29712998
break;
29722999
}
29733000
case Token.Type: { // also identifier
@@ -2994,7 +3021,8 @@ export class Parser extends DiagnosticEmitter {
29943021

29953022
parseBlockStatement(
29963023
tn: Tokenizer,
2997-
topLevel: bool
3024+
topLevel: bool,
3025+
label: IdentifierExpression | null = null
29983026
): BlockStatement | null {
29993027

30003028
// at '{': Statement* '}' ';'?
@@ -3013,7 +3041,7 @@ export class Parser extends DiagnosticEmitter {
30133041
statements.push(statement);
30143042
}
30153043
}
3016-
let ret = Node.createBlockStatement(statements, tn.range(startPos, tn.pos));
3044+
let ret = Node.createBlockStatement(statements, label,tn.range(startPos, tn.pos));
30173045
if (topLevel) tn.skip(Token.Semicolon);
30183046
return ret;
30193047
}
@@ -3051,7 +3079,8 @@ export class Parser extends DiagnosticEmitter {
30513079
}
30523080

30533081
parseDoStatement(
3054-
tn: Tokenizer
3082+
tn: Tokenizer,
3083+
label: IdentifierExpression | null
30553084
): DoStatement | null {
30563085

30573086
// at 'do': Statement 'while' '(' Expression ')' ';'?
@@ -3067,7 +3096,7 @@ export class Parser extends DiagnosticEmitter {
30673096
if (!condition) return null;
30683097

30693098
if (tn.skip(Token.CloseParen)) {
3070-
let ret = Node.createDoStatement(statement, condition, tn.range(startPos, tn.pos));
3099+
let ret = Node.createDoStatement(statement, condition, label,tn.range(startPos, tn.pos));
30713100
tn.skip(Token.Semicolon);
30723101
return ret;
30733102
} else {
@@ -3106,7 +3135,8 @@ export class Parser extends DiagnosticEmitter {
31063135
}
31073136

31083137
parseForStatement(
3109-
tn: Tokenizer
3138+
tn: Tokenizer,
3139+
label: IdentifierExpression | null
31103140
): Statement | null {
31113141

31123142
// at 'for': '(' Statement? Expression? ';' Expression? ')' Statement
@@ -3139,7 +3169,7 @@ export class Parser extends DiagnosticEmitter {
31393169
);
31403170
return null;
31413171
}
3142-
return this.parseForOfStatement(tn, startPos, initializer);
3172+
return this.parseForOfStatement(tn, startPos, initializer,label);
31433173
}
31443174
if (initializer.kind == NodeKind.Variable) {
31453175
let declarations = (<VariableStatement>initializer).declarations;
@@ -3153,7 +3183,7 @@ export class Parser extends DiagnosticEmitter {
31533183
); // recoverable
31543184
}
31553185
}
3156-
return this.parseForOfStatement(tn, startPos, initializer);
3186+
return this.parseForOfStatement(tn, startPos, initializer,label);
31573187
}
31583188
this.error(
31593189
DiagnosticCode.Identifier_expected,
@@ -3215,6 +3245,7 @@ export class Parser extends DiagnosticEmitter {
32153245
: null,
32163246
incrementor,
32173247
statement,
3248+
label,
32183249
tn.range(startPos, tn.pos)
32193250
);
32203251

@@ -3243,6 +3274,7 @@ export class Parser extends DiagnosticEmitter {
32433274
tn: Tokenizer,
32443275
startPos: i32,
32453276
variable: Statement,
3277+
label: IdentifierExpression | null
32463278
): ForOfStatement | null {
32473279

32483280
// at 'of': Expression ')' Statement
@@ -3265,6 +3297,7 @@ export class Parser extends DiagnosticEmitter {
32653297
variable,
32663298
iterable,
32673299
statement,
3300+
label,
32683301
tn.range(startPos, tn.pos)
32693302
);
32703303
}
@@ -3609,7 +3642,8 @@ export class Parser extends DiagnosticEmitter {
36093642
}
36103643

36113644
parseWhileStatement(
3612-
tn: Tokenizer
3645+
tn: Tokenizer,
3646+
label: IdentifierExpression | null
36133647
): WhileStatement | null {
36143648

36153649
// at 'while': '(' Expression ')' Statement ';'?
@@ -3621,7 +3655,7 @@ export class Parser extends DiagnosticEmitter {
36213655
if (tn.skip(Token.CloseParen)) {
36223656
let statement = this.parseStatement(tn);
36233657
if (!statement) return null;
3624-
let ret = Node.createWhileStatement(expression, statement, tn.range(startPos, tn.pos));
3658+
let ret = Node.createWhileStatement(expression, statement, label,tn.range(startPos, tn.pos));
36253659
tn.skip(Token.Semicolon);
36263660
return ret;
36273661
} else {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /