Skip to main content

Module expr

Module expr 

Source

Modules§

prec 🔒
Output-precedence ranks, derived directly from the parser’s Precedence ladder (higher binds tighter) so it stays the single source of truth: reordering or inserting a parser level reranks these automatically, and only the variant each rank maps to is maintained by hand. They classify the top operator an expr prints with, so the binary-operator printer can parenthesize an operand that would otherwise re-associate on reparse. ATOM, the one rank with no parser counterpart, is layered one above the tightest parser level to mark the self-delimiting primaries. They never need parens.

Structs§

Function
A function call
MapEntry
Op
A reference to an operator.
SubscriptPosition
WindowFrame
Specifies the data processed by a window function, e.g. RANGE UNBOUNDED PRECEDING or ROWS BETWEEN 5 PRECEDING AND CURRENT ROW.
WindowSpec
A window specification (i.e. OVER (PARTITION BY .. ORDER BY .. etc.)) Includes potential IGNORE NULLS or RESPECT NULLS from before the OVER clause.

Enums§

Expr
An SQL expression of any type.
FunctionArgs
Arguments for a function call.
HomogenizingFunction
IsExprConstruct
WindowFrameBound
Specifies WindowFrame’s start_bound and end_bound
WindowFrameUnits

Functions§

binary_op_precedence 🔒
The precedence of a binary operator, mirroring Parser::get_next_precedence. A namespaced OPERATOR(...) binds at OTHER, like the parser.
left_edge 🔒
The loosest precedence exposed on expr’s left spine, the mirror of right_edge. For a right operand (an operator on its left), this is what decides parenthesization: a left-associative operator printed to its left reaches into the left spine and re-associates if that spine exposes a precedence at or below the operator’s. The top operator alone is not enough, because a left-nested chain can bury a looser operator down its left edge: 387 = ANY (...) LIKE a IN (...) has a top IN (Like) but exposes the = ANY (Cmp) on its left, so a tighter <> to its left (48 <> 387 = ANY (...) ...) would steal the <> into the = ANY’s left rather than leave it as the <>’s right operand. Forms that open with their own token on the left (a prefix operator, a keyword, (…), a literal) are ATOM.
prefix_operand_needs_parens 🔒
Whether the operand of a prefix operator (-/+/~) must be parenthesized to round-trip. A prefix op binds tighter than COLLATE/AT TIME ZONE and the binary/comparison operators, but looser than the postfix ::/[…] forms — and - <number> additionally lexes as a negative literal. So peel the tight postfixes (::/[…]); if the chain bottoms out at a numeric literal the sign would fold into it, and if it bottoms out at anything other than a self-delimiting non-COLLATE primary (a COLLATE, a binary op, …) the prefix op would re-associate — both need parens. (a + b COLLATE c reparses as a + (b COLLATE c); - x COLLATE c as (- x) COLLATE c.)
prints_self_delimiting 🔒
Whether expr prints in a self-delimiting form — atomic, or wrapped in its own brackets/parens (name(...), (…), ARRAY[…], CASE … END, …) — so it is safe to print immediately to the left of a tight postfix operator (::, COLLATE, or the IN delimiter of the position(<needle> IN …) special form) without the operator re-associating into the expression’s spine.
right_edge 🔒
The loosest precedence exposed on expr’s right spine, the precedence at which an operator printed immediately to its right would bind into it rather than wrap it. For a left operand / subject of a construct that prints to its right, this is what decides parenthesization (its mirror, left_edge, decides right operands), because a prefix operator and the right operand of a binary/BETWEEN/LIKE/IS DISTINCT FROM are right-transparent: - NOT a IN (b) exposes the NOT’s IN on the right even though its top node is unary -. Forms that close with a bracket on the right ((…), […], ::type, IS NULL) are ATOM.
unary_prec 🔒
The precedence at which a prefix operator (Op with no second operand) parses its operand, mirroring Parser::parse_prefix: -/+ at PrefixPlusMinus, but ~ (and namespaced prefixes) at Other, so ~ a + b parses as ~ (a + b). ~ binds looser than +/-/*.
write_between_bound 🔒
Write bound as a BETWEEN … AND … bound. The parser parses both bounds with parse_subexpr(Precedence::Like) (see Parser::parse_between), starting fresh with nothing to the bound’s left, so it walks the bound’s left spine and stops at the first operator binding at or below Like, leaving that operator outside the bound (x BETWEEN 1 IS NULL AND y parses 1 as the bound, then expects AND but finds IS). A bound is therefore safe bare only when its left edge binds strictly above Like. Use left_edge (not right_edge, which closes at ATOM for the right-closing IS NULL/= ANY (…)/IN (…) forms whose looseness is on the left). The parser wraps these bounds in Expr::Nested (which is ATOM, so it prints bare). This re-adds the parens for ASTs where that wrapper is absent.
write_binary_operand 🔒
Write operand for a binary operator, parenthesizing it iff needs_parens.
write_dot_receiver 🔒
Write expr as the receiver of a . operator (used by FieldAccess and WildcardAccess), parenthesizing when the receiver could re-bind the trailing dot on reparse. The . token has very high precedence and both the lexer and parser greedily extend adjacent tokens: 1.x tokenizes the number 1. and leaves x as an alias, and 'a'::T.x consumes T.x as a qualified type name. The whitelist below covers receivers that print as self-terminating syntax (parenthesized exprs, function calls, bracketed collections, etc.). Anything else gets explicit parens.
write_quantified_left 🔒
Write left as the LHS of <left> <op> ANY/ALL (...). The printed <op> is an ordinary binary infix. It can be any operator the parser accepts here, from =/< (Cmp) all the way down to *///% (MultiplyDivide), and on reparse it binds into any operator exposed on left’s right spine that is strictly looser than <op> itself, stealing that suffix into the quantified expression’s left rather than wrapping the whole left. So parenthesize exactly when left’s right_edge binds looser than <op>’s own precedence (binary_op_precedence), mirroring the binary-Op arm. Using the operator’s real precedence (not a fixed Like threshold) both parenthesizes a tighter-binding <op> over a looser left and leaves an equal-or-tighter left bare (a = b = ANY (…), a LIKE b = ANY (…)), which the old fixed threshold over-parenthesized. The tighter-binding case, (a + b) * ANY (…), would otherwise print a + b * ANY (…) and reparse as the different a + (b * ANY (…)). right_edge also sees a looser spine hidden under right-transparent prefixes, e.g. the NOT’s IN in - NOT a IN (b) = ANY (…).
write_subscript_receiver 🔒
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.