content: {-# LANGUAGE OverloadedStrings #-}
  
  module Hydra.Ext.Sources.Sql.Ansi where
  
  import Hydra.Kernel hiding (parens)
  import Hydra.Dsl.Grammars
  import Hydra.Grammars
  import qualified Hydra.Dsl.Annotations as Ann
  import qualified Hydra.Grammar as G
  
  import qualified Data.List as L
  
  
  sqlModule :: Module
  sqlModule = grammarToModule ns sqlGrammar $
      Just ("A subset of ANSI SQL:2003, capturing selected productions of the BNF grammar provided at "
        ++ "https://ronsavage.github.io/SQL/sql-2003-2.bnf.html, which is based on "
        ++ "the Final Committee Draft (FCD) of ISO/IEC 9075-2:2003")
    where
      ns = Namespace "hydra.ext.org.ansi.sql.syntax"
  
  sqlGrammar :: G.Grammar
  sqlGrammar = G.Grammar $ tokens ++ productions
  
  tokens :: [G.Production]
  tokens = [
      -- <approximate numeric literal>    ::=   <mantissa> E <exponent>
      define "ApproximateNumericLiteral" [regex $ mantissa ++ "E" ++ exponent],
  
      -- <binary string literal>    ::=
      --         X <quote> [ { <hexit> <hexit> }... ] <quote>
      --         [ { <separator> <quote> [ { <hexit> <hexit> }... ] <quote> }... ]
      --         [ ESCAPE <escape character> ]
      define "BinaryStringLiteral" unsupported,
  
      -- <character string literal>    ::=
      --         [ <introducer> <character set specification> ]
      --         <quote> [ <character representation> ... ] <quote>
      --         [ { <separator> <quote> [ <character representation> ... ] <quote> }... ]
      define "CharacterStringLiteral" [regex $
        opt(introducer ++ characterSetSpecification)
        ++ quote ++ star(characterRepresentation) ++ quote
        ++ star(separator ++ quote ++ star(characterRepresentation) ++ quote)],
  
      -- <column name>    ::=   <identifier>
      define "ColumnName" [regex identifier],
  
      -- <date string>    ::=   <quote> <unquoted date string> <quote>
      define "DateString" unsupported,
  
      -- <domain name>    ::=   <schema qualified name>
      define "DomainName" [regex schemaQualifiedName],
  
      -- <exact numeric literal>    ::=
           --         <unsigned integer> [ <period> [ <unsigned integer> ] ]
           --     |     <period> <unsigned integer>
      define "ExactNumericLiteral" [regex $ or [
        unsignedInteger ++ opt (period ++ unsignedInteger),
        period ++ unsignedInteger]],
  
      -- <left bracket or trigraph>    ::=   <left bracket> | <left bracket trigraph>
      define "LeftBracketOrTrigraph" [regex $ or [leftBracket, leftBracketTrigraph]],
  
      -- <right bracket or trigraph>    ::=   <right bracket> | <right bracket trigraph>
      define "RightBracketOrTrigraph" [regex $ or [rightBracket, rightBracketTrigraph]],
  
      -- <national character string literal>    ::=
      --         N <quote> [ <character representation> ... ] <quote>
      --         [ { <separator> <quote> [ <character representation> ... ] <quote> }... ]
      define "NationalCharacterStringLiteral" unsupported,
  
      -- <path-resolved user-defined type name>    ::=   <user-defined type name>
      define "PathResolvedUserDefinedTypeName" [regex userDefinedTypeName],
  
      -- <table name>    ::=   <local or schema qualified name>
      define "TableName" [regex localOrSchemaQualifiedName],
  
      -- <time string>    ::=   <quote> <unquoted time string> <quote>
      define "TimeString" unsupported,
  
      -- <timestamp string>    ::=   <quote> <unquoted timestamp string> <quote>
      define "TimestampLiteral" unsupported,
  
      -- <Unicode character string literal>    ::=
      --         [ <introducer> <character set specification> ]
      --         U <ampersand> <quote> [ <Unicode representation> ... ] <quote>
      --         [ { <separator> <quote> [ <Unicode representation> ... ] <quote> }... ]
      --         [ ESCAPE <escape character> ]
      define "UnicodeCharacterStringLiteral" unsupported,
  
      -- <unsigned integer>    ::=   <digit> ...
      define "UnsignedInteger" [regex unsignedInteger]]
    where
      opt pat = par pat ++ "?"
      or pats = par $ L.intercalate "|" (par <$> pats)
      par pat = "(" ++ pat ++ ")"
      plus pat = par pat ++ "+"
      star pat = par pat ++ "*"
  
      -- <actual identifier>    ::=   <regular identifier> | <delimited identifier>
      actualIdentifier = regularIdentifier -- Note: this is a simplification
  
      -- <asterisk>    ::=   *
      asterisk = "*"
  
      -- <bracketed comment>    ::=
      --         <bracketed comment introducer> <bracketed comment contents> <bracketed comment terminator>
      bracketedComment = bracketedCommentIntroducer ++ bracketedCommentContents ++ bracketedCommentTerminator
  
      -- <bracketed comment contents>    ::=   [ { <comment character> | <separator> }... ]
      bracketedCommentContents = star $ or [commentCharacter, separator]
  
      -- <bracketed comment introducer>    ::=   <slash> <asterisk>
      bracketedCommentIntroducer = slash ++ asterisk
  
      -- <bracketed comment terminator>    ::=   <asterisk> <slash>
      bracketedCommentTerminator = asterisk ++ slash
  
      -- <catalog name>    ::=   <identifier>
      catalogName = identifier
  
      -- <character representation>    ::=   <nonquote character> | <quote symbol>
      characterRepresentation = or [nonquoteCharacter, quoteSymbol]
  
      -- <character set specification>    ::=
      --         <standard character set name>
      --     |     <implementation-defined character set name>
      --     |     <user-defined character set name>
      characterSetSpecification = "" -- TODO
  
      -- <comment>    ::=   <simple comment> | <bracketed comment>
      comment = or[simpleComment, bracketedComment]
  
      -- <comment character>    ::=   <nonquote character> | <quote>
      commentCharacter = or [nonquoteCharacter, quote]
  
      -- <digit>    ::=   0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
      digit = "[0-9]"
  
      -- <exact numeric literal>    ::=
      --         <unsigned integer> [ <period> [ <unsigned integer> ] ]
      --     |     <period> <unsigned integer>
      exactNumericLiteral = or [
        unsignedInteger ++ opt (period ++ opt unsignedInteger),
        period ++ unsignedInteger]
  
      -- <exponent>    ::=   <signed integer>
      exponent = signedInteger
  
      -- <identifier>    ::=   <actual identifier>
      identifier = actualIdentifier
  
      -- <identifier body>    ::=   <identifier start> [ <identifier part> ... ]
      identifierBody = identifierStart ++ star identifierPart
  
      -- <identifier extend>    ::=   !! See the Syntax Rules.
      identifierExtend = "[0-9_]" -- TODO
  
      -- <identifier part>    ::=   <identifier start> | <identifier extend>
      identifierPart = or [identifierStart, identifierExtend]
  
      -- <identifier start>    ::=   !! See the Syntax Rules.
      identifierStart = "[A-Za-z]" -- TODO
  
      -- <introducer>    ::=   <underscore>
      introducer = underscore
  
      -- <left bracket>    ::=   [
      leftBracket = "["
  
      -- <left bracket trigraph>    ::=   ??(
      leftBracketTrigraph = "??("
  
      -- <local or schema qualifier>    ::=   <schema name> | MODULE
      localOrSchemaQualifier = or [schemaName, "MODULE"]
  
      -- <local or schema qualified name>    ::=   [ <local or schema qualifier> <period> ] <qualified identifier>
      localOrSchemaQualifiedName = opt (localOrSchemaQualifier ++ period) ++ qualifiedIdentifier
  
      -- <mantissa>    ::=   <exact numeric literal>
      mantissa = exactNumericLiteral
  
      -- <minus sign>    ::=   -
      minusSign = "-"
  
      -- <newline>    ::=   !! See the Syntax Rules.
      newline = "[\\n]" -- TODO
  
      -- <nonquote character>    ::=   !! See the Syntax Rules.
      nonquoteCharacter = "[ -&(-~]" -- TODO
  
      -- <period>    ::=   .
      period = "[.]"
  
      -- <plus sign>    ::=   +
      plusSign = "+"
  
      -- <quote>    ::=   '
      quote = "'"
  
      -- <quote symbol>    ::=   <quote> <quote>
      quoteSymbol = quote ++ quote
  
      -- <qualified identifier>    ::=   <identifier>
      qualifiedIdentifier = identifier
  
      -- <regular identifier>    ::=   <identifier body>
      regularIdentifier = identifierBody
  
      -- <right bracket>    ::=   ]
      rightBracket = "]"
  
      -- <right bracket trigraph>    ::=   ??)
      rightBracketTrigraph = "??)"
  
      -- <separator>    ::=   { <comment> | <white space> }...
      separator = star(or[comment, whiteSpace])
  
      -- <schema name>    ::=   [ <catalog name> <period> ] <unqualified schema name>
      schemaName = opt (catalogName ++ period) ++ unqualifiedSchemaName
  
      -- <schema qualified name>    ::=   [ <schema name> <period> ] <qualified identifier>
      schemaQualifiedName = opt (schemaName ++ period) ++ qualifiedIdentifier
  
      -- <schema qualified type name>    ::=   [ <schema name> <period> ] <qualified identifier>
      schemaQualifiedTypeName = opt (schemaName ++ period) ++ qualifiedIdentifier
  
      -- <sign>    ::=   <plus sign> | <minus sign>
      sign = or [plusSign, minusSign]
  
      -- <signed integer>    ::=   [ <sign> ] <unsigned integer>
      signedInteger = opt sign ++ unsignedInteger
  
      -- <simple comment>    ::=   <simple comment introducer> [ <comment character> ... ] <newline>
      simpleComment = simpleCommentIntroducer ++ star(commentCharacter) ++ newline
  
      -- <simple comment introducer>    ::=   <minus sign> <minus sign> [ <minus sign> ... ]
      simpleCommentIntroducer = minusSign ++ plus(minusSign)
  
      slash = "/"
  
      -- <underscore>    ::=   _
      underscore = "_"
  
      -- <unqualified schema name> ::= <schema name>
      unqualifiedSchemaName = schemaName
  
      -- <unsigned integer>    ::=   <digit> ...
      unsignedInteger = plus digit
  
      -- <user-defined type name>    ::=   <schema qualified type name>
      userDefinedTypeName = schemaQualifiedTypeName
  
      whiteSpace = "[ \\t]" -- TODO
  
  productions :: [G.Production]
  productions = [
    -- <approximate numeric type>    ::=
         --         FLOAT [ <left paren> <precision> <right paren> ]
         --     |     REAL
         --     |     DOUBLE PRECISION
    define "ApproximateNumericType" [
      "float">: list[float_, opt(parens["Precision"])],
      "real">: real_,
      "double">: double_precision_],
  
    -- <array element>    ::=   <value expression>
    define "ArrayElement" [
      "ValueExpression"],
  
    -- <array element list>    ::=   <array element> [ { <comma> <array element> }... ]
    define "ArrayElementList" [commaList "ArrayElement"],
  
    -- <array element reference>    ::=
    --         <array value expression> <left bracket or trigraph> <numeric value expression> <right bracket or trigraph>
    define "ArrayElementReference" unsupported,
  
    -- <array type>    ::=   <data type> ARRAY [ <left bracket or trigraph> <unsigned integer> <right bracket or trigraph> ]
    define "ArrayType" unsupported,
  
    -- <array value constructor>    ::=
    --         <array value constructor by enumeration>
    --     |     <array value constructor by query>
    define "ArrayValueConstructor" [
      "enumeration">: "ArrayValueConstructorByEnumeration",
      "query">: "ArrayValueConstructorByQuery"],
  
    -- <array value constructor by query>    ::=
    --         ARRAY <left paren> <query expression> [ <order by clause> ] <right paren>
    define "ArrayValueConstructorByQuery" unsupported,
  
    -- <array value constructor by enumeration>    ::=
    --         ARRAY <left bracket or trigraph> <array element list> <right bracket or trigraph>
    define "ArrayValueConstructorByEnumeration" [
      list[array_, "LeftBracketOrTrigraph", "ArrayElementList", "RightBracketOrTrigraph"]],
  
    -- <array value expression>    ::=   <array concatenation> | <array factor>
    define "ArrayValueExpression" unsupported,
  
    -- <as subquery clause>    ::=   [ <left paren> <column name list> <right paren> ] AS <subquery> <with or without data>
    define "AsSubqueryClause" unsupported,
  
    -- <attribute or method reference>    ::=
    --         <value expression primary> <dereference operator> <qualified identifier>
    --         [ <SQL argument list> ]
    define "AttributeOrMethodReference" unsupported,
  
    -- <binary large object string type>    ::=
    --         BINARY LARGE OBJECT [ <left paren> <large object length> <right paren> ]
    --     |     BLOB [ <left paren> <large object length> <right paren> ]
    define "BinaryLargeObjectStringType" [
      "binary">: list[binary_large_object_, opt(parens["LargeObjectLength"])],
      "blob">: list[blob_, opt(parens["LargeObjectLength"])]],
  
    -- <boolean factor>    ::=   [ NOT ] <boolean test>
    define "BooleanFactor" [
      list[opt(not_), "BooleanTest"]],
  
    -- <boolean literal>    ::=   TRUE | FALSE | UNKNOWN
    define "BooleanLiteral" [
      true_,
      false_,
      unknown_],
  
    -- <boolean predicand>    ::=
    --         <parenthesized boolean value expression>
    --     |     <nonparenthesized value expression primary>
    define "BooleanPredicand" unsupported,
  
    -- <boolean primary>    ::=   <predicate> | <boolean predicand>
    define "BooleanPrimary" [
      "predicate">: "Predicate",
      "predicand">: "BooleanPredicand"],
  
    -- <boolean term>    ::=
    --         <boolean factor>
    --     |     <boolean term> AND <boolean factor>
    define "BooleanTerm" [
      "factor">: "BooleanFactor",
      "and">: list[
        "lhs">: "BooleanTerm",
        and_,
        "rhs">: "BooleanFactor"]],
  
    -- <boolean test>    ::=   <boolean primary> [ IS [ NOT ] <truth value> ]
    define "BooleanTest" [
      list["BooleanPrimary", opt(list[is_, opt(not_), "TruthValue"])]],
  
    -- <boolean type>    ::=   BOOLEAN
    define "BooleanType" [
      boolean_],
  
    -- <boolean value expression>    ::=
    --         <boolean term>
    --     |     <boolean value expression> OR <boolean term>
    define "BooleanValueExpression" [
      "term">: "BooleanTerm",
      "or">: list[
        "lhs">: "BooleanValueExpression",
        or_,
        "rhs">: "BooleanTerm"]],
  
    -- <case expression>    ::=   <case abbreviation> | <case specification>
    define "CaseExpression" unsupported,
  
    -- <cast specification>    ::=   CAST <left paren> <cast operand> AS <cast target> <right paren>
    define "CastSpecification" unsupported,
  
    -- <character set specification>    ::=
    --         <standard character set name>
    --     |     <implementation-defined character set name>
    --     |     <user-defined character set name>
    define "CharacterSetSpecification" unsupported,
  
    -- <character string type>    ::=
    --         CHARACTER [ <left paren> <length> <right paren> ]
    --     |     CHAR [ <left paren> <length> <right paren> ]
    --     |     CHARACTER VARYING <left paren> <length> <right paren>
    --     |     CHAR VARYING <left paren> <length> <right paren>
    --     |     VARCHAR <left paren> <length> <right paren>
    --     |     CHARACTER LARGE OBJECT [ <left paren> <large object length> <right paren> ]
    --     |     CHAR LARGE OBJECT [ <left paren> <large object length> <right paren> ]
    --     |     CLOB [ <left paren> <large object length> <right paren> ]
    define "CharacterStringType" [
      "character">: list[character_, opt(parens["Length"])],
      "char">: list[char_, opt(parens["Length"])],
      "characterVarying">: list[character_varying_, left_paren_, "Length", right_paren_],
      "charVarying">: list[char_varying_, left_paren_, "Length", right_paren_],
      "varchar">: list[varchar_, left_paren_, "Length", right_paren_],
      "characterLargeObject">: list[character_large_object_, opt(parens["LargeObjectLength"])],
      "charLargeObject">: list[char_large_object_, opt(parens["LargeObjectLength"])],
      "clob">: list[clob_, opt(parens["LargeObjectLength"])]],
  
    -- <collate clause>    ::=   COLLATE <collation name>
    define "CollateClause" unsupported,
  
    -- <collection type>    ::=   <array type> | <multiset type>
    define "CollectionType" [
      "array">: "ArrayType",
      "multiset">: "MultisetType"],
  
    -- <collection value constructor>    ::=   <array value constructor> | <multiset value constructor>
    define "CollectionValueConstructor" [
      "array">: "ArrayValueConstructor",
      "multiset">: "MultisetValueConstructor"],
  
    -- <collection value expression>    ::=   <array value expression> | <multiset value expression>
    define "CollectionValueExpression" [
      "array">: "ArrayValueExpression",
      "multiset">: "MultisetValueExpression"],
  
    -- <column constraint definition>    ::=   [ <constraint name definition> ] <column constraint> [ <constraint characteristics> ]
    define "ColumnConstraintDefinition" unsupported,
  
    -- <column definition>    ::=
    --         <column name> [ <data type> | <domain name> ] [ <reference scope check> ]
    --         [ <default clause> | <identity column specification> | <generation clause> ]
    --         [ <column constraint definition> ... ] [ <collate clause> ]
    define "ColumnDefinition" [
      list[
        "name">: "ColumnName",
        "typeOrDomain">: opt(alts["DataType", "DomainName"]),
        "refScope">: opt"ReferenceScopeCheck",
        "defaultOrIdentityOrGeneration">: opt(alts["DefaultClause", "IdentityColumnSpecification", "GenerationClause"]),
        "constraints">: star"ColumnConstraintDefinition",
        "collate">: opt"CollateClause"]],
  
    -- <column name list>    ::=   <column name> [ { <comma> <column name> }... ]
    define "ColumnNameList" [commaList "ColumnName"],
  
    -- <column options>    ::=   <column name> WITH OPTIONS <column option list>
    define "ColumnOptions" unsupported,
  
    -- <column reference>    ::=
         --         <basic identifier chain>
         --     |     MODULE <period> <qualified identifier> <period> <column name>
    define "ColumnReference" unsupported,
  
    -- <common value expression>    ::=
    --         <numeric value expression>
    --     |     <string value expression>
    --     |     <datetime value expression>
    --     |     <interval value expression>
    --     |     <user-defined type value expression>
    --     |     <reference value expression>
    --     |     <collection value expression>
    define "CommonValueExpression" [
      "numeric">: "NumericValueExpression",
      "string">: "StringValueExpression",
      "datetime">: "DatetimeValueExpression",
      "interval">: "IntervalValueExpression",
      "userDefined">: "UserDefinedTypeValueExpression",
      "reference">: "ReferenceValueExpression",
      "collection">: "CollectionValueExpression"],
  
    -- <contextually typed row value expression>    ::=
    --         <row value special case>
    --     |     <contextually typed row value constructor>
    define "ContextuallyTypedRowValueExpression" [
      "specialCase">: "RowValueSpecialCase",
      "constructor">: "ContextuallyTypedRowValueConstructor"],
  
    -- <contextually typed row value constructor>    ::=
    --         <common value expression>
    --     |     <boolean value expression>
    --     |     <contextually typed value specification>
    --     |     <left paren> <contextually typed row value constructor element> <comma> <contextually typed row value constructor element list> <right paren>
    --     |     ROW <left paren> <contextually typed row value constructor element list> <right paren>
    define "ContextuallyTypedRowValueConstructor" unsupported,
  
    -- <contextually typed row value expression list>    ::=   <contextually typed row value expression> [ { <comma> <contextually typed row value expression> }... ]
    define "ContextuallyTypedRowValueExpressionList" [commaList "ContextuallyTypedRowValueExpression"],
  
    -- <contextually typed table value constructor>    ::=   VALUES <contextually typed row value expression list>
    define "ContextuallyTypedTableValueConstructor" [
      list[values_, "ContextuallyTypedRowValueExpressionList"]],
  
    -- <data type>    ::=
    --         <predefined type>
    --     |     <row type>
    --     |     <path-resolved user-defined type name>
    --     |     <reference type>
    --     |     <collection type>
    define "DataType" [
      "predefined">: "PredefinedType",
      "row">: "RowType",
      "named">: "PathResolvedUserDefinedTypeName",
      "reference">: "ReferenceType",
      "collection">: "CollectionType"],
  
    -- <date literal>    ::=   DATE <date string>
    define "DateLiteral" [
      list[date_, "DateString"]],
  
    -- <datetime literal>    ::=   <date literal> | <time literal> | <timestamp literal>
    define "DatetimeLiteral" [
      "date">: "DateLiteral",
      "time">: "TimeLiteral",
      "timestamp">: "TimestampLiteral"],
  
    -- <datetime type>    ::=
    --         DATE
    --     |     TIME [ <left paren> <time precision> <right paren> ] [ <with or without time zone> ]
    --     |     TIMESTAMP [ <left paren> <timestamp precision> <right paren> ] [ <with or without time zone> ]
    define "DatetimeType" unsupported,
  
    -- <datetime value expression>    ::=
    --         <datetime term>
    --     |     <interval value expression> <plus sign> <datetime term>
    --     |     <datetime value expression> <plus sign> <interval term>
    --     |     <datetime value expression> <minus sign> <interval term>
    define "DatetimeValueExpression" unsupported,
  
    -- <default clause>    ::=   DEFAULT <default option>
    define "DefaultClause" unsupported,
  
    -- <exact numeric type>    ::=
    --         NUMERIC [ <left paren> <precision> [ <comma> <scale> ] <right paren> ]
    --     |     DECIMAL [ <left paren> <precision> [ <comma> <scale> ] <right paren> ]
    --     |     DEC [ <left paren> <precision> [ <comma> <scale> ] <right paren> ]
    --     |     SMALLINT
    --     |     INTEGER
    --     |     INT
    --     |     BIGINT
    define "ExactNumericType" [
      "numeric">: list[numeric_, opt(parens["Precision", opt(list[comma_, "Scale"])])],
      "decimal">: list[decimal_, opt(parens["Precision", opt(list[comma_, "Scale"])])],
      "dec">: list[dec_, opt(parens["Precision", opt(list[comma_, "Scale"])])],
      "smallint">: smallint_,
      "integer">: integer_,
      "int">: int_,
      "bigint">: bigint_],
  
    -- <field reference>    ::=   <value expression primary> <period> <field name>
    define "FieldReference" unsupported,
  
    -- <from constructor>    ::=
    --         [ <left paren> <insert column list> <right paren> ] [ <override clause> ] <contextually typed table value constructor>
    define "FromConstructor" [
      list[
        "columns">: opt(parens["InsertColumnList"]),
        "override">: opt"OverrideClause",
        "values">: "ContextuallyTypedTableValueConstructor"]],
  
    -- <from default>    ::=   DEFAULT VALUES
    define "FromDefault" [
      default_values_],
  
    -- <from subquery>    ::=   [ <left paren> <insert column list> <right paren> ] [ <override clause> ] <query expression>
    define "FromSubquery" unsupported,
  
    -- <general literal>    ::=
    --         <character string literal>
    --     |     <national character string literal>
    --     |     <Unicode character string literal>
    --     |     <binary string literal>
    --     |     <datetime literal>
    --     |     <interval literal>
    --     |     <boolean literal>
    define "GeneralLiteral" [
      "string">: "CharacterStringLiteral",
      "nationalString">: "NationalCharacterStringLiteral",
      "unicode">: "UnicodeCharacterStringLiteral",
      "binary">: "BinaryStringLiteral",
      "dateTime">: "DatetimeLiteral",
      "interval">: "IntervalLiteral",
      "boolean">: "BooleanLiteral"],
  
    -- <general value specification>    ::=
         --         <host parameter specification>
         --     |     <SQL parameter reference>
         --     |     <dynamic parameter specification>
         --     |     <embedded variable specification>
         --     |     <current collation specification>
         --     |     CURRENT_DEFAULT_TRANSFORM_GROUP
         --     |     CURRENT_PATH
         --     |     CURRENT_ROLE
         --     |     CURRENT_TRANSFORM_GROUP_FOR_TYPE <path-resolved user-defined type name>
         --     |     CURRENT_USER
         --     |     SESSION_USER
         --     |     SYSTEM_USER
         --     |     USER
         --     |     VALUE
    define "GeneralValueSpecification" unsupported,
  
    -- <generation clause>    ::=   <generation rule> AS <generation expression>
    define "GenerationClause" unsupported,
  
    -- <global or local>    ::=   GLOBAL | LOCAL
    define "GlobalOrLocal" [
      "global">: global_,
      "local">: local_],
  
    -- <identity column specification>    ::=
    --         GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
    --         [ <left paren> <common sequence generator options> <right paren> ]
    define "IdentityColumnSpecification" unsupported,
  
    -- <insert column list>    ::=   <column name list>
    define "InsertColumnList" [
      "ColumnNameList"],
  
    -- <insert columns and source>    ::=
    --         <from subquery>
    --     |     <from constructor>
    --     |     <from default>
    define "InsertColumnsAndSource" [
      "subquery">: "FromSubquery",
      "constructor">: "FromConstructor",
      "default">: "FromDefault"],
  
    -- <insert statement>    ::=   INSERT INTO <insertion target> <insert columns and source>
    define "InsertStatement" [
      list[
        insert_into_,
        "target">: "InsertionTarget",
        "columnsAndSource">: "InsertColumnsAndSource"]],
  
    -- <insertion target>    ::=   <table name>
    define "InsertionTarget" [
      "TableName"],
  
    -- <interval literal>    ::=   INTERVAL [ <sign> ] <interval string> <interval qualifier>
    define "IntervalLiteral" unsupported,
  
    -- <interval type>    ::=   INTERVAL <interval qualifier>
    define "IntervalType" unsupported,
  
    -- <interval value expression>    ::=
    --         <interval term>
    --     |     <interval value expression 1> <plus sign> <interval term 1>
    --     |     <interval value expression 1> <minus sign> <interval term 1>
    --     |     <left paren> <datetime value expression> <minus sign> <datetime term> <right paren> <interval qualifier>
    define "IntervalValueExpression" unsupported,
  
    -- <large object length>    ::=
    --         <unsigned integer> [ <multiplier> ] [ <char length units> ]
    --     |     <large object length token> [ <char length units> ]
    define "LargeObjectLength" unsupported,
  
    -- <length>    ::=   <unsigned integer>
    define "Length" [
        "UnsignedInteger"],
  
    -- <like clause>    ::=   LIKE <table name> [ <like options> ]
    define "LikeClause" unsupported,
  
    -- <method invocation>    ::=   <direct invocation> | <generalized invocation>
    define "MethodInvocation" unsupported,
  
    -- <multiset element reference>    ::=
    --         ELEMENT <left paren> <multiset value expression> <right paren>
    define "MultisetElementReference" unsupported,
  
    -- <multiset type>    ::=   <data type> MULTISET
    define "MultisetType" [
      list["DataType", multiset_]],
  
    -- <multiset value constructor>    ::=
    --         <multiset value constructor by enumeration>
    --     |     <multiset value constructor by query>
    --     |     <table value constructor by query>
    define "MultisetValueConstructor" unsupported,
  
    -- <multiset value expression>    ::=
    --         <multiset term>
    --     |     <multiset value expression> MULTISET UNION [ ALL | DISTINCT ] <multiset term>
    --     |     <multiset value expression> MULTISET EXCEPT [ ALL | DISTINCT ] <multiset term>
    define "MultisetValueExpression" unsupported,
  
    -- <national character string type>    ::=
    --         NATIONAL CHARACTER [ <left paren> <length> <right paren> ]
    --     |     NATIONAL CHAR [ <left paren> <length> <right paren> ]
    --     |     NCHAR [ <left paren> <length> <right paren> ]
    --     |     NATIONAL CHARACTER VARYING <left paren> <length> <right paren>
    --     |     NATIONAL CHAR VARYING <left paren> <length> <right paren>
    --     |     NCHAR VARYING <left paren> <length> <right paren>
    --     |     NATIONAL CHARACTER LARGE OBJECT [ <left paren> <large object length> <right paren> ]
    --     |     NCHAR LARGE OBJECT [ <left paren> <large object length> <right paren> ]
    --     |     NCLOB [ <left paren> <large object length> <right paren> ]
    define "NationalCharacterStringType" unsupported,
  
    -- <new specification>    ::=   NEW <routine invocation>
    define "NewSpecification" unsupported,
  
    -- <next value expression>    ::=   NEXT VALUE FOR <sequence generator name>
    define "NextValueExpression" unsupported,
  
    -- <numeric type>    ::=   <exact numeric type> | <approximate numeric type>
    define "NumericType" [
      "exact">: "ExactNumericType",
      "approximate">: "ApproximateNumericType"],
  
    -- <numeric value expression>    ::=
    --         <term>
    --     |     <numeric value expression> <plus sign> <term>
    --     |     <numeric value expression> <minus sign> <term>
    define "NumericValueExpression" unsupported,
  
    -- <override clause>    ::=   OVERRIDING USER VALUE | OVERRIDING SYSTEM VALUE
    define "OverrideClause" [
      overriding_user_value_,
      overriding_system_value],
  
    -- <parenthesized value expression>    ::=   <left paren> <value expression> <right paren>
    define "ParenthesizedValueExpression" [
      parens["ValueExpression"]],
  
    -- <precision>    ::=   <unsigned integer>
    define "Precision" [
      "UnsignedInteger"],
  
    -- <predefined type>    ::=
    --         <character string type> [ CHARACTER SET <character set specification> ] [ <collate clause> ]
    --     |     <national character string type> [ <collate clause> ]
    --     |     <binary large object string type>
    --     |     <numeric type>
    --     |     <boolean type>
    --     |     <datetime type>
    --     |     <interval type>
    define "PredefinedType" [
      "string">: list[
        "type">: "CharacterStringType",
        "characters">: opt(list[character_set_, "CharacterSetSpecification"]),
        "collate">: opt"CollateClause"],
      "nationalString">: list[
        "type">: "NationalCharacterStringType",
        "collate">: opt"CollateClause"],
      "blob">: "BinaryLargeObjectStringType",
      "numeric">: "NumericType",
      "boolean">: "BooleanType",
      "datetime">: "DatetimeType",
      "interval">: "IntervalType"],
  
    -- <predicate>    ::=
    --         <comparison predicate>
    --     |     <between predicate>
    --     |     <in predicate>
    --     |     <like predicate>
    --     |     <similar predicate>
    --     |     <null predicate>
    --     |     <quantified comparison predicate>
    --     |     <exists predicate>
    --     |     <unique predicate>
    --     |     <normalized predicate>
    --     |     <match predicate>
    --     |     <overlaps predicate>
    --     |     <distinct predicate>
    --     |     <member predicate>
    --     |     <submultiset predicate>
    --     |     <set predicate>
    --     |     <type predicate>
    define "Predicate" unsupported,
  
    -- <query expression>    ::=   [ <with clause> ] <query expression body>
    define "QueryExpression" unsupported,
  
    -- <reference scope check>    ::=   REFERENCES ARE [ NOT ] CHECKED [ ON DELETE <reference scope check action> ]
    define "ReferenceScopeCheck" unsupported,
  
    -- <reference type>    ::=   REF <left paren> <referenced type> <right paren> [ <scope clause> ]
    define "ReferenceType" unsupported,
  
    -- <row type>    ::=   ROW <row type body>
    define "RowType" unsupported,
  
    -- <row value special case>    ::=   <nonparenthesized value expression primary>
    define "RowValueSpecialCase" [
      "NonparenthesizedValueExpressionPrimary"],
  
    -- <nonparenthesized value expression primary>    ::=
    --         <unsigned value specification>
    --     |     <column reference>
    --     |     <set function specification>
    --     |     <window function>
    --     |     <scalar subquery>
    --     |     <case expression>
    --     |     <cast specification>
    --     |     <field reference>
    --     |     <subtype treatment>
    --     |     <method invocation>
    --     |     <static method invocation>
    --     |     <new specification>
    --     |     <attribute or method reference>
    --     |     <reference resolution>
    --     |     <collection value constructor>
    --     |     <array element reference>
    --     |     <multiset element reference>
    --     |     <routine invocation>
    --     |     <next value expression>
    define "NonparenthesizedValueExpressionPrimary" [
      "unsigned">: "UnsignedValueSpecification",
      "column">: "ColumnReference",
      "setFunction">: "SetFunctionSpecification",
      "windowFunction">: "WindowFunction",
      "scalarSubquery">: "ScalarSubquery",
      "cases">: "CaseExpression",
      "cast">: "CastSpecification",
      "field">: "FieldReference",
      "subtype">: "SubtypeTreatment",
      "method">: "MethodInvocation",
      "staticMethod">: "StaticMethodInvocation",
      "new">: "NewSpecification",
      "attributeOrMethod">: "AttributeOrMethodReference",
      "reference">: "ReferenceResolution",
      "collection">: "CollectionValueConstructor",
      "arrayElement">: "ArrayElementReference",
      "multisetElement">: "MultisetElementReference",
      "routine">: "RoutineInvocation",
      "next">: "NextValueExpression"],
  
    -- <reference resolution>    ::=   DEREF <left paren> <reference value expression> <right paren>
    define "ReferenceResolution" unsupported,
  
    -- <reference value expression>    ::=   <value expression primary>
    define "ReferenceValueExpression" [
      "ValueExpressionPrimary"],
  
    -- <row value expression>    ::=
    --         <row value special case>
    --     |     <explicit row value constructor>
    define "RowValueExpression" unsupported,
  
    -- <routine invocation>    ::=   <routine name> <SQL argument list>
    define "RoutineInvocation" unsupported,
  
    -- <scalar subquery>    ::=   <subquery>
    define "ScalarSubquery" [
      "Subquery"],
  
    -- <scale>    ::=   <unsigned integer>
    define "Scale" [
      "UnsignedInteger"],
  
    -- <self-referencing column specification>    ::=   REF IS <self-referencing column name> <reference generation>
    define "SelfReferencingColumnSpecification" unsupported,
  
    -- <set function specification>    ::=   <aggregate function> | <grouping operation>
    define "SetFunctionSpecification" unsupported,
  
    -- <static method invocation>    ::=
    --         <path-resolved user-defined type name> <double colon> <method name> [ <SQL argument list> ]
    define "StaticMethodInvocation" unsupported,
  
    -- <string value expression>    ::=   <character value expression> | <blob value expression>
    define "StringValueExpression" unsupported,
  
    -- <subquery>    ::=   <left paren> <query expression> <right paren>
    define "Subquery" [
      parens["QueryExpression"]],
  
    -- <subtable clause>    ::=   UNDER <supertable clause>
    define "SubtableClause" unsupported,
  
    -- <subtype treatment>    ::=
    --         TREAT <left paren> <subtype operand> AS <target subtype> <right paren>
    define "SubtypeTreatment" unsupported,
  
    -- <table commit action>    ::=   PRESERVE | DELETE
    define "TableCommitAction" [
      "preserve">: preserve_,
      "delete">: delete_],
  
    -- <table constraint definition>    ::=   [ <constraint name definition> ] <table constraint> [ <constraint characteristics> ]
    define "TableConstraintDefinition" unsupported,
  
    -- <table contents source>    ::=
    --         <table element list>
    --     |     OF <path-resolved user-defined type name> [ <subtable clause> ] [ <table element list> ]
    --     |     <as subquery clause>
    define "TableContentsSource" [
      "list">: "TableElementList",
      "subtable">: list [
        of_,
        "type">: "PathResolvedUserDefinedTypeName",
        "subtable">: opt"SubtableClause",
        "elements">: opt"TableElementList"],
      "subquery">: "AsSubqueryClause"],
  
    -- <table definition>    ::=
    --          CREATE [ <table scope> ] TABLE <table name> <table contents source>
    --          [ ON COMMIT <table commit action> ROWS ]
    define "TableDefinition" [
      list[
        create_,
        "scope">: opt"TableScope",
        table_,
        "name">: "TableName",
        "source">: "TableContentsSource",
        "commitActions">: opt(list[on_commit_, "TableCommitAction", rows_])]],
  
    -- <table element>    ::=
    --         <column definition>
    --     |     <table constraint definition>
    --     |     <like clause>
    --     |     <self-referencing column specification>
    --     |     <column options>
    define "TableElement" [
      "column">: "ColumnDefinition",
      "tableConstraint">: "TableConstraintDefinition",
      "like">: "LikeClause",
      "selfReferencingColumn">: "SelfReferencingColumnSpecification",
      "columOptions">: "ColumnOptions"],
  
    -- <table element list>    ::=   <left paren> <table element> [ { <comma> <table element> }... ] <right paren>
    define "TableElementList" [
      parens[commaList "TableElement"]],
  
    -- <table scope>    ::=   <global or local> TEMPORARY
    define "TableScope" [
      list["GlobalOrLocal", temporary_]],
  
    -- <time literal>    ::=   TIME <time string>
    define "TimeLiteral" [
      list[time_, "TimeString"]],
  
    define "TruthValue" [
      true_,
      false_,
      unknown_],
  
    -- <unsigned literal>    ::=   <unsigned numeric literal> | <general literal>
    define "UnsignedLiteral" [
      "numeric">: "UnsignedNumericLiteral",
      "general">: "GeneralLiteral"],
  
    -- <unsigned numeric literal>    ::=   <exact numeric literal> | <approximate numeric literal>
    define "UnsignedNumericLiteral" [
      "exact">: "ExactNumericLiteral",
      "approximate">: "ApproximateNumericLiteral"],
  
    -- <unsigned value specification>    ::=   <unsigned literal> | <general value specification>
    define "UnsignedValueSpecification" [
      "literal">: "UnsignedLiteral",
      "general">: "GeneralValueSpecification"],
  
    -- <user-defined type value expression>    ::=   <value expression primary>
    define "UserDefinedTypeValueExpression" [
      "ValueExpressionPrimary"],
  
    -- <value expression>    ::=
    --         <common value expression>
    --     |     <boolean value expression>
    --     |     <row value expression>
    define "ValueExpression" [
      "common">: "CommonValueExpression",
      "boolean">: "BooleanValueExpression",
      "row">: "RowValueExpression"],
  
    -- <value expression primary>    ::=
    --         <parenthesized value expression>
    --     |     <nonparenthesized value expression primary>
    define "ValueExpressionPrimary" [
      "parens">: "ParenthesizedValueExpression",
      "noparens">: "NonparenthesizedValueExpressionPrimary"],
  
    -- <window function>    ::=   <window function type> OVER <window name or specification>
    define "WindowFunction" unsupported]
  
  and_ = terminal "AND"
  array_ = terminal "ARRAY"
  bigint_ = terminal "BIGINT"
  binary_large_object_ = terminal "BINARY LARGE OBJECT"
  blob_ = terminal "BLOB"
  boolean_ = terminal "BOOLEAN"
  char_ = terminal "CHAR"
  char_large_object_ = terminal "CHAR LARGE OBJECT"
  char_varying_ = terminal "CHAR VARYING"
  character_ = terminal "CHARACTER"
  character_large_object_ = terminal "CHARACTER LARGE OBJECT"
  character_set_ = terminal "CHARACTER SET"
  character_varying_ = terminal "CHARACTER VARYING"
  clob_ = terminal "CLOB"
  comma_ = terminal ","
  create_ = terminal "CREATE"
  date_ = terminal "DATE"
  dec_ = terminal "DEC"
  decimal_ = terminal "DECIMAL"
  default_values_ = terminal "DEFAULT VALUES"
  delete_ = terminal "DELETE"
  double_precision_ = terminal "DOUBLE PRECISION"
  false_ = terminal "FALSE"
  float_ = terminal "FLOAT"
  global_ = terminal "GLOBAL"
  insert_into_ = terminal "INSERT INTO"
  int_ = terminal "INT"
  integer_ = terminal "INTEGER"
  is_ = terminal "IS"
  left_paren_ = terminal "("
  local_ = terminal "LOCAL"
  multiset_ = terminal "MULTISET"
  numeric_ = terminal "NUMERIC"
  of_ = terminal "OF"
  not_ = terminal "NOT"
  on_commit_ = terminal "ON COMMIT"
  or_ = terminal "OR"
  overriding_user_value_ = terminal "OVERRIDING USER VALUE"
  overriding_system_value = terminal "OVERRIDING SYSTEM VALUE"
  preserve_ = terminal "PRESERVE"
  real_ = terminal "REAL"
  right_paren_ = terminal ")"
  rows_ = terminal "ROWS"
  smallint_ = terminal "SMALLINT"
  table_ = terminal "TABLE"
  temporary_ = terminal "TEMPORARY"
  time_ = terminal "TIME"
  true_ = terminal "TRUE"
  unknown_ = terminal "UNKNOWN"
  values_ = terminal "VALUES"
  varchar_ = terminal "VARCHAR"
  
  commaList pat = list[
    "first">: pat,
    "rest">: star(list[comma_, pat])]
  parens ps = list $ [left_paren_] ++ ps ++ [right_paren_]
  unsupported = [terminal "unsupported"]
  