Interpolated strings - IS4Code/Sona GitHub Wiki
Interpolated strings are strings that contain dynamic parts that are expressed directly as embedded expressions. The results of the expressions can be optionally formatted using a special format string.
interpolated_string:
'$"' (string_part | '{{' | '}}' | interpolation)* '"';
verbatim_interpolated_string:
('$@"' | '@$"') (verbatim_string_part | '{{' | '}}' | interpolation)* '"';
interpolation:
'{' expression (',' alignment)? (':' (checked_format | unchecked_format)) '}';
The syntax for interpolated strings is derived from that of regular strings, with a preceding $
character. Inside the string, {expression}
is used to embed a dynamically-computed value between the surrounding parts of the string. Literal characters {
and }
are escaped by doubling them (even in a verbatim string).
The ,
and :
characters in an interpolation are followed by the alignment and format specification. Other occurrences of these characters in the interpolation are invalid and must be wrapped in parentheses. All other pieces of syntax are valid in an interpolation, even other strings.
The interpolation expression may be followed by alignment, consisting of a single integer indicating the number of spaces to fit in (positive if spaces are added to the right, negative if to the left).
The last component, after :
, is the format specification. It takes one of the following forms, in this priority:
-
A character literal, denoting a single-character standard .NET-style format. The character must be a letter. Both this and the following kind of format is not type-checked, and uses the value's implementation of
ToString
. -
A string or a verbatim string, denoting a custom .NET-style format, or a standard format with 2 or more characters. The string must not be a single letter.
-
An F#-style format, as a sequence of the form
[flags][width][.precision]type
. The type is indicated by a single letter and constrains the type of the interpolated value. As the other components are optional, any single letter matches this form. Unlike in F#,%
is not used to indicate this form (and has no special meaning within interpolated strings altogether). -
A standard or custom numeric format, constraining the type of the interpolation to a number. The format supports escape sequences using
\
and treats spaces, tabs,+
,-
,_
, and anything enclosed in'
as literal. The format is further restricted to avoid potential sources of errors or confusion with other formats:- The precision specifier in the standard format is restricted to a maximum of 99. (
G100
is invalid.) - In the custom format, the integral part (before the decimal point) must contain at least one
0
or#
specifier. (.0
is invalid.) - The
,
specifier, when used to separate groups, must be surrounded on both sides by0
or#
. (0,,0.0
is invalid.) When used as a scaling specifier, it must not be interrupted by any other character, and must be placed immediately to the left of the decimal point, or where the decimal point would be. (0, ,.0
or0.0,,,
is invalid.) - The decimal point character (
.
) may appear unescaped at most once, and must be immediately followed by a0
or#
character. (0.0.0
or0.
is invalid.) - The
0
specifiers must be all clustered around the decimal point with respect to the#
specifiers. (0#
or#.#0
is invalid.) - The
e
orE
custom specifier may not be placed before the decimal point and may appear only once. (0e0.0
is invalid.) - The
%
or‰
character may appear unescaped at most once, and must be located at the edge of a section. (0%.0
is invalid.) - The number of
;
-separated sections is limited to 3. The;
character may not appear unescaped anywhere else in the format. (0;0;0;0
is invalid.) - Literal characters and escapes are allowed in all meaningful positions (i.e. not between
,
and.
or insidee
/E
).
- The precision specifier in the standard format is restricted to a maximum of 99. (
-
A custom date, time, or time span format, constraining the type of the interpolation based on the specifiers occurring in the format:
-
h
,m
,s
,f
, orF
require the value to have the traittime
ortimespan
. -
y
orM
require the value to have the traitdate
ordatespan
. -
d
requires the value to have the traitdate
ortimespan
. -
g
or/
require the value to have the traitdate
. -
H
,t
, or:
require the value to have the traittime
. -
z
orK
require the value to have the traitsdate
andtime
. - The instant and span traits must not mix as the only way for a type to be valid, for example a type is never required to have both the
date
andtimespan
trait. - In case of a combination of these specifier groups, the traits are determined by a logical conjunction, for example
yh
requirestime
ortimespan
anddate
ordatespan
, which is further restricted by the previous rule totime
anddate
ortimespan
anddatespan
.
The format supports same literal/escape sequences as above. Likewise, there are restrictions on the syntax itself:
- At least one letter specifier (i.e. not
:
or/
) must be present. - With the exception of non-letter specifiers, a specifier may not appear multiple times, including variants that effectively expose the same value (up to padding/truncation). This depends on the accepted type of the value, for example
dd
anddddd
are considered the same specifier fortimespan
types, but different fordate
types. - A specifier may not consist of more characters than what is necessary for its effect. This also depends on the type, for example
ddddd
is valid fortimespan
types, but not fordate
. Note that%
may be used to treat the following character as a singular specifier, so both%ddddd
anddddd%d
are valid formats fordate
types (but nottimespan
due to repetition). - Only one of the
h
andH
specifiers may be used. - Only one of the
f
andF
specifiers may be used. - The format must have distinct sections for date (
y
,M
,d
,/
), time (h
,H
,m
,s
,f
,F
,t
,:
), time zone (z
,K
), and era (g
). A particular section type may not occur multiple times, therefore all specifiers pertaining to the same section must appear together. - The
:
specifier is allowed only between other time specifiers. - The
/
specifier is allowed only between other date specifiers. - The
%
character must not appear at the end of the format. - Escapes are allowed in all positions except when immediately following a non-escaped
%
character.
-