Skip to content

Commit 01dddf6

Browse files
johnniwintherCommit Queue
authored andcommitted
[_fe_analyzer_shared] Shared literal parsing
This adds shared helpers for parsing bool, int, and double literals to their corresponding values. The macro metadata literals are updated support digit separators and to hold the literal value. Change-Id: I709018b6c3a3b8ab09188d36c28f3c09636e0ea0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391964 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Jens Johansen <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent d1d029f commit 01dddf6

File tree

8 files changed

+107
-46
lines changed

8 files changed

+107
-46
lines changed

pkg/_fe_analyzer_shared/lib/src/metadata/expressions.dart

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,21 +90,25 @@ class ConstructorInvocation extends Expression {
9090
}
9191

9292
class IntegerLiteral extends Expression {
93-
final String text;
93+
final String? text;
94+
final int? value;
95+
96+
IntegerLiteral.fromText(String this.text, [this.value]);
9497

95-
IntegerLiteral(this.text);
98+
IntegerLiteral.fromValue(int this.value) : text = null;
9699

97100
@override
98-
String toString() => 'IntegerLiteral($text)';
101+
String toString() => 'IntegerLiteral(${value ?? text})';
99102

100103
@override
101104
Expression? resolve() => null;
102105
}
103106

104107
class DoubleLiteral extends Expression {
105108
final String text;
109+
final double value;
106110

107-
DoubleLiteral(this.text);
111+
DoubleLiteral(this.text, this.value);
108112

109113
@override
110114
String toString() => 'DoubleLiteral($text)';
@@ -114,12 +118,12 @@ class DoubleLiteral extends Expression {
114118
}
115119

116120
class BooleanLiteral extends Expression {
117-
final String text;
121+
final bool value;
118122

119-
BooleanLiteral(this.text);
123+
BooleanLiteral(this.value);
120124

121125
@override
122-
String toString() => 'BooleanLiteral($text)';
126+
String toString() => 'BooleanLiteral($value)';
123127

124128
@override
125129
Expression? resolve() => null;

pkg/_fe_analyzer_shared/lib/src/metadata/parser.dart

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,17 +577,31 @@ class AnnotationsListener extends StackListener {
577577

578578
@override
579579
void handleLiteralInt(Token token) {
580-
push(new ExpressionProto(new IntegerLiteral(token.lexeme)));
580+
int? value = intFromToken(token, hasSeparators: false);
581+
push(new ExpressionProto(new IntegerLiteral.fromText(token.lexeme, value)));
582+
}
583+
584+
@override
585+
void handleLiteralIntWithSeparators(Token token) {
586+
int? value = intFromToken(token, hasSeparators: true);
587+
push(new ExpressionProto(new IntegerLiteral.fromText(token.lexeme, value)));
581588
}
582589

583590
@override
584591
void handleLiteralDouble(Token token) {
585-
push(new ExpressionProto(new DoubleLiteral(token.lexeme)));
592+
push(new ExpressionProto(new DoubleLiteral(
593+
token.lexeme, doubleFromToken(token, hasSeparators: false))));
594+
}
595+
596+
@override
597+
void handleLiteralDoubleWithSeparators(Token token) {
598+
push(new ExpressionProto(new DoubleLiteral(
599+
token.lexeme, doubleFromToken(token, hasSeparators: true))));
586600
}
587601

588602
@override
589603
void handleLiteralBool(Token token) {
590-
push(new ExpressionProto(new BooleanLiteral(token.lexeme)));
604+
push(new ExpressionProto(new BooleanLiteral(boolFromToken(token))));
591605
}
592606

593607
@override
@@ -953,7 +967,8 @@ enum _NullValues implements NullValue<Object> {
953967
TypeAnnotations,
954968
}
955969

956-
final Argument _dummyArgument = new PositionalArgument(new IntegerLiteral('0'));
970+
final Argument _dummyArgument =
971+
new PositionalArgument(new IntegerLiteral.fromText('0'));
957972

958973
final RecordField _dummyRecordField =
959974
new RecordPositionalField(_dummyExpression);

pkg/_fe_analyzer_shared/lib/src/parser/parser.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,15 @@ export 'parser_error.dart' show ParserError;
4141

4242
export 'top_level_parser.dart' show TopLevelParser;
4343

44-
export 'util.dart' show lengthForToken, lengthOfSpan, optional;
44+
export 'util.dart'
45+
show
46+
boolFromToken,
47+
doubleFromToken,
48+
intFromToken,
49+
lengthForToken,
50+
lengthOfSpan,
51+
optional,
52+
stripSeparators;
4553

4654
class ErrorCollectingListener extends Listener {
4755
final List<ParserError> recoverableErrors = <ParserError>[];

pkg/_fe_analyzer_shared/lib/src/parser/util.dart

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'dart:typed_data';
88

99
import '../messages/codes.dart' show noLength;
1010

11-
import '../scanner/scanner.dart' show Token;
11+
import '../scanner/scanner.dart' show Keyword, Token;
1212

1313
import '../scanner/token.dart'
1414
show BeginToken, SimpleToken, SyntheticToken, TokenIsAExtension, TokenType;
@@ -248,3 +248,39 @@ Token syntheticGt(Token next) {
248248
// so that the previous token is not set.
249249
..next = next;
250250
}
251+
252+
/// Returns the boolean value from a 'true' or 'false' [token].
253+
bool boolFromToken(Token token) {
254+
bool value = token.isA(Keyword.TRUE);
255+
assert(value || token.isA(Keyword.FALSE));
256+
return value;
257+
}
258+
259+
/// Returns the integer value from an integer literal token.
260+
///
261+
/// If [hasSeparators], separator characters, '_', are stripped before parsing
262+
/// the token text.
263+
///
264+
/// `null` is returned if the token text could not be parsed as an integer
265+
/// value. This does _not_ mean that the token is not valid as an integer token
266+
/// since negated integer literals are parsed as a unary operation on the
267+
/// positive integer.
268+
int? intFromToken(Token token, {required bool hasSeparators}) {
269+
String text = token.lexeme;
270+
if (hasSeparators) {
271+
text = stripSeparators(text);
272+
}
273+
return int.tryParse(text);
274+
}
275+
276+
/// Returns the double value from an double literal token.
277+
///
278+
/// If [hasSeparators], separator characters, '_', are stripped before parsing
279+
/// the token text.
280+
double doubleFromToken(Token token, {required bool hasSeparators}) {
281+
String text = token.lexeme;
282+
if (hasSeparators) {
283+
text = stripSeparators(text);
284+
}
285+
return double.parse(text);
286+
}

pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,19 @@ class Writer {
124124
_write(')');
125125
case IntegerLiteral():
126126
_write('IntegerLiteral(');
127-
_write(expression.text);
127+
if (expression.text != null) {
128+
_write(expression.text!);
129+
} else {
130+
_write('value=${expression.value}');
131+
}
128132
_write(')');
129133
case DoubleLiteral():
130134
_write('DoubleLiteral(');
131135
_write(expression.text);
132136
_write(')');
133137
case BooleanLiteral():
134138
_write('BooleanLiteral(');
135-
_write(expression.text);
139+
_write('${expression.value}');
136140
_write(')');
137141
case NullLiteral():
138142
_write('NullLiteral()');

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,20 @@ import 'package:_fe_analyzer_shared/src/parser/parser.dart'
3535
show
3636
Assert,
3737
BlockKind,
38+
boolFromToken,
3839
ConstructorReferenceContext,
3940
DeclarationHeaderKind,
4041
DeclarationKind,
42+
doubleFromToken,
4143
FormalParameterKind,
4244
IdentifierContext,
45+
intFromToken,
4346
MemberKind,
4447
optional,
4548
Parser;
4649
import 'package:_fe_analyzer_shared/src/parser/quote.dart';
4750
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
4851
show NullValues, StackListener;
49-
import 'package:_fe_analyzer_shared/src/parser/util.dart' show stripSeparators;
5052
import 'package:_fe_analyzer_shared/src/scanner/errors.dart'
5153
show translateErrorToken;
5254
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
@@ -4708,8 +4710,7 @@ class AstBuilder extends StackListener {
47084710

47094711
@override
47104712
void handleLiteralBool(Token token) {
4711-
bool value = identical(token.stringValue, "true");
4712-
assert(value || identical(token.stringValue, "false"));
4713+
bool value = boolFromToken(token);
47134714
debugEvent("LiteralBool");
47144715

47154716
push(
@@ -4745,14 +4746,10 @@ class AstBuilder extends StackListener {
47454746
);
47464747
}
47474748

4748-
// Only copy `source` if we find a separator ('_'). Most int literals
4749-
// will not have any separator, and so a quick scan will show we do not
4750-
// need to produce a new String.
4751-
var source = stripSeparators(token.lexeme);
47524749
push(
47534750
DoubleLiteralImpl(
47544751
literal: token,
4755-
value: double.parse(source),
4752+
value: doubleFromToken(token, hasSeparators: true),
47564753
),
47574754
);
47584755
}
@@ -4766,7 +4763,7 @@ class AstBuilder extends StackListener {
47664763
push(
47674764
IntegerLiteralImpl(
47684765
literal: token,
4769-
value: int.tryParse(token.lexeme),
4766+
value: intFromToken(token, hasSeparators: false),
47704767
),
47714768
);
47724769
}
@@ -4784,11 +4781,10 @@ class AstBuilder extends StackListener {
47844781
);
47854782
}
47864783

4787-
var source = stripSeparators(token.lexeme);
47884784
push(
47894785
IntegerLiteralImpl(
47904786
literal: token,
4791-
value: int.tryParse(source),
4787+
value: intFromToken(token, hasSeparators: true),
47924788
),
47934789
);
47944790
}

pkg/front_end/lib/src/kernel/body_builder.dart

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ import 'package:_fe_analyzer_shared/src/parser/parser.dart'
1414
IdentifierContext,
1515
MemberKind,
1616
Parser,
17+
boolFromToken,
18+
doubleFromToken,
19+
intFromToken,
1720
lengthForToken,
18-
lengthOfSpan;
21+
lengthOfSpan,
22+
stripSeparators;
1923
import 'package:_fe_analyzer_shared/src/parser/quote.dart'
2024
show
2125
Quote,
@@ -26,7 +30,6 @@ import 'package:_fe_analyzer_shared/src/parser/quote.dart'
2630
unescapeString;
2731
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
2832
show FixedNullableList, GrowableList, NullValues, ParserRecovery;
29-
import 'package:_fe_analyzer_shared/src/parser/util.dart' show stripSeparators;
3033
import 'package:_fe_analyzer_shared/src/scanner/token.dart'
3134
show Keyword, Token, TokenIsAExtension, TokenType;
3235
import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
@@ -3526,7 +3529,7 @@ class BodyBuilder extends StackListenerImpl
35263529
@override
35273530
void handleLiteralInt(Token token) {
35283531
debugEvent("LiteralInt");
3529-
int? value = int.tryParse(token.lexeme);
3532+
int? value = intFromToken(token, hasSeparators: false);
35303533
// Postpone parsing of literals resulting in a negative value
35313534
// (hex literals >= 2^63). These are only allowed when not negated.
35323535
if (value == null || value < 0) {
@@ -4795,16 +4798,15 @@ class BodyBuilder extends StackListenerImpl
47954798
@override
47964799
void handleLiteralBool(Token token) {
47974800
debugEvent("LiteralBool");
4798-
bool value = token.isA(Keyword.TRUE);
4799-
assert(value || token.isA(Keyword.FALSE));
4801+
bool value = boolFromToken(token);
48004802
push(forest.createBoolLiteral(offsetForToken(token), value));
48014803
}
48024804

48034805
@override
48044806
void handleLiteralDouble(Token token) {
48054807
debugEvent("LiteralDouble");
48064808
push(forest.createDoubleLiteral(
4807-
offsetForToken(token), double.parse(token.lexeme)));
4809+
offsetForToken(token), doubleFromToken(token, hasSeparators: false)));
48084810
}
48094811

48104812
@override
@@ -4819,8 +4821,7 @@ class BodyBuilder extends StackListenerImpl
48194821
token.length);
48204822
}
48214823

4822-
String source = stripSeparators(token.lexeme);
4823-
double value = double.parse(source);
4824+
double value = doubleFromToken(token, hasSeparators: true);
48244825
push(forest.createDoubleLiteral(offsetForToken(token), value));
48254826
}
48264827

pkg/front_end/lib/src/kernel/macro/annotation_parser.dart

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'package:_fe_analyzer_shared/src/experiments/flags.dart';
66
import 'package:_fe_analyzer_shared/src/messages/codes.dart';
77
import 'package:_fe_analyzer_shared/src/parser/parser.dart';
88
import 'package:_fe_analyzer_shared/src/parser/quote.dart';
9-
import 'package:_fe_analyzer_shared/src/parser/util.dart' show stripSeparators;
109
import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
1110
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
1211
import 'package:macros/src/executor.dart' as macro;
@@ -406,33 +405,31 @@ class _MacroListener implements Listener {
406405

407406
@override
408407
void handleLiteralBool(Token token) {
409-
push(
410-
new _MacroArgumentNode(new macro.BoolArgument(token.lexeme == 'true')));
408+
push(new _MacroArgumentNode(new macro.BoolArgument(boolFromToken(token))));
411409
}
412410

413411
@override
414412
void handleLiteralDouble(Token token) {
415-
push(new _MacroArgumentNode(
416-
new macro.DoubleArgument(double.parse(token.lexeme))));
413+
push(new _MacroArgumentNode(new macro.DoubleArgument(
414+
doubleFromToken(token, hasSeparators: false))));
417415
}
418416

419417
@override
420418
void handleLiteralDoubleWithSeparators(Token token) {
421-
String source = stripSeparators(token.lexeme);
422-
push(
423-
new _MacroArgumentNode(new macro.DoubleArgument(double.parse(source))));
419+
push(new _MacroArgumentNode(new macro.DoubleArgument(
420+
doubleFromToken(token, hasSeparators: true))));
424421
}
425422

426423
@override
427424
void handleLiteralInt(Token token) {
428-
push(
429-
new _MacroArgumentNode(new macro.IntArgument(int.parse(token.lexeme))));
425+
push(new _MacroArgumentNode(new macro.IntArgument(
426+
intFromToken(token, hasSeparators: false)!)));
430427
}
431428

432429
@override
433430
void handleLiteralIntWithSeparators(Token token) {
434-
String source = stripSeparators(token.lexeme);
435-
push(new _MacroArgumentNode(new macro.IntArgument(int.parse(source))));
431+
push(new _MacroArgumentNode(
432+
new macro.IntArgument(intFromToken(token, hasSeparators: true)!)));
436433
}
437434

438435
@override

0 commit comments

Comments
 (0)