Skip to content

Commit 7e52517

Browse files
authored
Parser syntax sparse bl (#76)
* Handle sparse messages in fluent-syntax * Fix tests affected by the sparse message parsing change * Handle sparse messages in fluent runtime * Fix linting errors * Apply reviewers feedback * One more indent
1 parent 64ef212 commit 7e52517

File tree

10 files changed

+613
-26
lines changed

10 files changed

+613
-26
lines changed

fluent-syntax/src/ftlstream.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ export class FTLParserStream extends ParserStream {
3131
}
3232
}
3333

34+
peekBlankLines() {
35+
while (true) {
36+
const lineStart = this.getPeekIndex();
37+
38+
this.peekInlineWS();
39+
40+
if (this.currentPeekIs('\n')) {
41+
this.peek();
42+
} else {
43+
this.resetPeek(lineStart);
44+
break;
45+
}
46+
}
47+
}
48+
3449
skipInlineWS() {
3550
while (this.ch) {
3651
if (!includes(INLINE_WS, this.ch)) {
@@ -54,6 +69,13 @@ export class FTLParserStream extends ParserStream {
5469
throw new ParseError('E0003', ch);
5570
}
5671

72+
expectIndent() {
73+
this.expectChar('\n');
74+
this.skipBlankLines();
75+
this.expectChar(' ');
76+
this.skipInlineWS();
77+
}
78+
5779
takeCharIf(ch) {
5880
if (this.ch === ch) {
5981
this.next();
@@ -94,6 +116,8 @@ export class FTLParserStream extends ParserStream {
94116

95117
this.peek();
96118

119+
this.peekBlankLines();
120+
97121
const ptr = this.getPeekIndex();
98122

99123
this.peekInlineWS();
@@ -122,6 +146,8 @@ export class FTLParserStream extends ParserStream {
122146

123147
this.peek();
124148

149+
this.peekBlankLines();
150+
125151
const ptr = this.getPeekIndex();
126152

127153
this.peekInlineWS();
@@ -140,13 +166,15 @@ export class FTLParserStream extends ParserStream {
140166
return false;
141167
}
142168

143-
isPeekNextLinePattern() {
169+
isPeekNextNonBlankLinePattern() {
144170
if (!this.currentPeekIs('\n')) {
145171
return false;
146172
}
147173

148174
this.peek();
149175

176+
this.peekBlankLines();
177+
150178
const ptr = this.getPeekIndex();
151179

152180
this.peekInlineWS();
@@ -176,6 +204,8 @@ export class FTLParserStream extends ParserStream {
176204

177205
this.peek();
178206

207+
this.peekBlankLines();
208+
179209
const ptr = this.getPeekIndex();
180210

181211
this.peekInlineWS();

fluent-syntax/src/parser.js

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ export default class FluentParser {
197197
if (ps.currentIs('=')) {
198198
ps.next();
199199
ps.skipInlineWS();
200+
ps.skipBlankLines();
200201

201202
pattern = this.getPattern(ps);
202203
}
@@ -241,8 +242,7 @@ export default class FluentParser {
241242
const attrs = [];
242243

243244
while (true) {
244-
ps.expectChar('\n');
245-
ps.skipInlineWS();
245+
ps.expectIndent();
246246

247247
const attr = this.getAttribute(ps);
248248
attrs.push(attr);
@@ -264,8 +264,7 @@ export default class FluentParser {
264264
const tags = [];
265265

266266
while (true) {
267-
ps.expectChar('\n');
268-
ps.skipInlineWS();
267+
ps.expectIndent();
269268

270269
const tag = this.getTag(ps);
271270
tags.push(tag);
@@ -340,8 +339,7 @@ export default class FluentParser {
340339
let hasDefault = false;
341340

342341
while (true) {
343-
ps.expectChar('\n');
344-
ps.skipInlineWS();
342+
ps.expectIndent();
345343

346344
const variant = this.getVariant(ps, hasDefault);
347345

@@ -419,7 +417,7 @@ export default class FluentParser {
419417
ps.skipInlineWS();
420418

421419
// Special-case: trim leading whitespace and newlines.
422-
if (ps.isPeekNextLinePattern()) {
420+
if (ps.isPeekNextNonBlankLinePattern()) {
423421
ps.skipBlankLines();
424422
ps.skipInlineWS();
425423
}
@@ -429,7 +427,7 @@ export default class FluentParser {
429427

430428
// The end condition for getPattern's while loop is a newline
431429
// which is not followed by a valid pattern continuation.
432-
if (ch === '\n' && !ps.isPeekNextLinePattern()) {
430+
if (ch === '\n' && !ps.isPeekNextNonBlankLinePattern()) {
433431
break;
434432
}
435433

@@ -456,7 +454,7 @@ export default class FluentParser {
456454
}
457455

458456
if (ch === '\n') {
459-
if (!ps.isPeekNextLinePattern()) {
457+
if (!ps.isPeekNextNonBlankLinePattern()) {
460458
return new AST.TextElement(buffer);
461459
}
462460

@@ -498,9 +496,7 @@ export default class FluentParser {
498496
if (ps.isPeekNextLineVariantStart()) {
499497
const variants = this.getVariants(ps);
500498

501-
ps.expectChar('\n');
502-
ps.expectChar(' ');
503-
ps.skipInlineWS();
499+
ps.expectIndent();
504500

505501
return new AST.SelectExpression(null, variants);
506502
}
@@ -523,13 +519,12 @@ export default class FluentParser {
523519

524520
const variants = this.getVariants(ps);
525521

522+
526523
if (variants.length === 0) {
527524
throw new ParseError('E0011');
528525
}
529526

530-
ps.expectChar('\n');
531-
ps.expectChar(' ');
532-
ps.skipInlineWS();
527+
ps.expectIndent();
533528

534529
return new AST.SelectExpression(selector, variants);
535530
}

fluent-syntax/src/stream.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,16 @@ export class ParserStream {
102102
return ret === ch;
103103
}
104104

105-
resetPeek() {
106-
this.peekIndex = this.index;
107-
this.peekEnd = this.iterEnd;
105+
resetPeek(pos) {
106+
if (pos) {
107+
if (pos < this.peekIndex) {
108+
this.peekEnd = false;
109+
}
110+
this.peekIndex = pos;
111+
} else {
112+
this.peekIndex = this.index;
113+
this.peekEnd = this.iterEnd;
114+
}
108115
}
109116

110117
skipToPeek() {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
key = { $foo ->
2-
//~ ERROR E0003, pos 16, args "["
2+
//~ ERROR E0003, pos 16, args " "

fluent-syntax/test/fixtures_structure/message_with_empty_pattern.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"elements": [],
1919
"span": {
2020
"type": "Span",
21-
"start": 6,
22-
"end": 6
21+
"start": 7,
22+
"end": 7
2323
}
2424
},
2525
"attributes": [],
@@ -28,7 +28,7 @@
2828
"span": {
2929
"type": "Span",
3030
"start": 0,
31-
"end": 6
31+
"end": 7
3232
}
3333
}
3434
],

fluent-syntax/test/fixtures_structure/placeable_at_eol.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
],
6363
"span": {
6464
"type": "Span",
65-
"start": 6,
65+
"start": 7,
6666
"end": 131
6767
}
6868
},
@@ -127,7 +127,7 @@
127127
],
128128
"span": {
129129
"type": "Span",
130-
"start": 139,
130+
"start": 140,
131131
"end": 184
132132
}
133133
},
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
key =
2+
3+
4+
Value
5+
6+
key2
7+
8+
9+
.attr = Attribute
10+
11+
12+
key3 =
13+
Value
14+
Value2
15+
16+
17+
Value 4
18+
Value3
19+
20+
21+
22+
.attr2 = Attr 2
23+
24+
25+
key4 = Value
26+
27+
28+
#tag1
29+
30+
31+
#tag2
32+
key5 = Value 5
33+
34+
key6 = {
35+
36+
37+
[one] One
38+
39+
40+
41+
42+
*[two] Two
43+
44+
45+
46+
}

0 commit comments

Comments
 (0)