Skip to content

Commit 87005b7

Browse files
committed
fix: Handle pipe characters preceeding into like a normal pipeline
Error message not great but can be improved separately. Closes PRQL#4291, I think without doing anything controversial
1 parent a32d59f commit 87005b7

File tree

1 file changed

+72
-4
lines changed
  • prqlc/prqlc-parser/src/parser

1 file changed

+72
-4
lines changed

prqlc/prqlc-parser/src/parser/stmt.rs

+72-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use itertools::Itertools;
55
use semver::VersionReq;
66

77
use super::expr::{expr, expr_call, ident, pipeline};
8-
use super::{ctrl, ident_part, into_stmt, keyword, new_line, with_doc_comment};
8+
use super::{ctrl, ident_part, into_stmt, keyword, new_line, pipe, with_doc_comment};
99
use crate::lexer::lr::{Literal, TokenKind};
1010
use crate::parser::perror::PError;
1111
use crate::parser::pr::*;
@@ -142,6 +142,10 @@ fn query_def() -> impl Parser<TokenKind, Stmt, Error = PError> + Clone {
142142
.labelled("query header")
143143
}
144144

145+
/// A variable definition could be any of:
146+
/// - `let foo = 5`
147+
/// - `from artists` — captured as a "main"
148+
/// - `from artists | into x` — captured as an "into"`
145149
fn var_def() -> impl Parser<TokenKind, StmtKind, Error = PError> + Clone {
146150
let let_ = new_line()
147151
.repeated()
@@ -162,8 +166,7 @@ fn var_def() -> impl Parser<TokenKind, StmtKind, Error = PError> + Clone {
162166
let main_or_into = pipeline(expr_call())
163167
.map(Box::new)
164168
.then(
165-
new_line()
166-
.repeated()
169+
pipe()
167170
.ignore_then(keyword("into").ignore_then(ident_part()))
168171
.or_not(),
169172
)
@@ -204,7 +207,7 @@ fn import_def() -> impl Parser<TokenKind, StmtKind, Error = PError> + Clone {
204207

205208
#[cfg(test)]
206209
mod tests {
207-
use insta::assert_yaml_snapshot;
210+
use insta::{assert_debug_snapshot, assert_yaml_snapshot};
208211

209212
use super::*;
210213
use crate::test::parse_with_parser;
@@ -239,6 +242,71 @@ mod tests {
239242
"###);
240243
}
241244

245+
#[test]
246+
fn into() {
247+
assert_yaml_snapshot!(parse_with_parser(r#"
248+
from artists
249+
into x
250+
"#, var_def()).unwrap(), @r###"
251+
---
252+
VarDef:
253+
kind: Into
254+
name: x
255+
value:
256+
FuncCall:
257+
name:
258+
Ident: from
259+
span: "0:13-17"
260+
args:
261+
- Ident: artists
262+
span: "0:18-25"
263+
span: "0:13-25"
264+
"###);
265+
266+
assert_yaml_snapshot!(parse_with_parser(r#"
267+
from artists | into x
268+
"#, var_def()).unwrap(), @r###"
269+
---
270+
VarDef:
271+
kind: Into
272+
name: x
273+
value:
274+
FuncCall:
275+
name:
276+
Ident: from
277+
span: "0:13-17"
278+
args:
279+
- Ident: artists
280+
span: "0:18-25"
281+
span: "0:13-25"
282+
"###);
283+
}
284+
285+
#[test]
286+
fn let_into() {
287+
// TODO: Error message can probably be better
288+
assert_debug_snapshot!(parse_with_parser(r#"
289+
let y = (
290+
from artists
291+
into x
292+
)
293+
"#, module_contents()).unwrap_err(), @r###"
294+
[
295+
Error {
296+
kind: Error,
297+
span: Some(
298+
0:56-60,
299+
),
300+
reason: Simple(
301+
"unexpected keyword into while parsing function call",
302+
),
303+
hints: [],
304+
code: None,
305+
},
306+
]
307+
"###);
308+
}
309+
242310
#[test]
243311
fn test_module_def() {
244312
// Same line

0 commit comments

Comments
 (0)