MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / write_subscript_receiver

Function write_subscript_receiver

src/sql-parser/src/ast/defs/expr.rs:908–956  ·  view source on GitHub ↗

Write `expr` as the receiver of a `[…]` subscript. An unparenthesized `Identifier(["map"])` reparses as `Token::Keyword(MAP)` followed by `[`, which dispatches to `parse_map` (the map-literal grammar) instead of a regular subscript. Parenthesize identifiers whose last component is a context-sensitive keyword so the round trip stays an identifier subscript.

(f: &mut AstFormatter<W>, expr: &Expr<T>)

Source from the content-addressed store, hash-verified

906/// regular subscript. Parenthesize identifiers whose last component is a
907/// context-sensitive keyword so the round trip stays an identifier subscript.
908fn write_subscript_receiver<W: fmt::Write, T: AstInfo>(f: &mut AstFormatter<W>, expr: &Expr<T>) {
909 let needs_parens = match expr {
910 // A bare keyword identifier (`map`, `list`, …) dispatches to the
911 // map/list-literal grammar before `[`, so it needs parens even though
912 // identifiers are otherwise safe receivers.
913 Expr::Identifier(idents) => idents
914 .last()
915 .and_then(|id| id.as_keyword())
916 .map(|kw| kw.is_context_sensitive_keyword())
917 .unwrap_or(false),
918 // Self-delimiting primaries, the bracketed collections, and the postfix
919 // forms that end in an identifier or `)` are safe: a following `[…]`
920 // attaches to the whole receiver as a fresh subscript.
921 Expr::QualifiedWildcard(_)
922 | Expr::Parameter(_)
923 | Expr::Value(_)
924 | Expr::Function(_)
925 | Expr::HomogenizingFunction { .. }
926 | Expr::NullIf { .. }
927 | Expr::Nested(_)
928 | Expr::Subquery(_)
929 | Expr::Exists(_)
930 | Expr::Case { .. }
931 | Expr::Row { .. }
932 | Expr::Array(_)
933 | Expr::ArraySubquery(_)
934 | Expr::List(_)
935 | Expr::ListSubquery(_)
936 | Expr::Map(_)
937 | Expr::MapSubquery(_)
938 | Expr::FieldAccess { .. }
939 | Expr::WildcardAccess(_)
940 | Expr::Collate { .. } => false,
941 // `Cast`: the type parser swallows a following `[…]` as an array suffix
942 // (`a::int4[1]` is `a` cast to `int4[]`, not a subscript of `a::int4`).
943 // `Subscript`: consecutive `[…]` flatten into one node (`a[1][2]` is a
944 // single subscript), so a nested subscript receiver must be parenthesized
945 // to stay nested. Everything else (operators, `IS`/`LIKE`/… constructs)
946 // binds looser than `[` and would re-associate, so parenthesize by default.
947 _ => true,
948 };
949 if needs_parens {
950 f.write_str("(");
951 f.write_node(expr);
952 f.write_str(")");
953 } else {
954 f.write_node(expr);
955 }
956}
957
958impl<T: AstInfo> Expr<T> {
959 pub fn null() -> Expr<T> {

Callers 1

fmtMethod · 0.85

Calls 6

lastMethod · 0.80
as_keywordMethod · 0.80
write_nodeMethod · 0.80
mapMethod · 0.45
write_strMethod · 0.45

Tested by

no test coverage detected