()
| 94 | } |
| 95 | |
| 96 | fn query_def<'a, I>() -> impl Parser<'a, I, Stmt, ParserError<'a>> + Clone |
| 97 | where |
| 98 | I: Input<'a, Token = lr::Token, Span = Span> + BorrowInput<'a> + chumsky::input::ValueInput<'a>, |
| 99 | { |
| 100 | new_line() |
| 101 | .repeated() |
| 102 | .at_least(1) |
| 103 | .collect::<Vec<_>>() |
| 104 | .ignore_then(keyword("prql")) |
| 105 | .ignore_then( |
| 106 | // named arg |
| 107 | ident_part() |
| 108 | .then_ignore(ctrl(':')) |
| 109 | .then(expr()) |
| 110 | .repeated() |
| 111 | .collect::<Vec<_>>(), |
| 112 | ) |
| 113 | .then_ignore(new_line()) |
| 114 | .validate(|args, extra, emit| { |
| 115 | let span = extra.span(); |
| 116 | let mut args: HashMap<_, _> = args.into_iter().collect(); |
| 117 | |
| 118 | let version = args.remove("version").and_then(|v| match v.kind { |
| 119 | ExprKind::Literal(Literal::String(v)) => match VersionReq::parse(&v) { |
| 120 | Ok(ver) => Some(ver), |
| 121 | Err(e) => { |
| 122 | emit.emit(Rich::custom(span, e.to_string())); |
| 123 | None |
| 124 | } |
| 125 | }, |
| 126 | _ => { |
| 127 | emit.emit(Rich::custom(span, "version must be a string literal")); |
| 128 | None |
| 129 | } |
| 130 | }); |
| 131 | |
| 132 | // TODO: `QueryDef` is currently implemented as `version` & `other` |
| 133 | // fields. We want to raise an error if an unsupported field is |
| 134 | // used, to avoid confusion (e.g. if someone passes `dialect`). So |
| 135 | // at the moment we implement this as having a HashMap with 0 or 1 |
| 136 | // entries... We can decide how to implement `QueryDef` later, and |
| 137 | // have this awkward construction in the meantime. |
| 138 | let other = args |
| 139 | .remove("target") |
| 140 | .and_then(|v| { |
| 141 | if let ExprKind::Ident(name) = v.kind { |
| 142 | Some(name.to_string()) |
| 143 | } else { |
| 144 | emit.emit(Rich::custom(span, "target must be a string literal")); |
| 145 | None |
| 146 | } |
| 147 | }) |
| 148 | .map_or_else(HashMap::new, |x| { |
| 149 | HashMap::from_iter(vec![("target".to_string(), x)]) |
| 150 | }); |
| 151 | |
| 152 | if !args.is_empty() { |
| 153 | emit.emit(Rich::custom( |
no test coverage detected