Subversion

2lt

?curdirlinks? - Rev 1

?prevdifflink? - Blame



{

-----------------------------------------------------------------------------
-- |
-- Maintainer  :  dtlapa@yahoo.com, flavioxavier@gmail.com, hpacheco@gmail.com
-- Stability   :  experimental
-- Portability :  portable
--
-- See
--
--     Haskell SQL Parser Full Grammar
-- 
-- by
--
--     Digo Lapa, Flavio Ferreira and Hugo Pacheco
--
-----------------------------------------------------------------------------


module Language.SQL.PostgreSQL where
import Language.SQL.Lexer
import Language.SQL.Tokens
import Language.SQL.ASTPostgreSQL
import Text.XML.HaXml.OneOfN
}

%name parsePostgreSQL
%tokentype {Token}

%token
        ABORT {Token (TokKeyword "ABORT") _ }
        ABSOLUTE {Token (TokKeyword "ABSOLUTE") _ }
        ACCESS {Token (TokKeyword "ACCESS") _ }
        ACTION {Token (TokKeyword "ACTION") _ }
        ADD {Token (TokKeyword "ADD") _ }
        ADMIN {Token (TokKeyword "ADMIN") _ }
        AFTER {Token (TokKeyword "AFTER") _ }
        AGGREGATE {Token (TokKeyword "AGGREGATE") _ }
        ALL {Token (TokKeyword "ALL") _ }
        ALSO {Token (TokKeyword "ALSO") _ }
        ALTER {Token (TokKeyword "ALTER") _ }
        ANALYSE {Token (TokKeyword "ANALYSE") _ }
        ANALYZE {Token (TokKeyword "ANALYZE") _ }
        AND {Token (TokKeyword "AND") _ }
        ANY {Token (TokKeyword "ANY") _ }
        ARRAY {Token (TokKeyword "ARRAY") _ }
        AS {Token (TokKeyword "AS") _ }
        ASC {Token (TokKeyword "ASC") _ }
        ASSERTION {Token (TokKeyword "ASSERTION") _ }
        ASSIGNMENT {Token (TokKeyword "ASSIGNMENT") _ }
        ASYMMETRIC {Token (TokKeyword "ASYMMETRIC") _ }
        AT {Token (TokKeyword "AT") _ }
        AUTHORIZATION {Token (TokKeyword "AUTHORIZATION") _ }
        BACKWARD {Token (TokKeyword "BACKWARD") _ }
        BEFORE {Token (TokKeyword "BEFORE") _ }
        BEGIN {Token (TokKeyword "BEGIN") _ }
        BETWEEN {Token (TokKeyword "BETWEEN") _ }
        BIGINT {Token (TokKeyword "BIGINT") _ }
        BINARY {Token (TokKeyword "BINARY") _ }
        BIT {Token (TokKeyword "BIT") _ }
        BOOLEAN {Token (TokKeyword "BOOLEAN") _ }
        BOTH {Token (TokKeyword "BOTH") _ }
        BY {Token (TokKeyword "BY") _ }
        CACHE {Token (TokKeyword "CACHE") _ }
        CALLED {Token (TokKeyword "CALLED") _ }
        CASCADE {Token (TokKeyword "CASCADE") _ }
        CASE {Token (TokKeyword "CASE") _ }
        CAST {Token (TokKeyword "CAST") _ }
        CHAIN {Token (TokKeyword "CHAIN") _ }
        CHAR {Token (TokKeyword "CHAR") _ }
        CHARACTER {Token (TokKeyword "CHARACTER") _ }
        CHARACTERISTICS {Token (TokKeyword "CHARACTERISTICS") _ }
        CHECK {Token (TokKeyword "CHECK") _ }
        CHECKPOINT {Token (TokKeyword "CHECKPOINT") _ }
        CLASS {Token (TokKeyword "CLASS") _ }
        CLOSE {Token (TokKeyword "CLOSE") _ }
        CLUSTER {Token (TokKeyword "CLUSTER") _ }
        COALESCE {Token (TokKeyword "COALESCE") _ }
        COLLATE {Token (TokKeyword "COLLATE") _ }
        COLUMN {Token (TokKeyword "COLUMN") _ }
        COMMENT {Token (TokKeyword "COMMENT") _ }
        COMMIT {Token (TokKeyword "COMMIT") _ }
        COMMITTED {Token (TokKeyword "COMMITTED") _ }
        CONNECTION {Token (TokKeyword "CONNECTION") _ }
        CONSTRAINT {Token (TokKeyword "CONSTRAINT") _ }
        CONSTRAINTS {Token (TokKeyword "CONSTRAINTS") _ }
        CONVERSION {Token (TokKeyword "CONVERSION") _ }
        CONVERT {Token (TokKeyword "CONVERT") _ }
        COPY {Token (TokKeyword "COPY") _ }
        CREATE {Token (TokKeyword "CREATE") _ }
        CREATEDB {Token (TokKeyword "CREATEDB") _ }
        CREATEROLE {Token (TokKeyword "CREATEROLE") _ }
        CREATEUSER {Token (TokKeyword "CREATEUSER") _ }
        CROSS {Token (TokKeyword "CROSS") _ }
        CSV {Token (TokKeyword "CSV") _ }
        CURRENT_DATE {Token (TokKeyword "CURRENT_DATE") _ }
        CURRENT_ROLE {Token (TokKeyword "CURRENT_ROLE") _ }
        CURRENT_TIME {Token (TokKeyword "CURRENT_TIME") _ }
        CURRENT_TIMESTAMP {Token (TokKeyword "CURRENT_TIMESTAMP") _ }
        CURRENT_USER {Token (TokKeyword "CURRENT_USER") _ }
        CURSOR {Token (TokKeyword "CURSOR") _ }
        CYCLE {Token (TokKeyword "CYCLE") _ }
        DATABASE {Token (TokKeyword "DATABASE") _ }
        DAY {Token (TokKeyword "DAY") _ }
        DEALLOCATE {Token (TokKeyword "DEALLOCATE") _ }
        DEC {Token (TokKeyword "DEC") _ }
        DECIMAL {Token (TokKeyword "DECIMAL") _ }
        DECLARE {Token (TokKeyword "DECLARE") _ }
        DEFAULT {Token (TokKeyword "DEFAULT") _ }
        DEFAULTS {Token (TokKeyword "DEFAULTS") _ }
        DEFERRABLE {Token (TokKeyword "DEFERRABLE") _ }
        DEFERRED {Token (TokKeyword "DEFERRED") _ }
        DEFINER {Token (TokKeyword "DEFINER") _ }
        DELETE {Token (TokKeyword "DELETE") _ }
        DELIMITER {Token (TokKeyword "DELIMITER") _ }
        DELIMITERS {Token (TokKeyword "DELIMITERS") _ }
        DESC {Token (TokKeyword "DESC") _ }
        DISABLE {Token (TokKeyword "DISABLE") _ }
        DISTINCT {Token (TokKeyword "DISTINCT") _ }
        DO {Token (TokKeyword "DO") _ }
        DOMAIN {Token (TokKeyword "DOMAIN") _ }
        DOUBLE {Token (TokKeyword "DOUBLE") _ }
        DROP {Token (TokKeyword "DROP") _ }
        EACH {Token (TokKeyword "EACH") _ }
        ELSE {Token (TokKeyword "ELSE") _ }
        ENABLE {Token (TokKeyword "ENABLE") _ }
        ENCODING {Token (TokKeyword "ENCODING") _ }
        ENCRYPTED {Token (TokKeyword "ENCRYPTED") _ }
        END {Token (TokKeyword "END") _ }
        ESCAPE {Token (TokKeyword "ESCAPE") _ }
        EXCEPT {Token (TokKeyword "EXCEPT") _ }
        EXCLUDING {Token (TokKeyword "EXCLUDING") _ }
        EXCLUSIVE {Token (TokKeyword "EXCLUSIVE") _ }
        EXECUTE {Token (TokKeyword "EXECUTE") _ }
        EXISTS {Token (TokKeyword "EXISTS") _ }
        EXPLAIN {Token (TokKeyword "EXPLAIN") _ }
        EXTERNAL {Token (TokKeyword "EXTERNAL") _ }
        EXTRACT {Token (TokKeyword "EXTRACT") _ }
        FALSE {Token (TokKeyword "FALSE") _ }
        FETCH {Token (TokKeyword "FETCH") _ }
        FIRST {Token (TokKeyword "FIRST") _ }
        FLOAT {Token (TokKeyword "FLOAT") _ }
        FOR {Token (TokKeyword "FOR") _ }
        FORCE {Token (TokKeyword "FORCE") _ }
        FOREIGN {Token (TokKeyword "FOREIGN") _ }
        FORWARD {Token (TokKeyword "FORWARD") _ }
        FREEZE {Token (TokKeyword "FREEZE") _ }
        FROM {Token (TokKeyword "FROM") _ }
        FULL {Token (TokKeyword "FULL") _ }
        FUNCTION {Token (TokKeyword "FUNCTION") _ }
        GLOBAL {Token (TokKeyword "GLOBAL") _ }
        GRANT {Token (TokKeyword "GRANT") _ }
        GRANTED {Token (TokKeyword "GRANTED") _ }
        GREATEST {Token (TokKeyword "GREATEST") _ }
        GROUP {Token (TokKeyword "GROUP") _ }
        HANDLER {Token (TokKeyword "HANDLER") _ }
        HAVING {Token (TokKeyword "HAVING") _ }
        HEADER {Token (TokKeyword "HEADER") _ }
        HOLD {Token (TokKeyword "HOLD") _ }
        HOUR {Token (TokKeyword "HOUR") _ }
        ILIKE {Token (TokKeyword "ILIKE") _ }
        IMMEDIATE {Token (TokKeyword "IMMEDIATE") _ }
        IMMUTABLE {Token (TokKeyword "IMMUTABLE") _ }
        IMPLICIT {Token (TokKeyword "IMPLICIT") _ }
        IN {Token (TokKeyword "IN") _ }
        INCLUDING {Token (TokKeyword "INCLUDING") _ }
        INCREMENT {Token (TokKeyword "INCREMENT") _ }
        INDEX {Token (TokKeyword "INDEX") _ }
        INHERIT {Token (TokKeyword "INHERIT") _ }
        INHERITS {Token (TokKeyword "INHERITS") _ }
        INITIALLY {Token (TokKeyword "INITIALLY") _ }
        INNER {Token (TokKeyword "INNER") _ }
        INOUT {Token (TokKeyword "INOUT") _ }
        INPUT {Token (TokKeyword "INPUT") _ }
        INSENSITIVE {Token (TokKeyword "INSENSITIVE") _ }
        INSERT {Token (TokKeyword "INSERT") _ }
        INSTEAD {Token (TokKeyword "INSTEAD") _ }
        INT {Token (TokKeyword "INT") _ }
        INTEGER {Token (TokKeyword "INTEGER") _ }
        INTERSECT {Token (TokKeyword "INTERSECT") _ }
        INTERVAL {Token (TokKeyword "INTERVAL") _ }
        INTO {Token (TokKeyword "INTO") _ }
        INVOKER {Token (TokKeyword "INVOKER") _ }
        IS {Token (TokKeyword "IS") _ }
        ISNULL {Token (TokKeyword "ISNULL") _ }
        ISOLATION {Token (TokKeyword "ISOLATION") _ }
        JOIN {Token (TokKeyword "JOIN") _ }
        KEY {Token (TokKeyword "KEY") _ }
        LANCOMPILER {Token (TokKeyword "LANCOMPILER") _ }
        LANGUAGE {Token (TokKeyword "LANGUAGE") _ }
        LARGE {Token (TokKeyword "LARGE") _ }
        LAST {Token (TokKeyword "LAST") _ }
        LEADING {Token (TokKeyword "LEADING") _ }
        LEAST {Token (TokKeyword "LEAST") _ }
        LEFT {Token (TokKeyword "LEFT") _ }
        LEVEL {Token (TokKeyword "LEVEL") _ }
        LIKE {Token (TokKeyword "LIKE") _ }
        LIMIT {Token (TokKeyword "LIMIT") _ }
        LISTEN {Token (TokKeyword "LISTEN") _ }
        LOAD {Token (TokKeyword "LOAD") _ }
        LOCAL {Token (TokKeyword "LOCAL") _ }
        LOCALTIME {Token (TokKeyword "LOCALTIME") _ }
        LOCALTIMESTAMP {Token (TokKeyword "LOCALTIMESTAMP") _ }
        LOCATION {Token (TokKeyword "LOCATION") _ }
        LOCK {Token (TokKeyword "LOCK") _ }
        LOGIN {Token (TokKeyword "LOGIN") _ }
        MATCH {Token (TokKeyword "MATCH") _ }
        MAXVALUE {Token (TokKeyword "MAXVALUE") _ }
        MINUTE {Token (TokKeyword "MINUTE") _ }
        MINVALUE {Token (TokKeyword "MINVALUE") _ }
        MODE {Token (TokKeyword "MODE") _ }
        MONTH {Token (TokKeyword "MONTH") _ }
        MOVE {Token (TokKeyword "MOVE") _ }
        NAMES {Token (TokKeyword "NAMES") _ }
        NATIONAL {Token (TokKeyword "NATIONAL") _ }
        NATURAL {Token (TokKeyword "NATURAL") _ }
        NCHAR {Token (TokKeyword "NCHAR") _ }
        NEW {Token (TokKeyword "NEW") _ }
        NEXT {Token (TokKeyword "NEXT") _ }
        NO {Token (TokKeyword "NO") _ }
        NOCREATEDB {Token (TokKeyword "NOCREATEDB") _ }
        NOCREATEROLE {Token (TokKeyword "NOCREATEROLE") _ }
        NOCREATEUSER {Token (TokKeyword "NOCREATEUSER") _ }
        NOINHERIT {Token (TokKeyword "NOINHERIT") _ }
        NOLOGIN {Token (TokKeyword "NOLOGIN") _ }
        NONE {Token (TokKeyword "NONE") _ }
        NOSUPERUSER {Token (TokKeyword "NOSUPERUSER") _ }
        NOT {Token (TokKeyword "NOT") _ }
        NOTHING {Token (TokKeyword "NOTHING") _ }
        NOTIFY {Token (TokKeyword "NOTIFY") _ }
        NOTNULL {Token (TokKeyword "NOTNULL") _ }
        NOWAIT {Token (TokKeyword "NOWAIT") _ }
        NULL {Token (TokKeyword "NULL") _ }
        NULLIF {Token (TokKeyword "NULLIF") _ }
        NUMERIC {Token (TokKeyword "NUMERIC") _ }
        OBJECT {Token (TokKeyword "OBJECT") _ }
        OF {Token (TokKeyword "OF") _ }
        OFF {Token (TokKeyword "OFF") _ }
        OFFSET {Token (TokKeyword "OFFSET") _ }
        OIDS {Token (TokKeyword "OIDS") _ }
        OLD {Token (TokKeyword "OLD") _ }
        ON {Token (TokKeyword "ON") _ }
        ONLY {Token (TokKeyword "ONLY") _ }
        OPERATOR {Token (TokKeyword "OPERATOR") _ }
        OPTION {Token (TokKeyword "OPTION") _ }
        OR {Token (TokKeyword "OR") _ }
        ORDER {Token (TokKeyword "ORDER") _ }
        OUT {Token (TokKeyword "OUT") _ }
        OUTER {Token (TokKeyword "OUTER") _ }
        OVERLAPS {Token (TokKeyword "OVERLAPS") _ }
        OVERLAY {Token (TokKeyword "OVERLAY") _ }
        OWNER {Token (TokKeyword "OWNER") _ }
        PARTIAL {Token (TokKeyword "PARTIAL") _ }
        PASSWORD {Token (TokKeyword "PASSWORD") _ }
        PLACING {Token (TokKeyword "PLACING") _ }
        POSITION {Token (TokKeyword "POSITION") _ }
        PRECISION {Token (TokKeyword "PRECISION") _ }
        PRESERVE {Token (TokKeyword "PRESERVE") _ }
        PREPARE {Token (TokKeyword "PREPARE") _ }
        PREPARED {Token (TokKeyword "PREPARED") _ }
        PRIMARY {Token (TokKeyword "PRIMARY") _ }
        PRIOR {Token (TokKeyword "PRIOR") _ }
        PRIVILEGES {Token (TokKeyword "PRIVILEGES") _ }
        PROCEDURAL {Token (TokKeyword "PROCEDURAL") _ }
        PROCEDURE {Token (TokKeyword "PROCEDURE") _ }
        QUOTE {Token (TokKeyword "QUOTE") _ }
        READ {Token (TokKeyword "READ") _ }
        REAL {Token (TokKeyword "REAL") _ }
        RECHECK {Token (TokKeyword "RECHECK") _ }
        REFERENCES {Token (TokKeyword "REFERENCES") _ }
        REINDEX {Token (TokKeyword "REINDEX") _ }
        RELATIVE {Token (TokKeyword "RELATIVE") _ }
        RELEASE {Token (TokKeyword "RELEASE") _ }
        RENAME {Token (TokKeyword "RENAME") _ }
        REPEATABLE {Token (TokKeyword "REPEATABLE") _ }
        REPLACE {Token (TokKeyword "REPLACE") _ }
        RESET {Token (TokKeyword "RESET") _ }
        RESTART {Token (TokKeyword "RESTART") _ }
        RESTRICT {Token (TokKeyword "RESTRICT") _ }
        RETURNS {Token (TokKeyword "RETURNS") _ }
        REVOKE {Token (TokKeyword "REVOKE") _ }
        RIGHT {Token (TokKeyword "RIGHT") _ }
        ROLE {Token (TokKeyword "ROLE") _ }
        ROLLBACK {Token (TokKeyword "ROLLBACK") _ }
        ROW {Token (TokKeyword "ROW") _ }
        ROWS {Token (TokKeyword "ROWS") _ }
        RULE {Token (TokKeyword "RULE") _ }
        SAVEPOINT {Token (TokKeyword "SAVEPOINT") _ }
        SCHEMA {Token (TokKeyword "SCHEMA") _ }
        SCROLL {Token (TokKeyword "SCROLL") _ }
        SECOND {Token (TokKeyword "SECOND") _ }
        SECURITY {Token (TokKeyword "SECURITY") _ }
        SELECT {Token (TokKeyword "SELECT") _ }
        SEQUENCE {Token (TokKeyword "SEQUENCE") _ }
        SERIALIZABLE {Token (TokKeyword "SERIALIZABLE") _ }
        SESSION {Token (TokKeyword "SESSION") _ }
        SESSION_USER {Token (TokKeyword "SESSION_USER") _ }
        SET {Token (TokKeyword "SET") _ }
        SETOF {Token (TokKeyword "SETOF") _ }
        SHARE {Token (TokKeyword "SHARE") _ }
        SHOW {Token (TokKeyword "SHOW") _ }
        SIMILAR {Token (TokKeyword "SIMILAR") _ }
        SIMPLE {Token (TokKeyword "SIMPLE") _ }
        SMALLINT {Token (TokKeyword "SMALLINT") _ }
        SOME {Token (TokKeyword "SOME") _ }
        STABLE {Token (TokKeyword "STABLE") _ }
        START {Token (TokKeyword "START") _ }
        STATEMENT {Token (TokKeyword "STATEMENT") _ }
        STATISTICS {Token (TokKeyword "STATISTICS") _ }
        STDIN {Token (TokKeyword "STDIN") _ }
        STDOUT {Token (TokKeyword "STDOUT") _ }
        STORAGE {Token (TokKeyword "STORAGE") _ }
        STRICT {Token (TokKeyword "STRICT") _ }
        SUBSTRING {Token (TokKeyword "SUBSTRING") _ }
        SUPERUSER {Token (TokKeyword "SUPERUSER") _ }
        SYMMETRIC {Token (TokKeyword "SYMMETRIC") _ }
        SYSID {Token (TokKeyword "SYSID") _ }
        SYSTEM {Token (TokKeyword "SYSTEM") _ }
        TABLE {Token (TokKeyword "TABLE") _ }
        TABLESPACE {Token (TokKeyword "TABLESPACE") _ }
        TEMP {Token (TokKeyword "TEMP") _ }
        TEMPLATE {Token (TokKeyword "TEMPLATE") _ }
        TEMPORARY {Token (TokKeyword "TEMPORARY") _ }
        THEN {Token (TokKeyword "THEN") _ }
        TIME {Token (TokKeyword "TIME") _ }
        TIMESTAMP {Token (TokKeyword "TIMESTAMP") _ }
        TO {Token (TokKeyword "TO") _ }
        TOAST {Token (TokKeyword "TOAST") _ }
        TRAILING {Token (TokKeyword "TRAILING") _ }
        TRANSACTION {Token (TokKeyword "TRANSACTION") _ }
        TREAT {Token (TokKeyword "TREAT") _ }
        TRIGGER {Token (TokKeyword "TRIGGER") _ }
        TRIM {Token (TokKeyword "TRIM") _ }
        TRUE {Token (TokKeyword "TRUE") _ }
        TRUNCATE {Token (TokKeyword "TRUNCATE") _ }
        TRUSTED {Token (TokKeyword "TRUSTED") _ }
        TYPE {Token (TokKeyword "TYPE") _ }
        UNCOMMITTED {Token (TokKeyword "UNCOMMITTED") _ }
        UNENCRYPTED {Token (TokKeyword "UNENCRYPTED") _ }
        UNION {Token (TokKeyword "UNION") _ }
        UNIQUE {Token (TokKeyword "UNIQUE") _ }
        UNKNOWN {Token (TokKeyword "UNKNOWN") _ }
        UNLISTEN {Token (TokKeyword "UNLISTEN") _ }
        UNTIL {Token (TokKeyword "UNTIL") _ }
        UPDATE {Token (TokKeyword "UPDATE") _ }
        USER {Token (TokKeyword "USER") _ }
        USING {Token (TokKeyword "USING") _ }
        VACUUM {Token (TokKeyword "VACUUM") _ }
        VALID {Token (TokKeyword "VALID") _ }
        VALIDATOR {Token (TokKeyword "VALIDATOR") _ }
        VALUES {Token (TokKeyword "VALUES") _ }
        VARCHAR {Token (TokKeyword "VARCHAR") _ }
        VARYING {Token (TokKeyword "VARYING") _ }
        VERBOSE {Token (TokKeyword "VERBOSE") _ }
        VIEW {Token (TokKeyword "VIEW") _ }
        VOLATILE {Token (TokKeyword "VOLATILE") _ }
        WHEN {Token (TokKeyword "WHEN") _ }
        WHERE {Token (TokKeyword "WHERE") _ }
        WITH {Token (TokKeyword "WITH") _ }
        WITHOUT {Token (TokKeyword "WITHOUT") _ }
        WORK {Token (TokKeyword "WORK") _ }
        WRITE {Token (TokKeyword "WRITE") _ }
        YEAR {Token (TokKeyword "YEAR") _ }
        ZONE {Token (TokKeyword "ZONE") _ }
        
        TYPECAST {Token (TokTypecast) _ }
        UNIONJOIN {Token (TokKeyword "UNIONJOIN") _ }
        
        IDENT {Token (TokIdent $$) _ }
        FCONST {Token (TokFconst $$) _ }
        SCONST {Token (TokSconst $$) _ }
        BCONST {Token (TokBconst $$) _ }
        XCONST {Token (TokXconst $$) _ }
        Op {Token (TokOp $$) _ }

        ICONST {Token (TokIconst $$) _ }
        PARAM {Token (TokParam $$) _ }

        ')' {Token (TokSymbol ')') _ }
        '(' {Token (TokSymbol '(') _ }
        ',' {Token (TokSymbol ',') _ }
        '*' {Token (TokSymbol '*') _ }
        '.' {Token (TokSymbol '.') _ }
        '[' {Token (TokSymbol '[') _ }
        ']' {Token (TokSymbol ']') _ }
        '+' {Token (TokSymbol '+') _ }
        '>' {Token (TokSymbol '>') _ }
        '<' {Token (TokSymbol '<') _ }
        '=' {Token (TokSymbol '=') _ }
        ';' {Token (TokSymbol ';') _ }
        '%' {Token (TokSymbol '%') _ }
        '/' {Token (TokSymbol '/') _ }
        '^' {Token (TokSymbol '^') _ }
        ':' {Token (TokSymbol ':') _ }
        '-' {Token (TokSymbol '-') _ }

%left           UNION EXCEPT
%left           INTERSECT
%left           OR
%left           AND
%right          NOT
%right          '='
%nonassoc       '<' '>'
%nonassoc       LIKE ILIKE SIMILAR
%nonassoc       ESCAPE
%nonassoc       OVERLAPS
%nonassoc       BETWEEN
%nonassoc       IN
%left           POSTFIXOP
%left           Op OPERATOR
%nonassoc       NOTNULL
%nonassoc       ISNULL
%nonassoc       IS NULL TRUE FALSE UNKNOWN
%left           '+' '-'
%left           '*' '/' '%'
%left           '^'
%left           AT ZONE
%right          UMINUS
%left           '[' ']'
%left           '(' ')'
%left           TYPECAST
%left           '.'
%left           JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER NATURAL

%%

start   :: { ASTPostgreSQL }
start   : stmtmulti { AST $1 }

stmtmulti       :: { Statements }
stmtmulti
        : stmtmulti ';' stmt { $1 ++ $3 }
        | stmt { $1 }

stmt    :: { [Statement] }
stmt
        : AlterDatabaseStmt { [$1] }
        | AlterDatabaseSetStmt { [$1] }
        | AlterDomainStmt { [$1] }
        | AlterFunctionStmt { [$1] }
        | AlterGroupStmt { [$1] }
        | AlterObjectSchemaStmt { [$1] }
        | AlterOwnerStmt { [$1] }
        | AlterSeqStmt { [$1] }
        | AlterTableStmt { [$1] }
        | AlterRoleSetStmt { [$1] }
        | AlterRoleStmt { [$1] }
        | AlterUserSetStmt { [$1] }
        | AlterUserStmt { [$1] }
        | AnalyzeStmt { [$1] }
        | CheckPointStmt { [$1] }
        | ClosePortalStmt { [$1] }
        | ClusterStmt { [$1] }
        | CommentStmt { [$1] }
        | ConstraintsSetStmt { [$1] }
        | CopyStmt { [$1] }
        | CreateAsStmt { [$1] }
        | CreateAssertStmt { [$1] }
        | CreateCastStmt { [$1] }
        | CreateConversionStmt { [$1] }
        | CreateDomainStmt { [$1] }
        | CreateFunctionStmt { [$1] }
        | CreateGroupStmt { [$1] }
        | CreateOpClassStmt { [$1] }
        | CreatePLangStmt { [$1] }
        | CreateSchemaStmt { [$1] }
        | CreateSeqStmt { [$1] }
        | CreateStmt { [$1] }
        | CreateTableSpaceStmt { [$1] }
        | CreateTrigStmt { [$1] }
        | CreateRoleStmt { [$1] }
        | CreateUserStmt { [$1] }
        | CreatedbStmt { [$1] }
        | DeallocateStmt { [$1] }
        | DeclareCursorStmt { [$1] }
        | DefineStmt { [$1] }
        | DeleteStmt { [$1] }
        | DropAssertStmt { [$1] }
        | DropCastStmt { [$1] }
        | DropGroupStmt { [$1] }
        | DropOpClassStmt { [$1] }
        | DropPLangStmt { [$1] }
        | DropRuleStmt { [$1] }
        | DropStmt { [$1] }
        | DropTableSpaceStmt { [$1] }
        | DropTrigStmt { [$1] }
        | DropRoleStmt { [$1] }
        | DropUserStmt { [$1] }
        | DropdbStmt { [$1] }
        | ExecuteStmt { [$1] }
        | ExplainStmt { [$1] }
        | FetchStmt { [$1] }
        | GrantStmt { [$1] }
        | GrantRoleStmt { [$1] }
        | IndexStmt { [$1] }
        | InsertStmt { [$1] }
        | ListenStmt { [$1] }
        | LoadStmt { [$1] }
        | LockStmt { [$1] }
        | NotifyStmt { [$1] }
        | PrepareStmt { [$1] }
        | ReindexStmt { [$1] }
        | RemoveAggrStmt { [$1] }
        | RemoveFuncStmt { [$1] }
        | RemoveOperStmt { [$1] }
        | RenameStmt { [$1] }
        | RevokeStmt { [$1] }
        | RevokeRoleStmt { [$1] }
        | RuleStmt { [$1] }
        | SelectStmt { [$1] }
        | TransactionStmt { [$1] }
        | TruncateStmt { [$1] }
        | UnlistenStmt { [$1] }
        | UpdateStmt { [$1] }
        | VacuumStmt { [$1] }
        | VariableResetStmt { [$1] }
        | VariableSetStmt { [$1] }
        | VariableShowStmt { [$1] }
        | ViewStmt { [$1] }
        | {- empty -} { [] }

CreateRoleStmt  :: { Statement }
CreateRoleStmt
        : CREATE ROLE RoleId opt_with OptRoleList { CreateRoleStmt $3 $4 $5 }
        
opt_with :: { OptWith }
opt_with
        : WITH { Just WITH }
        | {- EMPTY -} { Nothing }

OptRoleList :: { OptRoleList }
OptRoleList
        : OptRoleList OptRoleElem { $1 ++ [$2] }
        | {- EMPTY -} { [] }
        
OptRoleElem     :: { OptRoleElem }
OptRoleElem
        : PASSWORD Sconst { RolePassword $2 }
        | ENCRYPTED PASSWORD Sconst { RoleEncryptedPassword $3 }
        | UNENCRYPTED PASSWORD Sconst { RoleUnencryptedPassword $3 }
        | SUPERUSER { RoleSuperUser }
        | NOSUPERUSER { RoleNoSuperUser }
        | INHERIT { RoleInherit }
        | NOINHERIT { RoleNoInherit }
        | CREATEDB { RoleCreateDB }
        | NOCREATEDB { RoleNoCreateDB }
        | CREATEROLE { RoleCreateRole }
        | NOCREATEROLE { RoleNoCreateRole }
        | CREATEUSER { RoleCreateUser }
        | NOCREATEUSER { RoleNoCreateUser }
        | LOGIN { RoleLogin }
        | NOLOGIN { RoleNoLogin }
        | CONNECTION LIMIT SignedIconst { RoleConnectionLimit $3 }
        | VALID UNTIL Sconst { RoleValidUntil $3 }
        | USER name_list { RoleUser $2 }
        | SYSID Iconst { RoleSysId $2 }
        | ADMIN name_list { RoleAdmin $2 }
        | ROLE name_list { RoleRole $2 }
        | IN ROLE name_list { RoleInRole $3 }
        | IN GROUP name_list { RoleInGroup $3 }

CreateUserStmt  :: { Statement }
CreateUserStmt
        : CREATE USER RoleId opt_with OptRoleList { CreateUserStmt $3 $4 $5 }

AlterRoleStmt :: { Statement }
AlterRoleStmt
        : ALTER ROLE RoleId opt_with OptRoleList { AlterRoleStmt $3 $4 $5 }

AlterRoleSetStmt        :: { Statement }
AlterRoleSetStmt
        : ALTER ROLE RoleId SET set_rest { AlterRoleSetStmt $3 (Left $5) }
        | ALTER ROLE RoleId VariableResetStmt { AlterRoleSetStmt $3 (Right $4) } 

AlterUserStmt   :: { Statement }
AlterUserStmt
        : ALTER USER RoleId opt_with OptRoleList { AlterUserStmt $3 $4 $5 }

AlterUserSetStmt :: { Statement }
AlterUserSetStmt
        : ALTER USER RoleId SET set_rest { AlterUserSetStmt $3 (Left $5) }
        | ALTER USER RoleId VariableResetStmt { AlterUserSetStmt $3 (Right $4) }

DropRoleStmt    :: { Statement }
DropRoleStmt
        : DROP ROLE name_list { DropRoleStmt $3 }

DropUserStmt    :: { Statement }
DropUserStmt
        : DROP USER name_list { DropUserStmt $3 }

CreateGroupStmt :: { Statement }
CreateGroupStmt
        : CREATE GROUP RoleId opt_with OptRoleList { CreateGroupStmt $3 $4 $5 }

AlterGroupStmt  :: { Statement }
AlterGroupStmt
        : ALTER GROUP RoleId add_drop USER name_list { AlterGroupStmt $3 $4 $6 }
        
add_drop        :: { AddDrop }
add_drop
        : ADD { Left ADD }
        | DROP { Right DROP }

DropGroupStmt   :: { Statement }
DropGroupStmt
        : DROP GROUP name_list { DropGroupStmt $3 }

CreateSchemaStmt        :: { Statement }
CreateSchemaStmt
        : CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList { CreateSchemaStmt (Just $3) $5 $6 }
        | CREATE SCHEMA ColId OptSchemaEltList { CreateSchemaStmt Nothing $3 $4 }
        
OptSchemaName   :: { OptSchemaName }
OptSchemaName
        : ColId { Just $1 }
        | {- EMPTY -} { Nothing }
        
OptSchemaEltList        :: { OptSchemaEltList }
OptSchemaEltList
        : OptSchemaEltList schema_stmt { $1 ++ [$2] }
        | {- EMPTY -} { [] }

schema_stmt     :: { SchemaStmt }
schema_stmt
        : CreateStmt { $1 }
        | IndexStmt { $1 }
        | CreateSeqStmt { $1 }
        | CreateTrigStmt { $1 }
        | GrantStmt { $1 }
        | ViewStmt { $1 }

VariableSetStmt :: { Statement }
VariableSetStmt
        : SET set_rest { VariableSetStmt Nothing $2 }
        | SET LOCAL set_rest { VariableSetStmt (Just (Left LOCAL)) $3 }
        | SET SESSION set_rest { VariableSetStmt (Just (Right SESSION)) $3 }
        
set_rest        :: { SetRest }
set_rest
        : var_name TO var_list_or_default { SetTo $1 $3 }
        | var_name '=' var_list_or_default { SetEqual $1 $3 }
        | TIME ZONE zone_value { SetTimeZone $3 }
        | TRANSACTION transaction_mode_list { SetTransaction $ Left $2 }
        | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list { SetTransaction $ Right $5 }
        | NAMES opt_encoding { SetName $2 }
        | ROLE ColId_or_Sconst { SetRole $2 }
        | SESSION AUTHORIZATION ColId_or_Sconst { SetSessionAuthorization (Left $3) }
        | SESSION AUTHORIZATION DEFAULT { SetSessionAuthorization (Right DEFAULT) }
        
var_name        :: { VarName }
var_name
        : var_name_aux {MyLst $1}

var_name_aux    :: { [ColId] }
var_name_aux
        : ColId { [$1] }
        | var_name_aux '.' ColId { $1 ++ [$3] }
        
var_list_or_default     :: { VarListOrDefault }
var_list_or_default
        : var_list { Left $1 }
        | DEFAULT { Right DEFAULT }
        
var_list        :: { VarList }
var_list
        : var_list_aux { MyLst $1 }

var_list_aux    :: { [VarValue] }
var_list_aux
        : var_value { [$1] }
        | var_list_aux ',' var_value { $1 ++ [$3] }
        
var_value       :: { VarValue }
var_value
        : opt_boolean { OneOf3 $1 }
        | ColId_or_Sconst { TwoOf3 $1 }
        | NumericOnly { ThreeOf3 $1 }
        
iso_level       :: { IsoLevel }
iso_level
        : READ UNCOMMITTED { IsoReadUncommited }
        | READ COMMITTED { IsoReadCommited }
        | REPEATABLE READ { IsoRepeatableRead }
        | SERIALIZABLE { IsoSerializable }
        
opt_boolean     :: { OptBoolean }
opt_boolean
        : TRUE { OptBoolTrue }
        | FALSE { OptBoolFalse }
        | ON { OptBoolOn }
        | OFF { OptBoolOff }

zone_value      :: { ZoneValue }
zone_value
        : Sconst { ZoneSconst $1 }
        | IDENT { ZoneIdent }
        | ConstInterval Sconst opt_interval { ZoneConstInterval $1 Nothing $2 $3 }
        | ConstInterval '(' Iconst ')' Sconst opt_interval { ZoneConstInterval $1 (Just $3) $5 $6 }
        | NumericOnly { ZoneNum $1 }
        | DEFAULT { ZoneDefault }
        | LOCAL { ZoneLocal }
        
opt_encoding    :: { OptEncoding }
opt_encoding
        : Sconst { Just (Left $1) }
        | DEFAULT { Just (Right DEFAULT) }
        | {-EMPTY-} { Nothing }
        
ColId_or_Sconst :: { ColIdOrSconst }
ColId_or_Sconst
        : ColId { Left $1 }
        | SCONST { Right $1 }
        
VariableShowStmt        :: { Statement }
VariableShowStmt
        : SHOW var_name { VariableShowStmt $ OneOf5 $2 }
        | SHOW TIME ZONE { VariableShowStmt $ TwoOf5 (TIME,ZONE) }
        | SHOW TRANSACTION ISOLATION LEVEL { VariableShowStmt $ ThreeOf5 (TRANSACTION,ISOLATION,LEVEL) }
        | SHOW SESSION AUTHORIZATION { VariableShowStmt $ FourOf5 (SESSION,AUTHORIZATION) }
        | SHOW ALL { VariableShowStmt $ FiveOf5 ALL }
        
VariableResetStmt       :: { Statement }
VariableResetStmt
        : RESET var_name { VariableResetStmt $ OneOf5 $2 }
        | RESET TIME ZONE { VariableResetStmt $ TwoOf5 (TIME,ZONE) }
        | RESET TRANSACTION ISOLATION LEVEL { VariableResetStmt $ ThreeOf5 (TRANSACTION,ISOLATION,LEVEL) }
        | RESET SESSION AUTHORIZATION { VariableResetStmt $ FourOf5 (SESSION,AUTHORIZATION) }
        | RESET ALL { VariableResetStmt $ FiveOf5 ALL }
        
ConstraintsSetStmt      :: { Statement }
ConstraintsSetStmt
        : SET CONSTRAINTS constraints_set_list constraints_set_mode { ConstraintsSetStmt $3 $4 }
        
constraints_set_list    :: { ConstraintsSetList }
constraints_set_list
        : ALL { Left ALL }
        | name_list { Right $1 }
        
constraints_set_mode    :: { ConstraintsSetMode }
constraints_set_mode
        : DEFERRED { Left DEFERRED }
        | IMMEDIATE { Right IMMEDIATE }

CheckPointStmt  :: { Statement }
CheckPointStmt
        : CHECKPOINT { CheckPointStmt }

AlterTableStmt  :: { Statement }
AlterTableStmt
        : ALTER TABLE relation_expr alter_table_cmds { AlterTableStmt $3 (Left $4) }
        | ALTER INDEX relation_expr alter_rel_cmds { AlterTableStmt $3 (Right $4) }
        
alter_table_cmds        :: { AlterTableCmds }
alter_table_cmds
        : alter_table_cmds_aux { MyLst $1 }

alter_table_cmds_aux
        : alter_table_cmd { [$1] }
        | alter_table_cmds_aux ',' alter_table_cmd { $1 ++ [$3] }

alter_table_cmd :: { AlterTableCmd }
alter_table_cmd
        : ADD opt_column columnDef { AlterTableAdd $ Left ($2,$3) }
        | ADD TableConstraint { AlterTableAdd $ Right $2 }
        | ALTER opt_column ColId alter_column_default { AlterTableAlter $2 $3 (OneOf4 $4) }
        | ALTER opt_column ColId DROP NOT NULL { AlterTableAlter $2 $3 (TwoOf4 (DROP,NOT,NULL)) }
        | ALTER opt_column ColId SET NOT NULL { AlterTableAlter $2 $3 (ThreeOf4 (SET,OneOf3 (NOT,NULL))) }
        | ALTER opt_column ColId SET STATISTICS IntegerOnly { AlterTableAlter $2 $3 (ThreeOf4 (SET,TwoOf3 (STATISTICS,$6))) }
        | ALTER opt_column ColId SET STORAGE ColId { AlterTableAlter $2 $3 (ThreeOf4 (SET,ThreeOf3 (STORAGE,$6))) }
        | ALTER opt_column ColId TYPE Typename alter_using { AlterTableAlter $2 $3 (FourOf4 (TYPE,$5,$6)) }
        | DROP opt_column ColId opt_drop_behavior { AlterTableDrop (Left ($2,$3)) $4 }
        | DROP CONSTRAINT name opt_drop_behavior { AlterTableDrop (Right (CONSTRAINT,$3)) $4 }
        | CREATE TOAST TABLE { AlterTableCreateToastTable }
        | CLUSTER ON name { AlterTableClusterOn $3 }
        | SET WITHOUT OIDS { AlterTableSetWithout $ Left OIDS }
        | SET WITHOUT CLUSTER { AlterTableSetWithout $ Right CLUSTER }
        | ENABLE TRIGGER name { AlterTableEnableTrigger $ OneOf3 $3 }
        | ENABLE TRIGGER ALL { AlterTableEnableTrigger $ TwoOf3 ALL }
        | ENABLE TRIGGER USER { AlterTableEnableTrigger $ ThreeOf3 USER }
        | DISABLE TRIGGER name { AlterTableDisableTrigger $ OneOf3 $3 }
        | DISABLE TRIGGER ALL { AlterTableDisableTrigger $ TwoOf3 ALL }
        | DISABLE TRIGGER USER { AlterTableDisableTrigger $ ThreeOf3 USER }
        | alter_rel_cmd { AlterTableRelCmd $1 }

alter_rel_cmds  :: { AlterRelCmds }
alter_rel_cmds
        : alter_rel_cmds_aux { MyLst $1 }

alter_rel_cmds_aux      :: { [AlterRelCmd] }
alter_rel_cmds_aux
        : alter_rel_cmd { [$1] }
        | alter_rel_cmds_aux ',' alter_rel_cmd { $1 ++ [$3] }

alter_rel_cmd   :: { AlterRelCmd }
alter_rel_cmd
        : OWNER TO RoleId { AlterRelCmdOwnerTo $3 }
        | SET TABLESPACE name {  AlterRelCmdSetTablespace $3 }
        
alter_column_default    :: { AlterColumnDefault }
alter_column_default
        : SET DEFAULT a_expr { AlterColumnSetDefault $3 }
        | DROP DEFAULT { AlterColumnDropDefault }
        
opt_drop_behavior       :: { OptDropBehavior }
opt_drop_behavior
        : CASCADE { Just $ Left CASCADE }
        | RESTRICT { Just $ Right RESTRICT }
        | {- EMPTY -} { Nothing }
        
alter_using     :: { AlterUsing }
alter_using
        : USING a_expr { AlterUse $ Just $2 }
        | {- EMPTY -} { AlterUse $ Nothing }

ClosePortalStmt :: { Statement }
ClosePortalStmt
        : CLOSE name { ClosePortalStmt $2 }

CopyStmt        :: { Statement }
CopyStmt
        : COPY opt_binary qualified_name opt_column_list opt_oids copy_from copy_file_name copy_delimiter opt_with copy_opt_list { CopyStmt $2 $3 $4 $5 $6 $7 $8 $9 $10 }

copy_from       :: { CopyFrom }
copy_from
        : FROM { Left FROM }
        | TO { Right TO }

copy_file_name  :: { CopyFileName }
copy_file_name
        : Sconst { OneOf3 $1 }
        | STDIN { TwoOf3 STDIN }
        | STDOUT { ThreeOf3 STDOUT }
        
copy_opt_list   :: { CopyOptList }
copy_opt_list
        : copy_opt_list copy_opt_item { $1 ++ [$2] }
        | {- EMPTY -} { [] }
        
copy_opt_item   :: { CopyOptItem }
copy_opt_item
        : BINARY { CpItemBinary }
        | OIDS { CpItemOids }
        | DELIMITER opt_as Sconst { CpItemDelimiter $2 $3 }
        | NULL opt_as Sconst { CpItemNull $2 $3 }
        | CSV { CpItemCsv }
        | HEADER { CpItemHeader }
        | QUOTE opt_as Sconst { CpItemQuote $2 $3 }
        | ESCAPE opt_as Sconst { CpItemEscape $2 $3 }
        | FORCE QUOTE columnList { CpItemForceQuote $3 }
        | FORCE NOT NULL columnList { CpItemForceNotNull $4 }

opt_binary      :: { OptBinary }
opt_binary
        : BINARY { Just BINARY }
        | {-EMPTY-} { Nothing }
        
opt_oids        :: { OptOids }
opt_oids
        : WITH OIDS { Just (WITH,OIDS) }
        | {-EMPTY-} { Nothing }
        
copy_delimiter  :: { CopyDelimiter }    
copy_delimiter
        : opt_using DELIMITERS Sconst { Just ($1,DELIMITERS,$3) }
        | {-EMPTY-} { Nothing }
        
opt_using       :: { OptUsing }
opt_using
        : USING { Just USING }
        | {-EMPTY-} { Nothing }

CreateStmt      :: { Statement }
CreateStmt
        : CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptInherit OptWithOids OnCommitOption OptTableSpace { CreateStmt $2 $4 Nothing $6 (Just $8) $9 $10 $11 }
        | CREATE OptTemp TABLE qualified_name OF qualified_name '(' OptTableElementList ')' OptWithOids OnCommitOption OptTableSpace { CreateStmt $2 $4 (Just $6) $8 Nothing $10 $11 $12 }

OptTemp :: { OptTemp }
OptTemp
        : TEMPORARY { Just TmpTemporary }
        | TEMP { Just TmpTemp }
        | LOCAL TEMPORARY { Just TmpLocalTemporary }
        | LOCAL TEMP { Just TmpLocalTemp }
        | GLOBAL TEMPORARY { Just TmpGlobalTemporary }
        | GLOBAL TEMP { Just TmpGlobalTemp }
        | {-EMPTY-} { Nothing }
        

OptTableElementList     :: { OptTableElementList }
OptTableElementList
        : TableElementList { Just $1 }
        | {-EMPTY-} { Nothing }
        
TableElementList        :: { TableElementList }
TableElementList
        : TableElementList_aux { MyLst $1 }

TableElementList_aux    :: { [TableElement] }
TableElementList_aux
        : TableElement { [$1] }
        | TableElementList_aux ',' TableElement { $1 ++ [$3] }
        
TableElement    :: { TableElement }
TableElement
        : columnDef { OneOf3 $1 }
        | TableLikeClause { TwoOf3 $1 }
        | TableConstraint { ThreeOf3 $1 }
        
columnDef       :: { ColumnDef }
columnDef
        : ColId Typename ColQualList { CDef $1 $2 $3 }
        
ColQualList     :: { ColQualList }
ColQualList
        : ColQualList ColConstraint { $1 ++ [$2] }
        | {-EMPTY-} { [] }
        
ColConstraint   :: { ColConstraint }
ColConstraint
        : CONSTRAINT name ColConstraintElem { OneOf3 (CONSTRAINT,$2,$3) }
        | ColConstraintElem { TwoOf3 $1 }
        | ConstraintAttr { ThreeOf3 $1 }

ColConstraintElem       :: { ColConstraintElem }
ColConstraintElem
        : NOT NULL { CstrNotNull }
        | NULL { CstrNull }
        | UNIQUE OptConsTableSpace { CstrUnique $2 }
        | PRIMARY KEY OptConsTableSpace {  CstrPrimaryKey $3 }
        | CHECK '(' a_expr ')' { CstrCheck $3 }
        | DEFAULT b_expr { CstrDefault $2 }
        | REFERENCES qualified_name opt_column_list key_match key_actions { CstrReferences $2 $3 $4 $5 }

ConstraintAttr  :: { ConstraintAttr }
ConstraintAttr
        : DEFERRABLE { CstrAttrDeferrable }
        | NOT DEFERRABLE { CstrAttrNotDeferrable }
        | INITIALLY DEFERRED { CstrAttrInitiallyDeferred }
        | INITIALLY IMMEDIATE { CstrAttrInitiallyImmediate }

TableLikeClause :: { TableLikeClause }
TableLikeClause
        : LIKE qualified_name like_including_defaults { TLike $2 $3 }
        
like_including_defaults :: { LikeIncludingDefaults }
like_including_defaults
        : INCLUDING DEFAULTS { Just LikeIncludingDefaults }
        | EXCLUDING DEFAULTS { Just LikeExcludingDefaults }
        | {- EMPTY -} { Nothing }

TableConstraint :: { TableConstraint }
TableConstraint
        : CONSTRAINT name ConstraintElem { TConstraint (Just $2) $3 }
        | ConstraintElem { TConstraint Nothing $1 }
        
ConstraintElem  :: { ConstraintElem }
ConstraintElem
        : CHECK '(' a_expr ')' { CstrElemCheck $3 }
        | UNIQUE '(' columnList ')' OptConsTableSpace { CstrElemUnique $3 $5 }
        | PRIMARY KEY '(' columnList ')' OptConsTableSpace { CstrElemPrimaryKey $4 $6 }
        | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name opt_column_list key_match key_actions ConstraintAttributeSpec { CstrElemForeignKey $4 $7 $8 $9 $10 $11 }
        
opt_column_list :: { OptColumnList }
opt_column_list
        : '(' columnList ')' { OptColList $ Just $2 }
        | {-EMPTY-} { OptColList Nothing }
        
columnList      :: { ColumnList }
columnList
        : columnList_aux { MyLst $1 }

columnList_aux  :: { [ColumnElem] }
columnList_aux
        : columnElem { [$1] }
        | columnList_aux ',' columnElem {  $1 ++ [$3] }
        
columnElem      :: { ColumnElem }
columnElem
        : ColId { $1 }
        
key_match       :: { KeyMatch }
key_match
        : MATCH FULL { Just MatchFull }
        | MATCH PARTIAL { Just MatchPartial }
        | MATCH SIMPLE { Just MatchSimple }
        | {-EMPTY-} { Nothing }

key_actions     :: { KeyActions }
key_actions
        : key_update { Just $ OneOf3 $1 }
        | key_delete { Just $ TwoOf3 $1 }
        | key_update key_delete { Just $ ThreeOf3 ($1,$2) }
        | key_delete key_update { Just $ ThreeOf3 ($2,$1) }
        | {-EMPTY-} { Nothing }
        
key_update      :: { KeyUpdate }
key_update
        : ON UPDATE key_action { OnUpdate $3 }
        
key_delete      :: { KeyDelete }
key_delete
        : ON DELETE key_action { OnDelete $3 }
        
key_action      :: { KeyAction }
key_action
        : NO ACTION { KeyNoAction }
        | RESTRICT { KeyRestrict }
        | CASCADE { KeyCascade }
        | SET NULL { KeySetNull }
        | SET DEFAULT { KeySetDefault }
        
OptInherit      :: { OptInherit }
OptInherit
        : INHERITS '(' qualified_name_list ')' { OptInherits $ Just $3 }
        | {-EMPTY-} { OptInherits Nothing }
        
OptWithOids     :: { OptWithOids }
OptWithOids
        : WITH OIDS { WithOids }
        | WITHOUT OIDS { WithoutOids }
        | {- empty -} { NoOids }
        
OnCommitOption  :: { OnCommitOption }
OnCommitOption
        : ON COMMIT DROP { Just OnCommitDrop }
        | ON COMMIT DELETE ROWS { Just OnCommitDeleteRows }
        | ON COMMIT PRESERVE ROWS { Just OnCommitPreserveRows }
        | {- empty -} { Nothing }
        
OptTableSpace   :: { OptTableSpace }
OptTableSpace
        : TABLESPACE name { OptTableSpaceConst $ Just $2 }
        | {- empty -} { OptTableSpaceConst Nothing }
        

OptConsTableSpace       :: { OptConsTableSpace }
OptConsTableSpace
        : USING INDEX TABLESPACE name { OptConsTableSpaceConst $ Just $4 }
        | {- empty -} { OptConsTableSpaceConst Nothing }

CreateAsStmt    :: { Statement }
CreateAsStmt
        : CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs SelectStmt { CreateAsStmt $2 $4 $5 $6 $7 }
        
WithOidsAs      :: { WithOidsAs }
WithOidsAs
        : WITH OIDS AS { WOA_WithOidsAs }
        | WITHOUT OIDS AS { WOA_WithoutOidsAs }
        | AS { WOA_As }
                
OptCreateAs     :: { OptCreateAs }
OptCreateAs
        : '(' CreateAsList ')' { OptCreateAsConst $ Just $2 }
        | {- empty -} { OptCreateAsConst Nothing }
        
CreateAsList    :: { CreateAsList }
CreateAsList
        : CreateAsList_aux { MyLst $1 }

CreateAsList_aux        :: { [CreateAsElement] }
CreateAsList_aux
        : CreateAsElement { [$1] }
        | CreateAsList_aux ',' CreateAsElement { $1 ++ [$3] }
        
CreateAsElement :: { CreateAsElement }
CreateAsElement
        : ColId { $1 }

CreateSeqStmt   :: { Statement }
CreateSeqStmt
        : CREATE OptTemp SEQUENCE qualified_name OptSeqList { CreateSeqStmt $2 $4 $5 }
        
AlterSeqStmt    :: { Statement }
AlterSeqStmt
        : ALTER SEQUENCE qualified_name OptSeqList { AlterSeqStmt $3 $4 }
        

OptSeqList      :: { OptSeqList }
OptSeqList
        : OptSeqList OptSeqElem { $1 ++ [$2] }
        | {-EMPTY-} { [] }
        
OptSeqElem      :: { OptSeqElem }
OptSeqElem
        : CACHE NumericOnly { SeqElemCache $2 }
        | CYCLE { SeqElemCycle }
        | NO CYCLE { SeqElemNoCycle }
        | INCREMENT opt_by NumericOnly { SeqElemIncrement $2 $3 }
        | MAXVALUE NumericOnly { SeqElemMaxValue $2 }
        | MINVALUE NumericOnly { SeqElemMinValue $2 }
        | NO MAXVALUE { SeqElemNoMaxValue }
        | NO MINVALUE { SeqElemNoMinValue }
        | START opt_with NumericOnly { SeqElemStart $2 $3 }
        | RESTART opt_with NumericOnly { SeqElemRestart $2 $3 }

opt_by  :: { OptBy }
opt_by  : BY { Just BY }
        | {- empty -} { Nothing }

NumericOnly     :: { NumericOnly }
NumericOnly
        : FloatOnly { Left $1 }
        | IntegerOnly { Right $1 }
        
FloatOnly       :: { FloatOnly }        
FloatOnly
        : FCONST { FloatConst $1 }
        | '-' FCONST { MinusFloatConst $2 }
        
IntegerOnly     :: { IntegerOnly }
IntegerOnly
        : SignedIconst { $1 }

CreatePLangStmt :: { Statement }
CreatePLangStmt
        : CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst { CreatePLangStmt $2 $3 $5 Nothing }
        | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst HANDLER handler_name opt_validator opt_lancompiler { CreatePLangStmt $2 $3 $5 (Just ($7,$8,$9)) }
        
opt_trusted     :: { OptTrusted }       
opt_trusted
        : TRUSTED { Just TRUSTED }
        | {- empty -} { Nothing }

handler_name    :: { HandlerName }
handler_name
        : name { Left $1 }
        | name attrs { Right ($1,$2) }
        
opt_validator   :: { OptValidator }
opt_validator
        : VALIDATOR handler_name { OptVal $ Just $2 }
        | {- empty -} { OptVal Nothing }
        
opt_lancompiler :: { OptLancompiler }
opt_lancompiler
        : LANCOMPILER Sconst { OptLanComp $ Just $2 }
        | {- empty -} { OptLanComp $ Nothing }
        
DropPLangStmt   :: { Statement }
DropPLangStmt
        : DROP opt_procedural LANGUAGE ColId_or_Sconst opt_drop_behavior { DropPLangStmt $2 $4 $5 }
        
opt_procedural  :: { OptProcedural }
opt_procedural
        : PROCEDURAL { Just PROCEDURAL }
        | {- empty -} { Nothing }

CreateTableSpaceStmt    :: { Statement }
CreateTableSpaceStmt
        : CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst { CreateTableSpaceStmt $3 $4 $6 }
        
OptTableSpaceOwner      :: { OptTableSpaceOwner }
OptTableSpaceOwner
        : OWNER name { OptTSOwner $ Just $2 }
        | {- empty -} { OptTSOwner Nothing }

DropTableSpaceStmt      :: { Statement }
DropTableSpaceStmt
        : DROP TABLESPACE name { DropTableSpaceStmt $3 }

CreateTrigStmt  :: { Statement }
CreateTrigStmt
        : CREATE TRIGGER name TriggerActionTime TriggerEvents ON qualified_name TriggerForSpec EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt $3 (Just $4) $5 $7 (Left $8) $11 $13 }
        | CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON qualified_name OptConstrFromTable ConstraintAttributeSpec FOR EACH ROW EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt $4 Nothing $6 $8 (Right ($9,$10)) $16 $18 }

TriggerActionTime       :: { TriggerActionTime }
TriggerActionTime
        : BEFORE { Left BEFORE }
        | AFTER { Right AFTER }
        
TriggerEvents   :: { TriggerEvents }    
TriggerEvents
        : TriggerOneEvent { OneTrigger $1 }
        | TriggerOneEvent OR TriggerOneEvent { TwoTriggers $1 $3 }
        | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent { ThreeTriggers $1 $3 $5 }

TriggerOneEvent :: { TriggerOneEvent }
TriggerOneEvent
        : INSERT { OneOf3 INSERT }
        | DELETE { TwoOf3 DELETE }
        | UPDATE { ThreeOf3 UPDATE }
        
TriggerForSpec  :: { TriggerForSpec }
TriggerForSpec
        : FOR TriggerForOpt TriggerForType { TriggerForSpecConst $ Just ($2,$3) }
        | {- empty -} { TriggerForSpecConst Nothing }

TriggerForOpt   :: { TriggerForOpt }
TriggerForOpt
        : EACH { Just EACH }
        | {- empty -} { Nothing }       

TriggerForType  :: { TriggerForType }
TriggerForType
        : ROW { Left ROW }
        | STATEMENT { Right STATEMENT }
        
TriggerFuncArgs :: { TriggerFuncArgs }
TriggerFuncArgs
        : TriggerFuncArgs_aux { MyLst $1 }

TriggerFuncArgs_aux     :: { [TriggerFuncArg] }
TriggerFuncArgs_aux
        : TriggerFuncArg { [$1] }
        | TriggerFuncArgs_aux ',' TriggerFuncArg { $1 ++ [$3] }
        | {- empty -} { [] }
        
TriggerFuncArg  :: { TriggerFuncArg }
TriggerFuncArg
        : ICONST { OneOf6 $1 }
        | FCONST { TwoOf6 $1 }
        | Sconst { ThreeOf6 $1 }
        | BCONST { FourOf6 $1 }
        | XCONST { FiveOf6 $1 }
        | ColId { SixOf6 $1 }
        
OptConstrFromTable      :: { OptConstrFromTable }
OptConstrFromTable
        : FROM qualified_name { OptConstrFromTableConst $ Just $2 }
        | {- empty -} { OptConstrFromTableConst Nothing }
        
ConstraintAttributeSpec :: { ConstraintAttributeSpec }
ConstraintAttributeSpec
        : ConstraintDeferrabilitySpec { (Just $1,Nothing) }
        | ConstraintDeferrabilitySpec ConstraintTimeSpec { (Just $1,Just $2) }
        | ConstraintTimeSpec { (Nothing,Just $1) }
        | ConstraintTimeSpec ConstraintDeferrabilitySpec { (Just $2,Just $1) }
        | {- empty -} { (Nothing,Nothing) }

ConstraintDeferrabilitySpec     :: { ConstraintDeferrabilitySpec }      
ConstraintDeferrabilitySpec
        : NOT DEFERRABLE { Left (NOT,DEFERRABLE) }
        | DEFERRABLE { Right DEFERRABLE }
        
ConstraintTimeSpec      :: { ConstraintTimeSpec }
ConstraintTimeSpec
        : INITIALLY IMMEDIATE { CnstrTimeSpec $ Left IMMEDIATE }
        | INITIALLY DEFERRED { CnstrTimeSpec $ Right DEFERRED }
        
DropTrigStmt    :: { Statement }
DropTrigStmt
        : DROP TRIGGER name ON qualified_name opt_drop_behavior { DropTrigStmt $3 $5 $6 }

CreateAssertStmt        :: { Statement }
CreateAssertStmt
        : CREATE ASSERTION name CHECK '(' a_expr ')' ConstraintAttributeSpec { CreateAssertStmt $3 $6 $8 }
        
DropAssertStmt  :: { Statement }
DropAssertStmt
        : DROP ASSERTION name opt_drop_behavior { DropAssertStmt $3 $4 }

DefineStmt      :: { Statement }
DefineStmt
        : CREATE AGGREGATE func_name definition { DefineStmt $ OneOf3 ($3,$4) }
        | CREATE OPERATOR any_operator definition { DefineStmt $ TwoOf3 ($3,$4) }
        | CREATE TYPE any_name definition { DefineStmt $ ThreeOf3 ($3,Left $4) }
        | CREATE TYPE any_name AS '(' TableFuncElementList ')' { DefineStmt $ ThreeOf3 ($3,Right $6) }

definition      :: { Definition }       
definition
        : '(' def_list ')' { DefList $2 }
        
def_list        :: { [DefElem] }
def_list
        : def_elem { [$1] }
        | def_list ','  def_elem { $1 ++ [$3] }
        

def_elem        :: { DefElem }
def_elem
        : ColLabel '=' def_arg { DefEqual $1 $3 }
        | ColLabel { DefLabel $1 }

def_arg :: { DefArg }
def_arg
        : func_type { DefArgFunc $1 }
        | qual_all_Op { DefArgOp $1 }
        | NumericOnly {DefArgNum $1  }
        | Sconst { DefArgS $1 }

CreateOpClassStmt       :: { Statement }
CreateOpClassStmt
        : CREATE OPERATOR CLASS any_name opt_default FOR TYPE Typename USING access_method AS opclass_item_list { CreateOpClassStmt $4 $5 $8 $10 $12 }  

opclass_item_list       :: { OpClassItemList }
opclass_item_list
        : opclass_item_list_aux { MyLst $1 }

opclass_item_list_aux   :: { [OpClassItem] }
opclass_item_list_aux
        : opclass_item { [$1] }
        | opclass_item_list_aux ',' opclass_item { $1 ++ [$3] }
        
opclass_item    :: { OpClassItem }
opclass_item
        : OPERATOR Iconst any_operator opt_recheck { OpClassItemOperator $2 $3 Nothing $4 }
        | OPERATOR Iconst any_operator '(' oper_argtypes ')' opt_recheck { OpClassItemOperator $2 $3 (Just $5) $7 }
        | FUNCTION Iconst func_name func_args { OpClassItemFunction $2 $3 $4 }
        | STORAGE Typename { OpClassItemStorage $2 }

opt_default     :: { OptDefault }
opt_default
        : DEFAULT { Just DEFAULT }
        | {- empty -} { Nothing }
        
opt_recheck     :: { OptRecheck }
opt_recheck
        : RECHECK { Just RECHECK }
        | {- empty -} { Nothing }
        
DropOpClassStmt :: { Statement }
DropOpClassStmt
        : DROP OPERATOR CLASS any_name USING access_method opt_drop_behavior { DropOpClassStmt $4 $6 $7 }

DropStmt        :: { Statement }
DropStmt
        : DROP drop_type any_name_list opt_drop_behavior { DropStmt $2 $3 $4 }  

drop_type       :: { DropType }
drop_type
        : TABLE { DTTable }
        | SEQUENCE { DTSequence }
        | VIEW { DTView }
        | INDEX { DTIndex }
        | TYPE { DTType }
        | DOMAIN { DTDomain }
        | CONVERSION { DTConversion }
        | SCHEMA { DTSchema }

any_name_list   :: { AnyNameList }
any_name_list
        : any_name_list_aux { AnyNameLst $1 }

any_name_list_aux       :: { [AnyName] }
any_name_list_aux
        : any_name { [$1] }
        | any_name_list_aux ',' any_name { $1 ++ [$3] }
        
any_name        :: { AnyName }
any_name
        : ColId { ($1,Nothing) }
        | ColId attrs { ($1,Just $2) }
        
attrs   :: { Attrs }
attrs   : attrs_aux { AttrsCont $1 }

attrs_aux       :: { [AttrName] }       
attrs_aux
        : '.' attr_name { [$2] }
        | attrs_aux '.' attr_name { $1 ++ [$3] }

TruncateStmt    :: { Statement }
TruncateStmt
        : TRUNCATE opt_table qualified_name_list { TruncateStmt $2 $3 }

CommentStmt     :: { Statement }
CommentStmt
        : COMMENT ON comment_type any_name IS comment_text { CommentStmt $ CmtOn $3 $4 $6 }
        | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text { CommentStmt $ CmtOnAggregate $4 $6 $9 }
        | COMMENT ON FUNCTION func_name func_args IS comment_text { CommentStmt $ CmtOnFunction $4 $5 $7 }
        | COMMENT ON OPERATOR any_operator '(' oper_argtypes ')' IS comment_text { CommentStmt $ CmtOnOperator $4 $6 $9 }
        | COMMENT ON CONSTRAINT name ON any_name IS comment_text { CommentStmt $  CmtOnConstraint $4 $6 $8}
        | COMMENT ON RULE name ON any_name IS comment_text { CommentStmt $ CmtOnRule $4 (Just $6) $8 }
        | COMMENT ON RULE name IS comment_text { CommentStmt $ CmtOnRule $4 Nothing $6 }
        | COMMENT ON TRIGGER name ON any_name IS comment_text { CommentStmt $ CmtOnTrigger $4 $6 $8 }
        | COMMENT ON OPERATOR CLASS any_name USING access_method IS comment_text { CommentStmt $ CmtOnOperatorClass $5 $7 $9 }
        | COMMENT ON LARGE OBJECT NumericOnly IS comment_text { CommentStmt $ CmtOnLarge $5 $7 }
        | COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text { CommentStmt $ CmtOnCast $5 $7 $10 }
        | COMMENT ON opt_procedural LANGUAGE any_name IS comment_text { CommentStmt $ CmtOnLanguage $3 $5 $7 }  

comment_type    :: { CommentType }
comment_type
        : COLUMN { OneOf10 COLUMN }
        | DATABASE { TwoOf10 DATABASE }
        | SCHEMA { ThreeOf10 SCHEMA }
        | INDEX { FourOf10 INDEX }
        | SEQUENCE { FiveOf10 SEQUENCE }
        | TABLE { SixOf10 TABLE }
        | DOMAIN { SevenOf10 DOMAIN }
        | TYPE { EightOf10 TYPE }
        | VIEW { NineOf10 VIEW }
        | CONVERSION { TenOf10 CONVERSION }
        
comment_text    :: { CommentText }
comment_text
        : Sconst { Left $1 }
        | NULL { Right NULL }

FetchStmt       :: { Statement }
FetchStmt
        : FETCH fetch_direction from_in name { FetchStmt (Left FETCH) (Just ($2,$3)) $4 }
        | FETCH name { FetchStmt (Left FETCH) Nothing $2 }
        | MOVE fetch_direction from_in name { FetchStmt (Right MOVE) (Just ($2,$3)) $4 }
        | MOVE name { FetchStmt (Right MOVE) Nothing $2 }

fetch_direction :: { FetchDirection }   
fetch_direction
        : {- empty -} { Nothing }
        | NEXT { Just $ OneOf10 NEXT }
        | PRIOR { Just $ TwoOf10 PRIOR }
        | FIRST { Just $ ThreeOf10 FIRST }
        | LAST { Just $ FourOf10 LAST }
        | ABSOLUTE SignedIconst { Just $ FiveOf10 (ABSOLUTE,$2) }
        | RELATIVE SignedIconst { Just $ SixOf10 (RELATIVE,$2) }
        | SignedIconst { Just $ SevenOf10 $1 }
        | ALL { Just $ EightOf10 ALL }
        | FORWARD { Just $ NineOf10 (FORWARD,Nothing) }
        | FORWARD SignedIconst { Just $ NineOf10 (FORWARD,Just (Left $2)) }
        | FORWARD ALL { Just $ NineOf10 (FORWARD,Just (Right ALL)) }
        | BACKWARD { Just $ TenOf10 (BACKWARD,Nothing) }
        | BACKWARD SignedIconst { Just $ TenOf10 (BACKWARD,Just (Left $2)) }
        | BACKWARD ALL { Just $ TenOf10 (BACKWARD,Just (Right ALL)) }

from_in :: { FromIn }   
from_in
        : FROM { Left FROM }
        | IN { Right IN }

GrantStmt       :: { Statement }
GrantStmt
        : GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option { GrantStmt $2 $4 $6 $7 }

RevokeStmt      :: { Statement }
RevokeStmt
        : REVOKE privileges ON privilege_target FROM grantee_list opt_drop_behavior { RevokeStmt $ Left (ON,$2,$4,$6,$7) }
        | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_drop_behavior { RevokeStmt $ Right (FOR,$5,$7,$9,$10) }

privileges      :: { Privileges }
privileges
        : privilege_list { Priv $ Left $1 }
        | ALL { Priv $ Right Nothing }
        | ALL PRIVILEGES { Priv $ Right $ Just PRIVILEGES }

privilege_list  :: { PrivilegeList }
privilege_list
        : privilege_list_aux { MyLst $1 }

privilege_list_aux      :: { [Privilege] }
privilege_list_aux
        : privilege { [$1] }
        | privilege_list_aux ',' privilege { $1 ++ [$3] }

privilege       :: { Privilege }        
privilege
        : SELECT { PrivSelect }
        | REFERENCES { PrivReferences }
        | CREATE { PrivCreate }
        | ColId { PrivColId $1 }

privilege_target        :: { PrivilegeTarget }
privilege_target
        : qualified_name_list { PrivName $1 }
        | TABLE qualified_name_list { PrivTable $2 }
        | FUNCTION function_with_argtypes_list { PrivFunction $2 }
        | DATABASE name_list { PrivDatabase $2 }
        | LANGUAGE name_list { PrivLanguage $2 }
        | SCHEMA name_list { PrivSchema $2 }
        | TABLESPACE name_list { PrivTablespace $2 }

grantee_list    :: { GranteeList }
grantee_list
        : grantee_list_aux { MyLst $1 }

grantee_list_aux        :: { [Grantee] }
grantee_list_aux        
        : grantee { [$1] }
        | grantee_list_aux ',' grantee { $1 ++ [$3] }   

grantee :: { Grantee }
grantee : RoleId { (Nothing,$1) }
        | GROUP RoleId { (Just GROUP,$2) }
        
opt_grant_grant_option  :: { OptGrantGrantOption }
opt_grant_grant_option
        : WITH GRANT OPTION { WithGrantOption }
        | {- empty -} { NoGrant }       

function_with_argtypes_list     :: { FunctionWithArgTypesList } 
function_with_argtypes_list
        : function_with_argtypes_list_aux { FuncLst $1 }        

function_with_argtypes_list_aux :: { [FunctionWithArgTypes] }
function_with_argtypes_list_aux
        : function_with_argtypes { [$1] }
        | function_with_argtypes_list_aux ',' function_with_argtypes { $1 ++ [$3] }
        
function_with_argtypes  :: { FunctionWithArgTypes }     
function_with_argtypes
        : func_name func_args { FuncArgType $1 $2 }

GrantRoleStmt   :: { Statement }
GrantRoleStmt
        : GRANT privilege_list TO name_list opt_grant_admin_option opt_granted_by { GrantRoleStmt $2 $4 $5 $6 } 

RevokeRoleStmt  :: { Statement }
RevokeRoleStmt
        : REVOKE privilege_list FROM name_list opt_granted_by opt_drop_behavior { RevokeRoleStmt $ Left ($2,$4,$5,$6) }
        | REVOKE ADMIN OPTION FOR privilege_list FROM name_list opt_granted_by opt_drop_behavior { RevokeRoleStmt $ Right ($5,$7,$8,$9) }
        
opt_grant_admin_option  :: { OptGrantAdminOption }
opt_grant_admin_option
        : WITH ADMIN OPTION { WithAdminOption }
        | {- empty -} { NoGrantAdmin }
        
opt_granted_by  :: { OptGrantedBy }
opt_granted_by
        : GRANTED BY RoleId { GrantedBy $3 }
        | {- empty -} { NoGrantedBy }

IndexStmt       :: { Statement }
IndexStmt
        : CREATE index_opt_unique INDEX index_name ON qualified_name access_method_clause '(' index_params ')' OptTableSpace where_clause { IndexStmt $2 $4 $6 $7 $9 $11 $12 }
        
index_opt_unique        :: { IndexOptUnique }   
index_opt_unique
        : UNIQUE { Just UNIQUE }
        | {- empty -} { Nothing }

access_method_clause    :: { AccessMethodClause }
access_method_clause
        : USING access_method { Just (USING,$2) }
        | {- empty -} { Nothing }

index_params    :: { IndexParams }
index_params
        : index_params_aux { IndexParamsConst $1 }

index_params_aux        :: { [IndexElem] }
index_params_aux
        : index_elem { [$1] }
        | index_params_aux ',' index_elem { $1 ++ [$3] }

index_elem      :: { IndexElem }
index_elem
        : ColId opt_class { IElem $1 $2 }
        | func_expr opt_class { IFuncElem $1 $2 }
        | '(' a_expr ')' opt_class { IExprElem $2 $4 }
        

opt_class       :: { OptClass }
opt_class
        : any_name { Just (Nothing,$1) }
        | USING any_name { Just (Just USING,$2) }
        | { Nothing }

CreateFunctionStmt      :: { Statement }
CreateFunctionStmt
        : CREATE opt_or_replace FUNCTION func_name func_args RETURNS func_return createfunc_opt_list opt_definition { CreateFunctionStmt $2 $4 $5 (Just $7) $8 $9 }
        | CREATE opt_or_replace FUNCTION func_name func_args createfunc_opt_list opt_definition { CreateFunctionStmt $2 $4 $5 Nothing $6 $7 }

opt_or_replace  :: { OptOrReplace }
opt_or_replace
        : OR REPLACE { OrReplace }
        | {- empty -} { NoOrReplace }
        
func_args       :: { FuncArgs } 
func_args
        : '(' func_args_list ')' { FArgs $ Just $2 }
        | '(' ')' { FArgs Nothing }

func_args_list  :: { FuncArgsList }
func_args_list
        : func_args_list_aux { FuncArgsLst $1 } 

func_args_list_aux      :: { [FuncArg] }
func_args_list_aux
        : func_arg { [$1] }
        | func_args_list_aux ',' func_arg { $1 ++ [$3] }

func_arg        :: { FuncArg }
func_arg
        : arg_class param_name func_type { (Just $1,Just $2,Just $3) }
        | param_name arg_class func_type { (Just $2,Just $1,Just $3) }
        | param_name func_type { (Nothing,Just $1,Just $2) }
        | arg_class func_type { (Just $1,Nothing,Just $2) }
        | func_type { (Nothing,Nothing,Just $1) }

arg_class       :: { ArgClass }
arg_class
        : IN { (Just IN,Nothing) }
        | OUT   { (Nothing,Just OUT) }
        | INOUT { (Just IN,Just OUT) }
        | IN OUT { (Just IN,Just OUT) }

param_name      :: { ParamName }
param_name
        : function_name { $1 }

func_return     :: { FuncReturn }       
func_return
        : func_type { $1 }

func_type       :: { FuncType }
func_type
        : Typename { FuncTypename $1 }
        | type_name attrs '%' TYPE { FuncAttrs $1 $2 }
        | SETOF type_name attrs '%' TYPE { FuncSetOf $2 $3 }
        
createfunc_opt_list     :: { CreateFuncOptList }
createfunc_opt_list
        : createfunc_opt_item { [$1] }
        | createfunc_opt_list createfunc_opt_item { $1 ++ [$2] }

common_func_opt_item    :: { CommonFuncOptItem }
common_func_opt_item
        : CALLED ON NULL INPUT { CalledOnNullInput }
        | RETURNS NULL ON NULL INPUT { ReturnsNullOnNummInput }
        | STRICT { Strict }
        | IMMUTABLE { Immutable }
        | STABLE { Stable }
        | VOLATILE { Volatile }
        | EXTERNAL SECURITY DEFINER { ExternalSecurityDefiner }
        | EXTERNAL SECURITY INVOKER { ExternalSecurityInvoker }
        | SECURITY DEFINER { SecurityDefiner }
        | SECURITY INVOKER { SecurityInvoker }

createfunc_opt_item     :: { CreateFuncOptItem }
createfunc_opt_item
        : AS func_as { FuncItemAs $2 }
        | LANGUAGE ColId_or_Sconst { FuncItemLanguage $2 }
        | common_func_opt_item { FuncItemCommon $1 }

func_as :: { FuncAs }
func_as : Sconst { SingleFuncAs $1 }
        | Sconst ',' Sconst { BinFuncAs $1 $3 }

opt_definition  :: { OptDefinition }
opt_definition
        : WITH definition { Just (WITH,$2) }
        | {-empty -} { Nothing }

AlterFunctionStmt       :: { Statement }
AlterFunctionStmt
        : ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict { AlterFunctionStmt $3 $4 $5 }

alterfunc_opt_list      :: { AlterFuncOptList }
alterfunc_opt_list
        : common_func_opt_item { [$1] }
        | alterfunc_opt_list common_func_opt_item { $1 ++ [$2] }

opt_restrict    :: { OptRestrict }
opt_restrict
        : RESTRICT { Just RESTRICT }
        | {- empty -} { Nothing }

RemoveFuncStmt  :: { Statement }
RemoveFuncStmt
        : DROP FUNCTION func_name func_args opt_drop_behavior { RemoveFuncStmt $3 $4 $5 }

RemoveAggrStmt  :: { Statement }
RemoveAggrStmt
        : DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior { RemoveAggrStmt $3 $5 $7 }
        
aggr_argtype    :: { AggrArgType }
aggr_argtype
        : Typename { Left $1 }
        | '*' { Right STAR }

RemoveOperStmt  :: { Statement }
RemoveOperStmt
        : DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior { RemoveOperStmt $3 $5 $7 }
        
oper_argtypes   :: { OperArgTypes }
oper_argtypes
        : Typename { SingleArg $1 }
        | Typename ',' Typename { BinArg $1 $3 }
        | NONE ',' Typename { LeftUnaryArg $3 }
        | Typename ',' NONE { RightUnaryArg $1 }
        

any_operator    :: { AnyOperator }
any_operator
        : all_Op { AnyOpAll $1 }
        | ColId '.' any_operator { AnyOpCol $1 $3 }

CreateCastStmt  :: { Statement }
CreateCastStmt
        : CREATE CAST '(' Typename AS Typename ')' WITH FUNCTION function_with_argtypes cast_context { CreateCastStmt $4 $6 (Just $10) $11 }
        | CREATE CAST '(' Typename AS Typename ')' WITHOUT FUNCTION cast_context { CreateCastStmt $4 $6 Nothing $10 }

cast_context    :: { CastContext }      
cast_context
        : AS IMPLICIT   { AsImplicit }
        | AS ASSIGNMENT { AsAssignment }
        | {- empty -} { NoCastContext }
        
DropCastStmt    :: { Statement }
DropCastStmt
        : DROP CAST '(' Typename AS Typename ')' opt_drop_behavior { DropCastStmt $4 $6 $8 }

ReindexStmt     :: { Statement }
ReindexStmt
        : REINDEX reindex_type qualified_name opt_force { ReindexStmt (Left ($2,$3)) $4 }
        | REINDEX SYSTEM name opt_force { ReindexStmt (Right (Left SYSTEM,$3)) $4 }
        | REINDEX DATABASE name opt_force { ReindexStmt (Right (Right DATABASE,$3)) $4 }

reindex_type    :: { ReindexType }      
reindex_type
        : INDEX { Left INDEX }
        | TABLE { Right TABLE }

opt_force       :: { OptForce } 
opt_force
        : FORCE { Just FORCE }
        | {- empty -} { Nothing }

RenameStmt      :: { Statement }
RenameStmt
        : ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name { RenameStmt $ RenAggregate $3 $5 $9 }
        | ALTER CONVERSION any_name RENAME TO name { RenameStmt $ RenConversion $3 $6 }
        | ALTER DATABASE database_name RENAME TO database_name { RenameStmt $ RenDatabase $3 $6 }
        | ALTER FUNCTION func_name func_args RENAME TO name { RenameStmt $ RenFunction $3 $4 $7 }
        | ALTER GROUP RoleId RENAME TO RoleId { RenameStmt $ RenGroup $3 $6 }
        | ALTER LANGUAGE name RENAME TO name { RenameStmt $ RenLanguage $3 $6 }
        | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name { RenameStmt $ RenOperator $4 $6 $9 }
        | ALTER SCHEMA name RENAME TO name { RenameStmt $ RenSchema $3 $6 }
        | ALTER TABLE relation_expr RENAME TO name { RenameStmt $ RenTable $3 $6 }
        | ALTER INDEX relation_expr RENAME TO name { RenameStmt $ RenIndex $3 $6 }
        | ALTER TABLE relation_expr RENAME opt_column name TO name { RenameStmt $ RenTableRename $3 $5 $6 $8 }
        | ALTER TRIGGER name ON relation_expr RENAME TO name { RenameStmt $ RenTrigger $3 $5 $8 }
        | ALTER ROLE RoleId RENAME TO RoleId { RenameStmt $ RenRole $3 $6 }
        | ALTER USER RoleId RENAME TO RoleId { RenameStmt $ RenUser $3 $6 }
        | ALTER TABLESPACE name RENAME TO name { RenameStmt $ RenTablespace $3 $6 }

opt_column      :: { OptColumn }        
opt_column
        : COLUMN { Just COLUMN }
        | {- empty -} { Nothing }

AlterObjectSchemaStmt   :: { Statement }
AlterObjectSchemaStmt
        : ALTER AGGREGATE func_name '(' aggr_argtype ')' SET SCHEMA name { AlterObjectSchemaStmt $ AltAggregate $3 $5 $9 }
        | ALTER DOMAIN any_name SET SCHEMA name { AlterObjectSchemaStmt $ AltDomain $3 $6 }
        | ALTER FUNCTION func_name func_args SET SCHEMA name { AlterObjectSchemaStmt $ AltFunction $3 $4 $7 }
        | ALTER SEQUENCE relation_expr SET SCHEMA name { AlterObjectSchemaStmt $  AltSequence $3 $6 }
        | ALTER TABLE relation_expr SET SCHEMA name { AlterObjectSchemaStmt $ AltTable $3 $6 }
        | ALTER TYPE any_name SET SCHEMA name { AlterObjectSchemaStmt $ AltType $3 $6 }

AlterOwnerStmt  :: { Statement }
AlterOwnerStmt
        : ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO RoleId { AlterOwnerStmt $ AltOwnerAggregate $3 $5 $9 }
        | ALTER CONVERSION any_name OWNER TO RoleId { AlterOwnerStmt $ AltOwnerConversion $3 $6 }
        | ALTER DATABASE database_name OWNER TO RoleId { AlterOwnerStmt $ AltOwnerDatabase $3 $6 }
        | ALTER DOMAIN any_name OWNER TO RoleId { AlterOwnerStmt $ AltOwnerDomain $3 $6 }
        | ALTER FUNCTION func_name func_args OWNER TO RoleId { AlterOwnerStmt $ AltOwnerFunction $3 $4 $7 }
        | ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO RoleId { AlterOwnerStmt $ AltOwnerOperator $3 $5 $9 }
        | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId { AlterOwnerStmt $ AltOwnerOperatorClass $4 $6 $9 }
        | ALTER SCHEMA name OWNER TO RoleId { AlterOwnerStmt $ AltOwnerSchema $3 $6 }
        | ALTER TYPE any_name OWNER TO RoleId { AlterOwnerStmt $ AltOwnerType $3 $6 }
        | ALTER TABLESPACE name OWNER TO RoleId { AlterOwnerStmt $ AltOwnerTablespace $3 $6 }

RuleStmt        :: { Statement }
RuleStmt
        : CREATE opt_or_replace RULE name AS ON event TO qualified_name where_clause DO opt_instead RuleActionList { RuleStmt $2 $4 $7 $9 $10 $12 $13 }

RuleActionList  :: { RuleActionList }
RuleActionList
        : NOTHING { RuleActNothing }
        | RuleActionStmt { RuleActStmt $1 }
        | '(' RuleActionMulti ')' { RuleActMulti $2 }

RuleActionMulti :: { RuleActionMulti }
RuleActionMulti
        : RuleActionMulti_aux { MyLst $1 }

RuleActionMulti_aux     :: { [RuleActionStmtOrEmpty] }
RuleActionMulti_aux
        : RuleActionMulti_aux ';' RuleActionStmtOrEmpty { $1 ++ [$3] }
        | RuleActionStmtOrEmpty { [$1] }
        
RuleActionStmt  :: { Statement }
RuleActionStmt
        : SelectStmt { $1 }
        | InsertStmt { $1 }
        | UpdateStmt { $1 }
        | DeleteStmt { $1 }
        | NotifyStmt { $1 }
        
RuleActionStmtOrEmpty   :: { RuleActionStmtOrEmpty }
RuleActionStmtOrEmpty
        : RuleActionStmt { Just $1 }
        | {- empty -} { Nothing }

event   :: { Event }
event   : SELECT { OneOf4 SELECT }
        | UPDATE { TwoOf4 UPDATE }
        | DELETE { ThreeOf4 DELETE }
        | INSERT { FourOf4 INSERT }

opt_instead     :: { OptInstead }       
opt_instead
        : INSTEAD { Just $ Left INSTEAD }
        | ALSO { Just $ Right ALSO }
        | { Nothing }
        

DropRuleStmt    :: { Statement }
DropRuleStmt
        : DROP RULE name ON qualified_name opt_drop_behavior { DropRuleStmt $3 $5 $6 }

NotifyStmt      :: { Statement }
NotifyStmt
        : NOTIFY qualified_name { NotifyStmt $2 }
        
ListenStmt      :: { Statement }
ListenStmt
        : LISTEN qualified_name { ListenStmt $2 }       

UnlistenStmt    :: { Statement }
UnlistenStmt
        : UNLISTEN qualified_name { UnlistenStmt $ Left $2 }
        | UNLISTEN '*' { UnlistenStmt $ Right STAR }

TransactionStmt :: { Statement }
TransactionStmt
        : ABORT opt_transaction { TransactionStmt $ TransAbort $2 }
        | BEGIN opt_transaction transaction_mode_list_or_empty { TransactionStmt $ TransBegin $2 $3 }
        | START TRANSACTION transaction_mode_list_or_empty { TransactionStmt $ TransStart $3 }
        | COMMIT opt_transaction { TransactionStmt $ TransCommit $2 }
        | END opt_transaction { TransactionStmt $ TransEnd $2 }
        | ROLLBACK opt_transaction { TransactionStmt $ TransRollback $2 }
        | SAVEPOINT ColId { TransactionStmt $ TransSavepoint $2 }
        | RELEASE SAVEPOINT ColId { TransactionStmt $ TransRelease (Just SAVEPOINT) $3 }
        | RELEASE ColId { TransactionStmt $ TransRelease Nothing $2 }
        | ROLLBACK opt_transaction TO SAVEPOINT ColId { TransactionStmt $ TransRollbackSave $2 (Just SAVEPOINT) $5 }
        | ROLLBACK opt_transaction TO ColId { TransactionStmt $ TransRollbackSave $2 Nothing $4 }
        | PREPARE TRANSACTION Sconst { TransactionStmt $ TransPrepare $3 }
        | COMMIT PREPARED Sconst { TransactionStmt $ TransCommitPreparred $3 }
        | ROLLBACK PREPARED Sconst { TransactionStmt $ TransRollbackPrepared $3 }

opt_transaction :: { OptTransaction }
opt_transaction
        : WORK { Just $ Left WORK }
        | TRANSACTION { Just $ Right TRANSACTION }
        | {- empty -} { Nothing }
        
transaction_mode_item   :: { TransactionModeItem }
transaction_mode_item
        : ISOLATION LEVEL iso_level { TransactionItemIsolationLevel $3 }
        | READ ONLY { TransactionItemReadOnly }
        | READ WRITE { TransactionItemReadWrite }

transaction_mode_list   :: { TransactionModeList }
transaction_mode_list
        : transaction_mode_item { [$1] }
        | transaction_mode_list ',' transaction_mode_item { $1 ++ [$3] }
        | transaction_mode_list transaction_mode_item { $1 ++ [$2] }

transaction_mode_list_or_empty  :: { TransactionModeListOrEmpty }
transaction_mode_list_or_empty
        : transaction_mode_list { Just $1 }
        | {- empty -} { Nothing }

ViewStmt        :: { Statement }
ViewStmt
        : CREATE OptTemp VIEW qualified_name opt_column_list AS SelectStmt { ViewStmt Nothing $2 $4 $5 $7 }
        | CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list AS SelectStmt { ViewStmt (Just REPLACE) $4 $6 $7 $9 }

LoadStmt        :: { Statement }
LoadStmt
        : LOAD file_name { LoadStmt $2 }

CreatedbStmt    :: { Statement }
CreatedbStmt
        : CREATE DATABASE database_name opt_with createdb_opt_list { CreatedbStmt $3 $4 $5 }    

createdb_opt_list       :: { CreatedbOptList }
createdb_opt_list
        : createdb_opt_list createdb_opt_item { $1 ++ [$2] }
        | {- empty -} { [] }
        
createdb_opt_item       :: { CreatedbOptItem }
createdb_opt_item
        : TABLESPACE opt_equal name { DBItemTablespace $2 (Left $3) }
        | TABLESPACE opt_equal DEFAULT { DBItemTablespace $2 (Right DEFAULT) }
        | LOCATION opt_equal Sconst { DBItemLocation $2 (Left $3) }
        | LOCATION opt_equal DEFAULT { DBItemLocation $2 (Right DEFAULT) }
        | TEMPLATE opt_equal name { DBItemTemplate $2 (Left $3) }
        | TEMPLATE opt_equal DEFAULT { DBItemTemplate $2 (Right DEFAULT) }
        | ENCODING opt_equal Sconst { DBItemEncoding $2 (OneOf3 $3) }
        | ENCODING opt_equal Iconst { DBItemEncoding $2 (TwoOf3 $3) }
        | ENCODING opt_equal DEFAULT { DBItemEncoding $2 (ThreeOf3 DEFAULT) }
        | CONNECTION LIMIT opt_equal SignedIconst { DBItemConnection $3 $4 }
        | OWNER opt_equal name { DbItemOwner $2 (Left $3) }
        | OWNER opt_equal DEFAULT { DbItemOwner $2 (Right DEFAULT) }

opt_equal       :: { OptEqual }
opt_equal
        : '=' { Just EQUAL }
        | {- empty -} { Nothing }

AlterDatabaseStmt       :: { Statement }
AlterDatabaseStmt
        : ALTER DATABASE database_name opt_with alterdb_opt_list { AlterDatabaseStmt $3 $4 $5 }
        
AlterDatabaseSetStmt    :: { Statement }
AlterDatabaseSetStmt
        : ALTER DATABASE database_name SET set_rest { AlterDatabaseSetStmt $3 (Left $5) }
        | ALTER DATABASE database_name VariableResetStmt { AlterDatabaseSetStmt $3 (Right $4) }

alterdb_opt_list        :: { AlterdbOptList }
alterdb_opt_list
        : alterdb_opt_list alterdb_opt_item { $1 ++ [$2] }
        | {- empty -} { [] }

alterdb_opt_item        :: { AlterdbOptItem }
alterdb_opt_item
        : CONNECTION LIMIT opt_equal SignedIconst { AlterdbItemConst $3 $4 }

DropdbStmt      :: { Statement }
DropdbStmt
        : DROP DATABASE database_name { DropdbStmt $3 }

CreateDomainStmt        :: { Statement }
CreateDomainStmt
        : CREATE DOMAIN any_name opt_as Typename ColQualList { CreateDomainStmt $3 $4 $5 $6 }

AlterDomainStmt :: { Statement }
AlterDomainStmt
        : ALTER DOMAIN any_name alter_column_default { AlterDomainStmt $3 (OneOf5 $4) }
        | ALTER DOMAIN any_name DROP NOT NULL { AlterDomainStmt $3 (TwoOf5 ()) }
        | ALTER DOMAIN any_name SET NOT NULL { AlterDomainStmt $3 (ThreeOf5 ()) }
        | ALTER DOMAIN any_name ADD TableConstraint { AlterDomainStmt $3 (FourOf5 $5) }
        | ALTER DOMAIN any_name DROP CONSTRAINT name opt_drop_behavior { AlterDomainStmt $3 (FiveOf5 ($6,$7)) }

opt_as  :: { OptAs }
opt_as  : AS { Just AS }
        | {- empty -} { Nothing }

CreateConversionStmt    :: { Statement }
CreateConversionStmt
        : CREATE opt_default CONVERSION any_name FOR Sconst TO Sconst FROM any_name { CreateConversionStmt $2 $4 $6 $8 $10 }

ClusterStmt     :: { Statement }
ClusterStmt
        : CLUSTER index_name ON qualified_name { ClusterStmt $ Just (Just $2,$4) }
        | CLUSTER qualified_name { ClusterStmt $ Just (Nothing,$2) }
        | CLUSTER { ClusterStmt Nothing }

VacuumStmt      :: { Statement }
VacuumStmt
        : VACUUM opt_full opt_freeze opt_verbose { VacuumStmt $2 $3 $4 Nothing }
        | VACUUM opt_full opt_freeze opt_verbose qualified_name { VacuumStmt $2 $3 $4 (Just (Left $5)) }
        | VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt { VacuumStmt $2 $3 $4 (Just (Right $5)) }

AnalyzeStmt     :: { Statement }        
AnalyzeStmt
        : analyze_keyword opt_verbose { AnalyzeStmt $1 $2 Nothing }
        | analyze_keyword opt_verbose qualified_name opt_name_list { AnalyzeStmt $1 $2 (Just ($3,$4)) }

analyze_keyword :: { AnalyzeKeyword }
analyze_keyword
        : ANALYZE { Right ANALYZE }
        | ANALYSE { Left ANALYSE }

opt_verbose     :: { OptVerbose }
opt_verbose
        : VERBOSE { Just VERBOSE }
        | {- empty -} { Nothing }       

opt_full        :: { OptFull }
opt_full
        : FULL { Just FULL }
        | {- empty -} { Nothing }       

opt_freeze      :: { OptFreeze }
opt_freeze
        : FREEZE { Just FREEZE }
        | {- empty -} { Nothing }
        
opt_name_list   :: { OptNameList }
opt_name_list   
        : '(' name_list ')' { OptNameLst $ Just $2 }
        | {- empty -} { OptNameLst Nothing }

ExplainStmt     :: { Statement }
ExplainStmt
        : EXPLAIN opt_analyze opt_verbose ExplainableStmt { ExplainStmt $2 $3 $4 }

ExplainableStmt :: { ExplainableStmt }
ExplainableStmt
        : SelectStmt { $1 }
        | InsertStmt { $1 }
        | UpdateStmt { $1 }
        | DeleteStmt { $1 }
        | DeclareCursorStmt { $1 }
        | ExecuteStmt { $1 }
        
opt_analyze     :: { OptAnalyze }
opt_analyze
        : analyze_keyword { Just $1 }
        | {- empty -} { Nothing }

PrepareStmt     :: { Statement }
PrepareStmt
        : PREPARE name prep_type_clause AS PreparableStmt { PrepareStmt $2 $3 $5 }

prep_type_clause        :: { PrepTypeClause }
prep_type_clause
        : '(' prep_type_list ')' { PrepTypeClauseConst (Just $2) }
        | {- empty -} { PrepTypeClauseConst Nothing }
        
prep_type_list  :: { PrepTypeList }
prep_type_list
        : prep_type_list_aux { MyLst $1 }

prep_type_list_aux      :: { [Typename] }
prep_type_list_aux
        : Typename { [$1] }
        | prep_type_list_aux ',' Typename { $1 ++ [$3] }

PreparableStmt  :: { PreparableStmt }
PreparableStmt
        : SelectStmt { $1 }
        | InsertStmt { $1 }
        | UpdateStmt { $1 }
        | DeleteStmt { $1 }

ExecuteStmt     :: { Statement }
ExecuteStmt
        : EXECUTE name execute_param_clause { ExecuteStmt $ ExecStmtExecute $2 $3 }
        | CREATE OptTemp TABLE qualified_name OptCreateAs AS EXECUTE name execute_param_clause { ExecuteStmt $ ExecStmtCreate $2 $4 $5 $8 $9 }
        

execute_param_clause    :: { ExecuteParamClause }
execute_param_clause
        : '(' expr_list ')' { ExecClause $ Just $2 }
        | {- empty -} { ExecClause Nothing }

DeallocateStmt  :: { Statement }
DeallocateStmt
        : DEALLOCATE name { DeallocateStmt $ Left $2 }
        | DEALLOCATE PREPARE name { DeallocateStmt $ Right $3 }

InsertStmt      :: { Statement }
InsertStmt
        : INSERT INTO qualified_name insert_rest { InsertStmt $3 $4 }   

insert_rest     :: { InsertRest }
insert_rest
        : VALUES '(' insert_target_list ')' { InsValues $3 }
        | DEFAULT VALUES { InsDefaultValues }
        | SelectStmt { InsSelect $1 }
        | '(' insert_column_list ')' VALUES '(' insert_target_list ')' { InsColValues $2 $6 }
        | '(' insert_column_list ')' SelectStmt { InsCol $2 $4 }        

insert_column_list      :: { InsertColumnList } 
insert_column_list
        : insert_column_list_aux { MyLst $1 }   

insert_column_list_aux  :: { [InsertColumnItem] }
insert_column_list_aux
        : insert_column_item { [$1] }
        | insert_column_list_aux ',' insert_column_item { $1 ++ [$3] }
        
insert_column_item      :: { InsertColumnItem }
insert_column_item
        : ColId opt_indirection { InsColItem $1 $2 }

DeleteStmt      :: { Statement }
DeleteStmt
        : DELETE FROM relation_expr using_clause where_clause { DeleteStmt $3 $4 $5 }

using_clause    :: { UsingClause }
using_clause
        : USING from_list { UseClause $ Just $2 }
        | {- empty -} { UseClause Nothing }

LockStmt        :: { Statement }
LockStmt
        : LOCK opt_table qualified_name_list opt_lock opt_nowait { LockStmt $2 $3 $4 $5 }

opt_lock        :: { OptLock }
opt_lock
        : IN lock_type MODE { OptLck $ Just $2 }
        | {- empty -} { OptLck Nothing }
        
lock_type       :: { LockType }
lock_type
        : ACCESS SHARE { LckAccessShare }
        | ROW SHARE { LckRowShare }
        | ROW EXCLUSIVE { LckRowExclusive }
        | SHARE UPDATE EXCLUSIVE { LckShareUptateExclusive }
        | SHARE { LckShare }
        | SHARE ROW EXCLUSIVE { LckShareRowExclusive }
        | EXCLUSIVE { LckExclusive }
        | ACCESS EXCLUSIVE { LckAccessExclusive }
        

opt_nowait      :: { OptNowait }
opt_nowait
        : NOWAIT { Just NOWAIT }
        | {- empty -} { Nothing }

UpdateStmt      :: { Statement }
UpdateStmt
        : UPDATE relation_expr SET update_target_list from_clause where_clause {  UpdateStmt $2 $4 $5 $6}

DeclareCursorStmt       :: { Statement }
DeclareCursorStmt
        : DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt { DeclareCursorStmt $2 $3 $5 $7 }

cursor_options  :: { CursorOptions }
cursor_options
        : {- empty -} { CursorOpt Nothing }
        | cursor_options NO SCROLL { CursorOpt $ Just $ ($1,OneOf4 (NO,SCROLL)) }
        | cursor_options SCROLL { CursorOpt $ Just $ ($1,TwoOf4 SCROLL) }
        | cursor_options BINARY { CursorOpt $ Just $ ($1,ThreeOf4 BINARY) }
        | cursor_options INSENSITIVE { CursorOpt $ Just $ ($1,FourOf4 INSENSITIVE) }

opt_hold        :: { OptHold }  
opt_hold
        : {- empty -} { NoHold }
        | WITH HOLD { WithHold }
        | WITHOUT HOLD { WithoutHold }

SelectStmt      :: { Statement }
SelectStmt
        : select_no_parens %prec UMINUS { SelectStmt $ Left $1 }
        | select_with_parens %prec UMINUS { SelectStmt $ Right $1 }

select_with_parens      :: { SelectWithParens }
select_with_parens
        : '(' select_no_parens ')' { SlctNo $2 }
        | '(' select_with_parens ')' { SlctWith $2 }

select_no_parens        :: { SelectNoParens }
select_no_parens
        : simple_select { SlctSimple $1 }
        | select_clause sort_clause { SlctBin $1 $2 }
        | select_clause opt_sort_clause for_locking_clause opt_select_limit { SlctMulti1 $1 $2 $3 $4 }
        | select_clause opt_sort_clause select_limit opt_for_locking_clause { SlctMulti2 $1 $2 $3 $4 }

select_clause   :: { SelectClause }
select_clause
        : simple_select { Left $1 }
        | select_with_parens { Right $1 }

simple_select   :: { SimpleSelect }
simple_select
        : SELECT opt_distinct target_list into_clause from_clause where_clause group_clause having_clause { SimpSlct $2 $3 $4 $5 $6 $7 $8 }
        | select_clause UNION opt_all select_clause { UnionSlct $1 $3 $4 }
        | select_clause INTERSECT opt_all select_clause { IntersectSlct $1 $3 $4 }
        | select_clause EXCEPT opt_all select_clause { ExceptSlct $1 $3 $4 }

into_clause     :: { IntoClause }
into_clause
        : INTO OptTempTableName { Just (INTO,$2) }
        | {- empty -} { Nothing }

OptTempTableName        :: { OptTempTableName }
OptTempTableName
        : TEMPORARY opt_table qualified_name { TNTemporary $2 $3 }
        | TEMP opt_table qualified_name { TNTemp $2 $3 }
        | LOCAL TEMPORARY opt_table qualified_name { TNLocalTemporary $3 $4 }
        | LOCAL TEMP opt_table qualified_name { TNLocalTemp $3 $4 }
        | GLOBAL TEMPORARY opt_table qualified_name { TNGlobalTemporary $3 $4 }
        | GLOBAL TEMP opt_table qualified_name { TNGlobalTemp $3 $4 }
        | TABLE qualified_name { TNTable $2 }
        | qualified_name { TN $1 }
        
opt_table       :: { OptTable }
opt_table
        : TABLE { Just TABLE }
        | {- empty -} { Nothing }       

opt_all :: { OptAll }
opt_all : ALL { Just $ Left ALL }
        | DISTINCT { Just $ Right DISTINCT }
        | {- empty -} { Nothing }

opt_distinct    :: { OptDistinct }
opt_distinct
        : DISTINCT { DisctDistinct }
        | DISTINCT ON '(' expr_list ')' { DisctDistinctOn $4 }
        | ALL { DisctAll }
        | {- empty -} { NoDisct }

opt_sort_clause :: { OptSortClause }
opt_sort_clause
        : sort_clause { Just $1 }
        | {- empty -} { Nothing }

sort_clause     :: { SortClause }
sort_clause
        : ORDER BY sortby_list { SortCl $3 }

sortby_list     :: { SortByList }       
sortby_list
        : sortby_list_aux { MyLst $1 }  

sortby_list_aux :: { [SortBy] }
sortby_list_aux
        : sortby { [$1] }
        | sortby_list_aux ',' sortby { $1 ++ [$3] }
        

sortby  :: { SortBy }
sortby  : a_expr USING qual_all_Op { SortByUsing $1 $3 }
        | a_expr ASC { SortByAsc $1 }
        | a_expr DESC { SortByDesc $1 }
        | a_expr { SortByExp $1 }
        
select_limit    :: { SelectLimit }
select_limit
        : LIMIT select_limit_value OFFSET select_offset_value { SlctLimitOffset $2 $4 }
        | OFFSET select_offset_value LIMIT select_limit_value { SlctLimitOffset $4 $2 }
        | LIMIT select_limit_value { SlctLimit $2 }
        | OFFSET select_offset_value { SlctOffset $2 }
        | LIMIT select_limit_value ',' select_offset_value { SlctLimitOffset $2 $4 }

opt_select_limit        :: { OptSelectLimit }
opt_select_limit
        : select_limit { Just $1 }
        | {- empty -} { Nothing }
        
select_limit_value      :: { SelectLimitValue }
select_limit_value
        : a_expr { Left $1 }
        | ALL { Right ALL }     

select_offset_value     :: { SelectOffsetValue }
select_offset_value
        : a_expr { $1 }

group_clause    :: { GroupClause }
group_clause
        : GROUP BY expr_list { GrpClause $ Just $3 }
        | {- empty -} { GrpClause Nothing }
        
having_clause   :: { HavingClause }
having_clause
        : HAVING a_expr { HavClause $ Just $2 }
        | {- empty -} { HavClause Nothing }

for_locking_clause      :: { ForLockingClause }
for_locking_clause
        : FOR UPDATE locked_rels_list opt_nowait { ForLckUpdate $3 $4 }
        | FOR SHARE locked_rels_list opt_nowait { ForLckShare $3 $4 }
        | FOR READ ONLY { ForLckReadOnly }
        
opt_for_locking_clause  :: { OptForLockingClause }
opt_for_locking_clause
        : for_locking_clause { Just $1 }
        | {- empty -} { Nothing }
        

locked_rels_list        :: { LockedRelsList }
locked_rels_list
        : OF name_list { LockedRelsLst $ Just $2 }
        | {- empty -} { LockedRelsLst Nothing }

from_clause     :: { FromClause }
from_clause
        : FROM from_list { FromClauseConst $ Just $2 }
        | {- empty -} { FromClauseConst Nothing }       

from_list       :: { FromList }
from_list
        : from_list_aux { MyLst $1 }

from_list_aux   :: { [TableRef] }
from_list_aux
        : table_ref { [$1] }
        | from_list_aux ',' table_ref { $1 ++ [$3] }

table_ref       :: { TableRef }
table_ref
        : relation_expr { TableRefExpr $1 Nothing }
        | relation_expr alias_clause { TableRefExpr $1 (Just $2) }
        | func_table { TableRefFunc $1 Nothing }
        | func_table alias_clause { TableRefFunc $1 (Just $2) }
        | func_table AS '(' TableFuncElementList ')' { TableRefFunc2 $1 (OneOf3 AS) $4 }
        | func_table AS ColId '(' TableFuncElementList ')' { TableRefFunc2 $1(ThreeOf3 (AS,$3)) $5 }
        | func_table ColId '(' TableFuncElementList ')' { TableRefFunc2 $1 (TwoOf3 $2) $4 }
        | select_with_parens { TableRefSelect $1 Nothing }
        | select_with_parens alias_clause { TableRefSelect $1 (Just $2) }
        | joined_table { TableRefJoin $1 Nothing }
        | '(' joined_table ')' alias_clause { TableRefJoin $2 (Just $4) }

joined_table    :: { JoinedTable }
joined_table
        : '(' joined_table ')' { JoinedTableJoined $2 }
        | table_ref CROSS JOIN table_ref { JoinedTableCrossJoin $1 $4 }
        | table_ref UNIONJOIN table_ref { JoinedTableUnionjoin $1 $3 }
        | table_ref join_type JOIN table_ref join_qual { JoinedTableJoin $1 (Just $2) $4 $5 }
        | table_ref JOIN table_ref join_qual { JoinedTableJoin $1 Nothing $3 $4 }
        | table_ref NATURAL join_type JOIN table_ref { JoinedTableNatural $1 (Just $3) $5 }
        | table_ref NATURAL JOIN table_ref { JoinedTableNatural $1 Nothing $4 }

alias_clause    :: { AliasClause }      
alias_clause
        : AS ColId '(' name_list ')' { AliasClauseConst (Just AS) $2 (Just $4) }
        | AS ColId { AliasClauseConst (Just AS) $2 Nothing }
        | ColId '(' name_list ')' { AliasClauseConst Nothing $1 (Just $3) }
        | ColId { AliasClauseConst Nothing $1 Nothing }


join_type       :: { JoinType } 
join_type
        : FULL join_outer { Left $ (OneOf3 FULL,$2) }
        | LEFT join_outer { Left $ (TwoOf3 LEFT,$2) }
        | RIGHT join_outer { Left $ (ThreeOf3 RIGHT,$2) }
        | INNER { Right INNER }

join_outer      :: { JoinOuter }
join_outer
        : OUTER { Just OUTER }
        | {- empty -} { Nothing }

join_qual       :: { JoinQual }
join_qual
        : USING '(' name_list ')' { JoinQualConst $ Left $3 }
        | ON a_expr { JoinQualConst $ Right $2 }

relation_expr   :: { RelationExpr }
relation_expr
        : qualified_name { RelationExprConst Nothing $1 Nothing }
        | qualified_name '*' { RelationExprConst Nothing $1 (Just STAR) }
        | ONLY qualified_name { RelationExprConst (Just ONLY) $2 Nothing }
        | ONLY '(' qualified_name ')' { RelationExprConst (Just ONLY) $3 Nothing }

func_table      :: { FuncTable }
func_table
        : func_expr { $1 }

where_clause    :: { WhereClause }
where_clause
        : WHERE a_expr { WhereClauseConst $ Just $2 }
        | {- empty -} { WhereClauseConst Nothing }

TableFuncElementList    :: { TableFuncElementList }
TableFuncElementList
        : TableFuncElementList_aux { MyLst $1 }

TableFuncElementList_aux        :: { [TableFuncElement] }
TableFuncElementList_aux
        : TableFuncElement { [$1] }
        | TableFuncElementList_aux ',' TableFuncElement { $1 ++ [$3] }

TableFuncElement        :: { TableFuncElement }
TableFuncElement
        : ColId Typename { ($1,$2) }

Typename        :: { Typename }
Typename
        : SimpleTypename opt_array_bounds { TypenameConst Nothing $1 (Left $2) }
        | SETOF SimpleTypename opt_array_bounds { TypenameConst (Just SETOF) $2 (Left $3) }
        | SimpleTypename ARRAY '[' Iconst ']' { TypenameConst Nothing $1 (Right $4)  }
        | SETOF SimpleTypename ARRAY '[' Iconst ']' { TypenameConst (Just SETOF) $2 (Right $5) }

opt_array_bounds        :: { OptArrayBounds }   
opt_array_bounds
        : opt_array_bounds '[' ']' { SingleArray $1 }
        | opt_array_bounds '[' Iconst ']' { IconstArray $1 $3 }
        | {- empty -} { EmptyArray }
        
SimpleTypename  :: { SimpleTypename }
SimpleTypename
        : GenericType { SimpTypeGeneric $1 }
        | Numeric { SimpTypeNum $1 }
        | Bit { SimpTypeBit $1 }
        | Character { SimpTypeChar $1 }
        | ConstDatetime { SimpTypeDate $1 }
        | ConstInterval opt_interval { SimpTypeInterval $1 Nothing $2 }
        | ConstInterval '(' Iconst ')' opt_interval { SimpTypeInterval $1 (Just $3) $5 }
        | type_name attrs { SimpType $1 $2 }

ConstTypename   :: { ConstTypename }
ConstTypename
        : GenericType { ConstTypeGeneric $1 }
        | Numeric { ConstTypeNum $1 }
        | ConstBit { ConstTypeBit $1 }
        | ConstCharacter { ConstTypeChar $1 }
        | ConstDatetime { ConstTypeDate $1 }

GenericType     :: { GenericType }
GenericType
        : type_name { $1 }

Numeric :: { Numeric }
Numeric
        : INT { NumInt }
        | INTEGER { NumInteger }
        | SMALLINT { NumSmallInt }
        | BIGINT { NumBigInt }
        | REAL { NumReal }
        | FLOAT opt_float { NumFloat $2 }
        | DOUBLE PRECISION { NumDouble }
        | DECIMAL opt_decimal { NumDecimal $2 }
        | DEC opt_decimal { NumDecimal $2 }
        | NUMERIC opt_numeric { NumNumeric $2 }
        | BOOLEAN { NumBool }
        
opt_float       :: { OptFloat }
opt_float
        : '(' Iconst ')' { OptFloatConst $ Just $2 }
        | {- empty -} { OptFloatConst Nothing }
        
opt_numeric     :: { OptNumeric }
opt_numeric
        : '(' Iconst ',' Iconst ')' { OptNumericConst $ Just ($2,Just $4) }
        | '(' Iconst ')' { OptNumericConst $ Just ($2,Nothing) }
        | {- empty -} { OptNumericConst Nothing }

        
opt_decimal     :: { OptDecimal }
opt_decimal
        : '(' Iconst ',' Iconst ')' { OptNumericConst $ Just ($2,Just $4) }
        | '(' Iconst ')' { OptNumericConst $ Just ($2,Nothing) }
        | {- empty -} { OptNumericConst Nothing }

Bit     :: { Bit }
Bit     : BitWithLength { Left $1 }
        | BitWithoutLength { Right $1 }

ConstBit        :: { ConstBit }
ConstBit
        : BitWithLength { Left $1 }
        | BitWithoutLength { Right $1 } 

BitWithLength   :: { BitWithLength }
BitWithLength
        : BIT opt_varying '(' Iconst ')' { BitDef $2 (Just $4) }

BitWithoutLength        :: { BitWithoutLength }
BitWithoutLength
        : BIT opt_varying { BitDef $2 Nothing }

Character       :: { Character }
Character
        : CharacterWithLength { $1 }
        | CharacterWithoutLength { $1 }

ConstCharacter  :: { ConstCharacter }
ConstCharacter
        : CharacterWithLength { $1 }
        | CharacterWithoutLength { $1 }
        
CharacterWithLength     :: { CharacterWithLength }
CharacterWithLength
        : character '(' Iconst ')' opt_charset { CharDef $1 (Just $3) $5 }
        
CharacterWithoutLength  :: { CharacterWithoutLength }
CharacterWithoutLength
        : character opt_charset { CharDef $1 Nothing $2 }

character       :: { Character2 }       
character
        : CHARACTER opt_varying { Char2Character $2 }
        | CHAR opt_varying { Char2Character $2 }
        | VARCHAR { Char2VarChar }
        | NATIONAL CHARACTER opt_varying { Char2National $3 }
        | NATIONAL CHAR opt_varying { Char2National $3 }
        | NCHAR opt_varying { Char2National $2 }

opt_varying     :: { OptVarying }
opt_varying
        : VARYING { Just VARYING }
        | {- empty -} { Nothing }

opt_charset     :: { OptCharset }
opt_charset
        : CHARACTER SET ColId { OptCharConst $ Just $3 }
        | {- empty -} { OptCharConst Nothing }
        
ConstDatetime   :: { ConstDatetime }
ConstDatetime
        : TIMESTAMP '(' Iconst ')' opt_timezone { ConstTimestamp (Just $3) $5 }
        | TIMESTAMP opt_timezone { ConstTimestamp Nothing $2 }
        | TIME '(' Iconst ')' opt_timezone { ConstTimestamp (Just $3) $5 }
        | TIME opt_timezone { ConstTimestamp Nothing $2 }       

ConstInterval   :: { ConstInterval }
ConstInterval
        : INTERVAL { INTERVAL }
        
opt_timezone    :: { OptTimezone }
opt_timezone
        : WITH TIME ZONE { WithTimeZone }
        | WITHOUT TIME ZONE { WithoutTimeZone }
        | {- empty -} { NoTimeZoneDecl }

opt_interval    :: { OptInterval }
opt_interval
        : YEAR { IntervalYear }
        | MONTH { IntervalMonth }
        | DAY   { IntervalDay }
        | HOUR { IntervalHour }
        | MINUTE { IntervalMinute }
        | SECOND { IntervalSecond }
        | YEAR TO MONTH { IntervalYearToMonth }
        | DAY TO HOUR { IntervalDayToHour }
        | DAY TO MINUTE { IntervalDayToMinute }
        | DAY TO SECOND { IntervalDayToSecond }
        | HOUR TO MINUTE { IntervalHourToMinute }
        | HOUR TO SECOND { IntrevalHourToSecond }
        | MINUTE TO SECOND { IntervalMinuteToSecond }
        | {- empty -} { NoInterval }

a_expr  :: { AExpr }
a_expr
        : c_expr {  AExpCExp $1 }
        | a_expr TYPECAST Typename { AExpTypecast $1 $3 }
        | a_expr AT TIME ZONE a_expr { AExpTZ $1 $5 }
        | '+' a_expr %prec UMINUS { AExpPositive $2 }
        | '-' a_expr %prec UMINUS { AExpNegative $2 }
        | a_expr '+' a_expr { AExpMath $1 (OneOf9 PLUS) $3 }
        | a_expr '-' a_expr { AExpMath $1 (TwoOf9 MINUS) $3 }
        | a_expr '*' a_expr { AExpMath $1 (ThreeOf9 STAR) $3 }
        | a_expr '/' a_expr { AExpMath $1 (FourOf9 SLASH) $3 }
        | a_expr '%' a_expr { AExpMath $1 (FiveOf9 PERCENTAGE) $3 }
        | a_expr '^' a_expr { AExpMath $1 (SixOf9 HAT) $3 }
        | a_expr '<' a_expr { AExpMath $1 (SevenOf9 SMALLER) $3 }
        | a_expr '>' a_expr { AExpMath $1 (EightOf9 GREATER) $3 }
        | a_expr '=' a_expr { AExpMath $1 (NineOf9 EQUAL) $3 }
        | a_expr qual_Op a_expr %prec Op { AExpQual (Just $1) $2 $3 }
        | qual_Op a_expr %prec Op { AExpQual Nothing $1 $2 }
        | a_expr qual_Op %prec POSTFIXOP { AExpQual Nothing $2 $1 }
        | a_expr AND a_expr { AExpAnd $1 $3 }
        | a_expr OR a_expr { AExpOr $1 $3 }
        | NOT a_expr { AExpNot $2 }
        | a_expr LIKE a_expr { AExpLike $1 $3 Nothing }
        | a_expr LIKE a_expr ESCAPE a_expr { AExpLike $1 $3 (Just $5) }
        | a_expr NOT LIKE a_expr { AExpNotLike $1 $4 Nothing }
        | a_expr NOT LIKE a_expr ESCAPE a_expr { AExpNotLike $1 $4 (Just $6) }
        | a_expr ILIKE a_expr { AExpILike $1 $3 Nothing }
        | a_expr ILIKE a_expr ESCAPE a_expr { AExpILike $1 $3 (Just $5) }
        | a_expr NOT ILIKE a_expr { AExpNotILike $1 $4 Nothing }
        | a_expr NOT ILIKE a_expr ESCAPE a_expr { AExpNotILike $1 $4 (Just $6) }
        | a_expr SIMILAR TO a_expr %prec SIMILAR { AExpSimilar $1 $4 Nothing }
        | a_expr SIMILAR TO a_expr ESCAPE a_expr { AExpSimilar $1 $4 (Just $6) }
        | a_expr NOT SIMILAR TO a_expr %prec SIMILAR { AExpNotSimilar $1 $5 Nothing }
        | a_expr NOT SIMILAR TO a_expr ESCAPE a_expr { AExpNotSimilar $1 $5 (Just $7) }
        | a_expr ISNULL { AExpIsNull $1 }
        | a_expr IS NULL { AExpIsNull $1 }
        | a_expr NOTNULL { AExpNotNull $1 }
        | a_expr IS NOT NULL { AExpIsNotNull $1 }
        | row OVERLAPS row { AExpOverlaps $1 $3 }
        | a_expr IS TRUE { AExpIsTrue $1 }
        | a_expr IS NOT TRUE { AExpIsNotTrue $1 }
        | a_expr IS FALSE { AExpIsFalse $1 }
        | a_expr IS NOT FALSE { AExpIsNotFalse $1 }
        | a_expr IS UNKNOWN { AExpIsUnknown $1 }
        | a_expr IS NOT UNKNOWN { AExpIsNotUnknown $1 }
        | a_expr IS DISTINCT FROM a_expr %prec IS { AExpIsDistinct $1 $5 }
        | a_expr IS OF '(' type_list ')' %prec IS { AExpIsOf $1 $5 }
        | a_expr IS NOT OF '(' type_list ')' %prec IS { AExpIsNotOf $1 $6 }
        | a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN { AExpBetween $1 $3 $4 $6 }
        | a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN { AExpNotBetween $1 $4 $5 $7 }
        | a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN { AExpBetweenSymmetric $1 $4 $6 }
        | a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN { AExpNotBetweenSymmetric $1 $5 $7 }
        | a_expr IN in_expr { AExpIn $1 $3 }
        | a_expr NOT IN in_expr { AExprNotIn $1 $4 }
        | a_expr subquery_Op sub_type select_with_parens %prec Op { AExpSub $1 $2 $3 (Left $4) }
        | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op { AExpSub $1 $2 $3 (Right $5) }
        | UNIQUE select_with_parens %prec Op { AExpUnique $2 }

b_expr  :: { BExpr }
b_expr  : c_expr { BExpCExp $1 }
        | b_expr TYPECAST Typename { BExpTypecast $1 $3 }
        | '+' b_expr %prec UMINUS { BExpPositive $2 }
        | '-' b_expr %prec UMINUS { BExpNegative $2 }
        | b_expr '+' b_expr { BExpMath $1 (OneOf9 PLUS) $3 }
        | b_expr '-' b_expr { BExpMath $1 (TwoOf9 MINUS) $3 }
        | b_expr '*' b_expr { BExpMath $1 (ThreeOf9 STAR) $3 }
        | b_expr '/' b_expr { BExpMath $1 (FourOf9 SLASH) $3 }
        | b_expr '%' b_expr { BExpMath $1 (FiveOf9 PERCENTAGE) $3 }
        | b_expr '^' b_expr { BExpMath $1 (SixOf9 HAT) $3 }
        | b_expr '<' b_expr { BExpMath $1 (SevenOf9 SMALLER) $3 }
        | b_expr '>' b_expr { BExpMath $1 (EightOf9 GREATER) $3 }
        | b_expr '=' b_expr { BExpMath $1 (NineOf9 EQUAL) $3 }
        | b_expr qual_Op b_expr %prec Op { BExpQual (Just $1) $2 $3 }
        | qual_Op b_expr %prec Op { BExpQual Nothing $1 $2 }
        | b_expr qual_Op %prec POSTFIXOP { BExpQual Nothing $2 $1 }
        | b_expr IS DISTINCT FROM b_expr %prec IS { BExpIsDistinct $1 $5 }
        | b_expr IS OF '(' type_list ')' %prec IS { BExpIsOf $1 $5 }
        | b_expr IS NOT OF '(' type_list ')' %prec IS { BExpIsNotOf $1 $6 }

c_expr  :: { CExpr }
c_expr  : columnref { CExpCol $1 }
        | AexprConst { CExpAExpC $1 }
        | PARAM opt_indirection { CExpParam $2 }
        | '(' a_expr ')' opt_indirection { CExpAExp $2 $4 }
        | case_expr { CExpCase $1 }
        | func_expr { CExpFunc $1 }
        | select_with_parens %prec UMINUS { CExpSelect $1 }
        | EXISTS select_with_parens { CExpExists $2 }
        | ARRAY select_with_parens { CExpArray $ Left $2 }
        | ARRAY array_expr { CExpArray $ Right $2 }
        | row { CExpRow $1 }

func_expr       :: { FuncExpr }
func_expr
        : func_name '(' ')' { FuncExpFunc $1 Nothing }
        | func_name '(' expr_list ')' { FuncExpFunc $1 $ Just $ OneOf4 $3 }
        | func_name '(' ALL expr_list ')' { FuncExpFunc $1 $ Just $ TwoOf4 $4 }
        | func_name '(' DISTINCT expr_list ')' { FuncExpFunc $1 $ Just $ ThreeOf4 $4 }
        | func_name '(' '*' ')' { FuncExpFunc $1 $ Just $ FourOf4 STAR }
        | CURRENT_DATE { FuncExpCurrentDate }
        | CURRENT_TIME { FuncExpCurrentTime Nothing }
        | CURRENT_TIME '(' Iconst ')' { FuncExpCurrentTime $ Just $3 }
        | CURRENT_TIMESTAMP { FuncExpCurrentTimestamp Nothing }
        | CURRENT_TIMESTAMP '(' Iconst ')' { FuncExpCurrentTimestamp $ Just $3 }
        | LOCALTIME { FuncExpLocalTime Nothing }
        | LOCALTIME '(' Iconst ')' { FuncExpLocalTime $ Just $3 }
        | LOCALTIMESTAMP { FuncExpLocalTimestamp Nothing }
        | LOCALTIMESTAMP '(' Iconst ')' { FuncExpLocalTimestamp $ Just $3 }
        | CURRENT_ROLE { FuncExpCurrentRole }
        | CURRENT_USER { FuncExpCurrentUser }
        | SESSION_USER { FuncExpSessionUser }
        | USER { FuncExpUser }
        | CAST '(' a_expr AS Typename ')' { FuncExpCast $3 $5 }
        | EXTRACT '(' extract_list ')' { FuncExpExtract $3 }
        | OVERLAY '(' overlay_list ')' { FuncExpOverlay $3 }
        | POSITION '(' position_list ')' { FuncExpPosition $3 }
        | SUBSTRING '(' substr_list ')' { FuncExpSubstring $3 }
        | TREAT '(' a_expr AS Typename ')' { FuncExpTreat $3 $5 }
        | TRIM '(' BOTH trim_list ')' { FuncExpTrim $ OneOf4 $4 }
        | TRIM '(' LEADING trim_list ')' { FuncExpTrim $ TwoOf4 $4 }
        | TRIM '(' TRAILING trim_list ')' { FuncExpTrim $ ThreeOf4 $4 }
        | TRIM '(' trim_list ')' { FuncExpTrim $ FourOf4 $3 }
        | CONVERT '(' a_expr USING any_name ')' { FuncExpConvert $ Left ($3,$5) }
        | CONVERT '(' expr_list ')' { FuncExpConvert $ Right $3 }
        | NULLIF '(' a_expr ',' a_expr ')' { FuncExpNullif $3 $5 }
        | COALESCE '(' expr_list ')' { FuncExpCoalesce $3 }
        | GREATEST '(' expr_list ')' { FuncExpGreatest $3 }
        | LEAST '(' expr_list ')' { FuncExpLeast $3 }

row     :: { Row }
row     : ROW '(' expr_list ')' { RowExpr $3 }
        | ROW '(' ')' { RowSingle }
        | '(' expr_list ',' a_expr ')' { RowExprs $2 $4 }

sub_type        :: { SubType }
sub_type
        : ANY { OneOf3 ANY }
        | SOME { TwoOf3 SOME }
        | ALL { ThreeOf3 ALL }

all_Op  :: { AllOp }
all_Op  : Op { Left $1 }
        | MathOp { Right $1 }
        
MathOp  :: { MathOp }
MathOp  : '+' { OneOf9 PLUS }
        | '-' { TwoOf9 MINUS }
        | '*' { ThreeOf9 STAR }
        | '/' { FourOf9 SLASH }
        | '%' { FiveOf9 PERCENTAGE }
        | '^' { SixOf9 HAT }
        | '<' { SevenOf9 SMALLER }
        | '>' { EightOf9 GREATER }
        | '=' { NineOf9 EQUAL }

qual_Op :: { QualOp }
qual_Op : Op { QualOper $ Left $1 }
        | OPERATOR '(' any_operator ')' { QualOper $ Right $3 }
        
qual_all_Op     :: { QualAllOp }
qual_all_Op
        : all_Op { QualAllOper $ Left $1 }
        | OPERATOR '(' any_operator ')' { QualAllOper $ Right $3 }
        
subquery_Op     :: { SubQueryOp }
subquery_Op
        : all_Op { SubQAll $1 }
        | OPERATOR '(' any_operator ')' { SubQOp $3 }
        | LIKE { SubQLike }
        | NOT LIKE { SubQNotLike }
        | ILIKE { SubQIlike }
        | NOT ILIKE { SubQNotIlike }            

expr_list       :: { ExprList }
expr_list
        : a_expr { MyLst [$1] }
        | expr_list ',' a_expr { MyLst $ (tkMyList $1) ++ [$3] }

extract_list    :: { ExtractList }
extract_list
        : extract_arg FROM a_expr { ExtractLst $1 $3 }
        | {- empty -} { ExtractEmpty }  

type_list       :: { TypeList }
type_list
        : type_list_aux { MyLst $1 }

type_list_aux   :: { [Typename] }
type_list_aux
        : type_list_aux ',' Typename { $1 ++ [$3] }
        | Typename { [$1] }     

array_expr_list :: { ArrayExprList }
array_expr_list
        : array_expr_list_aux { MyLst $1 }

array_expr_list_aux     :: { [ArrayExpr] }
array_expr_list_aux
        : array_expr { [$1] }
        | array_expr_list_aux ',' array_expr { $1 ++ [$3] }
        

array_expr      :: { ArrayExpr }
array_expr
        : '[' expr_list ']' { ArrayExp $ Left $2 }
        | '[' array_expr_list ']' { ArrayExp $ Right $2 }

extract_arg     :: { ExtractArg }
extract_arg
        : IDENT { OneOf8 $1 }
        | YEAR { TwoOf8 YEAR }
        | MONTH { ThreeOf8 MONTH }
        | DAY   { FourOf8 DAY }
        | HOUR { FiveOf8 HOUR }
        | MINUTE { SixOf8 MINUTE }
        | SECOND { SevenOf8 SECOND }
        | SCONST { EightOf8 $1 }

overlay_list    :: { OverlayList }
overlay_list
        : a_expr overlay_placing substr_from substr_for { OverLayLst $1 $2 $3 (Just $4) }
        | a_expr overlay_placing substr_from { OverLayLst $1 $2 $3 Nothing }

overlay_placing :: { OverlayPlacing }
overlay_placing
        : PLACING a_expr { OverlayPlace $2 }

position_list   :: { PositionList }
position_list
        : b_expr IN b_expr { PosLst $1 $3 }
        | {- empty -} { PosLstEmpty }

substr_list     :: { SubstrList }
substr_list
        : a_expr substr_from substr_for { SStrFromFor $1 $2 $3 }
        | a_expr substr_for substr_from { SStrFromFor $1 $3 $2 }
        | a_expr substr_from { SStrFrom $1 $2 }
        | a_expr substr_for { SStrFor $1 $2 }
        | expr_list { SStrLst $1 }
        | {- empty -} { SStrEmpty }
        
substr_from     :: { SubstrFrom }
substr_from
        : FROM a_expr { SubstringFrom $2 }

substr_for      :: { SubstrFor }
substr_for
        : FOR a_expr { SubstringFor $2 }

trim_list       :: { TrimList }
trim_list
        : a_expr FROM expr_list { (Just (Just $1,FROM),$3) }
        | FROM expr_list { (Just (Nothing,FROM),$2) }
        | expr_list { (Nothing,$1) }

in_expr :: { InExpr }
in_expr : select_with_parens { InExpSelect $1 }
        | '(' expr_list ')' { InExpLst $2 }

case_expr       :: { CaseExpr }
case_expr
        : CASE case_arg when_clause_list case_default END { CaseExp $2 $3 $4 }

when_clause_list        :: { WhenClauseList }
when_clause_list
-- There must be at least one
        : when_clause { [$1] }
        | when_clause_list when_clause { $1 ++ [$2] }   

when_clause     :: { WhenClause }
when_clause
        : WHEN a_expr THEN a_expr { WhenClauseConst $2 $4 }

case_default    :: { CaseDefault }
case_default
        : ELSE a_expr { CaseDef $ Just $2 }
        | {- empty -} { CaseDef Nothing }

case_arg        :: { CaseArg }
case_arg
        : a_expr { Just $1 }
        | {- empty -} { Nothing }

columnref       :: { Columnref }
columnref
        : relation_name { ColRefRel $1 }
        | relation_name indirection { ColRefRelInd $1 $2 }

indirection_el  :: { IndirectionEl }
indirection_el
        : '.' attr_name { IndAttr $2 }
        | '.' '*' { IndStar }
        | '[' a_expr ']' { IndExp $2 }
        | '[' a_expr ':' a_expr ']' { IndBinExp $2 $4 }

indirection     :: { Indirection }
indirection
        : indirection_el { [$1] }
        | indirection indirection_el { $1 ++ [$2] }

opt_indirection :: { OptIndirection }
opt_indirection
        : {- empty -} { [] }
        | opt_indirection indirection_el { $1 ++ [$2] } 

opt_asymmetric  :: { OptAsymmetric }
opt_asymmetric
        : ASYMMETRIC { Just ASYMMETRIC }
        | {- empty -} { Nothing }

target_list     :: { TargetList }
target_list
        : target_list_aux { MyLst $1 }

target_list_aux :: { [TargetEl] }
target_list_aux
        : target_el { [$1] }
        | target_list_aux ',' target_el { $1 ++ [$3] }

target_el       :: { TargetEl }
target_el
        : a_expr AS ColLabel { TargetElAs $1 $3 }
        | a_expr { TargetElExp $1 }
        | '*' { TargetElStar }

update_target_list      :: { UpdateTargetList }
update_target_list
        : update_target_list_aux { MyLst $1 }
        
update_target_list_aux  :: { [UpdateTargetEl] }
update_target_list_aux
        : update_target_el { [$1] }
        | update_target_list_aux ',' update_target_el { $1 ++ [$3] }
        
update_target_el        :: { UpdateTargetEl }
update_target_el
        : ColId opt_indirection '=' a_expr { UpdtTargetEl $1 $2 $ Left $4 }
        | ColId opt_indirection '=' DEFAULT { UpdtTargetEl $1 $2 $ Right DEFAULT }

insert_target_list      :: { InsertTargetList }
insert_target_list
        : insert_target_list_aux { MyLst $1 }
        
insert_target_list_aux  :: { [InsertTargetEl] }
insert_target_list_aux
        : insert_target_el { [$1] }
        | insert_target_list_aux ',' insert_target_el { $1 ++ [$3] }

insert_target_el        :: { InsertTargetEl }
insert_target_el
        : a_expr { Left $1 }
        | DEFAULT { Right DEFAULT }

relation_name   :: { RelationName }
relation_name
        : SpecialRuleRelation { Left $1 }
        | ColId { Right $1 }

qualified_name_list     :: { QualifiedNameList }
qualified_name_list
        : qualified_name_list_aux { MyLst $1 }

qualified_name_list_aux :: { [QualifiedName] }
qualified_name_list_aux
        : qualified_name { [$1] }
        | qualified_name_list_aux ',' qualified_name { $1 ++ [$3] }

qualified_name  :: { QualifiedName }
qualified_name
        : relation_name { QualNameRel $1 }
        | relation_name indirection { QualNameRelInd $1 $2 }

name_list       :: { NameList }
name_list
        : name_list_aux { MyLst $1 }

name_list_aux   :: { [Name] }
name_list_aux
        : name { [$1] }
        | name_list_aux ',' name { $1 ++ [$3] }

name    :: { Name }
name    : ColId { $1 }

database_name   :: { DatabaseName }
database_name
        : ColId { $1 }

access_method   :: { AccessMethod }     
access_method
        : ColId { $1 }

attr_name       :: { AttrName }
attr_name
        : ColLabel { $1 }

index_name      :: { IndexName }        
index_name
        : ColId { $1 }

file_name       :: { FileName }
file_name
        : Sconst { $1 }

func_name       :: { FuncName }
func_name
        : function_name { FuncNameFunc $1 }
        | relation_name indirection { FuncNameRelInd $1 $2 }

AexprConst      :: { AExprConst }
AexprConst
        : Iconst { AExpCI $1 }
        | FCONST { AExpCF $1 }
        | Sconst { AExpCS $1 }
        | BCONST { AExpCB $1 }
        | XCONST { AExpCX $1 }
        | ConstTypename Sconst { AExpCType $1 $2 }
        | ConstInterval Sconst opt_interval { AExpCInt $1 Nothing $2 $3 }
        | ConstInterval '(' Iconst ')' Sconst opt_interval { AExpCInt $1 (Just $3) $5 $6 }
        | TRUE { AExpCTrue }
        | FALSE { AExpCFalse }
        | NULL { AExpCNull }

Iconst  :: { Iconst }
Iconst  : ICONST { $1 }

Sconst  :: { Sconst }
Sconst  : SCONST { $1 }

RoleId  :: { RoleId }
RoleId  : ColId { $1 }

SignedIconst    :: { SignedIconst }
SignedIconst
        : ICONST { (Nothing,$1) }
        | '-' ICONST { (Just MINUS,$2) }

ColId   :: { ColId }
ColId   : IDENT { OneOf3 $1 }
        | unreserved_keyword { TwoOf3 $1 }
        | col_name_keyword { ThreeOf3 $1 }

type_name       :: { TypeName }
type_name
        : IDENT { Left $1 }
        | unreserved_keyword { Right $1 }

function_name   :: { FunctionName }
function_name
        : IDENT { OneOf3 $1 }
        | unreserved_keyword { TwoOf3 $1 }
        | func_name_keyword { ThreeOf3 $1 }

ColLabel        :: { ColLabel }
ColLabel
        : IDENT { OneOf5 $1 }
        | unreserved_keyword { TwoOf5 $1 }
        | col_name_keyword { ThreeOf5 $1 }
        | func_name_keyword { FourOf5 $1 }
        | reserved_keyword { FiveOf5 $1 }

unreserved_keyword      :: { UnreservedKeyword }
unreserved_keyword
        : ABORT { UnreservedKeywordABORT }
        | ABSOLUTE { UnreservedKeywordABSOLUTE }
        | ACCESS { UnreservedKeywordACCESS } 
        | ACTION { UnreservedKeywordACTION } 
        | ADD { UnreservedKeywordADD } 
        | ADMIN { UnreservedKeywordADMIN } 
        | AFTER { UnreservedKeywordAFTER } 
        | AGGREGATE { UnreservedKeywordAGGREGATE } 
        | ALSO { UnreservedKeywordALSO } 
        | ALTER { UnreservedKeywordALTER } 
        | ASSERTION { UnreservedKeywordASSERTION } 
        | ASSIGNMENT { UnreservedKeywordASSIGNMENT } 
        | AT { UnreservedKeywordAT } 
        | BACKWARD { UnreservedKeywordBACKWARD } 
        | BEFORE { UnreservedKeywordBEFORE } 
        | BEGIN { UnreservedKeywordBEGIN }
        | BY { UnreservedKeywordBY } 
        | CACHE { UnreservedKeywordCACHE } 
        | CALLED { UnreservedKeywordCALLED } 
        | CASCADE { UnreservedKeywordCASCADE } 
        | CHAIN { UnreservedKeywordCHAIN } 
        | CHARACTERISTICS { UnreservedKeywordCHARACTERISTICS } 
        | CHECKPOINT { UnreservedKeywordCHECKPOINT } 
        | CLASS { UnreservedKeywordCLASS } 
        | CLOSE { UnreservedKeywordCLOSE } 
        | CLUSTER { UnreservedKeywordCLUSTER } 
        | COMMENT { UnreservedKeywordCOMMENT } 
        | COMMIT { UnreservedKeywordCOMMIT } 
        | COMMITTED { UnreservedKeywordCOMMITTED } 
        | CONNECTION { UnreservedKeywordCONNECTION } 
        | CONSTRAINTS { UnreservedKeywordCONSTRAINTS } 
        | CONVERSION { UnreservedKeywordCONVERSION }
        | COPY { UnreservedKeywordCOPY } 
        | CREATEDB { UnreservedKeywordCREATEDB } 
        | CREATEROLE { UnreservedKeywordCREATEROLE } 
        | CREATEUSER { UnreservedKeywordCREATEUSER } 
        | CSV { UnreservedKeywordCSV } 
        | CURSOR { UnreservedKeywordCURSOR } 
        | CYCLE { UnreservedKeywordCYCLE } 
        | DATABASE { UnreservedKeywordDATABASE } 
        | DAY { UnreservedKeywordDAY } 
        | DEALLOCATE { UnreservedKeywordDEALLOCATE } 
        | DECLARE { UnreservedKeywordDECLARE } 
        | DEFAULTS { UnreservedKeywordDEFAULTS } 
        | DEFERRED { UnreservedKeywordDEFERRED } 
        | DEFINER { UnreservedKeywordDEFINER } 
        | DELETE { UnreservedKeywordDELETE }
        | DELIMITER { UnreservedKeywordDELIMITER } 
        | DELIMITERS { UnreservedKeywordDELIMITERS } 
        | DISABLE { UnreservedKeywordDISABLE }
        | DOMAIN { UnreservedKeywordDOMAIN }
        | DOUBLE { UnreservedKeywordDOUBLE }
        | DROP { UnreservedKeywordDROP } 
        | EACH { UnreservedKeywordEACH } 
        | ENABLE { UnreservedKeywordENABLE }
        | ENCODING { UnreservedKeywordENCODING } 
        | ENCRYPTED { UnreservedKeywordENCRYPTED } 
        | ESCAPE { UnreservedKeywordESCAPE } 
        | EXCLUDING { UnreservedKeywordEXCLUDING } 
        | EXCLUSIVE { UnreservedKeywordEXCLUSIVE } 
        | EXECUTE { UnreservedKeywordEXECUTE } 
        | EXPLAIN { UnreservedKeywordEXPLAIN } 
        | EXTERNAL { UnreservedKeywordEXTERNAL } 
        | FETCH { UnreservedKeywordFETCH } 
        | FIRST { UnreservedKeywordFIRST }
        | FORCE { UnreservedKeywordFORCE } 
        | FORWARD { UnreservedKeywordFORWARD } 
        | FUNCTION { UnreservedKeywordFUNCTION } 
        | GLOBAL { UnreservedKeywordGLOBAL }  
        | GRANTED { UnreservedKeywordGRANTED } 
        | HANDLER { UnreservedKeywordHANDLER } 
        | HEADER { UnreservedKeywordHEADER } 
        | HOLD { UnreservedKeywordHOLD } 
        | HOUR { UnreservedKeywordHOUR }
        | IMMEDIATE { UnreservedKeywordIMMEDIATE } 
        | IMMUTABLE { UnreservedKeywordIMMUTABLE } 
        | IMPLICIT { UnreservedKeywordIMPLICIT }
        | INCLUDING { UnreservedKeywordINCLUDING } 
        | INCREMENT { UnreservedKeywordINCREMENT } 
        | INDEX { UnreservedKeywordINDEX } 
        | INHERIT { UnreservedKeywordINHERIT } 
        | INHERITS { UnreservedKeywordINHERITS } 
        | INPUT { UnreservedKeywordINPUT } 
        | INSENSITIVE { UnreservedKeywordINSENSITIVE } 
        | INSERT { UnreservedKeywordINSERT } 
        | INSTEAD { UnreservedKeywordINSTEAD } 
        | INVOKER { UnreservedKeywordINVOKER } 
        | ISOLATION { UnreservedKeywordISOLATION } 
        | KEY { UnreservedKeywordKEY } 
        | LANCOMPILER { UnreservedKeywordLANCOMPILER } 
        | LANGUAGE { UnreservedKeywordLANGUAGE } 
        | LARGE { UnreservedKeywordLARGE }
        | LAST { UnreservedKeywordLAST }
        | LEVEL { UnreservedKeywordLEVEL } 
        | LISTEN { UnreservedKeywordLISTEN } 
        | LOAD { UnreservedKeywordLOAD } 
        | LOCAL { UnreservedKeywordLOCAL } 
        | LOCATION { UnreservedKeywordLOCATION } 
        | LOCK { UnreservedKeywordLOCK }
        | LOGIN { UnreservedKeywordLOGIN }
        | MATCH { UnreservedKeywordMATCH } 
        | MAXVALUE { UnreservedKeywordMAXVALUE } 
        | MINUTE { UnreservedKeywordMINUTE }
        | MINVALUE { UnreservedKeywordMINVALUE } 
        | MODE { UnreservedKeywordMODE } 
        | MONTH { UnreservedKeywordMONTH }
        | MOVE { UnreservedKeywordMOVE } 
        | NAMES { UnreservedKeywordNAMES } 
        | NEXT { UnreservedKeywordNEXT } 
        | NO { UnreservedKeywordNO } 
        | NOCREATEDB { UnreservedKeywordNOCREATEDB } 
        | NOCREATEROLE { UnreservedKeywordNOCREATEROLE } 
        | NOCREATEUSER { UnreservedKeywordNOCREATEUSER } 
        | NOINHERIT { UnreservedKeywordNOINHERIT } 
        | NOLOGIN { UnreservedKeywordNOLOGIN }
        | NOSUPERUSER { UnreservedKeywordNOSUPERUSER } 
        | NOTHING { UnreservedKeywordNOTHING } 
        | NOTIFY { UnreservedKeywordNOTIFY } 
        | NOWAIT { UnreservedKeywordNOWAIT } 
        | OBJECT { UnreservedKeywordOBJECT }
        | OF { UnreservedKeywordOF } 
        | OIDS { UnreservedKeywordOIDS } 
        | OPERATOR { UnreservedKeywordOPERATOR } 
        | OPTION { UnreservedKeywordOPTION } 
        | OWNER { UnreservedKeywordOWNER } 
        | PARTIAL { UnreservedKeywordPARTIAL } 
        | PASSWORD { UnreservedKeywordPASSWORD } 
        | PREPARE { UnreservedKeywordPREPARE } 
        | PREPARED { UnreservedKeywordPREPARED } 
        | PRESERVE { UnreservedKeywordPRESERVE } 
        | PRIOR { UnreservedKeywordPRIOR } 
        | PRIVILEGES { UnreservedKeywordPRIVILEGES } 
        | PROCEDURAL { UnreservedKeywordPROCEDURAL } 
        | PROCEDURE { UnreservedKeywordPROCEDURE } 
        | QUOTE { UnreservedKeywordQUOTE } 
        | READ { UnreservedKeywordREAD } 
        | RECHECK { UnreservedKeywordRECHECK } 
        | REINDEX { UnreservedKeywordREINDEX } 
        | RELATIVE { UnreservedKeywordRELATIVE }
        | RELEASE { UnreservedKeywordRELEASE } 
        | RENAME { UnreservedKeywordRENAME } 
        | REPEATABLE { UnreservedKeywordREPEATABLE } 
        | REPLACE { UnreservedKeywordREPLACE } 
        | RESET { UnreservedKeywordRESET } 
        | RESTART { UnreservedKeywordRESTART } 
        | RESTRICT { UnreservedKeywordRESTRICT } 
        | RETURNS { UnreservedKeywordRETURNS } 
        | REVOKE { UnreservedKeywordREVOKE } 
        | ROLE { UnreservedKeywordROLE } 
        | ROLLBACK { UnreservedKeywordROLLBACK } 
        | ROWS { UnreservedKeywordROWS } 
        | RULE { UnreservedKeywordRULE } 
        | SAVEPOINT { UnreservedKeywordSAVEPOINT } 
        | SCHEMA { UnreservedKeywordSCHEMA } 
        | SCROLL { UnreservedKeywordSCROLL } 
        | SECOND { UnreservedKeywordSECOND }
        | SECURITY { UnreservedKeywordSECURITY } 
        | SEQUENCE { UnreservedKeywordSEQUENCE } 
        | SERIALIZABLE { UnreservedKeywordSERIALIZABLE } 
        | SESSION { UnreservedKeywordSESSION } 
        | SET { UnreservedKeywordSET } 
        | SHARE { UnreservedKeywordSHARE } 
        | SHOW { UnreservedKeywordSHOW } 
        | SIMPLE { UnreservedKeywordSIMPLE } 
        | STABLE { UnreservedKeywordSTABLE } 
        | START { UnreservedKeywordSTART } 
        | STATEMENT { UnreservedKeywordSTATEMENT } 
        | STATISTICS { UnreservedKeywordSTATISTICS } 
        | STDIN { UnreservedKeywordSTDIN } 
        | STDOUT { UnreservedKeywordSTDOUT } 
        | STORAGE { UnreservedKeywordSTORAGE } 
        | SUPERUSER { UnreservedKeywordSUPERUSER }
        | SYSID { UnreservedKeywordSYSID } 
        | SYSTEM { UnreservedKeywordSYSTEM }
        | STRICT { UnreservedKeywordSTRICT }
        | TABLESPACE { UnreservedKeywordTABLESPACE } 
        | TEMP { UnreservedKeywordTEMP } 
        | TEMPLATE { UnreservedKeywordTEMPLATE } 
        | TEMPORARY { UnreservedKeywordTEMPORARY } 
        | TOAST { UnreservedKeywordTOAST } 
        | TRANSACTION { UnreservedKeywordTRANSACTION } 
        | TRIGGER { UnreservedKeywordTRIGGER } 
        | TRUNCATE { UnreservedKeywordTRUNCATE } 
        | TRUSTED { UnreservedKeywordTRUSTED } 
        | TYPE { UnreservedKeywordTYPE }
        | UNCOMMITTED { UnreservedKeywordUNCOMMITTED } 
        | UNENCRYPTED { UnreservedKeywordUNENCRYPTED } 
        | UNKNOWN { UnreservedKeywordUNKNOWN } 
        | UNLISTEN { UnreservedKeywordUNLISTEN } 
        | UNTIL { UnreservedKeywordUNTIL } 
        | UPDATE { UnreservedKeywordUPDATE } 
        | VACUUM { UnreservedKeywordVACUUM } 
        | VALID { UnreservedKeywordVALID } 
        | VALIDATOR { UnreservedKeywordVALIDATOR } 
        | VALUES { UnreservedKeywordVALUES } 
        | VARYING { UnreservedKeywordVARYING } 
        | VIEW { UnreservedKeywordVIEW } 
        | VOLATILE { UnreservedKeywordVOLATILE } 
        | WITH { UnreservedKeywordWITH } 
        | WITHOUT { UnreservedKeywordWITHOUT } 
        | WORK { UnreservedKeywordWORK } 
        | WRITE { UnreservedKeywordWRITE } 
        | YEAR { UnreservedKeywordYEAR }
        | ZONE { UnreservedKeywordZONE } 

col_name_keyword        :: { ColNameKeyword }
col_name_keyword
        : BIGINT { ColNameKeywordBIGINT } 
        | BIT { ColNameKeywordBIT } 
        | BOOLEAN { ColNameKeywordBOOLEAN }
        | CHAR { ColNameKeywordCHAR }
        | CHARACTER { ColNameKeywordCHARACTER } 
        | COALESCE { ColNameKeywordCOALESCE } 
        | CONVERT { ColNameKeywordCONVERT } 
        | DEC { ColNameKeywordDEC } 
        | DECIMAL { ColNameKeywordDECIMAL }
        | EXISTS { ColNameKeywordEXISTS } 
        | EXTRACT { ColNameKeywordEXTRACT } 
        | FLOAT { ColNameKeywordFLOAT }
        | GREATEST { ColNameKeywordGREATEST } 
        | INOUT { ColNameKeywordINOUT } 
        | INT { ColNameKeywordINT }
        | INTEGER { ColNameKeywordINTEGER } 
        | INTERVAL { ColNameKeywordINTERVAL } 
        | LEAST { ColNameKeywordLEAST } 
        | NATIONAL { ColNameKeywordNATIONAL } 
        | NCHAR { ColNameKeywordNCHAR } 
        | NONE { ColNameKeywordNONE } 
        | NULLIF { ColNameKeywordNULLIF } 
        | NUMERIC { ColNameKeywordNUMERIC } 
        | OUT { ColNameKeywordOUT }
        | OVERLAY { ColNameKeywordOVERLAY } 
        | POSITION { ColNameKeywordPOSITION } 
        | PRECISION { ColNameKeywordPRECISION } 
        | REAL { ColNameKeywordREAL } 
        | ROW { ColNameKeywordROW } 
        | SETOF { ColNameKeywordSETOF } 
        | SMALLINT { ColNameKeywordSMALLINT } 
        | SUBSTRING { ColNameKeywordSUBSTRING } 
        | TIME { ColNameKeywordTIME } 
        | TIMESTAMP { ColNameKeywordTIMESTAMP } 
        | TREAT { ColNameKeywordTREAT } 
        | TRIM { ColNameKeywordTRIM } 
        | VARCHAR { ColNameKeywordVARCHAR } 

func_name_keyword       :: { FuncNameKeyword }
func_name_keyword
        : AUTHORIZATION { FuncNameAUTHORIZATION } 
        | BETWEEN { FuncNameBETWEEN } 
        | BINARY { FuncNameBINARY } 
        | CROSS { FuncNameCROSS } 
        | FREEZE { FuncNameFREEZE } 
        | FULL { FuncNameFULL } 
        | ILIKE { FuncNameILIKE } 
        | INNER { FuncNameINNER }
        | IS { FuncNameIS } 
        | ISNULL { FuncNameISNULL } 
        | JOIN { FuncNameJOIN } 
        | LEFT { FuncNameLEFT } 
        | LIKE { FuncNameLIKE } 
        | NATURAL { FuncNameNATURAL } 
        | NOTNULL { FuncNameNOTNULL } 
        | OUTER { FuncNameOUTER }
        | OVERLAPS { FuncNameOVERLAPS } 
        | RIGHT { FuncNameRIGHT } 
        | SIMILAR { FuncNameSIMILAR } 
        | VERBOSE { FuncNameVERBOSE } 

reserved_keyword        :: { ReservedKeyword }
reserved_keyword
        : ALL { ReservedKeywordALL }
        | ANALYSE { ReservedKeywordANALYSE }
        | ANALYZE { ReservedKeywordANALYZE }
        | AND { ReservedKeywordAND }
        | ANY { ReservedKeywordANY }
        | ARRAY { ReservedKeywordARRAY }
        | AS { ReservedKeywordAS }
        | ASC { ReservedKeywordASC }
        | ASYMMETRIC { ReservedKeywordASYMMETRIC }
        | BOTH { ReservedKeywordBOTH }
        | CASE { ReservedKeywordCASE }
        | CAST { ReservedKeywordCAST }
        | CHECK { ReservedKeywordCHECK }
        | COLLATE { ReservedKeywordCOLLATE }
        | COLUMN { ReservedKeywordCOLUMN }
        | CONSTRAINT { ReservedKeywordCONSTRAINT }
        | CREATE { ReservedKeywordCREATE }
        | CURRENT_DATE { ReservedKeywordCURRENT_DATE }
        | CURRENT_ROLE { ReservedKeywordCURRENT_ROLE }
        | CURRENT_TIME { ReservedKeywordCURRENT_TIME }
        | CURRENT_TIMESTAMP { ReservedKeywordCURRENT_TIMESTAMP }
        | CURRENT_USER { ReservedKeywordCURRENT_USER }
        | DEFAULT { ReservedKeywordDEFAULT }
        | DEFERRABLE { ReservedKeywordDEFERRABLE }
        | DESC { ReservedKeywordDESC }
        | DISTINCT { ReservedKeywordDISTINCT }
        | DO { ReservedKeywordDO }
        | ELSE { ReservedKeywordELSE }
        | END { ReservedKeywordEND }
        | EXCEPT { ReservedKeywordEXCEPT }
        | FALSE { ReservedKeywordFALSE }
        | FOR { ReservedKeywordFOR }
        | FOREIGN { ReservedKeywordFOREIGN }
        | FROM { ReservedKeywordFROM }
        | GRANT { ReservedKeywordGRANT }
        | GROUP { ReservedKeywordGROUP }
        | HAVING { ReservedKeywordHAVING }
        | IN { ReservedKeywordIN }
        | INITIALLY { ReservedKeywordINITIALLY }
        | INTERSECT { ReservedKeywordINTERSECT }
        | INTO { ReservedKeywordINTO }
        | LEADING { ReservedKeywordLEADING }
        | LIMIT { ReservedKeywordLIMIT }
        | LOCALTIME { ReservedKeywordLOCALTIME }
        | LOCALTIMESTAMP { ReservedKeywordLOCALTIMESTAMP }
        | NEW { ReservedKeywordNEW }
        | NOT { ReservedKeywordNOT }
        | NULL { ReservedKeywordNULL }
        | OFF { ReservedKeywordOFF }
        | OFFSET { ReservedKeywordOFFSET }
        | OLD { ReservedKeywordOLD }
        | ON { ReservedKeywordON }
        | ONLY { ReservedKeywordONLY }
        | OR { ReservedKeywordOR }
        | ORDER { ReservedKeywordORDER }
        | PLACING { ReservedKeywordPLACING }
        | PRIMARY { ReservedKeywordPRIMARY }
        | REFERENCES { ReservedKeywordREFERENCES }
        | SELECT { ReservedKeywordSELECT }
        | SESSION_USER { ReservedKeywordSESSION_USER }
        | SOME { ReservedKeywordSOME }
        | SYMMETRIC { ReservedKeywordSYMMETRIC }
        | TABLE { ReservedKeywordTABLE }
        | THEN { ReservedKeywordTHEN }
        | TO { ReservedKeywordTO }
        | TRAILING { ReservedKeywordTRAILING }
        | TRUE { ReservedKeywordTRUE }
        | UNION { ReservedKeywordUNION }
        | UNIQUE { ReservedKeywordUNIQUE }
        | USER { ReservedKeywordUSER }
        | USING { ReservedKeywordUSING }
        | WHEN { ReservedKeywordWHEN }
        | WHERE { ReservedKeywordWHERE }

SpecialRuleRelation     :: { SpecialRuleRelation }
SpecialRuleRelation
        : OLD { Left OLD }
        | NEW { Right NEW }

{
happyError :: [Token] -> a
happyError (x:_) = error $ "Parser Error: " ++ show x
-- ^ returns the first non-valid token

-- | parses SQL string content to 'ASTPostgreSQL'
astPostgreSQL :: String -> ASTPostgreSQL
astPostgreSQL str =
        case (lexPostgreSQL str) of
         (Left err)   -> error ("Lexer error: " ++ show err)
         (Right toks) -> parsePostgreSQL toks
}

Theme by Vikram Singh | Powered by WebSVN v2.3.3