docs: protected AstNode parseAlterTableStatement( DdlTokenStream tokens,
                                                  AstNode parentNode ) throws ParsingException {
          assert tokens != null;
          assert parentNode != null;
  
          markStartOfStatement(tokens);
  
          // <alter table statement> ::=
          // ALTER TABLE <table name> <alter table action>
          //
          // <alter table action> ::=
          // <add column definition>
          // | <alter column definition>
          // | <drop column definition>
          // | <add table constraint definition>
          // | <drop table constraint definition>
  
          tokens.consume("ALTER", "TABLE"); // consumes 'ALTER'
          String tableName = parseName(tokens);
  
          AstNode alterTableNode = nodeFactory().node(tableName, parentNode, TYPE_ALTER_TABLE_STATEMENT);
  
          if (tokens.canConsume("ADD")) {
              if (isTableConstraint(tokens)) {
                  parseTableConstraint(tokens, alterTableNode, true);
              } else {
                  parseSingleTerminatedColumnDefinition(tokens, alterTableNode, true);
              }
          } else if (tokens.canConsume("DROP")) {
              if (tokens.canConsume(CONSTRAINT)) {
                  String constraintName = parseName(tokens); // constraint name
                  AstNode constraintNode = nodeFactory().node(constraintName, alterTableNode, TYPE_DROP_TABLE_CONSTRAINT_DEFINITION);
                  if (tokens.canConsume(DropBehavior.CASCADE)) {
                      constraintNode.setProperty(DROP_BEHAVIOR, DropBehavior.CASCADE);
                  } else if (tokens.canConsume(DropBehavior.RESTRICT)) {
                      constraintNode.setProperty(DROP_BEHAVIOR, DropBehavior.RESTRICT);
                  }
              } else {
                  // ALTER TABLE supplier
                  // DROP COLUMN supplier_name;
  
                  // DROP [ COLUMN ] <column name> <drop behavior>
                  tokens.canConsume("COLUMN"); // "COLUMN" is optional
                  String columnName = parseName(tokens);
                  AstNode columnNode = nodeFactory().node(columnName, alterTableNode, TYPE_DROP_COLUMN_DEFINITION);
                  if (tokens.canConsume(DropBehavior.CASCADE)) {
                      columnNode.setProperty(DROP_BEHAVIOR, DropBehavior.CASCADE);
                  } else if (tokens.canConsume(DropBehavior.RESTRICT)) {
                      columnNode.setProperty(DROP_BEHAVIOR, DropBehavior.RESTRICT);
                  }
              }
          } else if (tokens.canConsume("ALTER")) {
              // EXAMPLE: ALTER TABLE table_name [ ALTER column_name SET DEFAULT (0) ]
              //
              // ALTER [ COLUMN ] <column name> {SET <default clause> | DROP DEFAULT}
  
              tokens.canConsume("COLUMN");
              String alterColumnName = parseName(tokens);
              AstNode columnNode = nodeFactory().node(alterColumnName, alterTableNode, TYPE_ALTER_COLUMN_DEFINITION);
              if (tokens.canConsume("SET")) {
                  parseDefaultClause(tokens, columnNode);
              } else if (tokens.canConsume("DROP", "DEFAULT")) {
                  columnNode.setProperty(DROP_BEHAVIOR, "DROP DEFAULT");
              }
          } else {
              parseUntilTerminator(tokens); // COULD BE "NESTED TABLE xxxxxxxx" option clause
          }
  
          markEndOfStatement(tokens, alterTableNode);
          return alterTableNode;
      }