Skip to content

Commit 8cb3c47

Browse files
committed
implicit-concat-as-joined-str
1 parent 9af9c16 commit 8cb3c47

File tree

3 files changed

+55
-32
lines changed

3 files changed

+55
-32
lines changed

compiler/parser/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ edition = "2021"
1010

1111
[features]
1212
default = ["lalrpop"] # removing this causes potential build failure
13+
implicit-concat-as-joined-str = []
1314

1415
[build-dependencies]
1516
anyhow = "1.0.45"

compiler/parser/src/string.rs

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,29 @@ pub fn parse_strings(
2929
});
3030
}
3131

32+
if values.len() > 1 && cfg!(feature = "implicit-concat-as-joined-str") {
33+
let mut exprs: Vec<Expr> = vec![];
34+
for (start, (source, kind, triple_quoted), end) in values {
35+
let expr = parse_string(&source, kind, triple_quoted, start, end)?;
36+
exprs.push(expr);
37+
}
38+
return Ok(Expr::new(
39+
initial_start,
40+
last_end,
41+
ExprKind::JoinedStr { values: exprs },
42+
));
43+
}
44+
3245
if has_bytes {
3346
let mut content: Vec<u8> = vec![];
3447
for (start, (source, kind, triple_quoted), end) in values {
35-
for value in parse_string(&source, kind, triple_quoted, start, end)? {
36-
match value.node {
37-
ExprKind::Constant {
38-
value: Constant::Bytes(value),
39-
..
40-
} => content.extend(value),
41-
_ => unreachable!("Unexpected non-bytes expression."),
42-
}
48+
let expr = parse_string(&source, kind, triple_quoted, start, end)?;
49+
match expr.node {
50+
ExprKind::Constant {
51+
value: Constant::Bytes(value),
52+
..
53+
} => content.extend(value),
54+
_ => unreachable!("Unexpected non-bytes expression."),
4355
}
4456
}
4557
return Ok(Expr::new(
@@ -55,14 +67,13 @@ pub fn parse_strings(
5567
if !has_fstring {
5668
let mut content: Vec<String> = vec![];
5769
for (start, (source, kind, triple_quoted), end) in values {
58-
for value in parse_string(&source, kind, triple_quoted, start, end)? {
59-
match value.node {
60-
ExprKind::Constant {
61-
value: Constant::Str(value),
62-
..
63-
} => content.push(value),
64-
_ => unreachable!("Unexpected non-string expression."),
65-
}
70+
let expr = parse_string(&source, kind, triple_quoted, start, end)?;
71+
match expr.node {
72+
ExprKind::Constant {
73+
value: Constant::Str(value),
74+
..
75+
} => content.push(value),
76+
_ => unreachable!("Unexpected non-string expression."),
6677
}
6778
}
6879
return Ok(Expr::new(
@@ -91,20 +102,30 @@ pub fn parse_strings(
91102
};
92103

93104
for (start, (source, kind, triple_quoted), end) in values {
94-
for value in parse_string(&source, kind, triple_quoted, start, end)? {
95-
match value.node {
96-
ExprKind::FormattedValue { .. } => {
97-
if !current.is_empty() {
98-
deduped.push(take_current(&mut current));
105+
let expr = parse_string(&source, kind, triple_quoted, start, end)?;
106+
match expr.node {
107+
ExprKind::Constant {
108+
value: Constant::Str(value),
109+
..
110+
} => current.push(value),
111+
ExprKind::JoinedStr { values } => {
112+
for value in values {
113+
match value.node {
114+
ExprKind::Constant {
115+
value: Constant::Str(value),
116+
..
117+
} => current.push(value),
118+
ExprKind::FormattedValue { .. } => {
119+
if !current.is_empty() {
120+
deduped.push(take_current(&mut current));
121+
}
122+
deduped.push(value)
123+
}
124+
_ => unreachable!("Unexpected non-string expression."),
99125
}
100-
deduped.push(value)
101126
}
102-
ExprKind::Constant {
103-
value: Constant::Str(value),
104-
..
105-
} => current.push(value),
106-
_ => unreachable!("Unexpected non-string expression."),
107127
}
128+
_ => unreachable!("Unexpected non-string expression."),
108129
}
109130
}
110131
if !current.is_empty() {

compiler/parser/src/string_parser.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,13 +506,14 @@ impl<'a> StringParser<'a> {
506506
}))
507507
}
508508

509-
pub fn parse(&mut self) -> Result<Vec<Expr>, LexicalError> {
509+
pub fn parse(&mut self) -> Result<Expr, LexicalError> {
510510
if self.kind.is_fstring() {
511511
self.parse_fstring(0)
512+
.map(|values| self.expr(ExprKind::JoinedStr { values }))
512513
} else if self.kind.is_bytes() {
513-
self.parse_bytes().map(|expr| vec![expr])
514+
self.parse_bytes()
514515
} else {
515-
self.parse_string().map(|expr| vec![expr])
516+
self.parse_string()
516517
}
517518
}
518519
}
@@ -528,15 +529,15 @@ pub fn parse_string(
528529
triple_quoted: bool,
529530
start: Location,
530531
end: Location,
531-
) -> Result<Vec<Expr>, LexicalError> {
532+
) -> Result<Expr, LexicalError> {
532533
StringParser::new(source, kind, triple_quoted, start, end).parse()
533534
}
534535

535536
#[cfg(test)]
536537
mod tests {
537538
use super::*;
538539

539-
fn parse_fstring(source: &str) -> Result<Vec<Expr>, LexicalError> {
540+
fn parse_fstring(source: &str) -> Result<Expr, LexicalError> {
540541
StringParser::new(
541542
source,
542543
StringKind::FString,

0 commit comments

Comments
 (0)