postgresql-syntax:internal
Safe HaskellNone
LanguageHaskell2010

PostgresqlSyntax.Algebra

Synopsis

Documentation

class IsAst a where Source #

Class of AST types that can be rendered to SQL text and parsed back again.

Laws:

  • Roundtrips: parse settings (toText settings a) = Right a for every Settings — rendering and parsing are inverses.
  • Congruent rendering: a == b => toTextBuilder settings a == toTextBuilder settings b for every Settings — rendering only depends on the value, not on how it was constructed. This is what makes it meaningful to say two structurally different shapes can still render to identical text — the ambiguity that Canonicalizes exists to resolve.

Methods

toTextBuilder :: Settings -> a -> TextBuilder Source #

Render an AST value to a TextBuilder using the given Settings. This is the low-level rendering primitive; toText wraps it.

parser :: Settings -> Parser a Source #

A parser for this AST type, parameterized by Settings. The parser must satisfy the roundtrip law documented on IsAst.

Instances

Instances details
IsAst AExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AExpr

IsAst AExprReversableOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AExprReversableOp

IsAst AexprConst Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AexprConst

IsAst AliasClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AliasClause

IsAst AllOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AllOp

IsAst AnyName Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AnyName

IsAst AnyOperator Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AnyOperator

IsAst ArrayBounds Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ArrayBounds

IsAst ArrayExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ArrayExpr

IsAst ArrayExprList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ArrayExprList

IsAst AscDesc Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AscDesc

IsAst Attrs Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Attrs

IsAst BExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.BExpr

IsAst BExprIsOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.BExprIsOp

IsAst Bconst Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Bconst

IsAst Bit Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Bit

IsAst CExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.CExpr

IsAst CallStmt Source # 
Instance details

Defined in PostgresqlSyntax.Ast.CallStmt

IsAst CaseExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.CaseExpr

IsAst Character Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Character

IsAst Columnref Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Columnref

IsAst CommonTableExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.CommonTableExpr

IsAst ConfExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ConfExpr

IsAst ConstCharacter Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ConstCharacter

IsAst ConstDatetime Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ConstDatetime

IsAst ConstTypename Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ConstTypename

IsAst DeleteStmt Source # 
Instance details

Defined in PostgresqlSyntax.Ast.DeleteStmt

IsAst ExplicitRow Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ExplicitRow

IsAst ExprList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ExprList

IsAst ExtractArg Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ExtractArg

IsAst ExtractList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ExtractList

IsAst Fconst Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Fconst

IsAst ForLockingClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ForLockingClause

IsAst ForLockingItem Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ForLockingItem

IsAst ForLockingStrength Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ForLockingStrength

IsAst FrameBound Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FrameBound

IsAst FrameClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FrameClause

IsAst FrameClauseMode Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FrameClauseMode

IsAst FrameExtent Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FrameExtent

IsAst FromClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FromClause

IsAst FromList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FromList

IsAst FuncAliasClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncAliasClause

IsAst FuncApplication Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncApplication

IsAst FuncApplicationParams Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncApplicationParams

IsAst FuncArgExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncArgExpr

IsAst FuncConstArgs Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncConstArgs

IsAst FuncExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncExpr

IsAst FuncExprCommonSubexpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncExprCommonSubexpr

IsAst FuncExprWindowless Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncExprWindowless

IsAst FuncName Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncName

IsAst FuncTable Source # 
Instance details

Defined in PostgresqlSyntax.Ast.FuncTable

IsAst GenericType Source # 
Instance details

Defined in PostgresqlSyntax.Ast.GenericType

IsAst GroupByItem Source # 
Instance details

Defined in PostgresqlSyntax.Ast.GroupByItem

IsAst GroupClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.GroupClause

IsAst HavingClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.HavingClause

IsAst Iconst Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Iconst

IsAst Ident Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Ident

IsAst ImplicitRow Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ImplicitRow

IsAst InExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.InExpr

IsAst IndexElem Source # 
Instance details

Defined in PostgresqlSyntax.Ast.IndexElem

IsAst IndexElemDef Source # 
Instance details

Defined in PostgresqlSyntax.Ast.IndexElemDef

IsAst IndexParams Source # 
Instance details

Defined in PostgresqlSyntax.Ast.IndexParams

IsAst Indirection Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Indirection

IsAst IndirectionEl Source # 
Instance details

Defined in PostgresqlSyntax.Ast.IndirectionEl

IsAst InsertColumnItem Source # 
Instance details

Defined in PostgresqlSyntax.Ast.InsertColumnItem

IsAst InsertColumnList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.InsertColumnList

IsAst InsertRest Source # 
Instance details

Defined in PostgresqlSyntax.Ast.InsertRest

IsAst InsertStmt Source # 
Instance details

Defined in PostgresqlSyntax.Ast.InsertStmt

IsAst InsertTarget Source # 
Instance details

Defined in PostgresqlSyntax.Ast.InsertTarget

IsAst Interval Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Interval

IsAst IntervalSecond Source # 
Instance details

Defined in PostgresqlSyntax.Ast.IntervalSecond

IsAst IntoClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.IntoClause

IsAst JoinQual Source # 
Instance details

Defined in PostgresqlSyntax.Ast.JoinQual

IsAst JoinType Source # 
Instance details

Defined in PostgresqlSyntax.Ast.JoinType

IsAst JoinedTable Source #

Parsing delegates to parseExtended over the Extends instance below — a bare table_ref parse is greedy, absorbing any trailing CROSS JOIN/JOIN/NATURAL JOIN continuation into itself, so a joined_table is never reachable as a bare, zero-extension TableRef; it always needs at least one. Failing that, the only remaining joined_table production is the non-left-recursive parseBase.

Instance details

Defined in PostgresqlSyntax.Ast.JoinedTable

IsAst LimitClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.LimitClause

IsAst MathOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.MathOp

IsAst NameList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.NameList

IsAst NullsOrder Source # 
Instance details

Defined in PostgresqlSyntax.Ast.NullsOrder

IsAst Numeric Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Numeric

IsAst OffsetClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OffsetClause

IsAst OnConflict Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OnConflict

IsAst OnConflictDo Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OnConflictDo

IsAst Op Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Op

IsAst OptOrdinality Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OptOrdinality

IsAst OptTempTableName Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OptTempTableName

IsAst OptVarying Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OptVarying

IsAst OverClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OverClause

IsAst OverlayList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OverlayList

IsAst OverrideKind Source # 
Instance details

Defined in PostgresqlSyntax.Ast.OverrideKind

IsAst PositionList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.PositionList

IsAst PreparableStmt Source # 
Instance details

Defined in PostgresqlSyntax.Ast.PreparableStmt

IsAst QualAllOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.QualAllOp

IsAst QualOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.QualOp

IsAst QualifiedName Source # 
Instance details

Defined in PostgresqlSyntax.Ast.QualifiedName

IsAst RelationExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.RelationExpr

IsAst RelationExprOptAlias Source # 
Instance details

Defined in PostgresqlSyntax.Ast.RelationExprOptAlias

IsAst ReturningClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ReturningClause

IsAst Row Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Row

IsAst RowsfromItem Source # 
Instance details

Defined in PostgresqlSyntax.Ast.RowsfromItem

IsAst RowsfromList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.RowsfromList

IsAst Sconst Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Sconst

IsAst SelectBinOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectBinOp

IsAst SelectClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectClause

IsAst SelectFetchFirstValue Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectFetchFirstValue

IsAst SelectLimit Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectLimit

IsAst SelectLimitValue Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectLimitValue

IsAst SelectNoParens Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectNoParens

IsAst SelectStmt Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectStmt

IsAst SelectWithParens Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectWithParens

IsAst SetClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SetClause

IsAst SetClauseList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SetClauseList

IsAst SetTarget Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SetTarget

IsAst SetTargetList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SetTargetList

IsAst SimpleSelect Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SimpleSelect

IsAst SimpleTypename Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SimpleTypename

IsAst SortBy Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SortBy

IsAst SortClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SortClause

IsAst SubType Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SubType

IsAst SubqueryOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SubqueryOp

IsAst SubstrList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SubstrList

IsAst SubstrListFromFor Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SubstrListFromFor

IsAst SymbolicExprBinOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SymbolicExprBinOp

IsAst TableFuncElement Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TableFuncElement

IsAst TableFuncElementList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TableFuncElementList

IsAst TableRef Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TableRef

IsAst TablesampleClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TablesampleClause

IsAst TargetEl Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TargetEl

IsAst TargetList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TargetList

IsAst Targeting Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Targeting

IsAst Timezone Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Timezone

IsAst TrimList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TrimList

IsAst TrimModifier Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TrimModifier

IsAst TypeList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TypeList

IsAst Typename Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Typename

IsAst TypenameArrayDimensions Source # 
Instance details

Defined in PostgresqlSyntax.Ast.TypenameArrayDimensions

IsAst UpdateStmt Source # 
Instance details

Defined in PostgresqlSyntax.Ast.UpdateStmt

IsAst UsingClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.UsingClause

IsAst ValuesClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.ValuesClause

IsAst VerbalExprBinOp Source # 
Instance details

Defined in PostgresqlSyntax.Ast.VerbalExprBinOp

IsAst WhenClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WhenClause

IsAst WhenClauseList Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WhenClauseList

IsAst WhereClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WhereClause

IsAst WhereOrCurrentClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WhereOrCurrentClause

IsAst WindowClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WindowClause

IsAst WindowDefinition Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WindowDefinition

IsAst WindowExclusionClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WindowExclusionClause

IsAst WindowSpecification Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WindowSpecification

IsAst WithClause Source # 
Instance details

Defined in PostgresqlSyntax.Ast.WithClause

IsAst Xconst Source # 
Instance details

Defined in PostgresqlSyntax.Ast.Xconst

toText :: IsAst a => Settings -> a -> Text Source #

Render a value to Text via its toTextBuilder method.

parse :: IsAst a => Settings -> Text -> Either Text a Source #

Parse a Text input with the type's parser, returning either a pretty-printed error or the parsed value. The parser is chosen by the caller's type inference (via the IsAst constraint), so callers no longer pass an explicit parser argument.

parseWithPosError :: IsAst a => Settings -> Text -> Either (NonEmpty (Int, Text)) a Source #

Like parse but returns the structured error list (each error paired with its byte offset) instead of a single pretty-printed message.

parseWithSourcePosError :: IsAst a => Settings -> Text -> Either (NonEmpty (SourcePos, Text)) a Source #

Like parseWithPosError but pairs each error with its SourcePos instead of a raw byte offset.

isAstProperties :: (IsAst a, Eq a, Show a, Arbitrary a) => [(String, Property)] Source #

Property-checkers for IsAst's documented laws, keyed by name.

class IsAst a => Canonicalizes a where Source #

Laws:

  • Idempotent: canonicalize . canonicalize = canonicalize
  • Parse-agreement (the property this class exists to provide): parse settings . toText settings = Right . canonicalize for every Settings

Minimal complete definition

Nothing

Methods

canonicalize :: a -> a Source #

Instances

Instances details
Canonicalizes AExpr Source #

Collapses the non-canonical Right-wrapping-a-bare-select_with_parens shape of SubqueryAExpr's final field to the Left shape the parser actually produces for it.

a_expr subquery_Op sub_type select_with_parens (i.e. Left) and a_expr subquery_Op sub_type '(' a_expr ')' (i.e. Right) overlap whenever the parenthesized a_expr is itself nothing but a bare, indirection-less select_with_parens: both parse x = ANY ((select 1)). suffix tries the select_with_parens alternative before the parenthesized a_expr one (see the d Left <$ ... | Right $ ... line above), so that's always what the parser returns — never Right — making the latter non-canonical for this shape. Both arbitrary and shrink can otherwise construct it, which renders fine but parses back to a different, canonical value and so breaks the roundtrip property.

Instance details

Defined in PostgresqlSyntax.Ast.AExpr

Canonicalizes CExpr Source #

Collapses the non-canonical InParensCExpr-wrapping-a-SelectWithParensCExpr shape to the SelectWithParensCExpr/WithParensSelectWithParens shape the parser actually produces for it.

'(' a_expr ')' opt_indirection (i.e. InParensCExpr) and select_with_parens (i.e. SelectWithParensCExpr) overlap whenever the inner a_expr is itself nothing but a bare, indirection-less select_with_parens: both parse ((select 1)). customizedParser tries the select_with_parens alternative before parenthesizedExprCExpr, so that's always what the parser returns — never InParensCExpr — making the latter non-canonical for this shape. Both arbitrary and shrink can otherwise construct it (shrinking the outer indirection to Nothing is exactly how it arises), which renders fine but parses back to a different, canonical value and so breaks the roundtrip property.

Instance details

Defined in PostgresqlSyntax.Ast.CExpr

Canonicalizes InExpr Source #

Collapses the non-canonical SelectInExpr-of-WithParensSelectWithParens shape to the ExprListInExpr shape the parser actually produces for it: in_expr's two productions, select_with_parens and '(' expr_list ')', overlap whenever the parenthesised select itself contains another parenthesised select, since a single-element expr_list can itself be that inner parenthesised select wrapped as a c_expr. Both render to the same text; the parser's expr_list alternative is tried first and so wins. Both arbitrary and shrink can otherwise construct the non-canonical shape, which renders fine but parses back to a different, canonical value and so breaks the roundtrip property.

Instance details

Defined in PostgresqlSyntax.Ast.InExpr

Canonicalizes SelectWithParens Source #

Collapses the non-canonical NoParensSelectWithParens shape described above to the WithParensSelectWithParens shape the parser actually produces for it. Both arbitrary and shrink can otherwise construct the non-canonical shape (shrinking the inner SelectNoParens toward Nothings is exactly how it arises), which renders fine but parses back to a different, canonical value and so breaks the roundtrip property.

Instance details

Defined in PostgresqlSyntax.Ast.SelectWithParens

Canonicalizes SimpleSelect Source #

Collapses an arbitrary-shaped BinSimpleSelect chain to the shape foldChain actually produces for it (left-associated within each precedence level, INTERSECT binding tighter than UNION/EXCEPT — see foldChain above): flattenChain reduces the chain to its flat sequence of operators and operands regardless of how it's currently nested, and re-folding that sequence with the same foldChain the parser itself uses is by construction the shape parse . toText produces. Both arbitrary and shrink can otherwise construct a non-canonical shape, which renders fine but parses back to a different, canonical value and so breaks the roundtrip property.

Instance details

Defined in PostgresqlSyntax.Ast.SimpleSelect

canonicalizesProperties :: (Canonicalizes a, Eq a, Show a, Arbitrary a) => [(String, Property)] Source #

Property-checkers for Canonicalizes's documented laws, keyed by name. "Parse-agreement" is tested at mempty Settings, matching how isAstProperties's "Renders equal values equally" property handles "for every Settings" — no Arbitrary Settings instance exists or is being added.

class Refines sub sup where Source #

Laws:

  • Refinement law: project . embed = Just

Expresses embedding relationships between AST node types across module boundaries where cross-module pattern matching is unavailable. Instances hold between two types when the sub type can be trivially embedded into sup, and trivial sup values can be recognized as such a sub and extracted back out.

Methods

embed :: sub -> sup Source #

project :: sup -> Maybe sub Source #

Instances

Instances details
Refines JoinedTable TableRef Source #

JoinedTable embeds trivially into a bare, alias-less TableRef (joined_table is one of table_ref's alternatives), and a TableRef of that exact shape is recognizable back as one. See Extends for how this is used to fold a chain of joins onto a leading TableRef.

Instance details

Defined in PostgresqlSyntax.Ast.TableRef

Refines SelectWithParens AExpr Source # 
Instance details

Defined in PostgresqlSyntax.Ast.AExpr

Refines SelectWithParens SelectNoParens Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectNoParens

Refines SelectWithParens SelectWithParens Source # 
Instance details

Defined in PostgresqlSyntax.Ast.SelectWithParens

Refines SimpleSelect SelectClause Source #

A SimpleSelect embeds trivially into a SelectClause (it's one of its two alternatives), and a SelectClause of that exact shape is recognizable back as one. Needed so PostgresqlSyntax.Ast.SimpleSelect's Extends instance can fold a chain of UNION/INTERSECT/EXCEPT items onto a leading SelectClause.

Instance details

Defined in PostgresqlSyntax.Ast.SelectClause

refinesProperties :: (Refines sub sup, IsAst sub, Eq sub, Show sub, Arbitrary sub) => [(String, Property)] Source #

Property-checkers for Refines's documented laws, keyed by name.

class IsAst a => LeftRecursive a where Source #

A type some of whose grammar productions are left-recursive — i.e. there is a larger recursive form built by extending a value of this type on its left. parseBase is everything that is not one of those productions: the β of A -> Aα | β.

This is a strictly weaker claim than Extends, which additionally names the specific ext of one such hub. A type can be LeftRecursive without being any hub's baseJoinedTable and SimpleSelect both are, since each is reached by extending a different type (table_ref and select_clause respectively) yet still has non-left-recursive productions of its own.

Separating this from Extends is what lets each instance live with the type it constructs: parseBase mentions only its own type, so it belongs to that type's module, while a hub's parseExtensions belongs to the module defining ext. Because both are class methods, either module can reach the other's parser through an hs-boot instance declaration without exporting a bare helper.

Note that "non-recursive" here means non-left-recursive only: a production may still recurse, so long as it doesn't begin with the recursive position (e.g. '(' joined_table ')').

Methods

parseBase :: Settings -> Parser a Source #

Parse only the productions that don't left-recurse (β).

Instances

Instances details
LeftRecursive JoinedTable Source #

The one joined_table production that doesn't begin with a left-recursive table_ref:

  | '(' joined_table ')'

It still recurses — just not on the left, since the opening parenthesis has to be consumed first. PostgresqlSyntax.Ast.TableRef reaches it through this class method, which is why JoinedTable needs no helper export.

Instance details

Defined in PostgresqlSyntax.Ast.JoinedTable

LeftRecursive SelectClause Source #

Every select_clause production except the left-recursive ones (those are the UNION/INTERSECT/EXCEPT continuations, hosted by PostgresqlSyntax.Ast.SimpleSelect's Extends instance).

Instance details

Defined in PostgresqlSyntax.Ast.SelectClause

LeftRecursive SimpleSelect Source #

The simple_select productions that don't left-recurse through select_clause — i.e. everything but select_clause BINOP select_clause. PostgresqlSyntax.Ast.SelectClause reaches these through this class method, which is why SimpleSelect needs no helper export.

Instance details

Defined in PostgresqlSyntax.Ast.SimpleSelect

LeftRecursive TableRef Source #

Every table_ref production except the left-recursive ones (those are the joined_table continuations, hosted by PostgresqlSyntax.Ast.JoinedTable's Extends instance).

The two joined_table-shaped alternatives here are not left-recursive: both begin with a parenthesis, so neither can loop back into this parser without consuming input. They reach '(' joined_table ')' through JoinedTable's own parseBase rather than through a JoinedTable helper export.

Instance details

Defined in PostgresqlSyntax.Ast.TableRef

class (LeftRecursive base, Refines ext base) => Extends base ext | ext -> base where Source #

The two halves of a left-recursive grammar production, split apart by left-recursion elimination (A -> Aα | β becomes A -> β α*): base is A (and supplies β via its LeftRecursive instance), and ext is what one or more α's, applied to a base, produce.

Laws:

  • Base-parser agreement: parser @base = parseMaybeExtended @base
  • Maximal munch: parseExtensions must not return while a further extension is available — instances build this on parseExtensionChain where possible, which already guarantees it.

Methods

parseExtensions :: Settings -> base -> Parser ext Source #

Parse one or more extensions onto an already-parsed left operand, folding as it goes, and return the fully-extended result.

Instances

Instances details
Extends SelectClause SimpleSelect Source #

The left-recursion-eliminated form of select_clause: a bare SelectClause (either a parenthesized select, or one of SimpleSelect's non-chain cases) is the non-recursive base (β), and each UNION/INTERSECT/EXCEPT continuation is a SelectBinOp plus its ALL/DISTINCT qualifier and right operand, applied via BinSimpleSelect.

Keeps the collect-then-fold shape — parsing every SelectChainLink up front via parseExtensionChain, then folding via foldChain — rather than folding as it goes, because this hub's items aren't all one precedence level: gram.y declares %left UNION EXCEPT before (i.e. binding looser than) %left INTERSECT (gram.y:813-814), both left-associative, so a uniform left-to-right fold-as-you-parse would root a INTERSECT b UNION c at INTERSECT and nest a EXCEPT b EXCEPT c to the right — both wrong. foldChain needs the whole flat sequence in hand to sort that out; see its own docs above.

Instance details

Defined in PostgresqlSyntax.Ast.SimpleSelect

Extends TableRef JoinedTable Source #

The left-recursion-eliminated form of table_ref/joined_table: a TableRef is the non-recursive base (β, its own parseBase). All three join kinds sit at the same precedence (%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL in gram.y), and there's nothing to hold between parsing a join and applying it, so no item type is warranted here — unlike PostgresqlSyntax.Ast.SimpleSelect, this hub isn't collect-then-fold.

Instance details

Defined in PostgresqlSyntax.Ast.JoinedTable

extendedByProperties :: (Extends base ext, IsAst base, Eq base, Show base, Arbitrary base) => [(String, Property)] Source #

Property-checker for Extends's "Base-parser agreement" law, keyed by name. "Maximal munch" isn't checked here: it's a per-instance parsing obligation, not something a generated base value can exercise through parser alone. The agreement check is itself up to whether parsing succeeds, ignoring error message text, since a base's parser may wrap parseMaybeExtended in a label or similar that changes failure messages without changing what's accepted.

parseMaybeExtended :: forall ext base. Extends base ext => Settings -> Parser base Source #

Parses zero or more extensions onto a parseBase, via parseExtensions. This is what A -> β α* (the whole of A) means as a parser.

parseExtended :: Extends base ext => Settings -> Parser ext Source #

Like parseMaybeExtended, but requires at least one extension to follow the base, and so returns the fully-applied ext type directly rather than base. This is what a bare α* (one or more) means as a parser, for hubs where a chain of at least one extension is itself the interesting type (e.g. a joined_table, which is never a bare table_ref with zero joins).

Unlike parseMaybeExtended, parseBase here is wrapped in wrapToHead. Without it, if parseBase itself commits past an internal endHead (e.g. by matching a nested, fully-parenthesized instance of the very thing this function's caller is one alternative for), that commitment silently swallows the immediately-following "is there at least one extension?" check: a missing extension would fail as a hard, uncatchable error instead of a clean one this function's own caller can backtrack from. wrapToHead resets that, forcing the check to fail cleanly. parseMaybeExtended doesn't need this: its own extension check already goes through optional, which independently wraps in try regardless of what parseBase committed to.

parseExtensionChain :: Parser item -> Parser (NonEmpty item) Source #

Parses one or more items back-to-back, wrapping each in wrapToHead/endHead so that, once an item's own head has matched, backtracking out of the whole chain (back to "there are no more items") is no longer attempted — matching the hand-written recursive-descent loops this replaces. This is the shared backtracking protocol underlying Extends's "Maximal munch" law: an instance building parseExtensions on top of this combinator gets the law for free, since go only stops once a further item genuinely isn't available.