Repository: sqlfluff/sqlfluff
Pull request: Bracket Matching Refactor
Another biggie. Resolves #1046, relates to #962.

This took the linting time of out large dbt project from 16:37 to 7:30. That's over 50% so I'm pretty pleased.

The bottom line of what I've done is make bracketed elements their own segment and then made sure that in most cases, even where matching isn't successful, that this parsing is persisted. This has the following effects:
- The long parsing steps at the start of any file where we're mapping out the overall structure are *much* faster. This is because we only do the bracket matching once, and then later searches through the file (using the bracket sensitive matching) can go much faster because they reuse the previous markings around bracketed regions. This is the core idea of this PR.
- It changes a lot of the dialect steps around brackets. Unfortunately this changes *a lot* of the test cases, grammar routines and rules. These all follow from the first point above, but it makes this a big PR.
- I've added a few small things at the same time while I was in those places in the codesbase (adding python implementation to the config output, updating parts of the Exasol dialect to use `OptionallyBracketed`, basic `pyproject.toml` file, moving some dialect tests into their own `.sql` files rather than being in the python test cases).

Problem statement:
Performance: Bracket Matching
sqlfluff 0.5.3

When parsing and linting very long files (10k chars+), in particular one that I'm working with that has many many brackets, an unreasonable amount of time is spent in the bracket matching routines. In particular, within the `_bracket_sensitive_look_ahead_match` of `Delimited` grammars. I think there could be a significant speedup on large files by addressing this.

Hints from issue discussion:

Commit message: Revert "py project"

This reverts commit 78b5bdce07c1eb252975fdc1c7bc556fab19cef7.

Patch to review:
diff --git a/src/sqlfluff/cli/formatters.py b/src/sqlfluff/cli/formatters.py
index 666e26d60b8..8a30653508d 100644
--- a/src/sqlfluff/cli/formatters.py
+++ b/src/sqlfluff/cli/formatters.py
@@ -8,6 +8,7 @@
     cli_table,
     get_package_version,
     get_python_version,
+    get_python_implementation,
     pad_line,
 )
 
@@ -234,10 +235,13 @@ def _format_config(self, linter):
             config_content = [
                 ("sqlfluff", get_package_version()),
                 ("python", get_python_version()),
+                ("implementation", get_python_implementation()),
                 ("dialect", linter.dialect.name),
                 ("verbosity", self._verbosity),
             ] + linter.templater.config_pairs()
-            text_buffer.write(cli_table(config_content, col_width=25))
+            text_buffer.write(
+                cli_table(config_content, col_width=30, max_label_width=15)
+            )
             text_buffer.write("\n")
             if linter.config.get("rule_whitelist"):
                 text_buffer.write(
diff --git a/src/sqlfluff/cli/helpers.py b/src/sqlfluff/cli/helpers.py
index c8d29559479..a1e6d7f1276 100644
--- a/src/sqlfluff/cli/helpers.py
+++ b/src/sqlfluff/cli/helpers.py
@@ -35,6 +35,14 @@ def get_python_version():
     return "{0[0]}.{0[1]}.{0[2]}".format(sys.version_info)
 
 
+def get_python_implementation():
+    """Get the current python implementation as a string.
+
+    This is useful if testing in pypy or similar.
+    """
+    return sys.implementation.name
+
+
 def get_package_version():
     """Get the current version of the sqlfluff package."""
     return pkg_version
diff --git a/src/sqlfluff/core/parser/grammar/base.py b/src/sqlfluff/core/parser/grammar/base.py
index 4434154c9d1..ed8a59fd01a 100644
--- a/src/sqlfluff/core/parser/grammar/base.py
+++ b/src/sqlfluff/core/parser/grammar/base.py
@@ -1,12 +1,13 @@
 """Base grammar, Ref, Anything and Nothing."""
 
 import copy
-from typing import List, NamedTuple, Optional, Union, Type, Tuple, Any
+from dataclasses import dataclass
+from typing import List, Optional, Union, Type, Tuple, Any
 
 from sqlfluff.core.errors import SQLParseError
 from sqlfluff.core.string_helpers import curtail_string
 
-from sqlfluff.core.parser.segments import BaseSegment, allow_ephemeral
+from sqlfluff.core.parser.segments import BaseSegment, BracketedSegment, allow_ephemeral
 from sqlfluff.core.parser.helpers import trim_non_code_segments, iter_indices
 from sqlfluff.core.parser.match_result import MatchResult
 from sqlfluff.core.parser.match_logging import (
@@ -22,7 +23,8 @@
 MatchableType = Union[Matchable, Type[BaseSegment]]
 
 
-class BracketInfo(NamedTuple):
+@dataclass
+class BracketInfo:
     """BracketInfo tuple for keeping track of brackets during matching.
 
     This is used in BaseGrammar._bracket_sensitive_look_ahead_match but
@@ -30,6 +32,15 @@ class BracketInfo(NamedTuple):
     """
 
     bracket: BaseSegment
+    segments: Tuple[BaseSegment]
+
+    def to_segment(self, end_bracket):
+        """Turn the contained segments into a bracketed segment."""
+        return BracketedSegment(
+            segments=self.segments,
+            start_bracket=(self.bracket,),
+            end_bracket=end_bracket,
+        )
 
 
 def cached_method_for_parse_context(func):
@@ -222,6 +233,9 @@ def _longest_trimmed_match(
                 if res_match.matched_length > best_match_length:
                     best_match = res_match, matcher
                     best_match_length = res_match.matched_length
+            # We could stash segments here, but given we might have some successful
+            # matches here, we shouldn't, because they'll be mutated in the wrong way.
+            # Eventually there might be a performance gain from doing that sensibly here.
 
         # If we get here, then there wasn't a complete match. If we
         # has a best_match, return that.
@@ -465,7 +479,7 @@ def _bracket_sensitive_look_ahead_match(
         # to the list of matchers. We get them from the relevant set on the
         # dialect. We use zip twice to "unzip" them. We ignore the first
         # argument because that's just the name.
-        _, start_bracket_refs, end_bracket_refs = zip(
+        _, start_bracket_refs, end_bracket_refs, persists = zip(
             *parse_context.dialect.sets(bracket_pairs_set)
         )
         # These are matchables, probably StringParsers.
@@ -512,14 +526,15 @@ def _bracket_sensitive_look_ahead_match(
                         # handle identical start and end brackets. For now, consider this
                         # a small, speculative investment in a possible future requirement.
                         if matcher in start_brackets and matcher not in end_brackets:
-                            # Same procedure as below in finding brackets.
+                            # Add any segments leading up to this to the previous bracket.
+                            bracket_stack[-1].segments += pre
+                            # Add a bracket to the stack and add the matches from the segment.
                             bracket_stack.append(
                                 BracketInfo(
                                     bracket=match.matched_segments[0],
+                                    segments=match.matched_segments,
                                 )
                             )
-                            pre_seg_buff += pre
-                            pre_seg_buff += match.matched_segments
                             seg_buff = match.unmatched_segments
                             continue
                         elif matcher in end_brackets:
@@ -537,11 +552,32 @@ def _bracket_sensitive_look_ahead_match(
                             bracket_types_match = start_index == end_index
                             if bracket_types_match:
                                 # Yes, the types match. So we've found a
-                                # matching end bracket. Pop the stack and carry
+                                # matching end bracket. Pop the stack, construct
+                                # a bracketed segment and carry
                                 # on.
+
+                                # Complete the bracketed info
+                                bracket_stack[-1].segments += (
+                                    pre + match.matched_segments
+                                )
+                                # Construct a bracketed segment (as a tuple) if allowed.
+                                persist_bracket = persists[end_brackets.index(matcher)]
+                                if persist_bracket:
+                                    new_segments = (
+                                        bracket_stack[-1].to_segment(
+                                            end_bracket=match.matched_segments
+                                        ),
+                                    )
+                                else:
+                                    new_segments = bracket_stack[-1].segments
+                                # Remove the bracket set from the stack
                                 bracket_stack.pop()
-                                pre_seg_buff += pre
-                                pre_seg_buff += match.matched_segments
+                                # If we're still in a bracket, add the new segments to that bracket
+                                # Otherwise add them to the buffer
+                                if bracket_stack:
+                                    bracket_stack[-1].segments += new_segments
+                                else:
+                                    pre_seg_buff += new_segments
                                 seg_buff = match.unmatched_segments
                                 continue
                             else:
@@ -583,12 +619,13 @@ def _bracket_sensitive_look_ahead_match(
                             bracket_stack.append(
                                 BracketInfo(
                                     bracket=match.matched_segments[0],
+                                    segments=match.matched_segments,
                                 )
                             )
-                            # Add the matched elements and anything before it to the
-                            # pre segment buffer. Reset the working buffer.
+                            # The matched element has already been added to the bracket.
+                            # Add anything before it to the pre segment buffer.
+                            # Reset the working buffer.
                             pre_seg_buff += pre
-                            pre_seg_buff += match.matched_segments
                             seg_buff = match.unmatched_segments
                             continue
                         elif matcher in end_brackets:
@@ -604,7 +641,12 @@ def _bracket_sensitive_look_ahead_match(
                                 v_level=3,
                                 got=matcher,
                             )
-                            return ((), MatchResult.from_unmatched(segments), None)
+                            # We return with the mutated segments so we can reuse any bracket matching.
+                            return (
+                                (),
+                                MatchResult.from_unmatched(pre_seg_buff + seg_buff),
+                                None,
+                            )
                         else:
                             # This shouldn't happen!?
                             raise NotImplementedError(
@@ -612,8 +654,13 @@ def _bracket_sensitive_look_ahead_match(
                             )
                     else:
                         # Not in a bracket stack, but no match. This is a happy
-                        # unmatched exit.
-                        return ((), MatchResult.from_unmatched(segments), None)
+                        # unmatched exit. We return with the mutated segments so we can
+                        # reuse any bracket matching.
+                        return (
+                            (),
+                            MatchResult.from_unmatched(pre_seg_buff + seg_buff),
+                            None,
+                        )
             else:
                 # No we're at the end:
                 # Now check have we closed all our brackets?
@@ -625,8 +672,9 @@ def _bracket_sensitive_look_ahead_match(
                     )
 
                 # We reached the end with no open brackets. This is a friendly
-                # unmatched return.
-                return ((), MatchResult.from_unmatched(segments), None)
+                # unmatched return. We return with the mutated segments so we can
+                # reuse any bracket matching.
+                return ((), MatchResult.from_unmatched(pre_seg_buff + seg_buff), None)
 
     def __str__(self):
         return repr(self)
diff --git a/src/sqlfluff/core/parser/grammar/delimited.py b/src/sqlfluff/core/parser/grammar/delimited.py
index 29ac0f17985..885c294b29d 100644
--- a/src/sqlfluff/core/parser/grammar/delimited.py
+++ b/src/sqlfluff/core/parser/grammar/delimited.py
@@ -102,9 +102,9 @@ def match(
                     parse_context=ctx,
                     bracket_pairs_set=self.bracket_pairs_set,
                 )
-            # Keep track of the *length* of this pre-content section before we start
-            # to change it later. We need this for dealing with terminators.
-            pre_content_len = len(pre_content)
+
+            # Store the mutated segments to reuse.
+            mutated_segments = pre_content + delimiter_match.all_segments()
 
             # Have we found a delimiter or terminator looking forward?
             if delimiter_match:
@@ -126,7 +126,7 @@ def match(
 
                     # No match, or an incomplete match: Not allowed
                     if not match or not match.is_complete():
-                        return MatchResult.from_unmatched(segments)
+                        return MatchResult.from_unmatched(mutated_segments)
 
                     # We have a complete match!
 
@@ -146,23 +146,18 @@ def match(
                         delimiter_matcher, NonCodeMatcher
                     ):
                         # We just return straight away here. We don't add the terminator to
-                        # this match, it should go with the unmatched parts. The terminator
-                        # may also have mutated the returned segments so we also DON'T want
-                        # the mutated version, it can do that itself (so we return `seg_buff`
-                        # and not `delimiter_match.all_segments()``)
+                        # this match, it should go with the unmatched parts.
 
                         # First check we've had enough delimiters
                         if (
                             self.min_delimiters
                             and len(delimiters) < self.min_delimiters
                         ):
-                            return MatchResult.from_unmatched(segments)
+                            return MatchResult.from_unmatched(mutated_segments)
                         else:
                             return MatchResult(
                                 matched_segments.matched_segments,
-                                # Return the part of the seg_buff which isn't in the
-                                # pre-content.
-                                seg_buff[pre_content_len:],
+                                delimiter_match.all_segments(),
                             )
                     else:
                         raise RuntimeError(
@@ -174,7 +169,7 @@ def match(
                 else:
                     # Zero length section between delimiters, or zero code
                     # elements if appropriate. Return unmatched.
-                    return MatchResult.from_unmatched(segments)
+                    return MatchResult.from_unmatched(mutated_segments)
             else:
                 # No match for a delimiter looking forward, this means we're
                 # at the end. In this case we look for a potential partial match
@@ -184,13 +179,13 @@ def match(
                 # First check we're had enough delimiters, because if we haven't then
                 # there's no sense to try matching
                 if self.min_delimiters and len(delimiters) < self.min_delimiters:
-                    return MatchResult.from_unmatched(segments)
+                    return MatchResult.from_unmatched(mutated_segments)
 
                 # We use the whitespace padded match to hoover up whitespace if enabled,
                 # and default to the longest matcher. We don't care which one matches.
                 with parse_context.deeper_match() as ctx:
                     mat, _ = self._longest_trimmed_match(
-                        seg_buff,
+                        mutated_segments,
                         self._elements,
                         parse_context=ctx,
                         trim_noncode=self.allow_gaps,
@@ -215,4 +210,4 @@ def match(
                     if self.allow_trailing:
                         return MatchResult(matched_segments.matched_segments, seg_buff)
                     else:
-                        return MatchResult.from_unmatched(segments)
+                        return MatchResult.from_unmatched(mutated_segments)
diff --git a/src/sqlfluff/core/parser/grammar/sequence.py b/src/sqlfluff/core/parser/grammar/sequence.py
index b48dc89b11d..ca2eb26c366 100644
--- a/src/sqlfluff/core/parser/grammar/sequence.py
+++ b/src/sqlfluff/core/parser/grammar/sequence.py
@@ -4,7 +4,13 @@
 
 from sqlfluff.core.errors import SQLParseError
 
-from sqlfluff.core.parser.segments import BaseSegment, Indent, Dedent, allow_ephemeral
+from sqlfluff.core.parser.segments import (
+    BaseSegment,
+    Indent,
+    Dedent,
+    allow_ephemeral,
+    BracketedSegment,
+)
 from sqlfluff.core.parser.helpers import trim_non_code_segments, check_still_complete
 from sqlfluff.core.parser.match_result import MatchResult
 from sqlfluff.core.parser.match_wrapper import match_wrapper
@@ -201,12 +207,12 @@ def simple(self, parse_context: ParseContext) -> Optional[List[str]]:
 
         Bracketed does this easily, we just look for the bracket.
         """
-        start_bracket, _ = self.get_bracket_from_dialect(parse_context)
+        start_bracket, _, _ = self.get_bracket_from_dialect(parse_context)
         return start_bracket.simple(parse_context=parse_context)
 
     def get_bracket_from_dialect(self, parse_context):
         """Rehydrate the bracket segments in question."""
-        for bracket_type, start_ref, end_ref in parse_context.dialect.sets(
+        for bracket_type, start_ref, end_ref, persists in parse_context.dialect.sets(
             self.bracket_pairs_set
         ):
             if bracket_type == self.bracket_type:
@@ -219,7 +225,7 @@ def get_bracket_from_dialect(self, parse_context):
                     self.bracket_type, parse_context.dialect.name
                 )
             )
-        return start_bracket, end_bracket
+        return start_bracket, end_bracket, persists
 
     @match_wrapper()
     @allow_ephemeral
@@ -245,48 +251,57 @@ def match(
             seg_buff = segments
 
         # Rehydrate the bracket segments in question.
-        start_bracket, end_bracket = self.get_bracket_from_dialect(parse_context)
+        # bracket_persits controls whether we make a BracketedSegment or not.
+        start_bracket, end_bracket, bracket_persists = self.get_bracket_from_dialect(
+            parse_context
+        )
         # Allow optional override for special bracket-like things
         start_bracket = self.start_bracket or start_bracket
         end_bracket = self.end_bracket or end_bracket
 
-        # Look for the first bracket
-        with parse_context.deeper_match() as ctx:
-            start_match = start_bracket.match(seg_buff, parse_context=ctx)
-        if start_match:
-            seg_buff = start_match.unmatched_segments
+        # Are we dealing with a pre-existing BracketSegment?
+        if seg_buff[0].is_type("bracketed"):
+            seg: BracketedSegment = seg_buff[0]  # type: ignore
+            content_segs = seg.segments[len(seg.start_bracket) : -len(seg.end_bracket)]
+            bracket_segment = seg
+            trailing_segments = seg_buff[1:]
+        # Otherwise try and match the segments directly.
         else:
-            # Can't find the opening bracket. No Match.
-            return MatchResult.from_unmatched(segments)
+            # Look for the first bracket
+            with parse_context.deeper_match() as ctx:
+                start_match = start_bracket.match(seg_buff, parse_context=ctx)
+            if start_match:
+                seg_buff = start_match.unmatched_segments
+            else:
+                # Can't find the opening bracket. No Match.
+                return MatchResult.from_unmatched(segments)
 
-        # Look for the closing bracket
-        content_segs, end_match, _ = self._bracket_sensitive_look_ahead_match(
-            segments=seg_buff,
-            matchers=[end_bracket],
-            parse_context=parse_context,
-            start_bracket=start_bracket,
-            end_bracket=end_bracket,
-            bracket_pairs_set=self.bracket_pairs_set,
-        )
-        if not end_match:
-            raise SQLParseError(
-                "Couldn't find closing bracket for opening bracket.",
-                segment=start_match.matched_segments[0],
+            # Look for the closing bracket
+            content_segs, end_match, _ = self._bracket_sensitive_look_ahead_match(
+                segments=seg_buff,
+                matchers=[end_bracket],
+                parse_context=parse_context,
+                start_bracket=start_bracket,
+                end_bracket=end_bracket,
+                bracket_pairs_set=self.bracket_pairs_set,
             )
-
-        # Match the content now we've confirmed the brackets.
-
-        # First deal with the case of TOTALLY EMPTY BRACKETS e.g. "()"
-        if not content_segs:
-            # If it's allowed, return a match.
-            if not self._elements or all(e.is_optional() for e in self._elements):
-                return MatchResult(
-                    start_match.matched_segments + end_match.matched_segments,
-                    end_match.unmatched_segments,
+            if not end_match:
+                raise SQLParseError(
+                    "Couldn't find closing bracket for opening bracket.",
+                    segment=start_match.matched_segments[0],
                 )
-            # If not, don't.
-            else:
-                return MatchResult.from_unmatched(segments)
+
+            # Construct a bracket segment
+            bracket_segment = BracketedSegment(
+                segments=(
+                    start_match.matched_segments
+                    + content_segs
+                    + end_match.matched_segments
+                ),
+                start_bracket=start_match.matched_segments,
+                end_bracket=end_match.matched_segments,
+            )
+            trailing_segments = end_match.unmatched_segments
 
         # Then trim whitespace and deal with the case of no code content e.g. "(   )"
         if self.allow_gaps:
@@ -295,43 +310,59 @@ def match(
             pre_nc = ()
             post_nc = ()
 
-        # If we don't have anything left after trimming, act accordingly.
+        # If we've got a case of empty brackets check whether that is allowed.
         if not content_segs:
             if not self._elements or (
-                all(e.is_optional() for e in self._elements) and self.allow_gaps
+                all(e.is_optional() for e in self._elements)
+                and (self.allow_gaps or (not pre_nc and not post_nc))
             ):
                 return MatchResult(
-                    start_match.matched_segments
-                    + pre_nc
-                    + post_nc
-                    + end_match.matched_segments,
-                    end_match.unmatched_segments,
+                    (bracket_segment,)
+                    if bracket_persists
+                    else bracket_segment.segments,
+                    trailing_segments,
                 )
             else:
                 return MatchResult.from_unmatched(segments)
 
-        # Match using super. Sequence will interpret the content of the elements.
+        # Match the content using super. Sequence will interpret the content of the elements.
         with parse_context.deeper_match() as ctx:
             content_match = super().match(content_segs, parse_context=ctx)
 
         # We require a complete match for the content (hopefully for obvious reasons)
         if content_match.is_complete():
+            # Reconstruct the bracket segment post match.
+            # We need to realign the meta segments so the pos markers are correct.
+            # Have we already got indents?
+            meta_idx = None
+            for idx, seg in enumerate(bracket_segment.segments):
+                if seg.is_meta and seg.indent_val > 0:  # type: ignore
+                    meta_idx = idx
+                    break
+            # If we've already go indents, don't add more.
+            if meta_idx:
+                bracket_segment.segments = BaseSegment._position_segments(
+                    bracket_segment.start_bracket
+                    + pre_nc
+                    + content_match.all_segments()
+                    + post_nc
+                    + bracket_segment.end_bracket
+                )
             # Append some indent and dedent tokens at the start and the end.
+            else:
+                bracket_segment.segments = BaseSegment._position_segments(
+                    # NB: The nc segments go *outside* the indents.
+                    bracket_segment.start_bracket
+                    + (Indent(),)  # Add a meta indent here
+                    + pre_nc
+                    + content_match.all_segments()
+                    + post_nc
+                    + (Dedent(),)  # Add a meta indent here
+                    + bracket_segment.end_bracket
+                )
             return MatchResult(
-                # We need to realign the meta segments so the pos markers are correct.
-                BaseSegment._position_segments(
-                    (
-                        # NB: The nc segments go *outside* the indents.
-                        start_match.matched_segments
-                        + (Indent(),)  # Add a meta indent here
-                        + pre_nc
-                        + content_match.matched_segments
-                        + post_nc
-                        + (Dedent(),)  # Add a meta indent here
-                        + end_match.matched_segments
-                    ),
-                ),
-                end_match.unmatched_segments,
+                (bracket_segment,) if bracket_persists else bracket_segment.segments,
+                trailing_segments,
             )
         # No complete match. Fail.
         else:
diff --git a/src/sqlfluff/core/parser/match_wrapper.py b/src/sqlfluff/core/parser/match_wrapper.py
index a296a01bbdd..fc9c62cb08a 100644
--- a/src/sqlfluff/core/parser/match_wrapper.py
+++ b/src/sqlfluff/core/parser/match_wrapper.py
@@ -48,17 +48,19 @@ def wrapped_match_method(self_cls, segments: tuple, parse_context):
             # Do the match
             m = func(self_cls, segments, parse_context=parse_context)
 
+            name = getattr(self_cls, "__name__", self_cls.__class__.__name__)
+
             # Validate result
             if not isinstance(m, MatchResult):
                 parse_context.logger.warning(
                     "{0}.match, returned {1} rather than MatchResult".format(
-                        func.__qualname__, type(m)
+                        name, type(m)
                     )
                 )
 
             # Log the result.
             WrapParseMatchLogObject(
-                grammar=func.__qualname__,
+                grammar=name,
                 func="match",
                 match=m,
                 parse_context=parse_context,
diff --git a/src/sqlfluff/core/parser/parsers.py b/src/sqlfluff/core/parser/parsers.py
index 739c158e8a5..f6e98943145 100644
--- a/src/sqlfluff/core/parser/parsers.py
+++ b/src/sqlfluff/core/parser/parsers.py
@@ -91,7 +91,15 @@ def match(
 
         # We're only going to match against the first element
         if len(segments) >= 1:
-            if self._is_first_match(segments[0]):
+            # Is the first one already of this type?
+            if (
+                isinstance(segments[0], self.raw_class)
+                and segments[0].name == self.name
+                and segments[0].is_type(self.type)
+            ):
+                return MatchResult((segments[0],), segments[1:])
+            # Does it match?
+            elif self._is_first_match(segments[0]):
                 return self._make_match_from_first_result(segments)
         return MatchResult.from_unmatched(segments)
 
diff --git a/src/sqlfluff/core/parser/segments/__init__.py b/src/sqlfluff/core/parser/segments/__init__.py
index 141460046d1..7a30226d5e5 100644
--- a/src/sqlfluff/core/parser/segments/__init__.py
+++ b/src/sqlfluff/core/parser/segments/__init__.py
@@ -2,7 +2,11 @@
 
 # flake8: noqa: F401
 
-from sqlfluff.core.parser.segments.base import BaseSegment, UnparsableSegment
+from sqlfluff.core.parser.segments.base import (
+    BaseSegment,
+    UnparsableSegment,
+    BracketedSegment,
+)
 from sqlfluff.core.parser.segments.generator import SegmentGenerator
 from sqlfluff.core.parser.segments.raw import (
     RawSegment,
diff --git a/src/sqlfluff/core/parser/segments/base.py b/src/sqlfluff/core/parser/segments/base.py
index 666dda6528f..8e1d177fade 100644
--- a/src/sqlfluff/core/parser/segments/base.py
+++ b/src/sqlfluff/core/parser/segments/base.py
@@ -77,6 +77,8 @@ class (which still inherits from this one).
     # Can we allow it to be empty? Usually used in combination
     # with the can_start_end_non_code.
     allow_empty = False
+    # What other kwargs need to be copied when applying fixes.
+    additional_kwargs: List[str] = []
 
     def __init__(self, segments, pos_marker=None, name: Optional[str] = None):
         # A cache variable for expandable
@@ -831,7 +833,7 @@ def parse(self, parse_context=None, parse_grammar=None):
                     + (
                         UnparsableSegment(
                             segments=segments,
-                            expected=self.type,
+                            expected=self.name,
                         ),  # NB: tuple
                     )
                     + post_nc
@@ -938,6 +940,8 @@ def apply_fixes(self, fixes):
                     tuple(seg_buffer), parent_pos=r.pos_marker
                 ),
                 pos_marker=r.pos_marker,
+                # Pass through any additional kwargs
+                **{k: getattr(self, k) for k in self.additional_kwargs}
             )
             # Return the new segment with any unused fixes.
             return r, fixes
@@ -1033,6 +1037,53 @@ def iter_patches(self, templated_str: str) -> Iterator[FixPatch]:
                 )
 
 
+class BracketedSegment(BaseSegment):
+    """A segment containing a bracketed expression."""
+
+    type = "bracketed"
+    additional_kwargs = ["start_bracket", "end_bracket"]
+
+    def __init__(
+        self,
+        *args,
+        start_bracket: Tuple[BaseSegment] = None,
+        end_bracket: Tuple[BaseSegment] = None,
+        **kwargs
+    ):
+        """Stash the bracket segments for later."""
+        if not start_bracket or not end_bracket:
+            raise ValueError(
+                "Attempted to construct Bracketed segment without specifying brackets."
+            )
+        self.start_bracket = start_bracket
+        self.end_bracket = end_bracket
+        super().__init__(*args, **kwargs)
+
+    @classmethod
+    def simple(cls, parse_context: ParseContext) -> Optional[List[str]]:
+        """Simple methods for bracketed and the persitent brackets."""
+        start_brackets = [
+            start_bracket
+            for _, start_bracket, _, persistent in parse_context.dialect.sets(
+                "bracket_pairs"
+            )
+            if persistent
+        ]
+        start_simple = []
+        for ref in start_brackets:
+            start_simple += parse_context.dialect.ref(ref).simple(parse_context)
+        return start_simple
+
+    @classmethod
+    def match(
+        cls, segments: Tuple["BaseSegment", ...], parse_context: ParseContext
+    ) -> MatchResult:
+        """Only useful as a terminator."""
+        if segments and isinstance(segments[0], cls):
+            return MatchResult((segments[0],), segments[1:])
+        return MatchResult.from_unmatched(segments)
+
+
 class UnparsableSegment(BaseSegment):
     """This is a segment which can't be parsed. It indicates a error during parsing."""
 
diff --git a/src/sqlfluff/core/parser/segments/ephemeral.py b/src/sqlfluff/core/parser/segments/ephemeral.py
index f150c0cd2cc..442c1d0d82b 100644
--- a/src/sqlfluff/core/parser/segments/ephemeral.py
+++ b/src/sqlfluff/core/parser/segments/ephemeral.py
@@ -16,6 +16,8 @@ class EphemeralSegment(BaseSegment):
     it no longer exists.
     """
 
+    type = "ephemeral"
+
     def __init__(self, segments, pos_marker, parse_grammar, name: Optional[str] = None):
         # Stash the parse grammar for now.
         self._parse_grammar = parse_grammar
@@ -67,17 +69,22 @@ def wrapped_match_method(self, segments: tuple, parse_context):
             # Reset the ephemeral name on the new version of the grammar otherwise
             # we get infinite recursion.
             new_grammar.ephemeral_name = None
-            return MatchResult.from_matched(
-                (
-                    EphemeralSegment(
-                        segments=segments,
-                        pos_marker=None,
-                        # Ephemeral segments get a copy of the parent grammar.
-                        parse_grammar=new_grammar,
-                        name=self.ephemeral_name,
-                    ),
+            # We shouldn't allow nested ephemerals. If they're present. Don't create another.
+            # This can happen when grammars call super() on their match method.
+            if len(segments) == 1 and segments[0].is_type("ephemeral"):
+                return MatchResult.from_matched(segments)
+            else:
+                return MatchResult.from_matched(
+                    (
+                        EphemeralSegment(
+                            segments=segments,
+                            pos_marker=None,
+                            # Ephemeral segments get a copy of the parent grammar.
+                            parse_grammar=new_grammar,
+                            name=self.ephemeral_name,
+                        ),
+                    )
                 )
-            )
         else:
             # Otherwise carry on through with wrapping the function.
             return func(self, segments, parse_context=parse_context)
diff --git a/src/sqlfluff/core/rules/analysis/select.py b/src/sqlfluff/core/rules/analysis/select.py
index 4f5d8f3606c..582e9cc4da8 100644
--- a/src/sqlfluff/core/rules/analysis/select.py
+++ b/src/sqlfluff/core/rules/analysis/select.py
@@ -71,9 +71,8 @@ def get_select_statement_info(
     fc = segment.get_child("from_clause")
     if fc:
         for join_clause in fc.recursive_crawl("join_clause"):
-            in_using_brackets = False
             seen_using = False
-            for seg in join_clause.segments:
+            for seg in join_clause.iter_segments():
                 if seg.is_type("keyword") and seg.name == "using":
                     seen_using = True
                 elif seg.is_type("join_on_condition"):
@@ -83,13 +82,11 @@ def get_select_statement_info(
                             reference_buffer += list(
                                 seg.recursive_crawl("object_reference")
                             )
-                elif seen_using and seg.is_type("start_bracket"):
-                    in_using_brackets = True
-                elif seen_using and seg.is_type("end_bracket"):
-                    in_using_brackets = False
+                elif seen_using and seg.is_type("bracketed"):
+                    for subseg in seg.segments:
+                        if subseg.is_type("identifier"):
+                            using_cols.append(subseg.raw)
                     seen_using = False
-                elif in_using_brackets and seg.is_type("identifier"):
-                    using_cols.append(seg.raw)
 
     return SelectStatementColumnsAndTables(
         select_statement=segment,
diff --git a/src/sqlfluff/dialects/dialect_ansi.py b/src/sqlfluff/dialects/dialect_ansi.py
index 40c0b5defae..901bbef6501 100644
--- a/src/sqlfluff/dialects/dialect_ansi.py
+++ b/src/sqlfluff/dialects/dialect_ansi.py
@@ -47,6 +47,7 @@
 
 from sqlfluff.core.dialects.base import Dialect
 from sqlfluff.core.dialects.common import AliasInfo
+from sqlfluff.core.parser.segments.base import BracketedSegment
 
 from sqlfluff.dialects.ansi_keywords import (
     ansi_reserved_keywords,
@@ -154,12 +155,16 @@
 )
 
 # Bracket pairs (a set of tuples).
-# (name, startref, endref)
+# (name, startref, endref, persists)
+# NOTE: The `persists` value controls whether this type
+# of bracket is persisted during matching to speed up other
+# parts of the matching process. Round brackets are the most
+# common and match the largest areas and so are sufficient.
 ansi_dialect.sets("bracket_pairs").update(
     [
-        ("round", "StartBracketSegment", "EndBracketSegment"),
-        ("square", "StartSquareBracketSegment", "EndSquareBracketSegment"),
-        ("curly", "StartCurlyBracketSegment", "EndCurlyBracketSegment"),
+        ("round", "StartBracketSegment", "EndBracketSegment", True),
+        ("square", "StartSquareBracketSegment", "EndSquareBracketSegment", False),
+        ("curly", "StartCurlyBracketSegment", "EndCurlyBracketSegment", False),
     ]
 )
 
@@ -561,6 +566,7 @@ class ObjectReferenceSegment(BaseSegment):
             Ref("BinaryOperatorGrammar"),
             Ref("ColonSegment"),
             Ref("SemicolonSegment"),
+            BracketedSegment,
         ),
         allow_gaps=False,
     )
@@ -939,7 +945,10 @@ def get_eventual_alias(self) -> Optional[AliasInfo]:
 
         """
         alias_expression = self.get_child("alias_expression")
-        ref = self.get_child("table_expression").get_child("object_reference")
+        tbl_expression = self.get_child("table_expression")
+        if not tbl_expression:
+            tbl_expression = self.get_child("bracketed").get_child("table_expression")
+        ref = tbl_expression.get_child("object_reference")
         if alias_expression:
             # If it has an alias, return that
             segment = alias_expression.get_child("identifier")
diff --git a/src/sqlfluff/dialects/dialect_bigquery.py b/src/sqlfluff/dialects/dialect_bigquery.py
index 2e80fc034f6..25b1a76b253 100644
--- a/src/sqlfluff/dialects/dialect_bigquery.py
+++ b/src/sqlfluff/dialects/dialect_bigquery.py
@@ -122,7 +122,7 @@
 # eliminating many potential parsing errors with the "<" and ">" operators.
 bigquery_dialect.sets("angle_bracket_pairs").update(
     [
-        ("angle", "StartAngleBracketSegment", "EndAngleBracketSegment"),
+        ("angle", "StartAngleBracketSegment", "EndAngleBracketSegment", False),
     ]
 )
 
diff --git a/src/sqlfluff/dialects/dialect_exasol.py b/src/sqlfluff/dialects/dialect_exasol.py
index c736b93b9e6..e28533b08d0 100644
--- a/src/sqlfluff/dialects/dialect_exasol.py
+++ b/src/sqlfluff/dialects/dialect_exasol.py
@@ -335,9 +335,7 @@ class GroupByClauseSegment(BaseSegment):
                 Ref("ExpressionSegment"),
                 Ref("CubeRollupClauseSegment"),
                 Ref("GroupingSetsClauseSegment"),
-                Sequence(
-                    Ref("StartBracketSegment"), Ref("EndBracketSegment")
-                ),  # () possible
+                Bracketed(),  # () possible
             ),
             terminator=OneOf(
                 "ORDER",
@@ -396,9 +394,7 @@ class GroupingSetsClauseSegment(BaseSegment):
             Delimited(
                 Ref("CubeRollupClauseSegment"),
                 Ref("GroupingExpressionList"),
-                Sequence(
-                    Ref("StartBracketSegment"), Ref("EndBracketSegment")
-                ),  # () possible
+                Bracketed(),  # () possible
             )
         ),
     )
@@ -843,9 +839,7 @@ class ColumnOptionSegment(BaseSegment):
             Sequence(
                 # IDENTITY(1000) or IDENTITY 1000 or IDENTITY
                 "IDENTITY",
-                Ref("StartBracketSegment", optional=True),
-                Ref("NumericLiteralSegment", optional=True),
-                Ref("EndBracketSegment", optional=True),
+                OptionallyBracketed(Ref("NumericLiteralSegment"), optional=True),
             ),
             optional=True,
         ),
@@ -1000,9 +994,7 @@ class AlterTableAddColumnSegment(BaseSegment):
         "ADD",
         Ref.keyword("COLUMN", optional=True),
         Ref("IfNotExistsGrammar", optional=True),
-        Ref("StartBracketSegment", optional=True),
-        Ref("ColumnDefinitionSegment"),
-        Ref("EndBracketSegment", optional=True),
+        OptionallyBracketed(Ref("ColumnDefinitionSegment")),
     )
 
 
@@ -1028,11 +1020,11 @@ class AlterTableModifyColumnSegment(BaseSegment):
     match_grammar = Sequence(
         "MODIFY",
         Ref.keyword("COLUMN", optional=True),
-        Ref("StartBracketSegment", optional=True),
-        Ref("SingleIdentifierGrammar"),
-        Ref("DatatypeSegment", optional=True),
-        Ref("ColumnOptionSegment", optional=True),
-        Ref("EndBracketSegment", optional=True),
+        OptionallyBracketed(
+            Ref("SingleIdentifierGrammar"),
+            Ref("DatatypeSegment", optional=True),
+            Ref("ColumnOptionSegment", optional=True),
+        ),
     )
 
 
@@ -1066,9 +1058,7 @@ class AlterTableAlterColumnSegment(BaseSegment):
                     Sequence(
                         # IDENTITY(1000) or IDENTITY 1000
                         "IDENTITY",
-                        Ref("StartBracketSegment", optional=True),
-                        Ref("NumericLiteralSegment"),
-                        Ref("EndBracketSegment", optional=True),
+                        OptionallyBracketed(Ref("NumericLiteralSegment")),
                     ),
                     Sequence(
                         "DEFAULT",
diff --git a/src/sqlfluff/rules/L015.py b/src/sqlfluff/rules/L015.py
index c57b9cb7a6d..550719354b7 100644
--- a/src/sqlfluff/rules/L015.py
+++ b/src/sqlfluff/rules/L015.py
@@ -34,47 +34,44 @@ def _eval(self, segment, raw_stack, **kwargs):
 
         Look for DISTINCT keyword immediately followed by open parenthesis.
         """
-        # We only trigger when "DISTINCT" is the immediate parent of an
-        # expression that begins with start_bracket.
-        raw_stack_filtered = self.filter_meta(raw_stack)
-        if raw_stack_filtered and raw_stack_filtered[-1].name == "distinct":
-            if segment.is_type("expression"):
-                segments_filtered = self.filter_meta(segment.segments)
-                if segments_filtered and segments_filtered[0].is_type("start_bracket"):
-                    # If we find open_bracket immediately following DISTINCT,
-                    # then bad.
-                    fixes = []
-                    # The end bracket could be anywhere in segments_filtered,
-                    # e.g. if the expression is (a + b) * c. If and only if it's
-                    # at the *end*, then the parentheses are unnecessary and
-                    # confusing. Remove them.
-                    if segments_filtered[-1].is_type("end_bracket"):
-                        fixes += [
-                            LintFix("delete", segments_filtered[0]),
-                            LintFix("delete", segments_filtered[-1]),
-                        ]
-                        # Update segments_filtered to reflect the pending
-                        # deletions.
-                        segments_filtered = segments_filtered[1:-1]
-                    # If there are still segments remaining after the potential
-                    # deletions above, insert a space between DISTINCT and the
-                    # remainder of the expression. (I think there will always
-                    # be remaining segments; this is a sanity check to ensure
-                    # we don't cause an IndexError.)
-                    if segments_filtered:
-                        # Insert a single space after the open parenthesis being
-                        # removed. Reason: DISTINCT is not a function; it's more
-                        # of a modifier that acts on all the columns. Therefore,
-                        # adding a space makes it clearer what the SQL is
-                        # actually doing.
-                        insert_str = " "
-                        first_segment = segments_filtered[0]
-                        fixes.append(
-                            LintFix(
-                                "create",
-                                first_segment,
-                                [WhitespaceSegment(raw=insert_str)],
-                            )
-                        )
-                    return LintResult(anchor=segment, fixes=fixes)
+        # We trigger on `select_clause` and look for `select_clause_modifier`
+        if segment.is_type("select_clause"):
+            modifier = segment.get_child("select_clause_modifier")
+            if not modifier:
+                return None
+            first_element = segment.get_child("select_clause_element")
+            if not first_element:
+                return None
+            # is the first element only an expression with only brackets?
+            expression = first_element.get_child("expression")
+            if not expression:
+                expression = first_element
+            bracketed = expression.get_child("bracketed")
+            if not bracketed:
+                return None
+            fixes = []
+            # If there's nothing else in the expression, remove the brackets.
+            if len(expression.segments) == 1:
+                # Remove the brackets, and strip any meta segments.
+                fixes = [
+                    LintFix(
+                        "edit", bracketed, self.filter_meta(bracketed.segments)[1:-1]
+                    ),
+                ]
+            # Is there any whitespace between DISTINCT and the expression?
+            distinct_idx = segment.segments.index(modifier)
+            elem_idx = segment.segments.index(first_element)
+            if not any(
+                seg.is_whitespace for seg in segment.segments[distinct_idx:elem_idx]
+            ):
+                fixes.append(
+                    LintFix(
+                        "create",
+                        first_element,
+                        WhitespaceSegment(),
+                    )
+                )
+            # If no fixes, no problem.
+            if fixes:
+                return LintResult(anchor=modifier, fixes=fixes)
         return None
diff --git a/src/sqlfluff/rules/L018.py b/src/sqlfluff/rules/L018.py
index f7473b06ffd..bb5cec98d36 100644
--- a/src/sqlfluff/rules/L018.py
+++ b/src/sqlfluff/rules/L018.py
@@ -81,13 +81,18 @@ def indent_size_up_to(segs):
 
             balance = 0
             with_indent, with_indent_str = indent_size_up_to(raw_stack_buff)
-            for seg in segment.iter_segments(expanding=["common_table_expression"]):
+            print("SEG", segment, with_indent, repr(with_indent_str))
+            for seg in segment.iter_segments(
+                expanding=["common_table_expression", "bracketed"], pass_through=True
+            ):
+                print(seg)
                 if seg.name == "start_bracket":
                     balance += 1
                 elif seg.name == "end_bracket":
                     balance -= 1
                     if balance == 0:
                         closing_bracket_indent, _ = indent_size_up_to(raw_stack_buff)
+                        print("INDENT", closing_bracket_indent)
                         indent_diff = closing_bracket_indent - with_indent
                         # Is indent of closing bracket not the same as
                         # indent of WITH keyword.
@@ -110,7 +115,8 @@ def indent_size_up_to(segs):
                             prev_segs_on_line = [
                                 elem
                                 for elem in segment.iter_segments(
-                                    expanding=["common_table_expression"]
+                                    expanding=["common_table_expression", "bracketed"],
+                                    pass_through=True,
                                 )
                                 if elem.pos_marker.line_no == seg.pos_marker.line_no
                                 and elem.pos_marker.line_pos < seg.pos_marker.line_pos
diff --git a/src/sqlfluff/rules/L022.py b/src/sqlfluff/rules/L022.py
index 5910b54733a..08c86361e69 100644
--- a/src/sqlfluff/rules/L022.py
+++ b/src/sqlfluff/rules/L022.py
@@ -49,7 +49,7 @@ def _eval(self, segment, **kwargs):
                 segment.iter_segments(expanding=["common_table_expression"])
             )
             for idx, seg in enumerate(expanded_segments):
-                if seg.is_type("end_bracket"):
+                if seg.is_type("bracketed"):
                     bracket_indices.append(idx)
 
             # Work through each point and deal with it individually
diff --git a/src/sqlfluff/rules/L023.py b/src/sqlfluff/rules/L023.py
index c263a92ff09..8b3e9ce8126 100644
--- a/src/sqlfluff/rules/L023.py
+++ b/src/sqlfluff/rules/L023.py
@@ -39,7 +39,7 @@ class Rule_L023(BaseRule):
 
     expected_mother_segment_type = "with_compound_statement"
     pre_segment_identifier = ("name", "as")
-    post_segment_identifier = ("type", "start_bracket")
+    post_segment_identifier = ("type", "bracketed")
     allow_newline = False
     expand_children: Optional[List[str]] = ["common_table_expression"]
 
diff --git a/src/sqlfluff/rules/L024.py b/src/sqlfluff/rules/L024.py
index 19b02b3cf39..aa874f58d85 100644
--- a/src/sqlfluff/rules/L024.py
+++ b/src/sqlfluff/rules/L024.py
@@ -32,6 +32,6 @@ class Rule_L024(Rule_L023):
 
     expected_mother_segment_type = "join_clause"
     pre_segment_identifier = ("name", "using")
-    post_segment_identifier = ("type", "start_bracket")
+    post_segment_identifier = ("type", "bracketed")
     expand_children = None
     allow_newline = True
diff --git a/src/sqlfluff/rules/L042.py b/src/sqlfluff/rules/L042.py
index cd41fbf5119..17b66e64fe7 100644
--- a/src/sqlfluff/rules/L042.py
+++ b/src/sqlfluff/rules/L042.py
@@ -68,7 +68,11 @@ def _eval(self, segment, **kwargs):
                 )
                 if not from_expression_element:
                     return None  # There isn't one. We're done.
-
+                # Is it bracketed?
+                bracketed_expression = from_expression_element.get_child("bracketed")
+                # If it is, lint that instead
+                if bracketed_expression:
+                    from_expression_element = bracketed_expression
                 # If any of the following are found, raise an issue.
                 # If not, we're fine.
                 problem_children = [
diff --git a/src/sqlfluff/rules/L047.py b/src/sqlfluff/rules/L047.py
index f87e6d77f5c..7f4df9a1786 100644
--- a/src/sqlfluff/rules/L047.py
+++ b/src/sqlfluff/rules/L047.py
@@ -56,14 +56,19 @@ def _eval(self, segment, **kwargs):
             segment.is_type("function")
             and segment.get_child("function_name").raw_upper == "COUNT"
         ):
+            # Get bracketed content
+            bracketed = segment.get_child("bracketed")
+
+            if not bracketed:
+                return None
+
             f_content = [
                 seg
-                for seg in segment.segments
+                for seg in bracketed.segments
                 if not seg.is_meta
                 and not seg.is_type(
                     "start_bracket",
                     "end_bracket",
-                    "function_name",
                     "whitespace",
                     "newline",
                 )
diff --git a/test/core/parser/grammar_test.py b/test/core/parser/grammar_test.py
index 61d6f29c517..88a2ab6d15a 100644
--- a/test/core/parser/grammar_test.py
+++ b/test/core/parser/grammar_test.py
@@ -228,13 +228,18 @@ def test__parser__grammar__base__bracket_sensitive_look_ahead_match(
         pre_section, match, matcher = BaseGrammar._bracket_sensitive_look_ahead_match(
             bracket_seg_list, [fs], ctx
         )
-        # NB: The bracket segments will have been mutated, so we can't directly compare
-        assert len(pre_section) == 8
+        # NB: The bracket segments will have been mutated, so we can't directly compare.
+        # Make sure we've got a bracketed section in there.
+        assert len(pre_section) == 5
+        assert pre_section[2].is_type("bracketed")
+        assert len(pre_section[2].segments) == 4
         assert matcher == fs
         # We shouldn't match the whitespace with the keyword
         assert match.matched_segments == (
             KeywordSegment("foo", bracket_seg_list[8].pos_marker),
         )
+        # Check that the unmatched segments are nothing.
+        assert not match.unmatched_segments
 
 
 def test__parser__grammar__base__bracket_fail_with_open_paren_close_square_mismatch(
@@ -603,7 +608,13 @@ def test__parser__grammar_greedyuntil_bracketed(bracket_seg_list, fresh_ansi_dia
     g = GreedyUntil(fs)
     with RootParseContext(dialect=fresh_ansi_dialect) as ctx:
         # Check that we can make it past the brackets
-        assert len(g.match(bracket_seg_list, parse_context=ctx)) == 7
+        match = g.match(bracket_seg_list, parse_context=ctx)
+        assert len(match) == 4
+        # Check we successfully constructed a bracketed segment
+        assert match.matched_segments[2].is_type("bracketed")
+        assert match.matched_segments[2].raw == "(foo    )"
+        # Check that the unmatched segments is foo AND the whitespace
+        assert len(match.unmatched_segments) == 2
 
 
 def test__parser__grammar_anything(seg_list, fresh_ansi_dialect):
diff --git a/test/dialects/snowflake_test.py b/test/dialects/snowflake_test.py
index 1da069655d9..db8a0bc82b1 100644
--- a/test/dialects/snowflake_test.py
+++ b/test/dialects/snowflake_test.py
@@ -11,86 +11,10 @@
 @pytest.mark.parametrize(
     "segment_cls,raw",
     [
-        ("UseStatementSegment", 'USE ROLE "MY_ROLE";'),
-        ("UseStatementSegment", 'USE WAREHOUSE "MY_WAREHOUSE";'),
-        ("UseStatementSegment", 'USE DATABASE "MY_DATABASE";'),
-        ("UseStatementSegment", 'USE "MY_DATABASE";'),
-        ("UseStatementSegment", 'USE SCHEMA "MY_DATABASE"."MY_SCHEMA";'),
-        ("UseStatementSegment", 'USE SCHEMA "MY_SCHEMA";'),
-        ("UseStatementSegment", 'USE "MY_DATABASE"."MY_SCHEMA";'),
-        ("CreateRoleStatementSegment", "CREATE ROLE MY_ROLE;"),
-        ("CreateRoleStatementSegment", 'CREATE ROLE "my_role";'),
-        ("CreateDatabaseStatementSegment", "CREATE DATABASE MY_DATABASE;"),
-        (
-            "CreateDatabaseStatementSegment",
-            "CREATE DATABASE IF NOT EXISTS MY_DATABASE;",
-        ),
-        (
-            "CreateCloneStatementSegment",
-            "create schema mytestschema_clone_restore clone testschema;",
-        ),
-        (
-            "CreateCloneStatementSegment",
-            "create schema mytestschema_clone_restore clone testschema before (timestamp => to_timestamp(40*365*86400));",
-        ),
         (
             "CreateCloneStatementSegment",
             "create table orders_clone_restore clone orders at (timestamp => to_timestamp_tz('04/05/2013 01:02:03', 'mm/dd/yyyy hh24:mi:ss'));",
         ),
-        (
-            "AccessStatementSegment",
-            "GRANT OWNERSHIP ON SCHEMA MY_DATABASE.MY_SCHEMA TO ROLE MY_ROLE;",
-        ),
-        ("AccessStatementSegment", "GRANT ROLE MY_ROLE TO ROLE MY_OTHER_ROLE;"),
-        (
-            "AccessStatementSegment",
-            "grant use_any_role on integration external_oauth_1 to role1;",
-        ),
-        (
-            "AccessStatementSegment",
-            "grant ownership on table myschema.mytable to role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "grant ownership on all tables in schema public to role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "grant ownership on all tables in schema mydb.public to role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "grant ownership on all tables in schema mydb.public to role analyst copy current grants;",
-        ),
-        ("AccessStatementSegment", "revoke role analyst from role sysadmin;"),
-        (
-            "AccessStatementSegment",
-            "revoke select,insert on future tables in schema mydb.myschema from role role1;",
-        ),
-        (
-            "AccessStatementSegment",
-            "revoke all privileges on function add5(number) from role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "revoke grant option for operate on warehouse report_wh from role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "revoke select on all tables in schema mydb.myschema from role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "revoke operate on warehouse report_wh from role analyst;",
-        ),
-        (
-            "AccessStatementSegment",
-            "revoke reference_usage on database database2 from share share1;",
-        ),
-        (
-            "AccessStatementSegment",
-            "GRANT OWNERSHIP ON ROLE TEST_ROLE TO ROLE DIFFERENT_ROLE;",
-        ),
         ("ShowStatementSegment", "SHOW GRANTS ON ACCOUNT;"),
         ("ShowStatementSegment", "show tables history in tpch.public;"),
         ("ShowStatementSegment", "show future grants in schema sales.public;"),
diff --git a/test/fixtures/parser/ansi/arithmetic_a.yml b/test/fixtures/parser/ansi/arithmetic_a.yml
index aad8a760223..12525cd73da 100644
--- a/test/fixtures/parser/ansi/arithmetic_a.yml
+++ b/test/fixtures/parser/ansi/arithmetic_a.yml
@@ -7,12 +7,13 @@ file:
           expression:
           - literal: '1'
           - binary_operator: +
-          - start_bracket: (
-          - expression:
-            - literal: '2'
-            - binary_operator: '*'
-            - literal: '3'
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              expression:
+              - literal: '2'
+              - binary_operator: '*'
+              - literal: '3'
+              end_bracket: )
           - comparison_operator: '>='
           - literal: '4'
           - binary_operator: +
diff --git a/test/fixtures/parser/ansi/create_function.yml b/test/fixtures/parser/ansi/create_function.yml
index 3ee705c39eb..502776979c3 100644
--- a/test/fixtures/parser/ansi/create_function.yml
+++ b/test/fixtures/parser/ansi/create_function.yml
@@ -6,13 +6,14 @@ file:
     - function_name:
         function_name_identifier: add
     - base:
-      - start_bracket: (
-      - data_type:
-          data_type_identifier: integer
-      - comma: ','
-      - data_type:
-          data_type_identifier: integer
-      - end_bracket: )
+        bracketed:
+        - start_bracket: (
+        - data_type:
+            data_type_identifier: integer
+        - comma: ','
+        - data_type:
+            data_type_identifier: integer
+        - end_bracket: )
     - keyword: RETURNS
     - data_type:
         data_type_identifier: integer
diff --git a/test/fixtures/parser/ansi/create_index_if_not_exists.yml b/test/fixtures/parser/ansi/create_index_if_not_exists.yml
index 468b4787b21..5ec5f9ab7b2 100644
--- a/test/fixtures/parser/ansi/create_index_if_not_exists.yml
+++ b/test/fixtures/parser/ansi/create_index_if_not_exists.yml
@@ -11,8 +11,9 @@ file:
     - keyword: 'ON'
     - table_reference:
         identifier: transaction_master
-    - start_bracket: (
-    - index_column_definition:
-        identifier: last_updated
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        index_column_definition:
+          identifier: last_updated
+        end_bracket: )
   statement_terminator: ;
diff --git a/test/fixtures/parser/ansi/create_index_simple.yml b/test/fixtures/parser/ansi/create_index_simple.yml
index 4c6b4546a3f..dbce65aca4f 100644
--- a/test/fixtures/parser/ansi/create_index_simple.yml
+++ b/test/fixtures/parser/ansi/create_index_simple.yml
@@ -8,8 +8,9 @@ file:
     - keyword: 'ON'
     - table_reference:
         identifier: transaction_master
-    - start_bracket: (
-    - index_column_definition:
-        identifier: last_updated
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        index_column_definition:
+          identifier: last_updated
+        end_bracket: )
   statement_terminator: ;
diff --git a/test/fixtures/parser/ansi/create_model_options.yml b/test/fixtures/parser/ansi/create_model_options.yml
index cc594c88c59..a02d0d4fb44 100644
--- a/test/fixtures/parser/ansi/create_model_options.yml
+++ b/test/fixtures/parser/ansi/create_model_options.yml
@@ -8,21 +8,22 @@ file:
     - object_reference:
         identifier: model3
     - keyword: OPTIONS
-    - start_bracket: (
-    - parameter: MODEL_TYPE
-    - comparison_operator: '='
-    - literal: "'LOGISTIC_REG'"
-    - comma: ','
-    - parameter: AUTO_CLASS_WEIGHTS
-    - comparison_operator: '='
-    - literal: 'TRUE'
-    - comma: ','
-    - parameter: INPUT_LABEL_COLS
-    - comparison_operator: '='
-    - start_square_bracket: '['
-    - literal: "'label_str'"
-    - end_square_bracket: ']'
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - parameter: MODEL_TYPE
+      - comparison_operator: '='
+      - literal: "'LOGISTIC_REG'"
+      - comma: ','
+      - parameter: AUTO_CLASS_WEIGHTS
+      - comparison_operator: '='
+      - literal: 'TRUE'
+      - comma: ','
+      - parameter: INPUT_LABEL_COLS
+      - comparison_operator: '='
+      - start_square_bracket: '['
+      - literal: "'label_str'"
+      - end_square_bracket: ']'
+      - end_bracket: )
     - keyword: AS
     - select_statement:
         select_clause:
diff --git a/test/fixtures/parser/ansi/create_table_a_c1_c2.yml b/test/fixtures/parser/ansi/create_table_a_c1_c2.yml
index 7158f231051..71c60e6aff2 100644
--- a/test/fixtures/parser/ansi/create_table_a_c1_c2.yml
+++ b/test/fixtures/parser/ansi/create_table_a_c1_c2.yml
@@ -5,14 +5,15 @@ file:
     - keyword: table
     - table_reference:
         identifier: table1
-    - start_bracket: (
-    - column_definition:
-        identifier: c1
-        data_type:
-          data_type_identifier: SMALLINT
-    - comma: ','
-    - column_definition:
-        identifier: c2
-        data_type:
-          data_type_identifier: DATE
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - column_definition:
+          identifier: c1
+          data_type:
+            data_type_identifier: SMALLINT
+      - comma: ','
+      - column_definition:
+          identifier: c2
+          data_type:
+            data_type_identifier: DATE
+      - end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_table_a_column_constraints.yml b/test/fixtures/parser/ansi/create_table_a_column_constraints.yml
index 1f143b5d350..49df39a547c 100644
--- a/test/fixtures/parser/ansi/create_table_a_column_constraints.yml
+++ b/test/fixtures/parser/ansi/create_table_a_column_constraints.yml
@@ -5,80 +5,83 @@ file:
     - keyword: table
     - table_reference:
         identifier: table1
-    - start_bracket: (
-    - column_definition:
-        identifier: c1
-        data_type:
-          data_type_identifier: INT
-        column_constraint:
-        - keyword: NOT
-        - keyword: 'NULL'
-    - comma: ','
-    - column_definition:
-      - identifier: c2
-      - data_type:
-          data_type_identifier: INT
-      - column_constraint:
-          keyword: 'NULL'
-      - column_constraint:
-          keyword: DEFAULT
-          literal: '1'
-    - comma: ','
-    - column_definition:
-        identifier: c3
-        data_type:
-          data_type_identifier: INT
-        column_constraint:
-        - keyword: PRIMARY
-        - keyword: KEY
-    - comma: ','
-    - column_definition:
-        identifier: c4
-        data_type:
-          data_type_identifier: INT
-        column_constraint:
-          keyword: UNIQUE
-    - comma: ','
-    - column_definition:
-        identifier: c5
-        data_type:
-          data_type_identifier: INT
-        column_constraint:
-          keyword: REFERENCES
-          column_reference:
-            identifier: table2
-    - comma: ','
-    - column_definition:
-        identifier: c6
-        data_type:
-          data_type_identifier: INT
-        column_constraint:
-        - keyword: REFERENCES
-        - column_reference:
-            identifier: table2
-        - start_bracket: (
-        - column_reference:
-            identifier: c6_other
-        - end_bracket: )
-    - comma: ','
-    - column_definition:
-      - identifier: c7
-      - data_type:
-          data_type_identifier: INT
-      - column_constraint:
-        - keyword: NOT
-        - keyword: 'NULL'
-      - column_constraint:
-          keyword: DEFAULT
-          literal: '1'
-      - column_constraint:
-          keyword: UNIQUE
-      - column_constraint:
-        - keyword: REFERENCES
-        - column_reference:
-            identifier: table3
-        - start_bracket: (
-        - column_reference:
-            identifier: c7_other
-        - end_bracket: )
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - column_definition:
+          identifier: c1
+          data_type:
+            data_type_identifier: INT
+          column_constraint:
+          - keyword: NOT
+          - keyword: 'NULL'
+      - comma: ','
+      - column_definition:
+        - identifier: c2
+        - data_type:
+            data_type_identifier: INT
+        - column_constraint:
+            keyword: 'NULL'
+        - column_constraint:
+            keyword: DEFAULT
+            literal: '1'
+      - comma: ','
+      - column_definition:
+          identifier: c3
+          data_type:
+            data_type_identifier: INT
+          column_constraint:
+          - keyword: PRIMARY
+          - keyword: KEY
+      - comma: ','
+      - column_definition:
+          identifier: c4
+          data_type:
+            data_type_identifier: INT
+          column_constraint:
+            keyword: UNIQUE
+      - comma: ','
+      - column_definition:
+          identifier: c5
+          data_type:
+            data_type_identifier: INT
+          column_constraint:
+            keyword: REFERENCES
+            column_reference:
+              identifier: table2
+      - comma: ','
+      - column_definition:
+          identifier: c6
+          data_type:
+            data_type_identifier: INT
+          column_constraint:
+            keyword: REFERENCES
+            column_reference:
+              identifier: table2
+            bracketed:
+              start_bracket: (
+              column_reference:
+                identifier: c6_other
+              end_bracket: )
+      - comma: ','
+      - column_definition:
+        - identifier: c7
+        - data_type:
+            data_type_identifier: INT
+        - column_constraint:
+          - keyword: NOT
+          - keyword: 'NULL'
+        - column_constraint:
+            keyword: DEFAULT
+            literal: '1'
+        - column_constraint:
+            keyword: UNIQUE
+        - column_constraint:
+            keyword: REFERENCES
+            column_reference:
+              identifier: table3
+            bracketed:
+              start_bracket: (
+              column_reference:
+                identifier: c7_other
+              end_bracket: )
+      - end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_table_a_pk_unique_fk_constraints.yml b/test/fixtures/parser/ansi/create_table_a_pk_unique_fk_constraints.yml
index 498b16d3128..64f6fb8e8e3 100644
--- a/test/fixtures/parser/ansi/create_table_a_pk_unique_fk_constraints.yml
+++ b/test/fixtures/parser/ansi/create_table_a_pk_unique_fk_constraints.yml
@@ -5,58 +5,63 @@ file:
     - keyword: table
     - table_reference:
         identifier: table1
-    - start_bracket: (
-    - column_definition:
-        identifier: c1
-        data_type:
-          data_type_identifier: INT
-    - comma: ','
-    - column_definition:
-        identifier: c2
-        data_type:
-          data_type_identifier: INT
-    - comma: ','
-    - column_definition:
-        identifier: c3
-        data_type:
-          data_type_identifier: INT
-    - comma: ','
-    - table_constraint_definition:
-      - keyword: PRIMARY
-      - keyword: KEY
+    - bracketed:
       - start_bracket: (
-      - column_reference:
+      - column_definition:
           identifier: c1
-      - end_bracket: )
-    - comma: ','
-    - table_constraint_definition:
-      - keyword: UNIQUE
-      - start_bracket: (
-      - column_reference:
-          identifier: c2
+          data_type:
+            data_type_identifier: INT
       - comma: ','
-      - column_reference:
-          identifier: c3
-      - end_bracket: )
-    - comma: ','
-    - table_constraint_definition:
-      - keyword: FOREIGN
-      - keyword: KEY
-      - start_bracket: (
-      - column_reference:
+      - column_definition:
           identifier: c2
+          data_type:
+            data_type_identifier: INT
       - comma: ','
-      - column_reference:
+      - column_definition:
           identifier: c3
-      - end_bracket: )
-      - keyword: REFERENCES
-      - column_reference:
-          identifier: table2
-      - start_bracket: (
-      - column_reference:
-          identifier: c2_
+          data_type:
+            data_type_identifier: INT
+      - comma: ','
+      - table_constraint_definition:
+        - keyword: PRIMARY
+        - keyword: KEY
+        - bracketed:
+            start_bracket: (
+            column_reference:
+              identifier: c1
+            end_bracket: )
+      - comma: ','
+      - table_constraint_definition:
+          keyword: UNIQUE
+          bracketed:
+          - start_bracket: (
+          - column_reference:
+              identifier: c2
+          - comma: ','
+          - column_reference:
+              identifier: c3
+          - end_bracket: )
       - comma: ','
-      - column_reference:
-          identifier: c3_
+      - table_constraint_definition:
+        - keyword: FOREIGN
+        - keyword: KEY
+        - bracketed:
+          - start_bracket: (
+          - column_reference:
+              identifier: c2
+          - comma: ','
+          - column_reference:
+              identifier: c3
+          - end_bracket: )
+        - keyword: REFERENCES
+        - column_reference:
+            identifier: table2
+        - bracketed:
+          - start_bracket: (
+          - column_reference:
+              identifier: c2_
+          - comma: ','
+          - column_reference:
+              identifier: c3_
+          - end_bracket: )
       - end_bracket: )
-    - end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_table_as_select_cte_no_parentheses.yml b/test/fixtures/parser/ansi/create_table_as_select_cte_no_parentheses.yml
index f5d57399418..93c62193cdb 100644
--- a/test/fixtures/parser/ansi/create_table_as_select_cte_no_parentheses.yml
+++ b/test/fixtures/parser/ansi/create_table_as_select_cte_no_parentheses.yml
@@ -11,22 +11,23 @@ file:
         common_table_expression:
           identifier: source_table
           keyword: AS
-          start_bracket: (
-          select_statement:
-            select_clause:
-              keyword: SELECT
-              select_clause_element:
-                wildcard_expression:
-                  wildcard_identifier:
-                    star: '*'
-            from_clause:
-              keyword: FROM
-              from_expression:
-                from_expression_element:
-                  table_expression:
-                    table_reference:
-                      identifier: source_data
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            select_statement:
+              select_clause:
+                keyword: SELECT
+                select_clause_element:
+                  wildcard_expression:
+                    wildcard_identifier:
+                      star: '*'
+              from_clause:
+                keyword: FROM
+                from_expression:
+                  from_expression_element:
+                    table_expression:
+                      table_reference:
+                        identifier: source_data
+            end_bracket: )
         select_statement:
           select_clause:
             keyword: SELECT
diff --git a/test/fixtures/parser/ansi/create_table_as_select_cte_parentheses.yml b/test/fixtures/parser/ansi/create_table_as_select_cte_parentheses.yml
index e1d1e64fa87..aafbcce7f97 100644
--- a/test/fixtures/parser/ansi/create_table_as_select_cte_parentheses.yml
+++ b/test/fixtures/parser/ansi/create_table_as_select_cte_parentheses.yml
@@ -6,13 +6,30 @@ file:
     - table_reference:
         identifier: final_rows
     - keyword: AS
-    - start_bracket: (
-    - with_compound_statement:
-        keyword: WITH
-        common_table_expression:
-          identifier: source_table
-          keyword: AS
-          start_bracket: (
+    - bracketed:
+        start_bracket: (
+        with_compound_statement:
+          keyword: WITH
+          common_table_expression:
+            identifier: source_table
+            keyword: AS
+            bracketed:
+              start_bracket: (
+              select_statement:
+                select_clause:
+                  keyword: SELECT
+                  select_clause_element:
+                    wildcard_expression:
+                      wildcard_identifier:
+                        star: '*'
+                from_clause:
+                  keyword: FROM
+                  from_expression:
+                    from_expression_element:
+                      table_expression:
+                        table_reference:
+                          identifier: source_data
+              end_bracket: )
           select_statement:
             select_clause:
               keyword: SELECT
@@ -26,20 +43,5 @@ file:
                 from_expression_element:
                   table_expression:
                     table_reference:
-                      identifier: source_data
-          end_bracket: )
-        select_statement:
-          select_clause:
-            keyword: SELECT
-            select_clause_element:
-              wildcard_expression:
-                wildcard_identifier:
-                  star: '*'
-          from_clause:
-            keyword: FROM
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: source_table
-    - end_bracket: )
+                      identifier: source_table
+        end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_table_auto_increment.yml b/test/fixtures/parser/ansi/create_table_auto_increment.yml
index 733a743d1df..59426a305d1 100644
--- a/test/fixtures/parser/ansi/create_table_auto_increment.yml
+++ b/test/fixtures/parser/ansi/create_table_auto_increment.yml
@@ -5,11 +5,12 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: a
-    - start_bracket: (
-    - column_definition:
-        identifier: id
-        data_type:
-          data_type_identifier: INT
-        column_constraint:
-          keyword: AUTO_INCREMENT
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+          identifier: id
+          data_type:
+            data_type_identifier: INT
+          column_constraint:
+            keyword: AUTO_INCREMENT
+        end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_table_column_comment.yml b/test/fixtures/parser/ansi/create_table_column_comment.yml
index fb480e8db79..023f44a1028 100644
--- a/test/fixtures/parser/ansi/create_table_column_comment.yml
+++ b/test/fixtures/parser/ansi/create_table_column_comment.yml
@@ -5,17 +5,19 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: a
-    - start_bracket: (
-    - column_definition:
-        identifier: id
-        data_type:
-          data_type_identifier: VARCHAR
-          start_bracket: (
-          expression:
-            literal: '100'
-          end_bracket: )
-        column_constraint:
-          comment_clause:
-            keyword: COMMENT
-            literal: "'Column comment'"
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+          identifier: id
+          data_type:
+            data_type_identifier: VARCHAR
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '100'
+              end_bracket: )
+          column_constraint:
+            comment_clause:
+              keyword: COMMENT
+              literal: "'Column comment'"
+        end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_table_table_comment.yml b/test/fixtures/parser/ansi/create_table_table_comment.yml
index 3c72660a4c7..822d07478bf 100644
--- a/test/fixtures/parser/ansi/create_table_table_comment.yml
+++ b/test/fixtures/parser/ansi/create_table_table_comment.yml
@@ -5,16 +5,18 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: a
-    - start_bracket: (
-    - column_definition:
-        identifier: id
-        data_type:
-          data_type_identifier: VARCHAR
-          start_bracket: (
-          expression:
-            literal: '100'
-          end_bracket: )
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+          identifier: id
+          data_type:
+            data_type_identifier: VARCHAR
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '100'
+              end_bracket: )
+        end_bracket: )
     - comment_clause:
         keyword: COMMENT
         literal: "'Table comment'"
diff --git a/test/fixtures/parser/ansi/create_table_varchar.yml b/test/fixtures/parser/ansi/create_table_varchar.yml
index 4905ec1b8b1..254a0c6f2fe 100644
--- a/test/fixtures/parser/ansi/create_table_varchar.yml
+++ b/test/fixtures/parser/ansi/create_table_varchar.yml
@@ -5,13 +5,15 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: a
-    - start_bracket: (
-    - column_definition:
-        identifier: id
-        data_type:
-          data_type_identifier: VARCHAR
-          start_bracket: (
-          expression:
-            literal: '100'
-          end_bracket: )
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+          identifier: id
+          data_type:
+            data_type_identifier: VARCHAR
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '100'
+              end_bracket: )
+        end_bracket: )
diff --git a/test/fixtures/parser/ansi/create_view_a.yml b/test/fixtures/parser/ansi/create_view_a.yml
index 68033edabce..b4eeb33c150 100644
--- a/test/fixtures/parser/ansi/create_view_a.yml
+++ b/test/fixtures/parser/ansi/create_view_a.yml
@@ -28,15 +28,16 @@ file:
                     identifier: table2
             - join_on_condition:
                 keyword: 'ON'
-                start_bracket: (
-                expression:
-                - column_reference:
-                  - identifier: table1
-                  - dot: .
-                  - identifier: id
-                - comparison_operator: '='
-                - column_reference:
-                  - identifier: table2
-                  - dot: .
-                  - identifier: id
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  expression:
+                  - column_reference:
+                    - identifier: table1
+                    - dot: .
+                    - identifier: id
+                  - comparison_operator: '='
+                  - column_reference:
+                    - identifier: table2
+                    - dot: .
+                    - identifier: id
+                  end_bracket: )
diff --git a/test/fixtures/parser/ansi/functions_a.yml b/test/fixtures/parser/ansi/functions_a.yml
index 9f3ab1b3138..84d34acbf02 100644
--- a/test/fixtures/parser/ansi/functions_a.yml
+++ b/test/fixtures/parser/ansi/functions_a.yml
@@ -7,55 +7,60 @@ file:
           function:
             function_name:
               function_name_identifier: DATE
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: t
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: t
+              end_bracket: )
       - comma: ','
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: ROUND
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: b
-          - comma: ','
-          - expression:
-              literal: '2'
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: b
+            - comma: ','
+            - expression:
+                literal: '2'
+            - end_bracket: )
       - comma: ','
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: LEFT
-          - start_bracket: (
-          - expression:
-              function:
-              - function_name:
-                  function_name_identifier: right
-              - start_bracket: (
-              - expression:
-                  column_reference:
-                    identifier: s
-              - comma: ','
-              - expression:
-                  literal: '5'
-              - end_bracket: )
-          - comma: ','
-          - expression:
-              function:
-                function_name:
-                  function_name_identifier: LEN
-                start_bracket: (
-                expression:
-                  column_reference:
-                    identifier: s
-                  binary_operator: +
-                  literal: '6'
-                end_bracket: )
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                function:
+                  function_name:
+                    function_name_identifier: right
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      column_reference:
+                        identifier: s
+                  - comma: ','
+                  - expression:
+                      literal: '5'
+                  - end_bracket: )
+            - comma: ','
+            - expression:
+                function:
+                  function_name:
+                    function_name_identifier: LEN
+                  bracketed:
+                    start_bracket: (
+                    expression:
+                      column_reference:
+                        identifier: s
+                      binary_operator: +
+                      literal: '6'
+                    end_bracket: )
+            - end_bracket: )
           alias_expression:
             keyword: as
             identifier: compound
diff --git a/test/fixtures/parser/ansi/functions_b.yml b/test/fixtures/parser/ansi/functions_b.yml
index 330507c416d..17e97e6ad8f 100644
--- a/test/fixtures/parser/ansi/functions_b.yml
+++ b/test/fixtures/parser/ansi/functions_b.yml
@@ -5,22 +5,24 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: SPLIT
-          - start_bracket: (
-          - expression:
-              function:
-                function_name:
-                  function_name_identifier: LOWER
-                start_bracket: (
-                expression:
-                  column_reference:
-                    identifier: text
-                end_bracket: )
-          - comma: ','
-          - expression:
-              literal: "' '"
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                function:
+                  function_name:
+                    function_name_identifier: LOWER
+                  bracketed:
+                    start_bracket: (
+                    expression:
+                      column_reference:
+                        identifier: text
+                    end_bracket: )
+            - comma: ','
+            - expression:
+                literal: "' '"
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: text
diff --git a/test/fixtures/parser/ansi/grant_select_col1_col2_update_col1_on_mytable_to_public.yml b/test/fixtures/parser/ansi/grant_select_col1_col2_update_col1_on_mytable_to_public.yml
index f06a7a9e6c9..c4629a7f62d 100644
--- a/test/fixtures/parser/ansi/grant_select_col1_col2_update_col1_on_mytable_to_public.yml
+++ b/test/fixtures/parser/ansi/grant_select_col1_col2_update_col1_on_mytable_to_public.yml
@@ -3,19 +3,21 @@ file:
     access_statement:
     - keyword: grant
     - keyword: select
-    - start_bracket: (
-    - column_reference:
-        identifier: col1
-    - comma: ','
-    - column_reference:
-        identifier: col2
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - column_reference:
+          identifier: col1
+      - comma: ','
+      - column_reference:
+          identifier: col2
+      - end_bracket: )
     - comma: ','
     - keyword: update
-    - start_bracket: (
-    - column_reference:
-        identifier: col1
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_reference:
+          identifier: col1
+        end_bracket: )
     - keyword: 'on'
     - object_reference:
         identifier: mytable
diff --git a/test/fixtures/parser/ansi/insert_a.yml b/test/fixtures/parser/ansi/insert_a.yml
index 61814881d0a..f9ccd39fe18 100644
--- a/test/fixtures/parser/ansi/insert_a.yml
+++ b/test/fixtures/parser/ansi/insert_a.yml
@@ -5,13 +5,15 @@ file:
     - keyword: into
     - table_reference:
         identifier: tbl_b
-    - start_bracket: (
-    - column_reference:
-        identifier: col1
-    - end_bracket: )
-    - values_clause:
-        keyword: values
+    - bracketed:
         start_bracket: (
-        literal: '123'
+        column_reference:
+          identifier: col1
         end_bracket: )
+    - values_clause:
+        keyword: values
+        bracketed:
+          start_bracket: (
+          literal: '123'
+          end_bracket: )
   statement_terminator: ;
diff --git a/test/fixtures/parser/ansi/modulo.yml b/test/fixtures/parser/ansi/modulo.yml
index 3129f23c9b3..758a15b8f5a 100644
--- a/test/fixtures/parser/ansi/modulo.yml
+++ b/test/fixtures/parser/ansi/modulo.yml
@@ -9,32 +9,34 @@ file:
             - keyword: CASE
             - keyword: WHEN
             - expression:
-              - start_bracket: (
-              - expression:
-                - column_reference:
-                    identifier: year_number
-                - binary_operator: '%'
-                - literal: '400'
-                - comparison_operator: '='
-                - literal: '0'
-              - end_bracket: )
+              - bracketed:
+                  start_bracket: (
+                  expression:
+                  - column_reference:
+                      identifier: year_number
+                  - binary_operator: '%'
+                  - literal: '400'
+                  - comparison_operator: '='
+                  - literal: '0'
+                  end_bracket: )
               - binary_operator: OR
-              - start_bracket: (
-              - expression:
-                - column_reference:
-                    identifier: year_number
-                - binary_operator: '%'
-                - literal: '4'
-                - comparison_operator: '='
-                - literal: '0'
-                - binary_operator: AND
-                - column_reference:
-                    identifier: year_number
-                - binary_operator: '%'
-                - literal: '100'
-                - comparison_operator: '!='
-                - literal: '0'
-              - end_bracket: )
+              - bracketed:
+                  start_bracket: (
+                  expression:
+                  - column_reference:
+                      identifier: year_number
+                  - binary_operator: '%'
+                  - literal: '4'
+                  - comparison_operator: '='
+                  - literal: '0'
+                  - binary_operator: AND
+                  - column_reference:
+                      identifier: year_number
+                  - binary_operator: '%'
+                  - literal: '100'
+                  - comparison_operator: '!='
+                  - literal: '0'
+                  end_bracket: )
             - keyword: THEN
             - expression:
                 literal: 'TRUE'
diff --git a/test/fixtures/parser/ansi/multi_statement_b.yml b/test/fixtures/parser/ansi/multi_statement_b.yml
index 8836579d6c9..277aee7a5c7 100644
--- a/test/fixtures/parser/ansi/multi_statement_b.yml
+++ b/test/fixtures/parser/ansi/multi_statement_b.yml
@@ -18,16 +18,17 @@ file:
       where_clause:
         keyword: where
         expression:
-        - column_reference:
+          column_reference:
             identifier: a
-        - keyword: in
-        - start_bracket: (
-        - literal: "'RED'"
-        - comma: ','
-        - literal: "'GREEN'"
-        - comma: ','
-        - literal: "'BLUE'"
-        - end_bracket: )
+          keyword: in
+          bracketed:
+          - start_bracket: (
+          - literal: "'RED'"
+          - comma: ','
+          - literal: "'GREEN'"
+          - comma: ','
+          - literal: "'BLUE'"
+          - end_bracket: )
 - statement_terminator: ;
 - statement:
     select_statement:
@@ -53,15 +54,17 @@ file:
       - identifier: sch
       - dot: .
       - identifier: tbl_b
-    - start_bracket: (
-    - column_reference:
-        identifier: col1
-    - end_bracket: )
-    - values_clause:
-        keyword: values
+    - bracketed:
         start_bracket: (
-        literal: '123'
+        column_reference:
+          identifier: col1
         end_bracket: )
+    - values_clause:
+        keyword: values
+        bracketed:
+          start_bracket: (
+          literal: '123'
+          end_bracket: )
 - statement_terminator: ;
 - statement:
     with_compound_statement:
@@ -69,22 +72,23 @@ file:
       common_table_expression:
         identifier: tmp
         keyword: as
-        start_bracket: (
-        select_statement:
-          select_clause:
-            keyword: select
-            select_clause_element:
-              wildcard_expression:
-                wildcard_identifier:
-                  star: '*'
-          from_clause:
-            keyword: from
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: blah
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+              keyword: select
+              select_clause_element:
+                wildcard_expression:
+                  wildcard_identifier:
+                    star: '*'
+            from_clause:
+              keyword: from
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: blah
+          end_bracket: )
       select_statement:
         select_clause:
         - keyword: select
diff --git a/test/fixtures/parser/ansi/multi_statement_c.yml b/test/fixtures/parser/ansi/multi_statement_c.yml
index ee48a5fb12e..630402d2ce7 100644
--- a/test/fixtures/parser/ansi/multi_statement_c.yml
+++ b/test/fixtures/parser/ansi/multi_statement_c.yml
@@ -21,28 +21,29 @@ file:
       common_table_expression:
         identifier: blah
         keyword: AS
-        start_bracket: (
-        select_statement:
-          select_clause:
-          - keyword: select
-          - select_clause_element:
-              column_reference:
-                identifier: x
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: y
-          - comma: ','
-          - select_clause_element:
-              literal: '4.567'
-          from_clause:
-            keyword: FROM
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: foo
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+            - keyword: select
+            - select_clause_element:
+                column_reference:
+                  identifier: x
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: y
+            - comma: ','
+            - select_clause_element:
+                literal: '4.567'
+            from_clause:
+              keyword: FROM
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: foo
+          end_bracket: )
       select_statement:
         select_clause:
         - keyword: select
diff --git a/test/fixtures/parser/ansi/select_b.yml b/test/fixtures/parser/ansi/select_b.yml
index 4173e7171cb..dbe719d08cf 100644
--- a/test/fixtures/parser/ansi/select_b.yml
+++ b/test/fixtures/parser/ansi/select_b.yml
@@ -22,15 +22,16 @@ file:
                   identifier: bar
             join_on_condition:
               keyword: 'ON'
-              start_bracket: (
-              expression:
-              - column_reference:
-                - identifier: foo
-                - dot: .
-                - identifier: a
-              - comparison_operator: '='
-              - column_reference:
-                - identifier: bar
-                - dot: .
-                - identifier: a
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                - column_reference:
+                  - identifier: foo
+                  - dot: .
+                  - identifier: a
+                - comparison_operator: '='
+                - column_reference:
+                  - identifier: bar
+                  - dot: .
+                  - identifier: a
+                end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_c.yml b/test/fixtures/parser/ansi/select_c.yml
index c066cf37197..b1277259b90 100644
--- a/test/fixtures/parser/ansi/select_c.yml
+++ b/test/fixtures/parser/ansi/select_c.yml
@@ -33,22 +33,24 @@ file:
         - function:
             function_name:
               function_name_identifier: DATE
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: date_col_b
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: date_col_b
+              end_bracket: )
         - comparison_operator: '>='
         - bare_function: current_date
         - binary_operator: AND
         - function:
             function_name:
               function_name_identifier: length
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: col_a
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: col_a
+              end_bracket: )
         - comparison_operator: '='
         - literal: '4'
       orderby_clause:
diff --git a/test/fixtures/parser/ansi/select_case_a.yml b/test/fixtures/parser/ansi/select_case_a.yml
index e3c624f99af..c95a508481e 100644
--- a/test/fixtures/parser/ansi/select_case_a.yml
+++ b/test/fixtures/parser/ansi/select_case_a.yml
@@ -27,16 +27,17 @@ file:
               - literal: '2'
             - keyword: WHEN
             - expression:
-              - column_reference:
+                column_reference:
                   identifier: some_var
-              - keyword: IN
-              - start_bracket: (
-              - literal: '1'
-              - comma: ','
-              - literal: '2'
-              - comma: ','
-              - literal: '3'
-              - end_bracket: )
+                keyword: IN
+                bracketed:
+                - start_bracket: (
+                - literal: '1'
+                - comma: ','
+                - literal: '2'
+                - comma: ','
+                - literal: '3'
+                - end_bracket: )
             - keyword: then
             - expression:
                 column_reference:
diff --git a/test/fixtures/parser/ansi/select_cross_join.yml b/test/fixtures/parser/ansi/select_cross_join.yml
index 2a371661a95..e1fd58ddd60 100644
--- a/test/fixtures/parser/ansi/select_cross_join.yml
+++ b/test/fixtures/parser/ansi/select_cross_join.yml
@@ -5,16 +5,17 @@ file:
       common_table_expression:
         identifier: constants
         keyword: AS
-        start_bracket: (
-        select_statement:
-          select_clause:
-            keyword: SELECT
-            select_clause_element:
-              literal: '8760'
-              alias_expression:
-                keyword: AS
-                identifier: hours_per_year
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+              keyword: SELECT
+              select_clause_element:
+                literal: '8760'
+                alias_expression:
+                  keyword: AS
+                  identifier: hours_per_year
+          end_bracket: )
       select_statement:
         select_clause:
         - keyword: SELECT
@@ -68,6 +69,7 @@ file:
                   keyword: AS
                   identifier: foo
             - keyword: USING
-            - start_bracket: (
-            - identifier: id
-            - end_bracket: )
+            - bracketed:
+                start_bracket: (
+                identifier: id
+                end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_d.yml b/test/fixtures/parser/ansi/select_d.yml
index 411db117c69..5e5f0e4aefc 100644
--- a/test/fixtures/parser/ansi/select_d.yml
+++ b/test/fixtures/parser/ansi/select_d.yml
@@ -30,18 +30,19 @@ file:
             identifier: col_b
         - keyword: NOT
         - keyword: IN
-        - start_bracket: (
-        - select_statement:
-            select_clause:
-              keyword: SELECT
-              select_clause_element:
-                column_reference:
-                  identifier: c
-            from_clause:
-              keyword: FROM
-              from_expression:
-                from_expression_element:
-                  table_expression:
-                    table_reference:
-                      identifier: another_table
-        - end_bracket: )
+        - bracketed:
+            start_bracket: (
+            select_statement:
+              select_clause:
+                keyword: SELECT
+                select_clause_element:
+                  column_reference:
+                    identifier: c
+              from_clause:
+                keyword: FROM
+                from_expression:
+                  from_expression_element:
+                    table_expression:
+                      table_reference:
+                        identifier: another_table
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_f.yml b/test/fixtures/parser/ansi/select_f.yml
index 366f67b81d2..10f09991277 100644
--- a/test/fixtures/parser/ansi/select_f.yml
+++ b/test/fixtures/parser/ansi/select_f.yml
@@ -7,27 +7,29 @@ file:
           function:
             function_name:
               function_name_identifier: COS
-            start_bracket: (
-            expression:
-            - literal: '2'
-            - binary_operator: '*'
-            - function:
-                function_name:
-                  function_name_identifier: ACOS
-                start_bracket: (
-                expression:
-                  numeric_literal:
-                    binary_operator: '-'
-                    literal: '1'
-                end_bracket: )
-            - binary_operator: '*'
-            - literal: '2'
-            - binary_operator: '*'
-            - column_reference:
-                identifier: y
-            - binary_operator: /
-            - literal: '53'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - literal: '2'
+              - binary_operator: '*'
+              - function:
+                  function_name:
+                    function_name_identifier: ACOS
+                  bracketed:
+                    start_bracket: (
+                    expression:
+                      numeric_literal:
+                        binary_operator: '-'
+                        literal: '1'
+                    end_bracket: )
+              - binary_operator: '*'
+              - literal: '2'
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: y
+              - binary_operator: /
+              - literal: '53'
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: c2
diff --git a/test/fixtures/parser/ansi/select_fn_square_bracket_array_parameter.yml b/test/fixtures/parser/ansi/select_fn_square_bracket_array_parameter.yml
index aa1ac9b9c11..41ed25bb630 100644
--- a/test/fixtures/parser/ansi/select_fn_square_bracket_array_parameter.yml
+++ b/test/fixtures/parser/ansi/select_fn_square_bracket_array_parameter.yml
@@ -7,17 +7,18 @@ file:
           function:
             function_name:
               function_name_identifier: myfn
-            start_bracket: (
-            expression:
-              array_literal:
-              - start_square_bracket: '['
-              - expression:
-                  literal: '1'
-              - comma: ','
-              - expression:
-                  literal: '2'
-              - comma: ','
-              - expression:
-                  literal: '3'
-              - end_square_bracket: ']'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                array_literal:
+                - start_square_bracket: '['
+                - expression:
+                    literal: '1'
+                - comma: ','
+                - expression:
+                    literal: '2'
+                - comma: ','
+                - expression:
+                    literal: '3'
+                - end_square_bracket: ']'
+              end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_function_in_group_by.yml b/test/fixtures/parser/ansi/select_function_in_group_by.yml
index 8aa15011d11..b87311bedbf 100644
--- a/test/fixtures/parser/ansi/select_function_in_group_by.yml
+++ b/test/fixtures/parser/ansi/select_function_in_group_by.yml
@@ -5,16 +5,17 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: COALESCE
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: id
-          - comma: ','
-          - expression:
-              literal: '1'
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: id
+            - comma: ','
+            - expression:
+                literal: '1'
+            - end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
@@ -27,13 +28,14 @@ file:
       - keyword: BY
       - expression:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: COALESCE
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: id
-          - comma: ','
-          - expression:
-              literal: '1'
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: id
+            - comma: ','
+            - expression:
+                literal: '1'
+            - end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_h.yml b/test/fixtures/parser/ansi/select_h.yml
index e1ae7dbf307..19a000dff59 100644
--- a/test/fixtures/parser/ansi/select_h.yml
+++ b/test/fixtures/parser/ansi/select_h.yml
@@ -5,18 +5,19 @@ file:
       - keyword: SELECT
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: DATE
-          - start_bracket: (
-          - expression:
-              column_reference:
-              - identifier: zendesk
-              - dot: .
-              - identifier: created_at
-          - comma: ','
-          - expression:
-              literal: "'America/New_York'"
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                - identifier: zendesk
+                - dot: .
+                - identifier: created_at
+            - comma: ','
+            - expression:
+                literal: "'America/New_York'"
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: date
@@ -25,29 +26,31 @@ file:
           function:
             function_name:
               function_name_identifier: COUNT
-            start_bracket: (
-            expression:
-              case_expression:
-              - keyword: CASE
-              - keyword: WHEN
-              - expression:
-                - column_reference:
-                  - identifier: zendesk
-                  - dot: .
-                  - identifier: support_team
-                - keyword: IN
-                - start_bracket: (
-                - literal: "'tech support'"
-                - comma: ','
-                - literal: "'taskus'"
-                - comma: ','
-                - literal: "'onc'"
-                - end_bracket: )
-              - keyword: THEN
-              - expression:
-                  literal: '1'
-              - keyword: END
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                case_expression:
+                - keyword: CASE
+                - keyword: WHEN
+                - expression:
+                    column_reference:
+                    - identifier: zendesk
+                    - dot: .
+                    - identifier: support_team
+                    keyword: IN
+                    bracketed:
+                    - start_bracket: (
+                    - literal: "'tech support'"
+                    - comma: ','
+                    - literal: "'taskus'"
+                    - comma: ','
+                    - literal: "'onc'"
+                    - end_bracket: )
+                - keyword: THEN
+                - expression:
+                    literal: '1'
+                - keyword: END
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: tech_support
diff --git a/test/fixtures/parser/ansi/select_in_multiline_comment.yml b/test/fixtures/parser/ansi/select_in_multiline_comment.yml
index 1644a71ebb7..c7d8ebc4864 100644
--- a/test/fixtures/parser/ansi/select_in_multiline_comment.yml
+++ b/test/fixtures/parser/ansi/select_in_multiline_comment.yml
@@ -5,42 +5,44 @@ file:
     - common_table_expression:
         identifier: a
         keyword: as
-        start_bracket: (
-        select_statement:
-          select_clause:
-            keyword: select
-            select_clause_element:
-              wildcard_expression:
-                wildcard_identifier:
-                  star: '*'
-          from_clause:
-            keyword: from
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: table_a
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+              keyword: select
+              select_clause_element:
+                wildcard_expression:
+                  wildcard_identifier:
+                    star: '*'
+            from_clause:
+              keyword: from
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: table_a
+          end_bracket: )
     - comma: ','
     - common_table_expression:
         identifier: b
         keyword: as
-        start_bracket: (
-        select_statement:
-          select_clause:
-            keyword: select
-            select_clause_element:
-              wildcard_expression:
-                wildcard_identifier:
-                  star: '*'
-          from_clause:
-            keyword: from
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: a
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+              keyword: select
+              select_clause_element:
+                wildcard_expression:
+                  wildcard_identifier:
+                    star: '*'
+            from_clause:
+              keyword: from
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: a
+          end_bracket: )
     - select_statement:
         select_clause:
           keyword: select
diff --git a/test/fixtures/parser/ansi/select_j.yml b/test/fixtures/parser/ansi/select_j.yml
index 395d0d1e7b1..d2d6c62d28f 100644
--- a/test/fixtures/parser/ansi/select_j.yml
+++ b/test/fixtures/parser/ansi/select_j.yml
@@ -5,56 +5,61 @@ file:
         keyword: SELECT
         select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - function:
-              - function_name:
-                  function_name_identifier: POW
-              - start_bracket: (
-              - expression:
-                  column_reference:
-                    identifier: sd2
-              - comma: ','
-              - expression:
-                  literal: '2'
-              - end_bracket: )
-            - binary_operator: +
-            - function:
-              - function_name:
-                  function_name_identifier: POW
-              - start_bracket: (
-              - expression:
-                  column_reference:
-                    identifier: sd3
-              - comma: ','
-              - expression:
-                  literal: '2'
-              - end_bracket: )
-            - binary_operator: +
-            - function:
-              - function_name:
-                  function_name_identifier: POW
-              - start_bracket: (
-              - expression:
-                  column_reference:
-                    identifier: sd4
-              - comma: ','
-              - expression:
-                  literal: '2'
-              - end_bracket: )
-            - binary_operator: +
-            - function:
-              - function_name:
-                  function_name_identifier: POW
-              - start_bracket: (
-              - expression:
-                  column_reference:
-                    identifier: sd4
-              - comma: ','
-              - expression:
-                  literal: '2'
-              - end_bracket: )
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - function:
+                  function_name:
+                    function_name_identifier: POW
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      column_reference:
+                        identifier: sd2
+                  - comma: ','
+                  - expression:
+                      literal: '2'
+                  - end_bracket: )
+              - binary_operator: +
+              - function:
+                  function_name:
+                    function_name_identifier: POW
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      column_reference:
+                        identifier: sd3
+                  - comma: ','
+                  - expression:
+                      literal: '2'
+                  - end_bracket: )
+              - binary_operator: +
+              - function:
+                  function_name:
+                    function_name_identifier: POW
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      column_reference:
+                        identifier: sd4
+                  - comma: ','
+                  - expression:
+                      literal: '2'
+                  - end_bracket: )
+              - binary_operator: +
+              - function:
+                  function_name:
+                    function_name_identifier: POW
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      column_reference:
+                        identifier: sd4
+                  - comma: ','
+                  - expression:
+                      literal: '2'
+                  - end_bracket: )
+              end_bracket: )
           alias_expression:
             identifier: w1
       from_clause:
diff --git a/test/fixtures/parser/ansi/select_l.yml b/test/fixtures/parser/ansi/select_l.yml
index b38f391429f..e642aa63885 100644
--- a/test/fixtures/parser/ansi/select_l.yml
+++ b/test/fixtures/parser/ansi/select_l.yml
@@ -19,11 +19,12 @@ file:
           column_reference:
             identifier: c
           comparison_operator: '>='
-          start_bracket: (
-          expression:
-            select_statement:
-              select_clause:
-                keyword: SELECT
-                select_clause_element:
-                  literal: '1'
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            expression:
+              select_statement:
+                select_clause:
+                  keyword: SELECT
+                  select_clause_element:
+                    literal: '1'
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_m.yml b/test/fixtures/parser/ansi/select_m.yml
index e9b0909a8e0..5ad5f016b85 100644
--- a/test/fixtures/parser/ansi/select_m.yml
+++ b/test/fixtures/parser/ansi/select_m.yml
@@ -56,27 +56,29 @@ file:
             join_on_condition:
               keyword: 'ON'
               expression:
-              - start_bracket: (
-              - expression:
-                - column_reference:
-                    identifier: business_type
-                - comparison_operator: '='
-                - column_reference:
-                    identifier: low_business_type
-              - end_bracket: )
+              - bracketed:
+                  start_bracket: (
+                  expression:
+                  - column_reference:
+                      identifier: business_type
+                  - comparison_operator: '='
+                  - column_reference:
+                      identifier: low_business_type
+                  end_bracket: )
               - binary_operator: AND
-              - start_bracket: (
-              - expression:
-                - column_reference:
-                    identifier: business_type
-                - comparison_operator: '='
-                - column_reference:
-                    identifier: low_business_type
-                - binary_operator: OR
-                - column_reference:
-                    identifier: size_label
-                - comparison_operator: '='
-                - column_reference:
-                    identifier: low_size_label
-              - end_bracket: )
+              - bracketed:
+                  start_bracket: (
+                  expression:
+                  - column_reference:
+                      identifier: business_type
+                  - comparison_operator: '='
+                  - column_reference:
+                      identifier: low_business_type
+                  - binary_operator: OR
+                  - column_reference:
+                      identifier: size_label
+                  - comparison_operator: '='
+                  - column_reference:
+                      identifier: low_size_label
+                  end_bracket: )
 - statement_terminator: ;
diff --git a/test/fixtures/parser/ansi/select_many_join.yml b/test/fixtures/parser/ansi/select_many_join.yml
index 75a476510c0..675ede9abb8 100644
--- a/test/fixtures/parser/ansi/select_many_join.yml
+++ b/test/fixtures/parser/ansi/select_many_join.yml
@@ -60,10 +60,11 @@ file:
                 function:
                   function_name:
                     function_name_identifier: g
-                  start_bracket: (
-                  expression:
-                    literal: "'blah'"
-                  end_bracket: )
+                  bracketed:
+                    start_bracket: (
+                    expression:
+                      literal: "'blah'"
+                    end_bracket: )
               alias_expression:
                 keyword: as
                 identifier: tbl_func
diff --git a/test/fixtures/parser/ansi/select_multiple_named_windows.yml b/test/fixtures/parser/ansi/select_multiple_named_windows.yml
index b26e7488f11..f7a267b3d17 100644
--- a/test/fixtures/parser/ansi/select_multiple_named_windows.yml
+++ b/test/fixtures/parser/ansi/select_multiple_named_windows.yml
@@ -19,17 +19,19 @@ file:
           function:
             function_name:
               function_name_identifier: LAST_VALUE
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: item
-            end_bracket: )
-            over_clause:
-              keyword: OVER
+            bracketed:
               start_bracket: (
-              window_specification:
-                identifier: d
+              expression:
+                column_reference:
+                  identifier: item
               end_bracket: )
+            over_clause:
+              keyword: OVER
+              bracketed:
+                start_bracket: (
+                window_specification:
+                  identifier: d
+                end_bracket: )
           alias_expression:
             keyword: AS
             identifier: most_popular
@@ -45,49 +47,53 @@ file:
       - named_window_expression:
           identifier: a
           keyword: AS
-          start_bracket: (
-          window_specification:
-            partitionby_clause:
-            - keyword: PARTITION
-            - keyword: BY
-            - expression:
-                column_reference:
-                  identifier: category
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              partitionby_clause:
+              - keyword: PARTITION
+              - keyword: BY
+              - expression:
+                  column_reference:
+                    identifier: category
+            end_bracket: )
       - comma: ','
       - named_window_expression:
           identifier: b
           keyword: AS
-          start_bracket: (
-          window_specification:
-            identifier: a
-            orderby_clause:
-            - keyword: ORDER
-            - keyword: BY
-            - column_reference:
-                identifier: purchases
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              identifier: a
+              orderby_clause:
+              - keyword: ORDER
+              - keyword: BY
+              - column_reference:
+                  identifier: purchases
+            end_bracket: )
       - comma: ','
       - named_window_expression:
           identifier: c
           keyword: AS
-          start_bracket: (
-          window_specification:
-            identifier: b
-            frame_clause:
-            - keyword: ROWS
-            - raw: BETWEEN
-            - raw: '2'
-            - raw: PRECEDING
-            - raw: AND
-            - raw: '2'
-            - raw: FOLLOWING
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              identifier: b
+              frame_clause:
+              - keyword: ROWS
+              - raw: BETWEEN
+              - raw: '2'
+              - raw: PRECEDING
+              - raw: AND
+              - raw: '2'
+              - raw: FOLLOWING
+            end_bracket: )
       - comma: ','
       - named_window_expression:
           identifier: d
           keyword: AS
-          start_bracket: (
-          window_specification:
-            identifier: c
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              identifier: c
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_named_window.yml b/test/fixtures/parser/ansi/select_named_window.yml
index 6b013141b31..b7da195b7f7 100644
--- a/test/fixtures/parser/ansi/select_named_window.yml
+++ b/test/fixtures/parser/ansi/select_named_window.yml
@@ -7,17 +7,19 @@ file:
           function:
             function_name:
               function_name_identifier: AVG
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: col
-            end_bracket: )
-            over_clause:
-              keyword: OVER
+            bracketed:
               start_bracket: (
-              window_specification:
-                identifier: win
+              expression:
+                column_reference:
+                  identifier: col
               end_bracket: )
+            over_clause:
+              keyword: OVER
+              bracketed:
+                start_bracket: (
+                window_specification:
+                  identifier: win
+                end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
@@ -30,12 +32,13 @@ file:
         named_window_expression:
           identifier: win
           keyword: AS
-          start_bracket: (
-          window_specification:
-            partitionby_clause:
-            - keyword: PARTITION
-            - keyword: BY
-            - expression:
-                column_reference:
-                  identifier: date
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              partitionby_clause:
+              - keyword: PARTITION
+              - keyword: BY
+              - expression:
+                  column_reference:
+                    identifier: date
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_named_window_no_parentheses.yml b/test/fixtures/parser/ansi/select_named_window_no_parentheses.yml
index f1d66eada10..f685120a620 100644
--- a/test/fixtures/parser/ansi/select_named_window_no_parentheses.yml
+++ b/test/fixtures/parser/ansi/select_named_window_no_parentheses.yml
@@ -5,17 +5,18 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: NTH_VALUE
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: bar
-          - comma: ','
-          - expression:
-              literal: '1'
-          - end_bracket: )
-          - over_clause:
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: bar
+            - comma: ','
+            - expression:
+                literal: '1'
+            - end_bracket: )
+            over_clause:
               keyword: OVER
               identifier: w1
           alias_expression:
@@ -33,26 +34,27 @@ file:
         named_window_expression:
           identifier: w1
           keyword: AS
-          start_bracket: (
-          window_specification:
-            partitionby_clause:
-            - keyword: PARTITION
-            - keyword: BY
-            - expression:
-                column_reference:
-                  identifier: x
-            - comma: ','
-            - expression:
-                column_reference:
-                  identifier: y
-            - comma: ','
-            - expression:
-                column_reference:
-                  identifier: z
-            orderby_clause:
-            - keyword: ORDER
-            - keyword: BY
-            - column_reference:
-                identifier: abc
-            - keyword: DESC
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              partitionby_clause:
+              - keyword: PARTITION
+              - keyword: BY
+              - expression:
+                  column_reference:
+                    identifier: x
+              - comma: ','
+              - expression:
+                  column_reference:
+                    identifier: y
+              - comma: ','
+              - expression:
+                  column_reference:
+                    identifier: z
+              orderby_clause:
+              - keyword: ORDER
+              - keyword: BY
+              - column_reference:
+                  identifier: abc
+              - keyword: DESC
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_named_window_with_parentheses.yml b/test/fixtures/parser/ansi/select_named_window_with_parentheses.yml
index e38634d94e9..6f5e9d83c98 100644
--- a/test/fixtures/parser/ansi/select_named_window_with_parentheses.yml
+++ b/test/fixtures/parser/ansi/select_named_window_with_parentheses.yml
@@ -5,22 +5,24 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: NTH_VALUE
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: bar
-          - comma: ','
-          - expression:
-              literal: '1'
-          - end_bracket: )
-          - over_clause:
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: bar
+            - comma: ','
+            - expression:
+                literal: '1'
+            - end_bracket: )
+            over_clause:
               keyword: OVER
-              start_bracket: (
-              window_specification:
-                identifier: w1
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                window_specification:
+                  identifier: w1
+                end_bracket: )
           alias_expression:
             keyword: AS
             identifier: baz
@@ -36,26 +38,27 @@ file:
         named_window_expression:
           identifier: w1
           keyword: AS
-          start_bracket: (
-          window_specification:
-            partitionby_clause:
-            - keyword: PARTITION
-            - keyword: BY
-            - expression:
-                column_reference:
-                  identifier: x
-            - comma: ','
-            - expression:
-                column_reference:
-                  identifier: y
-            - comma: ','
-            - expression:
-                column_reference:
-                  identifier: z
-            orderby_clause:
-            - keyword: ORDER
-            - keyword: BY
-            - column_reference:
-                identifier: abc
-            - keyword: DESC
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              partitionby_clause:
+              - keyword: PARTITION
+              - keyword: BY
+              - expression:
+                  column_reference:
+                    identifier: x
+              - comma: ','
+              - expression:
+                  column_reference:
+                    identifier: y
+              - comma: ','
+              - expression:
+                  column_reference:
+                    identifier: z
+              orderby_clause:
+              - keyword: ORDER
+              - keyword: BY
+              - column_reference:
+                  identifier: abc
+              - keyword: DESC
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_named_windows_each_window_specification.yml b/test/fixtures/parser/ansi/select_named_windows_each_window_specification.yml
index ea5be81f976..6b4275e6e66 100644
--- a/test/fixtures/parser/ansi/select_named_windows_each_window_specification.yml
+++ b/test/fixtures/parser/ansi/select_named_windows_each_window_specification.yml
@@ -19,17 +19,19 @@ file:
           function:
             function_name:
               function_name_identifier: LAST_VALUE
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: item
-            end_bracket: )
-            over_clause:
-              keyword: OVER
+            bracketed:
               start_bracket: (
-              window_specification:
-                identifier: c
+              expression:
+                column_reference:
+                  identifier: item
               end_bracket: )
+            over_clause:
+              keyword: OVER
+              bracketed:
+                start_bracket: (
+                window_specification:
+                  identifier: c
+                end_bracket: )
           alias_expression:
             keyword: AS
             identifier: most_popular
@@ -45,39 +47,42 @@ file:
       - named_window_expression:
           identifier: a
           keyword: AS
-          start_bracket: (
-          window_specification:
-            partitionby_clause:
-            - keyword: PARTITION
-            - keyword: BY
-            - expression:
-                column_reference:
-                  identifier: category
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              partitionby_clause:
+              - keyword: PARTITION
+              - keyword: BY
+              - expression:
+                  column_reference:
+                    identifier: category
+            end_bracket: )
       - comma: ','
       - named_window_expression:
           identifier: b
           keyword: AS
-          start_bracket: (
-          window_specification:
-            orderby_clause:
-            - keyword: ORDER
-            - keyword: BY
-            - column_reference:
-                identifier: purchases
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              orderby_clause:
+              - keyword: ORDER
+              - keyword: BY
+              - column_reference:
+                  identifier: purchases
+            end_bracket: )
       - comma: ','
       - named_window_expression:
           identifier: c
           keyword: AS
-          start_bracket: (
-          window_specification:
-            frame_clause:
-            - keyword: ROWS
-            - raw: BETWEEN
-            - raw: '2'
-            - raw: PRECEDING
-            - raw: AND
-            - raw: '2'
-            - raw: FOLLOWING
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            window_specification:
+              frame_clause:
+              - keyword: ROWS
+              - raw: BETWEEN
+              - raw: '2'
+              - raw: PRECEDING
+              - raw: AND
+              - raw: '2'
+              - raw: FOLLOWING
+            end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_p.yml b/test/fixtures/parser/ansi/select_p.yml
index e4e805ca08e..6af12b4fab1 100644
--- a/test/fixtures/parser/ansi/select_p.yml
+++ b/test/fixtures/parser/ansi/select_p.yml
@@ -7,25 +7,27 @@ file:
           function:
             function_name:
               function_name_identifier: CAST
-            start_bracket: (
-            expression:
-              literal: '25.65'
-            keyword: AS
-            data_type:
-              data_type_identifier: int
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '25.65'
+              keyword: AS
+              data_type:
+                data_type_identifier: int
+              end_bracket: )
       - comma: ','
       - select_clause_element:
           function:
             function_name:
               function_name_identifier: SAFE_CAST
-            start_bracket: (
-            expression:
-              literal: 'NULL'
-            keyword: AS
-            data_type:
-              data_type_identifier: STRING
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: 'NULL'
+              keyword: AS
+              data_type:
+                data_type_identifier: STRING
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: age_label
@@ -34,13 +36,14 @@ file:
           function:
             function_name:
               function_name_identifier: EXTRACT
-            start_bracket: (
-            date_part: day
-            keyword: FROM
-            expression:
-              column_reference:
-                identifier: end_time
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              date_part: day
+              keyword: FROM
+              expression:
+                column_reference:
+                  identifier: end_time
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: day
diff --git a/test/fixtures/parser/ansi/select_r.yml b/test/fixtures/parser/ansi/select_r.yml
index f2d1187e7dd..6378d043ff0 100644
--- a/test/fixtures/parser/ansi/select_r.yml
+++ b/test/fixtures/parser/ansi/select_r.yml
@@ -5,44 +5,45 @@ file:
       common_table_expression:
         identifier: result
         keyword: AS
-        start_bracket: (
-        set_expression:
-        - select_statement:
-            select_clause:
-              keyword: SELECT
-              select_clause_element:
-                column_reference:
-                  identifier: customer
-            from_clause:
-              keyword: FROM
-              from_expression:
-                from_expression_element:
-                  table_expression:
-                    table_reference:
-                      identifier: sales_eu
-                  alias_expression:
-                    keyword: AS
-                    identifier: s
-        - set_operator:
-          - keyword: UNION
-          - keyword: ALL
-        - select_statement:
-            select_clause:
-              keyword: SELECT
-              select_clause_element:
-                column_reference:
-                  identifier: customer
-            from_clause:
-              keyword: FROM
-              from_expression:
-                from_expression_element:
-                  table_expression:
-                    table_reference:
-                      identifier: sales_us
-                  alias_expression:
-                    keyword: AS
-                    identifier: s2
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          set_expression:
+          - select_statement:
+              select_clause:
+                keyword: SELECT
+                select_clause_element:
+                  column_reference:
+                    identifier: customer
+              from_clause:
+                keyword: FROM
+                from_expression:
+                  from_expression_element:
+                    table_expression:
+                      table_reference:
+                        identifier: sales_eu
+                    alias_expression:
+                      keyword: AS
+                      identifier: s
+          - set_operator:
+            - keyword: UNION
+            - keyword: ALL
+          - select_statement:
+              select_clause:
+                keyword: SELECT
+                select_clause_element:
+                  column_reference:
+                    identifier: customer
+              from_clause:
+                keyword: FROM
+                from_expression:
+                  from_expression_element:
+                    table_expression:
+                      table_reference:
+                        identifier: sales_us
+                    alias_expression:
+                      keyword: AS
+                      identifier: s2
+          end_bracket: )
       select_statement:
         select_clause:
           keyword: SELECT
diff --git a/test/fixtures/parser/ansi/select_s.yml b/test/fixtures/parser/ansi/select_s.yml
index 0b85404cf99..8fb0aaa79bc 100644
--- a/test/fixtures/parser/ansi/select_s.yml
+++ b/test/fixtures/parser/ansi/select_s.yml
@@ -13,110 +13,117 @@ file:
       - comma: ','
       - select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - column_reference:
-                identifier: count_18_24
-            - binary_operator: '*'
-            - column_reference:
-                identifier: bits
-            - array_accessor:
-                start_square_bracket: '['
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: OFFSET
-                    start_bracket: (
-                    expression:
-                      literal: '0'
-                    end_bracket: )
-                end_square_bracket: ']'
-            - binary_operator: +
-            - column_reference:
-                identifier: count_25_34
-            - binary_operator: '*'
-            - column_reference:
-                identifier: bits
-            - array_accessor:
-                start_square_bracket: '['
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: OFFSET
-                    start_bracket: (
-                    expression:
-                      literal: '1'
-                    end_bracket: )
-                end_square_bracket: ']'
-            - binary_operator: +
-            - column_reference:
-                identifier: count_35_44
-            - binary_operator: '*'
-            - column_reference:
-                identifier: bits
-            - array_accessor:
-                start_square_bracket: '['
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: OFFSET
-                    start_bracket: (
-                    expression:
-                      literal: '2'
-                    end_bracket: )
-                end_square_bracket: ']'
-            - binary_operator: +
-            - column_reference:
-                identifier: count_45_54
-            - binary_operator: '*'
-            - column_reference:
-                identifier: bits
-            - array_accessor:
-                start_square_bracket: '['
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: OFFSET
-                    start_bracket: (
-                    expression:
-                      literal: '3'
-                    end_bracket: )
-                end_square_bracket: ']'
-            - binary_operator: +
-            - column_reference:
-                identifier: count_55_64
-            - binary_operator: '*'
-            - column_reference:
-                identifier: bits
-            - array_accessor:
-                start_square_bracket: '['
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: OFFSET
-                    start_bracket: (
-                    expression:
-                      literal: '4'
-                    end_bracket: )
-                end_square_bracket: ']'
-            - binary_operator: +
-            - column_reference:
-                identifier: count_65_plus
-            - binary_operator: '*'
-            - column_reference:
-                identifier: bits
-            - array_accessor:
-                start_square_bracket: '['
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: OFFSET
-                    start_bracket: (
-                    expression:
-                      literal: '5'
-                    end_bracket: )
-                end_square_bracket: ']'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - column_reference:
+                  identifier: count_18_24
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: bits
+              - array_accessor:
+                  start_square_bracket: '['
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: OFFSET
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: '0'
+                        end_bracket: )
+                  end_square_bracket: ']'
+              - binary_operator: +
+              - column_reference:
+                  identifier: count_25_34
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: bits
+              - array_accessor:
+                  start_square_bracket: '['
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: OFFSET
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: '1'
+                        end_bracket: )
+                  end_square_bracket: ']'
+              - binary_operator: +
+              - column_reference:
+                  identifier: count_35_44
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: bits
+              - array_accessor:
+                  start_square_bracket: '['
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: OFFSET
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: '2'
+                        end_bracket: )
+                  end_square_bracket: ']'
+              - binary_operator: +
+              - column_reference:
+                  identifier: count_45_54
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: bits
+              - array_accessor:
+                  start_square_bracket: '['
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: OFFSET
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: '3'
+                        end_bracket: )
+                  end_square_bracket: ']'
+              - binary_operator: +
+              - column_reference:
+                  identifier: count_55_64
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: bits
+              - array_accessor:
+                  start_square_bracket: '['
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: OFFSET
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: '4'
+                        end_bracket: )
+                  end_square_bracket: ']'
+              - binary_operator: +
+              - column_reference:
+                  identifier: count_65_plus
+              - binary_operator: '*'
+              - column_reference:
+                  identifier: bits
+              - array_accessor:
+                  start_square_bracket: '['
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: OFFSET
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: '5'
+                        end_bracket: )
+                  end_square_bracket: ']'
+              end_bracket: )
             binary_operator: /
             column_reference:
               identifier: audience_size
diff --git a/test/fixtures/parser/ansi/select_simple_h.yml b/test/fixtures/parser/ansi/select_simple_h.yml
index c818ffd1824..b989e560817 100644
--- a/test/fixtures/parser/ansi/select_simple_h.yml
+++ b/test/fixtures/parser/ansi/select_simple_h.yml
@@ -6,37 +6,41 @@ file:
         select_clause_element:
           expression:
             function:
-            - function_name:
+              function_name:
                 function_name_identifier: dateadd
-            - start_bracket: (
-            - expression:
-                literal: "'day'"
-            - comma: ','
-            - expression:
-                function:
-                  function_name:
-                    function_name_identifier: row_number
-                  start_bracket: (
-                  end_bracket: )
-                  over_clause:
-                    keyword: OVER
-                    start_bracket: (
-                    window_specification:
-                      orderby_clause:
-                      - keyword: ORDER
-                      - keyword: BY
-                      - expression:
-                          function:
-                            function_name:
-                              function_name_identifier: seq8
-                            start_bracket: (
-                            end_bracket: )
-                      - keyword: asc
-                    end_bracket: )
-            - comma: ','
-            - expression:
-                literal: "'2014-01-01'"
-            - end_bracket: )
+              bracketed:
+              - start_bracket: (
+              - expression:
+                  literal: "'day'"
+              - comma: ','
+              - expression:
+                  function:
+                    function_name:
+                      function_name_identifier: row_number
+                    bracketed:
+                      start_bracket: (
+                      end_bracket: )
+                    over_clause:
+                      keyword: OVER
+                      bracketed:
+                        start_bracket: (
+                        window_specification:
+                          orderby_clause:
+                          - keyword: ORDER
+                          - keyword: BY
+                          - expression:
+                              function:
+                                function_name:
+                                  function_name_identifier: seq8
+                                bracketed:
+                                  start_bracket: (
+                                  end_bracket: )
+                          - keyword: asc
+                        end_bracket: )
+              - comma: ','
+              - expression:
+                  literal: "'2014-01-01'"
+              - end_bracket: )
             cast_expression:
               casting_operator: '::'
               data_type:
diff --git a/test/fixtures/parser/ansi/select_simple_i.yml b/test/fixtures/parser/ansi/select_simple_i.yml
index 7e5590e4b0b..947b8a4cdd8 100644
--- a/test/fixtures/parser/ansi/select_simple_i.yml
+++ b/test/fixtures/parser/ansi/select_simple_i.yml
@@ -83,6 +83,7 @@ file:
               alias_expression:
                 identifier: bar
           - keyword: USING
-          - start_bracket: (
-          - identifier: b
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              identifier: b
+              end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_t.yml b/test/fixtures/parser/ansi/select_t.yml
index 92f163e8a2b..2ed35c1da09 100644
--- a/test/fixtures/parser/ansi/select_t.yml
+++ b/test/fixtures/parser/ansi/select_t.yml
@@ -20,54 +20,55 @@ file:
           - keyword: JOIN
           - from_expression_element:
               table_expression:
-                start_bracket: (
-                set_expression:
-                - select_statement:
-                    select_clause:
-                      keyword: SELECT
-                      select_clause_element:
-                        wildcard_expression:
-                          wildcard_identifier:
-                            star: '*'
-                    from_clause:
-                      keyword: FROM
-                      from_expression:
-                        from_expression_element:
-                          table_expression:
-                            table_reference:
-                              identifier: Table_B
-                    where_clause:
-                      keyword: WHERE
-                      expression:
-                        column_reference:
-                          identifier: COL_2
-                        comparison_operator: '='
-                        literal: "'B'"
-                - set_operator:
-                  - keyword: UNION
-                  - keyword: ALL
-                - select_statement:
-                    select_clause:
-                      keyword: SELECT
-                      select_clause_element:
-                        wildcard_expression:
-                          wildcard_identifier:
-                            star: '*'
-                    from_clause:
-                      keyword: FROM
-                      from_expression:
-                        from_expression_element:
-                          table_expression:
-                            table_reference:
-                              identifier: TABLE_C
-                    where_clause:
-                      keyword: WHERE
-                      expression:
-                        column_reference:
-                          identifier: COL_1
-                        comparison_operator: '='
-                        literal: '0'
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  set_expression:
+                  - select_statement:
+                      select_clause:
+                        keyword: SELECT
+                        select_clause_element:
+                          wildcard_expression:
+                            wildcard_identifier:
+                              star: '*'
+                      from_clause:
+                        keyword: FROM
+                        from_expression:
+                          from_expression_element:
+                            table_expression:
+                              table_reference:
+                                identifier: Table_B
+                      where_clause:
+                        keyword: WHERE
+                        expression:
+                          column_reference:
+                            identifier: COL_2
+                          comparison_operator: '='
+                          literal: "'B'"
+                  - set_operator:
+                    - keyword: UNION
+                    - keyword: ALL
+                  - select_statement:
+                      select_clause:
+                        keyword: SELECT
+                        select_clause_element:
+                          wildcard_expression:
+                            wildcard_identifier:
+                              star: '*'
+                      from_clause:
+                        keyword: FROM
+                        from_expression:
+                          from_expression_element:
+                            table_expression:
+                              table_reference:
+                                identifier: TABLE_C
+                      where_clause:
+                        keyword: WHERE
+                        expression:
+                          column_reference:
+                            identifier: COL_1
+                          comparison_operator: '='
+                          literal: '0'
+                  end_bracket: )
           - join_on_condition:
               keyword: 'ON'
               expression:
diff --git a/test/fixtures/parser/ansi/select_u.yml b/test/fixtures/parser/ansi/select_u.yml
index b5456b164d1..71bc2d7ec36 100644
--- a/test/fixtures/parser/ansi/select_u.yml
+++ b/test/fixtures/parser/ansi/select_u.yml
@@ -5,16 +5,17 @@ file:
         keyword: select
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: substring
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: a
-          - keyword: from
-          - expression:
-              literal: "'abc'"
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: a
+            - keyword: from
+            - expression:
+                literal: "'abc'"
+            - end_bracket: )
           alias_expression:
             keyword: as
             identifier: b
diff --git a/test/fixtures/parser/ansi/select_v.yml b/test/fixtures/parser/ansi/select_v.yml
index 6f14822c4ea..f0cc9b05c8f 100644
--- a/test/fixtures/parser/ansi/select_v.yml
+++ b/test/fixtures/parser/ansi/select_v.yml
@@ -5,38 +5,40 @@ file:
       common_table_expression:
         identifier: counter
         keyword: AS
-        start_bracket: (
-        with_compound_statement:
-          keyword: WITH
-          common_table_expression:
-            identifier: ladder
-            keyword: AS
-            start_bracket: (
+        bracketed:
+          start_bracket: (
+          with_compound_statement:
+            keyword: WITH
+            common_table_expression:
+              identifier: ladder
+              keyword: AS
+              bracketed:
+                start_bracket: (
+                select_statement:
+                  select_clause:
+                    keyword: SELECT
+                    select_clause_element:
+                      literal: '1'
+                end_bracket: )
             select_statement:
               select_clause:
                 keyword: SELECT
                 select_clause_element:
-                  literal: '1'
-            end_bracket: )
-          select_statement:
-            select_clause:
-              keyword: SELECT
-              select_clause_element:
-                wildcard_expression:
-                  wildcard_identifier:
-                    star: '*'
-            from_clause:
-              keyword: FROM
-              from_expression:
-                from_expression_element:
-                  table_expression:
-                    table_reference:
-                      identifier: ladder
-            orderby_clause:
-            - keyword: ORDER
-            - keyword: BY
-            - literal: '1'
-        end_bracket: )
+                  wildcard_expression:
+                    wildcard_identifier:
+                      star: '*'
+              from_clause:
+                keyword: FROM
+                from_expression:
+                  from_expression_element:
+                    table_expression:
+                      table_reference:
+                        identifier: ladder
+              orderby_clause:
+              - keyword: ORDER
+              - keyword: BY
+              - literal: '1'
+          end_bracket: )
       select_statement:
         select_clause:
           keyword: SELECT
diff --git a/test/fixtures/parser/ansi/select_where_in_unnest.yml b/test/fixtures/parser/ansi/select_where_in_unnest.yml
index b629de6f9b2..a225ccc6732 100644
--- a/test/fixtures/parser/ansi/select_where_in_unnest.yml
+++ b/test/fixtures/parser/ansi/select_where_in_unnest.yml
@@ -21,10 +21,11 @@ file:
           function:
             function_name:
               function_name_identifier: UNNEST
-            start_bracket: (
-            expression:
-              column_reference:
-              - identifier: t
-              - dot: .
-              - identifier: c
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                - identifier: t
+                - dot: .
+                - identifier: c
+              end_bracket: )
diff --git a/test/fixtures/parser/ansi/select_with_a.yml b/test/fixtures/parser/ansi/select_with_a.yml
index 296204eafa4..f1c062d0512 100644
--- a/test/fixtures/parser/ansi/select_with_a.yml
+++ b/test/fixtures/parser/ansi/select_with_a.yml
@@ -5,21 +5,22 @@ file:
       common_table_expression:
         identifier: cte
         keyword: as
-        start_bracket: (
-        select_statement:
-          select_clause:
-            keyword: select
-            select_clause_element:
-              column_reference:
-                identifier: a
-          from_clause:
-            keyword: from
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: tbla
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+              keyword: select
+              select_clause_element:
+                column_reference:
+                  identifier: a
+            from_clause:
+              keyword: from
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: tbla
+          end_bracket: )
       select_statement:
         select_clause:
           keyword: select
diff --git a/test/fixtures/parser/ansi/select_with_b.yml b/test/fixtures/parser/ansi/select_with_b.yml
index ca1131f43ba..3704001aa4e 100644
--- a/test/fixtures/parser/ansi/select_with_b.yml
+++ b/test/fixtures/parser/ansi/select_with_b.yml
@@ -5,29 +5,30 @@ file:
       common_table_expression:
         identifier: blah
         keyword: AS
-        start_bracket: (
-        select_statement:
-          select_clause:
-          - keyword: select
-          - select_clause_element:
-              column_reference:
-                identifier: x
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: y
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: z
-          from_clause:
-            keyword: FROM
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: foo
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+            - keyword: select
+            - select_clause_element:
+                column_reference:
+                  identifier: x
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: y
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: z
+            from_clause:
+              keyword: FROM
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: foo
+          end_bracket: )
       select_statement:
         select_clause:
         - keyword: select
diff --git a/test/fixtures/parser/ansi/set_order_by_complex.yml b/test/fixtures/parser/ansi/set_order_by_complex.yml
index db625423499..4a5baf5cdc4 100644
--- a/test/fixtures/parser/ansi/set_order_by_complex.yml
+++ b/test/fixtures/parser/ansi/set_order_by_complex.yml
@@ -1,55 +1,57 @@
 file:
   statement:
     set_expression:
-    - start_bracket: (
-    - select_statement:
-        select_clause:
-          keyword: SELECT
-          select_clause_element:
-            wildcard_expression:
-              wildcard_identifier:
-                star: '*'
-        from_clause:
-          keyword: FROM
-          from_expression:
-            from_expression_element:
-              table_expression:
-                table_reference:
-                  identifier: a
-        orderby_clause:
-        - keyword: ORDER
-        - keyword: BY
-        - literal: '1'
-        limit_clause:
-          keyword: LIMIT
-          literal: '1'
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        select_statement:
+          select_clause:
+            keyword: SELECT
+            select_clause_element:
+              wildcard_expression:
+                wildcard_identifier:
+                  star: '*'
+          from_clause:
+            keyword: FROM
+            from_expression:
+              from_expression_element:
+                table_expression:
+                  table_reference:
+                    identifier: a
+          orderby_clause:
+          - keyword: ORDER
+          - keyword: BY
+          - literal: '1'
+          limit_clause:
+            keyword: LIMIT
+            literal: '1'
+        end_bracket: )
     - set_operator:
       - keyword: UNION
       - keyword: ALL
-    - start_bracket: (
-    - select_statement:
-        select_clause:
-          keyword: SELECT
-          select_clause_element:
-            wildcard_expression:
-              wildcard_identifier:
-                star: '*'
-        from_clause:
-          keyword: FROM
-          from_expression:
-            from_expression_element:
-              table_expression:
-                table_reference:
-                  identifier: b
-        orderby_clause:
-        - keyword: ORDER
-        - keyword: BY
-        - literal: '1'
-        limit_clause:
-          keyword: LIMIT
-          literal: '1'
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        select_statement:
+          select_clause:
+            keyword: SELECT
+            select_clause_element:
+              wildcard_expression:
+                wildcard_identifier:
+                  star: '*'
+          from_clause:
+            keyword: FROM
+            from_expression:
+              from_expression_element:
+                table_expression:
+                  table_reference:
+                    identifier: b
+          orderby_clause:
+          - keyword: ORDER
+          - keyword: BY
+          - literal: '1'
+          limit_clause:
+            keyword: LIMIT
+            literal: '1'
+        end_bracket: )
     - orderby_clause:
       - keyword: ORDER
       - keyword: BY
diff --git a/test/fixtures/parser/ansi/table_expression.yml b/test/fixtures/parser/ansi/table_expression.yml
index 4b0ec2277fc..b70011d57df 100644
--- a/test/fixtures/parser/ansi/table_expression.yml
+++ b/test/fixtures/parser/ansi/table_expression.yml
@@ -17,19 +17,21 @@ file:
               function:
                 function_name:
                   function_name_identifier: UNNEST
-                start_bracket: (
-                expression:
-                  function:
-                  - function_name:
-                      function_name_identifier: GENERATE_ARRAY
-                  - start_bracket: (
-                  - expression:
-                      literal: '1'
-                  - comma: ','
-                  - expression:
-                      literal: '53'
-                  - end_bracket: )
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: GENERATE_ARRAY
+                      bracketed:
+                      - start_bracket: (
+                      - expression:
+                          literal: '1'
+                      - comma: ','
+                      - expression:
+                          literal: '53'
+                      - end_bracket: )
+                  end_bracket: )
             alias_expression:
               keyword: AS
               identifier: y
diff --git a/test/fixtures/parser/bigquery/array_agg_distinct_ignore_nulls.yml b/test/fixtures/parser/bigquery/array_agg_distinct_ignore_nulls.yml
index 9cd8a5e0e50..d1b9b9a2326 100644
--- a/test/fixtures/parser/bigquery/array_agg_distinct_ignore_nulls.yml
+++ b/test/fixtures/parser/bigquery/array_agg_distinct_ignore_nulls.yml
@@ -5,16 +5,17 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: ARRAY_AGG
-          - start_bracket: (
-          - keyword: DISTINCT
-          - expression:
-              column_reference:
-                identifier: x
-          - keyword: IGNORE
-          - keyword: NULLS
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - keyword: DISTINCT
+            - expression:
+                column_reference:
+                  identifier: x
+            - keyword: IGNORE
+            - keyword: NULLS
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: array_agg
diff --git a/test/fixtures/parser/bigquery/array_agg_ignore_nulls.yml b/test/fixtures/parser/bigquery/array_agg_ignore_nulls.yml
index df96234db8c..7b66a02c9f5 100644
--- a/test/fixtures/parser/bigquery/array_agg_ignore_nulls.yml
+++ b/test/fixtures/parser/bigquery/array_agg_ignore_nulls.yml
@@ -5,15 +5,16 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: ARRAY_AGG
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: x
-          - keyword: IGNORE
-          - keyword: NULLS
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: x
+            - keyword: IGNORE
+            - keyword: NULLS
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: array_agg
diff --git a/test/fixtures/parser/bigquery/array_agg_respect_nulls.yml b/test/fixtures/parser/bigquery/array_agg_respect_nulls.yml
index 8a99d14cb25..47aab4197cc 100644
--- a/test/fixtures/parser/bigquery/array_agg_respect_nulls.yml
+++ b/test/fixtures/parser/bigquery/array_agg_respect_nulls.yml
@@ -5,15 +5,16 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: ARRAY_AGG
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: x
-          - keyword: RESPECT
-          - keyword: NULLS
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: x
+            - keyword: RESPECT
+            - keyword: NULLS
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: array_agg
diff --git a/test/fixtures/parser/bigquery/create_js_function_complex_types.yml b/test/fixtures/parser/bigquery/create_js_function_complex_types.yml
index 2e8a4562239..a5532dc76a2 100644
--- a/test/fixtures/parser/bigquery/create_js_function_complex_types.yml
+++ b/test/fixtures/parser/bigquery/create_js_function_complex_types.yml
@@ -7,54 +7,30 @@ file:
     - function_name:
         function_name_identifier: qs
     - base:
-      - start_bracket: (
-      - parameter: foo1
-      - data_type:
-          data_type_identifier: INT64
-      - comma: ','
-      - parameter: foo2
-      - data_type:
-          keyword: ARRAY
-          start_angle_bracket: <
-          data_type:
-            data_type_identifier: STRING
-          end_angle_bracket: '>'
-      - comma: ','
-      - parameter: foo3
-      - data_type:
-          keyword: STRUCT
-          start_angle_bracket: <
-          parameter: x
-          data_type:
-            data_type_identifier: INT64
-          end_angle_bracket: '>'
-      - comma: ','
-      - parameter: foo4
-      - data_type:
-        - keyword: STRUCT
-        - start_angle_bracket: <
-        - parameter: x
+        bracketed:
+        - start_bracket: (
+        - parameter: foo1
         - data_type:
             data_type_identifier: INT64
         - comma: ','
-        - parameter: y
-        - data_type:
-            data_type_identifier: INT64
-        - end_angle_bracket: '>'
-      - comma: ','
-      - parameter: foo5
-      - data_type:
-        - keyword: STRUCT
-        - start_angle_bracket: <
-        - parameter: a
+        - parameter: foo2
         - data_type:
             keyword: ARRAY
             start_angle_bracket: <
             data_type:
-              data_type_identifier: FLOAT
+              data_type_identifier: STRING
+            end_angle_bracket: '>'
+        - comma: ','
+        - parameter: foo3
+        - data_type:
+            keyword: STRUCT
+            start_angle_bracket: <
+            parameter: x
+            data_type:
+              data_type_identifier: INT64
             end_angle_bracket: '>'
         - comma: ','
-        - parameter: b
+        - parameter: foo4
         - data_type:
           - keyword: STRUCT
           - start_angle_bracket: <
@@ -66,8 +42,33 @@ file:
           - data_type:
               data_type_identifier: INT64
           - end_angle_bracket: '>'
-        - end_angle_bracket: '>'
-      - end_bracket: )
+        - comma: ','
+        - parameter: foo5
+        - data_type:
+          - keyword: STRUCT
+          - start_angle_bracket: <
+          - parameter: a
+          - data_type:
+              keyword: ARRAY
+              start_angle_bracket: <
+              data_type:
+                data_type_identifier: FLOAT
+              end_angle_bracket: '>'
+          - comma: ','
+          - parameter: b
+          - data_type:
+            - keyword: STRUCT
+            - start_angle_bracket: <
+            - parameter: x
+            - data_type:
+                data_type_identifier: INT64
+            - comma: ','
+            - parameter: y
+            - data_type:
+                data_type_identifier: INT64
+            - end_angle_bracket: '>'
+          - end_angle_bracket: '>'
+        - end_bracket: )
     - keyword: RETURNS
     - data_type:
         keyword: STRUCT
diff --git a/test/fixtures/parser/bigquery/create_js_function_options_library_array.yml b/test/fixtures/parser/bigquery/create_js_function_options_library_array.yml
index fb408e1f215..ff5f3572cfd 100644
--- a/test/fixtures/parser/bigquery/create_js_function_options_library_array.yml
+++ b/test/fixtures/parser/bigquery/create_js_function_options_library_array.yml
@@ -7,11 +7,12 @@ file:
     - function_name:
         function_name_identifier: parseTopSellers
     - base:
-        start_bracket: (
-        parameter: arr_str
-        data_type:
-          data_type_identifier: STRING
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          parameter: arr_str
+          data_type:
+            data_type_identifier: STRING
+          end_bracket: )
     - keyword: RETURNS
     - data_type:
         keyword: ARRAY
@@ -32,14 +33,15 @@ file:
       - keyword: LANGUAGE
       - parameter: js
       - keyword: OPTIONS
-      - start_bracket: (
-      - parameter: library
-      - comparison_operator: '='
-      - start_square_bracket: '['
-      - raw: '"gs://my-bucket/path/to/lib1.js"'
-      - comma: ','
-      - raw: '"gs://my-bucket/path/to/lib2.js"'
-      - end_square_bracket: ']'
-      - end_bracket: )
+      - bracketed:
+        - start_bracket: (
+        - parameter: library
+        - comparison_operator: '='
+        - start_square_bracket: '['
+        - raw: '"gs://my-bucket/path/to/lib1.js"'
+        - comma: ','
+        - raw: '"gs://my-bucket/path/to/lib2.js"'
+        - end_square_bracket: ']'
+        - end_bracket: )
       - keyword: AS
       - literal: "\"\"\"\n    CODE GOES HERE\n\"\"\""
diff --git a/test/fixtures/parser/bigquery/create_js_function_simple.yml b/test/fixtures/parser/bigquery/create_js_function_simple.yml
index 5548b62f00a..32cba08100a 100644
--- a/test/fixtures/parser/bigquery/create_js_function_simple.yml
+++ b/test/fixtures/parser/bigquery/create_js_function_simple.yml
@@ -6,11 +6,12 @@ file:
     - function_name:
         function_name_identifier: qs
     - base:
-        start_bracket: (
-        parameter: y
-        data_type:
-          data_type_identifier: STRING
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          parameter: y
+          data_type:
+            data_type_identifier: STRING
+          end_bracket: )
     - base:
       - keyword: LANGUAGE
       - parameter: js
diff --git a/test/fixtures/parser/bigquery/create_or_replace_sql_function_any_type.yml b/test/fixtures/parser/bigquery/create_or_replace_sql_function_any_type.yml
index 52bac05f747..ea08abf2aed 100644
--- a/test/fixtures/parser/bigquery/create_or_replace_sql_function_any_type.yml
+++ b/test/fixtures/parser/bigquery/create_or_replace_sql_function_any_type.yml
@@ -8,64 +8,66 @@ file:
     - function_name:
         function_name_identifier: qs
     - base:
-      - start_bracket: (
-      - parameter: y
-      - keyword: ANY
-      - keyword: TYPE
-      - end_bracket: )
+        bracketed:
+        - start_bracket: (
+        - parameter: y
+        - keyword: ANY
+        - keyword: TYPE
+        - end_bracket: )
     - base:
         keyword: AS
-        start_bracket: (
-        expression:
-          case_expression:
-          - keyword: CASE
-          - keyword: WHEN
-          - expression:
-              column_reference:
-                identifier: y
-              comparison_operator: '='
-              literal: '1'
-          - keyword: THEN
-          - expression:
-              literal: "'low'"
-          - keyword: WHEN
-          - expression:
-              column_reference:
-                identifier: y
-              comparison_operator: '='
-              literal: '2'
-          - keyword: THEN
-          - expression:
-              literal: "'midlow'"
-          - keyword: WHEN
-          - expression:
-              column_reference:
-                identifier: y
-              comparison_operator: '='
-              literal: '3'
-          - keyword: THEN
-          - expression:
-              literal: "'mid'"
-          - keyword: WHEN
-          - expression:
-              column_reference:
-                identifier: y
-              comparison_operator: '='
-              literal: '4'
-          - keyword: THEN
-          - expression:
-              literal: "'midhigh'"
-          - keyword: WHEN
-          - expression:
-              column_reference:
-                identifier: y
-              comparison_operator: '='
-              literal: '5'
-          - keyword: THEN
-          - expression:
-              literal: "'high'"
-          - keyword: ELSE
-          - expression:
-              literal: '"unknown"'
-          - keyword: END
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          expression:
+            case_expression:
+            - keyword: CASE
+            - keyword: WHEN
+            - expression:
+                column_reference:
+                  identifier: y
+                comparison_operator: '='
+                literal: '1'
+            - keyword: THEN
+            - expression:
+                literal: "'low'"
+            - keyword: WHEN
+            - expression:
+                column_reference:
+                  identifier: y
+                comparison_operator: '='
+                literal: '2'
+            - keyword: THEN
+            - expression:
+                literal: "'midlow'"
+            - keyword: WHEN
+            - expression:
+                column_reference:
+                  identifier: y
+                comparison_operator: '='
+                literal: '3'
+            - keyword: THEN
+            - expression:
+                literal: "'mid'"
+            - keyword: WHEN
+            - expression:
+                column_reference:
+                  identifier: y
+                comparison_operator: '='
+                literal: '4'
+            - keyword: THEN
+            - expression:
+                literal: "'midhigh'"
+            - keyword: WHEN
+            - expression:
+                column_reference:
+                  identifier: y
+                comparison_operator: '='
+                literal: '5'
+            - keyword: THEN
+            - expression:
+                literal: "'high'"
+            - keyword: ELSE
+            - expression:
+                literal: '"unknown"'
+            - keyword: END
+          end_bracket: )
diff --git a/test/fixtures/parser/bigquery/create_temp_function_with_select.yml b/test/fixtures/parser/bigquery/create_temp_function_with_select.yml
index 0d7386c43b0..cc9b44aa814 100644
--- a/test/fixtures/parser/bigquery/create_temp_function_with_select.yml
+++ b/test/fixtures/parser/bigquery/create_temp_function_with_select.yml
@@ -7,53 +7,58 @@ file:
     - function_name:
         function_name_identifier: URLDECODE
     - base:
-        start_bracket: (
-        parameter: url
-        data_type:
-          data_type_identifier: STRING
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          parameter: url
+          data_type:
+            data_type_identifier: STRING
+          end_bracket: )
     - keyword: RETURNS
     - data_type:
         data_type_identifier: STRING
     - base:
         keyword: AS
-        start_bracket: (
-        expression:
+        bracketed:
           start_bracket: (
           expression:
-            select_statement:
-              select_clause:
-                keyword: SELECT
-                select_clause_element:
-                  literal: '1'
-              from_clause:
-                keyword: FROM
-                from_expression:
-                  from_expression_element:
-                  - table_expression:
-                      function:
-                        function_name:
-                          function_name_identifier: UNNEST
-                        start_bracket: (
-                        expression:
+            bracketed:
+              start_bracket: (
+              expression:
+                select_statement:
+                  select_clause:
+                    keyword: SELECT
+                    select_clause_element:
+                      literal: '1'
+                  from_clause:
+                    keyword: FROM
+                    from_expression:
+                      from_expression_element:
+                      - table_expression:
                           function:
-                          - function_name:
-                              function_name_identifier: REGEXP_EXTRACT_ALL
-                          - start_bracket: (
-                          - expression:
-                              column_reference:
-                                identifier: url
-                          - comma: ','
-                          - expression:
-                              literal: r"%[0-9a-fA-F]{2}|[^%]+"
-                          - end_bracket: )
-                        end_bracket: )
-                  - alias_expression:
-                      keyword: AS
-                      identifier: y
-                  - keyword: WITH
-                  - keyword: OFFSET
-                  - keyword: AS
-                  - identifier: i
+                            function_name:
+                              function_name_identifier: UNNEST
+                            bracketed:
+                              start_bracket: (
+                              expression:
+                                function:
+                                  function_name:
+                                    function_name_identifier: REGEXP_EXTRACT_ALL
+                                  bracketed:
+                                  - start_bracket: (
+                                  - expression:
+                                      column_reference:
+                                        identifier: url
+                                  - comma: ','
+                                  - expression:
+                                      literal: r"%[0-9a-fA-F]{2}|[^%]+"
+                                  - end_bracket: )
+                              end_bracket: )
+                      - alias_expression:
+                          keyword: AS
+                          identifier: y
+                      - keyword: WITH
+                      - keyword: OFFSET
+                      - keyword: AS
+                      - identifier: i
+              end_bracket: )
           end_bracket: )
-        end_bracket: )
diff --git a/test/fixtures/parser/bigquery/interval_function.yml b/test/fixtures/parser/bigquery/interval_function.yml
index fb0d9722210..d8f1d5a0a05 100644
--- a/test/fixtures/parser/bigquery/interval_function.yml
+++ b/test/fixtures/parser/bigquery/interval_function.yml
@@ -7,96 +7,102 @@ file:
           function:
             function_name:
               function_name_identifier: TIMESTAMP_TRUNC
-            start_bracket: (
-            expression:
-              function:
-              - function_name:
-                  function_name_identifier: TIMESTAMP_ADD
-              - start_bracket: (
-              - expression:
-                  column_reference:
-                  - identifier: session_start
-                  - dot: .
-                  - identifier: eventTimestamp
-              - comma: ','
-              - expression:
-                  interval_expression:
-                    keyword: INTERVAL
-                    expression:
-                      function:
-                        function_name:
-                          function_name_identifier: cast
-                        start_bracket: (
+            bracketed:
+              start_bracket: (
+              expression:
+                function:
+                  function_name:
+                    function_name_identifier: TIMESTAMP_ADD
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      column_reference:
+                      - identifier: session_start
+                      - dot: .
+                      - identifier: eventTimestamp
+                  - comma: ','
+                  - expression:
+                      interval_expression:
+                        keyword: INTERVAL
                         expression:
                           function:
-                          - function_name:
-                              function_name_identifier: TIMESTAMP_DIFF
-                          - start_bracket: (
-                          - expression:
-                              column_reference:
-                              - identifier: session_end
-                              - dot: .
-                              - identifier: eventTimestamp
-                          - comma: ','
-                          - expression:
-                              column_reference:
-                              - identifier: session_start
-                              - dot: .
-                              - identifier: eventTimestamp
-                          - comma: ','
-                          - date_part: SECOND
-                          - end_bracket: )
-                          binary_operator: /
-                          literal: '2'
-                        keyword: AS
-                        data_type:
-                          data_type_identifier: int64
-                        end_bracket: )
-                    date_part: second
-              - end_bracket: )
-            comma: ','
-            date_part: HOUR
-            end_bracket: )
+                            function_name:
+                              function_name_identifier: cast
+                            bracketed:
+                              start_bracket: (
+                              expression:
+                                function:
+                                  function_name:
+                                    function_name_identifier: TIMESTAMP_DIFF
+                                  bracketed:
+                                  - start_bracket: (
+                                  - expression:
+                                      column_reference:
+                                      - identifier: session_end
+                                      - dot: .
+                                      - identifier: eventTimestamp
+                                  - comma: ','
+                                  - expression:
+                                      column_reference:
+                                      - identifier: session_start
+                                      - dot: .
+                                      - identifier: eventTimestamp
+                                  - comma: ','
+                                  - date_part: SECOND
+                                  - end_bracket: )
+                                binary_operator: /
+                                literal: '2'
+                              keyword: AS
+                              data_type:
+                                data_type_identifier: int64
+                              end_bracket: )
+                        date_part: second
+                  - end_bracket: )
+              comma: ','
+              date_part: HOUR
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: avgAtHour
       - comma: ','
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: TIME_ADD
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: time1
-          - comma: ','
-          - expression:
-              interval_expression:
-                keyword: INTERVAL
-                expression:
-                  literal: '10'
-                date_part: MINUTE
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: time1
+            - comma: ','
+            - expression:
+                interval_expression:
+                  keyword: INTERVAL
+                  expression:
+                    literal: '10'
+                  date_part: MINUTE
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: after
       - comma: ','
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: DATE_SUB
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: time2
-          - comma: ','
-          - expression:
-              interval_expression:
-                keyword: INTERVAL
-                expression:
-                  literal: '5'
-                date_part: YEAR
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                  identifier: time2
+            - comma: ','
+            - expression:
+                interval_expression:
+                  keyword: INTERVAL
+                  expression:
+                    literal: '5'
+                  date_part: YEAR
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: before
diff --git a/test/fixtures/parser/bigquery/select_1_gt_0.yml b/test/fixtures/parser/bigquery/select_1_gt_0.yml
index ac9168a068c..cb9ebf18206 100644
--- a/test/fixtures/parser/bigquery/select_1_gt_0.yml
+++ b/test/fixtures/parser/bigquery/select_1_gt_0.yml
@@ -5,9 +5,10 @@ file:
         keyword: SELECT
         select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - literal: '1'
-            - comparison_operator: '>'
-            - literal: '0'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - literal: '1'
+              - comparison_operator: '>'
+              - literal: '0'
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_1_lt_0.yml b/test/fixtures/parser/bigquery/select_1_lt_0.yml
index fe3b2b1401b..1cbfadaf09b 100644
--- a/test/fixtures/parser/bigquery/select_1_lt_0.yml
+++ b/test/fixtures/parser/bigquery/select_1_lt_0.yml
@@ -5,9 +5,10 @@ file:
         keyword: SELECT
         select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - literal: '1'
-            - comparison_operator: <
-            - literal: '0'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - literal: '1'
+              - comparison_operator: <
+              - literal: '0'
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_datetime.yml b/test/fixtures/parser/bigquery/select_datetime.yml
index e19260a2fea..4653b63ea88 100644
--- a/test/fixtures/parser/bigquery/select_datetime.yml
+++ b/test/fixtures/parser/bigquery/select_datetime.yml
@@ -19,15 +19,16 @@ file:
           function:
             function_name:
               function_name_identifier: EXTRACT
-            start_bracket: (
-            date_part: DATE
-            keyword: FROM
-            expression:
-              column_reference:
-              - identifier: gmv
-              - dot: .
-              - identifier: order_created_at
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              date_part: DATE
+              keyword: FROM
+              expression:
+                column_reference:
+                - identifier: gmv
+                - dot: .
+                - identifier: order_created_at
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: order_dt
@@ -52,29 +53,32 @@ file:
           function:
             function_name:
               function_name_identifier: DATE_TRUNC
-            start_bracket: (
-            expression:
-              function:
-              - function_name:
-                  function_name_identifier: DATE_SUB
-              - start_bracket: (
-              - expression:
-                  function:
-                    function_name:
-                      function_name_identifier: CURRENT_DATE
-                    start_bracket: (
-                    end_bracket: )
-              - comma: ','
-              - expression:
-                  interval_expression:
-                    keyword: INTERVAL
-                    expression:
-                      literal: '2'
-                    date_part: YEAR
-              - end_bracket: )
-            comma: ','
-            date_part: year
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                function:
+                  function_name:
+                    function_name_identifier: DATE_SUB
+                  bracketed:
+                  - start_bracket: (
+                  - expression:
+                      function:
+                        function_name:
+                          function_name_identifier: CURRENT_DATE
+                        bracketed:
+                          start_bracket: (
+                          end_bracket: )
+                  - comma: ','
+                  - expression:
+                      interval_expression:
+                        keyword: INTERVAL
+                        expression:
+                          literal: '2'
+                        date_part: YEAR
+                  - end_bracket: )
+              comma: ','
+              date_part: year
+              end_bracket: )
       limit_clause:
         keyword: LIMIT
         literal: '1'
diff --git a/test/fixtures/parser/bigquery/select_example.yml b/test/fixtures/parser/bigquery/select_example.yml
index 1711944ee70..f80ccde11a3 100644
--- a/test/fixtures/parser/bigquery/select_example.yml
+++ b/test/fixtures/parser/bigquery/select_example.yml
@@ -5,222 +5,235 @@ file:
     - common_table_expression:
         identifier: age_buckets_bit_array
         keyword: AS
-        start_bracket: (
-        select_statement:
-          select_clause:
-          - keyword: SELECT
-          - select_clause_element:
-              column_reference:
-                identifier: bucket_id
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: num_ranges
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: min_age
-          - comma: ','
-          - select_clause_element:
-              function:
-                function_name:
-                  function_name_identifier: ARRAY
-                start_bracket: (
-                expression:
-                  select_statement:
-                    select_clause:
-                      keyword: SELECT
-                      select_clause_element:
-                        function:
-                          function_name:
-                            function_name_identifier: CAST
-                          start_bracket: (
-                          expression:
-                            column_reference:
-                              identifier: num
-                          keyword: AS
-                          data_type:
-                            data_type_identifier: INT64
-                          end_bracket: )
-                    from_clause:
-                      keyword: FROM
-                      from_expression:
-                        from_expression_element:
-                          table_expression:
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+            - keyword: SELECT
+            - select_clause_element:
+                column_reference:
+                  identifier: bucket_id
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: num_ranges
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: min_age
+            - comma: ','
+            - select_clause_element:
+                function:
+                  function_name:
+                    function_name_identifier: ARRAY
+                  bracketed:
+                    start_bracket: (
+                    expression:
+                      select_statement:
+                        select_clause:
+                          keyword: SELECT
+                          select_clause_element:
                             function:
                               function_name:
-                                function_name_identifier: UNNEST
-                              start_bracket: (
-                              expression:
+                                function_name_identifier: CAST
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  column_reference:
+                                    identifier: num
+                                keyword: AS
+                                data_type:
+                                  data_type_identifier: INT64
+                                end_bracket: )
+                        from_clause:
+                          keyword: FROM
+                          from_expression:
+                            from_expression_element:
+                              table_expression:
                                 function:
-                                - function_name:
-                                    function_name_identifier: SPLIT
-                                - start_bracket: (
-                                - expression:
-                                    column_reference:
-                                      identifier: binary
-                                - comma: ','
-                                - expression:
-                                    literal: "''"
-                                - end_bracket: )
-                              end_bracket: )
-                          alias_expression:
-                            keyword: AS
-                            identifier: num
-                end_bracket: )
-              alias_expression:
-                keyword: AS
-                identifier: bits
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: age_label
-          from_clause:
-            keyword: FROM
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: age_buckets
-        end_bracket: )
+                                  function_name:
+                                    function_name_identifier: UNNEST
+                                  bracketed:
+                                    start_bracket: (
+                                    expression:
+                                      function:
+                                        function_name:
+                                          function_name_identifier: SPLIT
+                                        bracketed:
+                                        - start_bracket: (
+                                        - expression:
+                                            column_reference:
+                                              identifier: binary
+                                        - comma: ','
+                                        - expression:
+                                            literal: "''"
+                                        - end_bracket: )
+                                    end_bracket: )
+                              alias_expression:
+                                keyword: AS
+                                identifier: num
+                    end_bracket: )
+                alias_expression:
+                  keyword: AS
+                  identifier: bits
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: age_label
+            from_clause:
+              keyword: FROM
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    table_reference:
+                      identifier: age_buckets
+          end_bracket: )
     - comma: ','
     - common_table_expression:
         identifier: bucket_abundance
         keyword: AS
-        start_bracket: (
-        select_statement:
-          select_clause:
-            keyword: SELECT
-            select_clause_element:
-              expression:
-                function:
-                  function_name:
-                    function_name_identifier: bucket_id
-                  start_bracket: (
-                  expression:
-                  - column_reference:
-                      identifier: count_18_24
-                  - binary_operator: '*'
-                  - column_reference:
-                      identifier: bits
-                  - array_accessor:
-                      start_square_bracket: '['
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+              keyword: SELECT
+              select_clause_element:
+                expression:
+                  function:
+                    function_name:
+                      function_name_identifier: bucket_id
+                    bracketed:
+                      start_bracket: (
                       expression:
-                        function:
-                          function_name:
-                            function_name_identifier: OFFSET
-                          start_bracket: (
+                      - column_reference:
+                          identifier: count_18_24
+                      - binary_operator: '*'
+                      - column_reference:
+                          identifier: bits
+                      - array_accessor:
+                          start_square_bracket: '['
                           expression:
-                            literal: '0'
-                          end_bracket: )
-                      end_square_bracket: ']'
-                  - binary_operator: +
-                  - column_reference:
-                      identifier: count_25_34
-                  - binary_operator: '*'
-                  - column_reference:
-                      identifier: bits
-                  - array_accessor:
-                      start_square_bracket: '['
-                      expression:
-                        function:
-                          function_name:
-                            function_name_identifier: OFFSET
-                          start_bracket: (
+                            function:
+                              function_name:
+                                function_name_identifier: OFFSET
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  literal: '0'
+                                end_bracket: )
+                          end_square_bracket: ']'
+                      - binary_operator: +
+                      - column_reference:
+                          identifier: count_25_34
+                      - binary_operator: '*'
+                      - column_reference:
+                          identifier: bits
+                      - array_accessor:
+                          start_square_bracket: '['
                           expression:
-                            literal: '1'
-                          end_bracket: )
-                      end_square_bracket: ']'
-                  - binary_operator: +
-                  - column_reference:
-                      identifier: count_35_44
-                  - binary_operator: '*'
-                  - column_reference:
-                      identifier: bits
-                  - array_accessor:
-                      start_square_bracket: '['
-                      expression:
-                        function:
-                          function_name:
-                            function_name_identifier: OFFSET
-                          start_bracket: (
+                            function:
+                              function_name:
+                                function_name_identifier: OFFSET
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  literal: '1'
+                                end_bracket: )
+                          end_square_bracket: ']'
+                      - binary_operator: +
+                      - column_reference:
+                          identifier: count_35_44
+                      - binary_operator: '*'
+                      - column_reference:
+                          identifier: bits
+                      - array_accessor:
+                          start_square_bracket: '['
                           expression:
-                            literal: '2'
-                          end_bracket: )
-                      end_square_bracket: ']'
-                  - binary_operator: +
-                  - column_reference:
-                      identifier: count_45_54
-                  - binary_operator: '*'
-                  - column_reference:
-                      identifier: bits
-                  - array_accessor:
-                      start_square_bracket: '['
-                      expression:
-                        function:
-                          function_name:
-                            function_name_identifier: OFFSET
-                          start_bracket: (
+                            function:
+                              function_name:
+                                function_name_identifier: OFFSET
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  literal: '2'
+                                end_bracket: )
+                          end_square_bracket: ']'
+                      - binary_operator: +
+                      - column_reference:
+                          identifier: count_45_54
+                      - binary_operator: '*'
+                      - column_reference:
+                          identifier: bits
+                      - array_accessor:
+                          start_square_bracket: '['
                           expression:
-                            literal: '3'
-                          end_bracket: )
-                      end_square_bracket: ']'
-                  - binary_operator: +
-                  - column_reference:
-                      identifier: count_55_64
-                  - binary_operator: '*'
-                  - column_reference:
-                      identifier: bits
-                  - array_accessor:
-                      start_square_bracket: '['
-                      expression:
-                        function:
-                          function_name:
-                            function_name_identifier: OFFSET
-                          start_bracket: (
+                            function:
+                              function_name:
+                                function_name_identifier: OFFSET
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  literal: '3'
+                                end_bracket: )
+                          end_square_bracket: ']'
+                      - binary_operator: +
+                      - column_reference:
+                          identifier: count_55_64
+                      - binary_operator: '*'
+                      - column_reference:
+                          identifier: bits
+                      - array_accessor:
+                          start_square_bracket: '['
                           expression:
-                            literal: '4'
-                          end_bracket: )
-                      end_square_bracket: ']'
-                  - binary_operator: +
-                  - column_reference:
-                      identifier: count_65_plus
-                  - binary_operator: '*'
-                  - column_reference:
-                      identifier: bits
-                  - array_accessor:
-                      start_square_bracket: '['
-                      expression:
-                        function:
-                          function_name:
-                            function_name_identifier: OFFSET
-                          start_bracket: (
+                            function:
+                              function_name:
+                                function_name_identifier: OFFSET
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  literal: '4'
+                                end_bracket: )
+                          end_square_bracket: ']'
+                      - binary_operator: +
+                      - column_reference:
+                          identifier: count_65_plus
+                      - binary_operator: '*'
+                      - column_reference:
+                          identifier: bits
+                      - array_accessor:
+                          start_square_bracket: '['
                           expression:
-                            literal: '5'
-                          end_bracket: )
-                      end_square_bracket: ']'
-                  end_bracket: )
-                binary_operator: /
-                column_reference:
-                  identifier: audience_size
-              alias_expression:
-                keyword: AS
-                identifier: relative_abundance
-          from_clause:
-            keyword: FROM
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  table_reference:
-                    identifier: audience_counts_gender_age
-              join_clause:
-              - keyword: CROSS
-              - keyword: JOIN
-              - from_expression_element:
+                            function:
+                              function_name:
+                                function_name_identifier: OFFSET
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  literal: '5'
+                                end_bracket: )
+                          end_square_bracket: ']'
+                      end_bracket: )
+                  binary_operator: /
+                  column_reference:
+                    identifier: audience_size
+                alias_expression:
+                  keyword: AS
+                  identifier: relative_abundance
+            from_clause:
+              keyword: FROM
+              from_expression:
+                from_expression_element:
                   table_expression:
                     table_reference:
-                      identifier: age_buckets_bit_array
-        end_bracket: )
+                      identifier: audience_counts_gender_age
+                join_clause:
+                - keyword: CROSS
+                - keyword: JOIN
+                - from_expression_element:
+                    table_expression:
+                      table_reference:
+                        identifier: age_buckets_bit_array
+          end_bracket: )
     - select_statement:
         select_clause:
           keyword: SELECT
@@ -242,6 +255,7 @@ file:
                   table_reference:
                     identifier: bucket_abundance
             - keyword: USING
-            - start_bracket: (
-            - identifier: bucket_id
-            - end_bracket: )
+            - bracketed:
+                start_bracket: (
+                identifier: bucket_id
+                end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_except.yml b/test/fixtures/parser/bigquery/select_except.yml
index d77534a576e..5a0dc896ac9 100644
--- a/test/fixtures/parser/bigquery/select_except.yml
+++ b/test/fixtures/parser/bigquery/select_except.yml
@@ -9,25 +9,27 @@ file:
               star: '*'
             select_except_clause:
               keyword: EXCEPT
-              start_bracket: (
-              identifier: seqnum
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier: seqnum
+                end_bracket: )
             select_replace_clause:
-            - keyword: REPLACE
-            - start_bracket: (
-            - select_clause_element:
-                column_reference:
-                  identifier: foo
-                alias_expression:
-                  keyword: as
-                  identifier: bar
-            - comma: ','
-            - select_clause_element:
-                column_reference:
-                  identifier: baz
-                alias_expression:
-                  identifier: foobar
-            - end_bracket: )
+              keyword: REPLACE
+              bracketed:
+              - start_bracket: (
+              - select_clause_element:
+                  column_reference:
+                    identifier: foo
+                  alias_expression:
+                    keyword: as
+                    identifier: bar
+              - comma: ','
+              - select_clause_element:
+                  column_reference:
+                    identifier: baz
+                  alias_expression:
+                    identifier: foobar
+              - end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
@@ -47,9 +49,10 @@ file:
                 star: '*'
               select_except_clause:
                 keyword: except
-                start_bracket: (
-                identifier: foo
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  identifier: foo
+                  end_bracket: )
         from_clause:
           keyword: from
           from_expression:
@@ -94,9 +97,10 @@ file:
               star: '*'
             select_except_clause:
               keyword: except
-              start_bracket: (
-              identifier: irrelevant
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier: irrelevant
+                end_bracket: )
       from_clause:
         keyword: from
         from_expression:
@@ -117,9 +121,10 @@ file:
               star: '*'
             select_except_clause:
               keyword: except
-              start_bracket: (
-              identifier: some_column
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier: some_column
+                end_bracket: )
       - comma: ','
       - select_clause_element:
           wildcard_expression:
@@ -129,9 +134,10 @@ file:
               star: '*'
             select_except_clause:
               keyword: except
-              start_bracket: (
-              identifier: other_column
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier: other_column
+                end_bracket: )
       from_clause:
         keyword: from
         from_expression:
diff --git a/test/fixtures/parser/bigquery/select_except_replace.yml b/test/fixtures/parser/bigquery/select_except_replace.yml
index 953536ec57d..191ea953148 100644
--- a/test/fixtures/parser/bigquery/select_except_replace.yml
+++ b/test/fixtures/parser/bigquery/select_except_replace.yml
@@ -9,28 +9,31 @@ file:
               star: '*'
             select_except_clause:
               keyword: except
-              start_bracket: (
-              identifier: foo
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier: foo
+                end_bracket: )
             select_replace_clause:
               keyword: replace
-              start_bracket: (
-              select_clause_element:
-                function:
-                - function_name:
-                    function_name_identifier: concat
-                - start_bracket: (
-                - expression:
-                    column_reference:
-                      identifier: fruit
-                - comma: ','
-                - expression:
-                    literal: "'berry'"
-                - end_bracket: )
-                alias_expression:
-                  keyword: as
-                  identifier: fruit
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                select_clause_element:
+                  function:
+                    function_name:
+                      function_name_identifier: concat
+                    bracketed:
+                    - start_bracket: (
+                    - expression:
+                        column_reference:
+                          identifier: fruit
+                    - comma: ','
+                    - expression:
+                        literal: "'berry'"
+                    - end_bracket: )
+                  alias_expression:
+                    keyword: as
+                    identifier: fruit
+                end_bracket: )
       from_clause:
         keyword: from
         from_expression:
diff --git a/test/fixtures/parser/bigquery/select_for_system_time.yml b/test/fixtures/parser/bigquery/select_for_system_time.yml
index 3a5b4501f98..2436ffec291 100644
--- a/test/fixtures/parser/bigquery/select_for_system_time.yml
+++ b/test/fixtures/parser/bigquery/select_for_system_time.yml
@@ -24,10 +24,11 @@ file:
               function:
                 function_name:
                   function_name_identifier: CAST
-                start_bracket: (
-                expression:
-                  literal: "'2019-12-02T20:52:34+00:00'"
-                keyword: AS
-                data_type:
-                  data_type_identifier: TIMESTAMP
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  expression:
+                    literal: "'2019-12-02T20:52:34+00:00'"
+                  keyword: AS
+                  data_type:
+                    data_type_identifier: TIMESTAMP
+                  end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_for_system_time_2.yml b/test/fixtures/parser/bigquery/select_for_system_time_2.yml
index 27e7ed042dd..425a55fd7a6 100644
--- a/test/fixtures/parser/bigquery/select_for_system_time_2.yml
+++ b/test/fixtures/parser/bigquery/select_for_system_time_2.yml
@@ -21,10 +21,11 @@ file:
               function:
                 function_name:
                   function_name_identifier: CAST
-                start_bracket: (
-                expression:
-                  literal: "'2020-05-11T14:02:52+00:00'"
-                keyword: AS
-                data_type:
-                  data_type_identifier: TIMESTAMP
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  expression:
+                    literal: "'2020-05-11T14:02:52+00:00'"
+                  keyword: AS
+                  data_type:
+                    data_type_identifier: TIMESTAMP
+                  end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_function_parameter_order_by_multiple_columns.yml b/test/fixtures/parser/bigquery/select_function_parameter_order_by_multiple_columns.yml
index 7063b2ac4dd..32dcf0b5a03 100644
--- a/test/fixtures/parser/bigquery/select_function_parameter_order_by_multiple_columns.yml
+++ b/test/fixtures/parser/bigquery/select_function_parameter_order_by_multiple_columns.yml
@@ -7,19 +7,20 @@ file:
           function:
             function_name:
               function_name_identifier: STRING_AGG
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: a
-            orderby_clause:
-            - keyword: ORDER
-            - keyword: BY
-            - column_reference:
-                identifier: b
-            - comma: ','
-            - column_reference:
-                identifier: c
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: a
+              orderby_clause:
+              - keyword: ORDER
+              - keyword: BY
+              - column_reference:
+                  identifier: b
+              - comma: ','
+              - column_reference:
+                  identifier: c
+              end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
diff --git a/test/fixtures/parser/bigquery/select_gt_lt.yml b/test/fixtures/parser/bigquery/select_gt_lt.yml
index 5e5afff04cf..9b45efcb074 100644
--- a/test/fixtures/parser/bigquery/select_gt_lt.yml
+++ b/test/fixtures/parser/bigquery/select_gt_lt.yml
@@ -5,13 +5,14 @@ file:
         keyword: SELECT
         select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - literal: '1'
-            - comparison_operator: '>'
-            - literal: '0'
-            - binary_operator: AND
-            - literal: '0'
-            - comparison_operator: <
-            - literal: '1'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - literal: '1'
+              - comparison_operator: '>'
+              - literal: '0'
+              - binary_operator: AND
+              - literal: '0'
+              - comparison_operator: <
+              - literal: '1'
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_hyphenated_table_name_in_from.yml b/test/fixtures/parser/bigquery/select_hyphenated_table_name_in_from.yml
index 312e1c90361..e6fc95ab146 100644
--- a/test/fixtures/parser/bigquery/select_hyphenated_table_name_in_from.yml
+++ b/test/fixtures/parser/bigquery/select_hyphenated_table_name_in_from.yml
@@ -37,6 +37,7 @@ file:
                 - binary_operator: '-'
                 - identifier: d
           - keyword: USING
-          - start_bracket: (
-          - identifier: a
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              identifier: a
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_interval_expression.yml b/test/fixtures/parser/bigquery/select_interval_expression.yml
index be8eeb3d9f1..ebe8d7139a6 100644
--- a/test/fixtures/parser/bigquery/select_interval_expression.yml
+++ b/test/fixtures/parser/bigquery/select_interval_expression.yml
@@ -5,24 +5,26 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: DATE_ADD
-          - start_bracket: (
-          - expression:
-              function:
-                function_name:
-                  function_name_identifier: CURRENT_DATE
-                start_bracket: (
-                end_bracket: )
-          - comma: ','
-          - expression:
-              interval_expression:
-                keyword: INTERVAL
-                expression:
-                  numeric_literal:
-                    binary_operator: '-'
-                    literal: '1'
-                  binary_operator: +
-                  literal: '2'
-                date_part: DAY
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                function:
+                  function_name:
+                    function_name_identifier: CURRENT_DATE
+                  bracketed:
+                    start_bracket: (
+                    end_bracket: )
+            - comma: ','
+            - expression:
+                interval_expression:
+                  keyword: INTERVAL
+                  expression:
+                    numeric_literal:
+                      binary_operator: '-'
+                      literal: '1'
+                    binary_operator: +
+                    literal: '2'
+                  date_part: DAY
+            - end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_lt_gt.yml b/test/fixtures/parser/bigquery/select_lt_gt.yml
index 385c418b061..175fb38b393 100644
--- a/test/fixtures/parser/bigquery/select_lt_gt.yml
+++ b/test/fixtures/parser/bigquery/select_lt_gt.yml
@@ -5,13 +5,14 @@ file:
         keyword: SELECT
         select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - literal: '0'
-            - comparison_operator: <
-            - literal: '1'
-            - binary_operator: AND
-            - literal: '1'
-            - comparison_operator: '>'
-            - literal: '0'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - literal: '0'
+              - comparison_operator: <
+              - literal: '1'
+              - binary_operator: AND
+              - literal: '1'
+              - comparison_operator: '>'
+              - literal: '0'
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_ml_predict_with_select.yml b/test/fixtures/parser/bigquery/select_ml_predict_with_select.yml
index 8926a9f0627..6ba0518714a 100644
--- a/test/fixtures/parser/bigquery/select_ml_predict_with_select.yml
+++ b/test/fixtures/parser/bigquery/select_ml_predict_with_select.yml
@@ -11,27 +11,29 @@ file:
         keyword: FROM
         from_expression:
           ml_table_expression:
-          - keyword: ML
-          - dot: .
-          - identifier: PREDICT
-          - start_bracket: (
-          - keyword: MODEL
-          - object_reference:
-              identifier: '`project.dataset.model`'
-          - comma: ','
-          - start_bracket: (
-          - select_statement:
-              select_clause:
-                keyword: SELECT
-                select_clause_element:
-                  column_reference:
-                    identifier: user_id
-              from_clause:
-                keyword: FROM
-                from_expression:
-                  from_expression_element:
-                    table_expression:
-                      table_reference:
-                        identifier: '`project.dataset.stats`'
-          - end_bracket: )
-          - end_bracket: )
+            keyword: ML
+            dot: .
+            identifier: PREDICT
+            bracketed:
+              start_bracket: (
+              keyword: MODEL
+              object_reference:
+                identifier: '`project.dataset.model`'
+              comma: ','
+              bracketed:
+                start_bracket: (
+                select_statement:
+                  select_clause:
+                    keyword: SELECT
+                    select_clause_element:
+                      column_reference:
+                        identifier: user_id
+                  from_clause:
+                    keyword: FROM
+                    from_expression:
+                      from_expression_element:
+                        table_expression:
+                          table_reference:
+                            identifier: '`project.dataset.stats`'
+                end_bracket: )
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_ml_weights.yml b/test/fixtures/parser/bigquery/select_ml_weights.yml
index 6e71de54c6c..8f37039a433 100644
--- a/test/fixtures/parser/bigquery/select_ml_weights.yml
+++ b/test/fixtures/parser/bigquery/select_ml_weights.yml
@@ -11,14 +11,15 @@ file:
         keyword: FROM
         from_expression:
           ml_table_expression:
-          - keyword: ML
-          - dot: .
-          - identifier: WEIGHTS
-          - start_bracket: (
-          - keyword: MODEL
-          - object_reference:
-              identifier: '`project.dataset.model`'
-          - end_bracket: )
+            keyword: ML
+            dot: .
+            identifier: WEIGHTS
+            bracketed:
+              start_bracket: (
+              keyword: MODEL
+              object_reference:
+                identifier: '`project.dataset.model`'
+              end_bracket: )
       orderby_clause:
       - keyword: ORDER
       - keyword: BY
diff --git a/test/fixtures/parser/bigquery/select_multi_except.yml b/test/fixtures/parser/bigquery/select_multi_except.yml
index 44cccdb9272..14ce7d33ca9 100644
--- a/test/fixtures/parser/bigquery/select_multi_except.yml
+++ b/test/fixtures/parser/bigquery/select_multi_except.yml
@@ -18,9 +18,10 @@ file:
               star: '*'
             select_except_clause:
               keyword: except
-              start_bracket: (
-              identifier: date_key
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier: date_key
+                end_bracket: )
       from_clause:
         keyword: from
         from_expression:
@@ -42,6 +43,7 @@ file:
                 keyword: as
                 identifier: r
           - keyword: using
-          - start_bracket: (
-          - identifier: date_key
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              identifier: date_key
+              end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_replace.yml b/test/fixtures/parser/bigquery/select_replace.yml
index d5e1182a479..d87977fed47 100644
--- a/test/fixtures/parser/bigquery/select_replace.yml
+++ b/test/fixtures/parser/bigquery/select_replace.yml
@@ -31,24 +31,25 @@ file:
             wildcard_identifier:
               star: '*'
             select_replace_clause:
-            - keyword: REPLACE
-            - start_bracket: (
-            - select_clause_element:
-                expression:
-                  column_reference:
+              keyword: REPLACE
+              bracketed:
+              - start_bracket: (
+              - select_clause_element:
+                  expression:
+                    column_reference:
+                      identifier: quantity
+                    binary_operator: /
+                    literal: '2'
+                  alias_expression:
+                    keyword: AS
                     identifier: quantity
-                  binary_operator: /
-                  literal: '2'
-                alias_expression:
-                  keyword: AS
-                  identifier: quantity
-            - comma: ','
-            - select_clause_element:
-                literal: "'thing'"
-                alias_expression:
-                  keyword: as
-                  identifier: foo
-            - end_bracket: )
+              - comma: ','
+              - select_clause_element:
+                  literal: "'thing'"
+                  alias_expression:
+                    keyword: as
+                    identifier: foo
+              - end_bracket: )
       from_clause:
         keyword: from
         from_expression:
diff --git a/test/fixtures/parser/bigquery/select_replace_2.yml b/test/fixtures/parser/bigquery/select_replace_2.yml
index f8c87145c96..5aa1d3544ca 100644
--- a/test/fixtures/parser/bigquery/select_replace_2.yml
+++ b/test/fixtures/parser/bigquery/select_replace_2.yml
@@ -9,34 +9,37 @@ file:
               star: '*'
             select_replace_clause:
               keyword: REPLACE
-              start_bracket: (
-              select_clause_element:
-                function:
-                  function_name:
-                    function_name_identifier: CAST
-                  start_bracket: (
-                  expression:
-                    literal: '1'
-                  keyword: AS
-                  data_type:
-                    data_type_identifier: BOOLEAN
-                  end_bracket: )
-                alias_expression:
-                  keyword: AS
-                  identifier: foo
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                select_clause_element:
+                  function:
+                    function_name:
+                      function_name_identifier: CAST
+                    bracketed:
+                      start_bracket: (
+                      expression:
+                        literal: '1'
+                      keyword: AS
+                      data_type:
+                        data_type_identifier: BOOLEAN
+                      end_bracket: )
+                  alias_expression:
+                    keyword: AS
+                    identifier: foo
+                end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
           from_expression_element:
             table_expression:
-              start_bracket: (
-              select_statement:
-                select_clause:
-                  keyword: SELECT
-                  select_clause_element:
-                    literal: '1'
-                    alias_expression:
-                      keyword: AS
-                      identifier: foo
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                select_statement:
+                  select_clause:
+                    keyword: SELECT
+                    select_clause_element:
+                      literal: '1'
+                      alias_expression:
+                        keyword: AS
+                        identifier: foo
+                end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_struct.yml b/test/fixtures/parser/bigquery/select_struct.yml
index c19ef9e8150..6be6957395c 100644
--- a/test/fixtures/parser/bigquery/select_struct.yml
+++ b/test/fixtures/parser/bigquery/select_struct.yml
@@ -13,34 +13,35 @@ file:
           function:
             function_name:
               function_name_identifier: array
-            start_bracket: (
-            expression:
-              select_statement:
-                select_clause:
-                - keyword: select
-                - keyword: as
-                - keyword: struct
-                - star: '*'
-                from_clause:
-                  keyword: from
-                  from_expression:
-                    from_expression_element:
-                      table_expression:
-                        table_reference:
-                          identifier: another_table
-                where_clause:
-                  keyword: where
-                  expression:
-                  - column_reference:
-                    - identifier: another_table
-                    - dot: .
-                    - identifier: foo_id
-                  - comparison_operator: '='
-                  - column_reference:
-                    - identifier: some_table
-                    - dot: .
-                    - identifier: foo_id
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                select_statement:
+                  select_clause:
+                  - keyword: select
+                  - keyword: as
+                  - keyword: struct
+                  - star: '*'
+                  from_clause:
+                    keyword: from
+                    from_expression:
+                      from_expression_element:
+                        table_expression:
+                          table_reference:
+                            identifier: another_table
+                  where_clause:
+                    keyword: where
+                    expression:
+                    - column_reference:
+                      - identifier: another_table
+                      - dot: .
+                      - identifier: foo_id
+                    - comparison_operator: '='
+                    - column_reference:
+                      - identifier: some_table
+                      - dot: .
+                      - identifier: foo_id
+              end_bracket: )
       from_clause:
         keyword: from
         from_expression:
@@ -55,24 +56,25 @@ file:
         keyword: select
         select_clause_element:
           typeless_struct:
-          - keyword: struct
-          - start_bracket: (
-          - column_reference:
-            - identifier: bar
-            - dot: .
-            - identifier: bar_id
-          - alias_expression:
-              keyword: as
-              identifier: id
-          - comma: ','
-          - column_reference:
-            - identifier: bar
-            - dot: .
-            - identifier: bar_name
-          - alias_expression:
-              keyword: as
-              identifier: bar
-          - end_bracket: )
+            keyword: struct
+            bracketed:
+            - start_bracket: (
+            - column_reference:
+              - identifier: bar
+              - dot: .
+              - identifier: bar_id
+            - alias_expression:
+                keyword: as
+                identifier: id
+            - comma: ','
+            - column_reference:
+              - identifier: bar
+              - dot: .
+              - identifier: bar_name
+            - alias_expression:
+                keyword: as
+                identifier: bar
+            - end_bracket: )
           alias_expression:
             keyword: as
             identifier: bar
diff --git a/test/fixtures/parser/bigquery/select_typeless_struct_inside_function.yml b/test/fixtures/parser/bigquery/select_typeless_struct_inside_function.yml
index 63302823813..17cd60ea5ac 100644
--- a/test/fixtures/parser/bigquery/select_typeless_struct_inside_function.yml
+++ b/test/fixtures/parser/bigquery/select_typeless_struct_inside_function.yml
@@ -6,19 +6,21 @@ file:
         select_clause_element:
           typeless_struct:
             keyword: STRUCT
-            start_bracket: (
-            typeless_struct:
-              keyword: STRUCT
+            bracketed:
               start_bracket: (
-              literal: '1'
+              typeless_struct:
+                keyword: STRUCT
+                bracketed:
+                  start_bracket: (
+                  literal: '1'
+                  alias_expression:
+                    keyword: AS
+                    identifier: b
+                  end_bracket: )
               alias_expression:
                 keyword: AS
-                identifier: b
+                identifier: a
               end_bracket: )
-            alias_expression:
-              keyword: AS
-              identifier: a
-            end_bracket: )
           alias_expression:
             keyword: AS
             identifier: foo
@@ -31,23 +33,25 @@ file:
           function:
             function_name:
               function_name_identifier: ARRAY_AGG
-            start_bracket: (
-            typeless_struct:
-            - keyword: STRUCT
-            - start_bracket: (
-            - column_reference:
-                identifier: a
-            - alias_expression:
-                keyword: AS
-                identifier: a
-            - comma: ','
-            - column_reference:
-                identifier: b
-            - alias_expression:
-                keyword: AS
-                identifier: b
-            - end_bracket: )
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              typeless_struct:
+                keyword: STRUCT
+                bracketed:
+                - start_bracket: (
+                - column_reference:
+                    identifier: a
+                - alias_expression:
+                    keyword: AS
+                    identifier: a
+                - comma: ','
+                - column_reference:
+                    identifier: b
+                - alias_expression:
+                    keyword: AS
+                    identifier: b
+                - end_bracket: )
+              end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
diff --git a/test/fixtures/parser/bigquery/select_udf_quote_everything.yml b/test/fixtures/parser/bigquery/select_udf_quote_everything.yml
index 93c425ed32a..256a5f627ff 100644
--- a/test/fixtures/parser/bigquery/select_udf_quote_everything.yml
+++ b/test/fixtures/parser/bigquery/select_udf_quote_everything.yml
@@ -7,13 +7,14 @@ file:
           function:
             function_name:
               identifier: '`another-gcp-project.functions.timestamp_parsing`'
-            start_bracket: (
-            expression:
-              column_reference:
-              - identifier: log_tbl
-              - dot: .
-              - identifier: orderdate
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                - identifier: log_tbl
+                - dot: .
+                - identifier: orderdate
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: orderdate
diff --git a/test/fixtures/parser/bigquery/select_udf_quote_nothing.yml b/test/fixtures/parser/bigquery/select_udf_quote_nothing.yml
index 3288255e425..b3288ec888a 100644
--- a/test/fixtures/parser/bigquery/select_udf_quote_nothing.yml
+++ b/test/fixtures/parser/bigquery/select_udf_quote_nothing.yml
@@ -11,13 +11,14 @@ file:
             - identifier: functions
             - dot: .
             - function_name_identifier: timestamp_parsing
-            start_bracket: (
-            expression:
-              column_reference:
-              - identifier: log_tbl
-              - dot: .
-              - identifier: orderdate
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                - identifier: log_tbl
+                - dot: .
+                - identifier: orderdate
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: orderdate
diff --git a/test/fixtures/parser/bigquery/select_udf_quote_project_and_datasetfunctionname.yml b/test/fixtures/parser/bigquery/select_udf_quote_project_and_datasetfunctionname.yml
index 76f54a16adc..2fd0e8a6107 100644
--- a/test/fixtures/parser/bigquery/select_udf_quote_project_and_datasetfunctionname.yml
+++ b/test/fixtures/parser/bigquery/select_udf_quote_project_and_datasetfunctionname.yml
@@ -9,13 +9,14 @@ file:
             - identifier: '`another-gcp-project`'
             - dot: .
             - identifier: '`functions.timestamp_parsing`'
-            start_bracket: (
-            expression:
-              column_reference:
-              - identifier: log_tbl
-              - dot: .
-              - identifier: first_move
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                - identifier: log_tbl
+                - dot: .
+                - identifier: first_move
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: first_move
diff --git a/test/fixtures/parser/bigquery/select_udf_quote_project_name.yml b/test/fixtures/parser/bigquery/select_udf_quote_project_name.yml
index 4e4953e6772..7ddbafcffde 100644
--- a/test/fixtures/parser/bigquery/select_udf_quote_project_name.yml
+++ b/test/fixtures/parser/bigquery/select_udf_quote_project_name.yml
@@ -11,13 +11,14 @@ file:
             - identifier: functions
             - dot: .
             - function_name_identifier: timestamp_parsing
-            start_bracket: (
-            expression:
-              column_reference:
-              - identifier: log_tbl
-              - dot: .
-              - identifier: first_move
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                - identifier: log_tbl
+                - dot: .
+                - identifier: first_move
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: first_move
diff --git a/test/fixtures/parser/bigquery/select_where_array_element_less_than.yml b/test/fixtures/parser/bigquery/select_where_array_element_less_than.yml
index c9e51faf6af..c77d98c777f 100644
--- a/test/fixtures/parser/bigquery/select_where_array_element_less_than.yml
+++ b/test/fixtures/parser/bigquery/select_where_array_element_less_than.yml
@@ -25,10 +25,11 @@ file:
               function:
                 function_name:
                   function_name_identifier: ORDINAL
-                start_bracket: (
-                expression:
-                  literal: '1'
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  expression:
+                    literal: '1'
+                  end_bracket: )
             end_square_bracket: ']'
         - comparison_operator: <
         - column_reference:
@@ -39,10 +40,11 @@ file:
               function:
                 function_name:
                   function_name_identifier: ORDINAL
-                start_bracket: (
-                expression:
-                - literal: '1'
-                - binary_operator: +
-                - literal: '1'
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  expression:
+                  - literal: '1'
+                  - binary_operator: +
+                  - literal: '1'
+                  end_bracket: )
             end_square_bracket: ']'
diff --git a/test/fixtures/parser/bigquery/select_with_date_literal_coercion_and_two_part_string_interval.yml b/test/fixtures/parser/bigquery/select_with_date_literal_coercion_and_two_part_string_interval.yml
index 1b62a76f654..d8354cd25d1 100644
--- a/test/fixtures/parser/bigquery/select_with_date_literal_coercion_and_two_part_string_interval.yml
+++ b/test/fixtures/parser/bigquery/select_with_date_literal_coercion_and_two_part_string_interval.yml
@@ -5,26 +5,27 @@ file:
         keyword: SELECT
         select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: GENERATE_DATE_ARRAY
-          - start_bracket: (
-          - expression:
-              cast_expression:
-                keyword: DATE
-                literal: "'2010-01-01'"
-          - comma: ','
-          - expression:
-              cast_expression:
-                keyword: DATE
-                literal: "'2010-01-31'"
-          - comma: ','
-          - expression:
-              interval_expression:
-                keyword: INTERVAL
-                expression:
-                  literal: "'7'"
-                date_part: DAY
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                cast_expression:
+                  keyword: DATE
+                  literal: "'2010-01-01'"
+            - comma: ','
+            - expression:
+                cast_expression:
+                  keyword: DATE
+                  literal: "'2010-01-31'"
+            - comma: ','
+            - expression:
+                interval_expression:
+                  keyword: INTERVAL
+                  expression:
+                    literal: "'7'"
+                  date_part: DAY
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: my_array
diff --git a/test/fixtures/parser/bigquery/select_with_offset.yml b/test/fixtures/parser/bigquery/select_with_offset.yml
index fe4ffbc33bf..72cf8bbd8f5 100644
--- a/test/fixtures/parser/bigquery/select_with_offset.yml
+++ b/test/fixtures/parser/bigquery/select_with_offset.yml
@@ -7,97 +7,102 @@ file:
           function:
             function_name:
               function_name_identifier: SUM
-            start_bracket: (
-            expression:
-              case_expression:
-              - keyword: CASE
-              - keyword: WHEN
-              - expression:
-                - column_reference:
-                    identifier: value
-                - comparison_operator: '!='
-                - column_reference:
-                    identifier: previous_value
-              - keyword: THEN
-              - expression:
-                  literal: '1.0'
-              - keyword: ELSE
-              - expression:
-                  literal: '0.0'
-              - keyword: END
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                case_expression:
+                - keyword: CASE
+                - keyword: WHEN
+                - expression:
+                  - column_reference:
+                      identifier: value
+                  - comparison_operator: '!='
+                  - column_reference:
+                      identifier: previous_value
+                - keyword: THEN
+                - expression:
+                    literal: '1.0'
+                - keyword: ELSE
+                - expression:
+                    literal: '0.0'
+                - keyword: END
+              end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
           from_expression_element:
             table_expression:
-              start_bracket: (
-              select_statement:
-                select_clause:
-                - keyword: SELECT
-                - select_clause_element:
-                    column_reference:
-                      identifier: value
-                - comma: ','
-                - select_clause_element:
-                    expression:
-                      case_expression:
-                      - keyword: CASE
-                      - keyword: WHEN
-                      - expression:
-                          column_reference:
-                            identifier: ix
-                          comparison_operator: '!='
-                          literal: '0'
-                      - keyword: THEN
-                      - expression:
+              bracketed:
+                start_bracket: (
+                select_statement:
+                  select_clause:
+                  - keyword: SELECT
+                  - select_clause_element:
+                      column_reference:
+                        identifier: value
+                  - comma: ','
+                  - select_clause_element:
+                      expression:
+                        case_expression:
+                        - keyword: CASE
+                        - keyword: WHEN
+                        - expression:
+                            column_reference:
+                              identifier: ix
+                            comparison_operator: '!='
+                            literal: '0'
+                        - keyword: THEN
+                        - expression:
+                            function:
+                              function_name:
+                                function_name_identifier: LAG
+                              bracketed:
+                                start_bracket: (
+                                expression:
+                                  column_reference:
+                                    identifier: value
+                                end_bracket: )
+                              over_clause:
+                                keyword: OVER
+                                bracketed:
+                                  start_bracket: (
+                                  window_specification:
+                                    orderby_clause:
+                                    - keyword: ORDER
+                                    - keyword: BY
+                                    - column_reference:
+                                        identifier: ix
+                                    - keyword: ASC
+                                  end_bracket: )
+                        - keyword: ELSE
+                        - expression:
+                            column_reference:
+                              identifier: value
+                        - keyword: END
+                      alias_expression:
+                        keyword: AS
+                        identifier: previous_value
+                  from_clause:
+                    keyword: FROM
+                    from_expression:
+                      from_expression_element:
+                      - table_expression:
                           function:
                             function_name:
-                              function_name_identifier: LAG
-                            start_bracket: (
-                            expression:
-                              column_reference:
-                                identifier: value
-                            end_bracket: )
-                            over_clause:
-                              keyword: OVER
+                              function_name_identifier: UNNEST
+                            bracketed:
                               start_bracket: (
-                              window_specification:
-                                orderby_clause:
-                                - keyword: ORDER
-                                - keyword: BY
-                                - column_reference:
-                                    identifier: ix
-                                - keyword: ASC
+                              expression:
+                                column_reference:
+                                - identifier: sequence_validation_and_business_rules
+                                - dot: .
+                                - identifier: sequence_validation_and_business_rules
                               end_bracket: )
-                      - keyword: ELSE
-                      - expression:
-                          column_reference:
-                            identifier: value
-                      - keyword: END
-                    alias_expression:
-                      keyword: AS
-                      identifier: previous_value
-                from_clause:
-                  keyword: FROM
-                  from_expression:
-                    from_expression_element:
-                    - table_expression:
-                        function:
-                          function_name:
-                            function_name_identifier: UNNEST
-                          start_bracket: (
-                          expression:
-                            column_reference:
-                            - identifier: sequence_validation_and_business_rules
-                            - dot: .
-                            - identifier: sequence_validation_and_business_rules
-                          end_bracket: )
-                    - alias_expression:
-                        keyword: AS
-                        identifier: value
-                    - keyword: WITH
-                    - keyword: OFFSET
-                    - keyword: AS
-                    - identifier: ix
-              end_bracket: )
+                      - alias_expression:
+                          keyword: AS
+                          identifier: value
+                      - keyword: WITH
+                      - keyword: OFFSET
+                      - keyword: AS
+                      - identifier: ix
+                end_bracket: )
diff --git a/test/fixtures/parser/bigquery/select_with_offset_2.yml b/test/fixtures/parser/bigquery/select_with_offset_2.yml
index 49b57cc184c..0db80645d5c 100644
--- a/test/fixtures/parser/bigquery/select_with_offset_2.yml
+++ b/test/fixtures/parser/bigquery/select_with_offset_2.yml
@@ -7,28 +7,29 @@ file:
           function:
             function_name:
               function_name_identifier: ARRAY
-            start_bracket: (
-            expression:
-              select_statement:
-                select_clause:
-                  keyword: SELECT
-                  select_clause_element:
-                    column_reference:
-                      identifier: a
-                from_clause:
-                  keyword: FROM
-                  from_expression:
-                    from_expression_element:
-                    - table_expression:
-                        table_reference:
-                          identifier: foo
-                    - keyword: WITH
-                    - keyword: OFFSET
-                where_clause:
-                  keyword: WHERE
-                  expression:
-                    column_reference:
-                      identifier: OFFSET
-                    comparison_operator: '>'
-                    literal: '1'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                select_statement:
+                  select_clause:
+                    keyword: SELECT
+                    select_clause_element:
+                      column_reference:
+                        identifier: a
+                  from_clause:
+                    keyword: FROM
+                    from_expression:
+                      from_expression_element:
+                      - table_expression:
+                          table_reference:
+                            identifier: foo
+                      - keyword: WITH
+                      - keyword: OFFSET
+                  where_clause:
+                    keyword: WHERE
+                    expression:
+                      column_reference:
+                        identifier: OFFSET
+                      comparison_operator: '>'
+                      literal: '1'
+              end_bracket: )
diff --git a/test/fixtures/parser/mysql/alter_table.yml b/test/fixtures/parser/mysql/alter_table.yml
index 087cf827330..094af525165 100644
--- a/test/fixtures/parser/mysql/alter_table.yml
+++ b/test/fixtures/parser/mysql/alter_table.yml
@@ -11,10 +11,11 @@ file:
         identifier: '`name`'
         data_type:
           data_type_identifier: varchar
-          start_bracket: (
-          expression:
-            literal: '255'
-          end_bracket: )
+          bracketed:
+            start_bracket: (
+            expression:
+              literal: '255'
+            end_bracket: )
         column_constraint:
         - keyword: NOT
         - keyword: 'NULL'
diff --git a/test/fixtures/parser/mysql/create_table.yml b/test/fixtures/parser/mysql/create_table.yml
index 04552fc89a0..586a4a9c5d8 100644
--- a/test/fixtures/parser/mysql/create_table.yml
+++ b/test/fixtures/parser/mysql/create_table.yml
@@ -5,31 +5,34 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: '`foo`'
-    - start_bracket: (
-    - column_definition:
-      - identifier: '`id`'
-      - data_type:
-          data_type_identifier: int
-          start_bracket: (
-          expression:
-            literal: '11'
-          end_bracket: )
-      - column_constraint:
-          keyword: unsigned
-      - column_constraint:
-        - keyword: NOT
-        - keyword: 'NULL'
-      - column_constraint:
-          keyword: AUTO_INCREMENT
-    - comma: ','
-    - table_constraint_definition:
-      - keyword: PRIMARY
-      - keyword: KEY
-      - start_bracket: (
-      - column_reference:
-          identifier: '`id`'
-      - end_bracket: )
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+        - identifier: '`id`'
+        - data_type:
+            data_type_identifier: int
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '11'
+              end_bracket: )
+        - column_constraint:
+            keyword: unsigned
+        - column_constraint:
+          - keyword: NOT
+          - keyword: 'NULL'
+        - column_constraint:
+            keyword: AUTO_INCREMENT
+        comma: ','
+        table_constraint_definition:
+        - keyword: PRIMARY
+        - keyword: KEY
+        - bracketed:
+            start_bracket: (
+            column_reference:
+              identifier: '`id`'
+            end_bracket: )
+        end_bracket: )
     - parameter: ENGINE
     - comparison_operator: '='
     - parameter: InnoDB
diff --git a/test/fixtures/parser/mysql/explain.yml b/test/fixtures/parser/mysql/explain.yml
index 8628d148fc3..1bb06b975e3 100644
--- a/test/fixtures/parser/mysql/explain.yml
+++ b/test/fixtures/parser/mysql/explain.yml
@@ -58,13 +58,15 @@ file:
       - keyword: into
       - table_reference:
           identifier: tbl
-      - start_bracket: (
-      - column_reference:
-          identifier: col1
-      - end_bracket: )
-      - values_clause:
-          keyword: values
+      - bracketed:
           start_bracket: (
-          literal: '123'
+          column_reference:
+            identifier: col1
           end_bracket: )
+      - values_clause:
+          keyword: values
+          bracketed:
+            start_bracket: (
+            literal: '123'
+            end_bracket: )
 - statement_terminator: ;
diff --git a/test/fixtures/parser/mysql/force_index.yml b/test/fixtures/parser/mysql/force_index.yml
index 5e43d8d835a..e14bacbe2f5 100644
--- a/test/fixtures/parser/mysql/force_index.yml
+++ b/test/fixtures/parser/mysql/force_index.yml
@@ -32,10 +32,11 @@ file:
             - keyword: INDEX
             - keyword: FOR
             - keyword: JOIN
-            - start_bracket: (
-            - object_reference:
-                identifier: idx_index
-            - end_bracket: )
+            - bracketed:
+                start_bracket: (
+                object_reference:
+                  identifier: idx_index
+                end_bracket: )
           - join_on_condition:
               keyword: 'ON'
               expression:
diff --git a/test/fixtures/parser/mysql/use_index.yml b/test/fixtures/parser/mysql/use_index.yml
index b3df274e273..3ef964bee4f 100644
--- a/test/fixtures/parser/mysql/use_index.yml
+++ b/test/fixtures/parser/mysql/use_index.yml
@@ -18,10 +18,11 @@ file:
               identifier: test
           - keyword: USE
           - keyword: INDEX
-          - start_bracket: (
-          - object_reference:
-              identifier: i2
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              object_reference:
+                identifier: i2
+              end_bracket: )
       orderby_clause:
       - keyword: ORDER
       - keyword: BY
diff --git a/test/fixtures/parser/postgres/postgres_create_dollar_quoted_function.yml b/test/fixtures/parser/postgres/postgres_create_dollar_quoted_function.yml
index 975a202eb86..25e656888a9 100644
--- a/test/fixtures/parser/postgres/postgres_create_dollar_quoted_function.yml
+++ b/test/fixtures/parser/postgres/postgres_create_dollar_quoted_function.yml
@@ -6,13 +6,14 @@ file:
     - function_name:
         function_name_identifier: foo
     - base:
-      - start_bracket: (
-      - data_type:
-          data_type_identifier: integer
-      - comma: ','
-      - data_type:
-          data_type_identifier: integer
-      - end_bracket: )
+        bracketed:
+        - start_bracket: (
+        - data_type:
+            data_type_identifier: integer
+        - comma: ','
+        - data_type:
+            data_type_identifier: integer
+        - end_bracket: )
     - keyword: RETURNS
     - data_type:
         data_type_identifier: integer
diff --git a/test/fixtures/parser/postgres/postgres_create_function.yml b/test/fixtures/parser/postgres/postgres_create_function.yml
index 71c8491f232..03182f521d9 100644
--- a/test/fixtures/parser/postgres/postgres_create_function.yml
+++ b/test/fixtures/parser/postgres/postgres_create_function.yml
@@ -6,13 +6,14 @@ file:
     - function_name:
         function_name_identifier: add
     - base:
-      - start_bracket: (
-      - data_type:
-          data_type_identifier: integer
-      - comma: ','
-      - data_type:
-          data_type_identifier: integer
-      - end_bracket: )
+        bracketed:
+        - start_bracket: (
+        - data_type:
+            data_type_identifier: integer
+        - comma: ','
+        - data_type:
+            data_type_identifier: integer
+        - end_bracket: )
     - keyword: RETURNS
     - data_type:
         data_type_identifier: integer
@@ -31,11 +32,12 @@ file:
     - function_name:
         function_name_identifier: increment
     - base:
-        start_bracket: (
-        parameter: i
-        data_type:
-          data_type_identifier: integer
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          parameter: i
+          data_type:
+            data_type_identifier: integer
+          end_bracket: )
     - keyword: RETURNS
     - data_type:
         data_type_identifier: integer
diff --git a/test/fixtures/parser/postgres/postgres_create_table.yml b/test/fixtures/parser/postgres/postgres_create_table.yml
index e684bbb6b75..3ab8135b9c5 100644
--- a/test/fixtures/parser/postgres/postgres_create_table.yml
+++ b/test/fixtures/parser/postgres/postgres_create_table.yml
@@ -5,11 +5,12 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: counters
-    - start_bracket: (
-    - column_definition:
-        identifier: my_type
-        data_type:
-          identifier: public
-          dot: .
-          data_type_identifier: MY_TYPE
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+          identifier: my_type
+          data_type:
+            identifier: public
+            dot: .
+            data_type_identifier: MY_TYPE
+        end_bracket: )
diff --git a/test/fixtures/parser/postgres/postgres_create_type.yml b/test/fixtures/parser/postgres/postgres_create_type.yml
index 3615b32c6a2..66e4820aaed 100644
--- a/test/fixtures/parser/postgres/postgres_create_type.yml
+++ b/test/fixtures/parser/postgres/postgres_create_type.yml
@@ -14,11 +14,12 @@ file:
         identifier: bar
     - keyword: AS
     - keyword: ENUM
-    - start_bracket: (
-    - raw: "'foo'"
-    - comma: ','
-    - raw: "'bar'"
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - raw: "'foo'"
+      - comma: ','
+      - raw: "'bar'"
+      - end_bracket: )
 - statement_terminator: ;
 - statement:
     create_type_statement:
@@ -28,11 +29,12 @@ file:
         identifier: foobar
     - keyword: AS
     - keyword: RANGE
-    - start_bracket: (
-    - raw: SUBTYPE
-    - raw: '='
-    - raw: FLOAT
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - raw: SUBTYPE
+      - raw: '='
+      - raw: FLOAT
+      - end_bracket: )
 - statement_terminator: ;
 - statement:
     create_type_statement:
@@ -41,15 +43,16 @@ file:
     - object_reference:
         identifier: barbar
     - keyword: AS
-    - start_bracket: (
-    - raw: INPUT
-    - raw: '='
-    - raw: foo
-    - comma: ','
-    - raw: OUTPUT
-    - raw: '='
-    - raw: bar
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - raw: INPUT
+      - raw: '='
+      - raw: foo
+      - comma: ','
+      - raw: OUTPUT
+      - raw: '='
+      - raw: bar
+      - end_bracket: )
 - statement_terminator: ;
 - statement:
     create_type_statement:
@@ -58,10 +61,11 @@ file:
     - object_reference:
         identifier: foofoo
     - keyword: AS
-    - start_bracket: (
-    - raw: foo
-    - raw: varchar
-    - raw: collate
-    - raw: utf8
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - raw: foo
+      - raw: varchar
+      - raw: collate
+      - raw: utf8
+      - end_bracket: )
 - statement_terminator: ;
diff --git a/test/fixtures/parser/postgres/postgres_explain.yml b/test/fixtures/parser/postgres/postgres_explain.yml
index df5e137ca5e..2722b7f9d0d 100644
--- a/test/fixtures/parser/postgres/postgres_explain.yml
+++ b/test/fixtures/parser/postgres/postgres_explain.yml
@@ -1,29 +1,30 @@
 file:
 - statement:
     explain_statement:
-    - keyword: explain
-    - start_bracket: (
-    - explain_option:
-        keyword: analyze
-        literal: 'true'
-    - comma: ','
-    - explain_option:
-        keyword: costs
-        literal: 'false'
-    - comma: ','
-    - explain_option:
-        keyword: verbose
-        literal: 'true'
-    - comma: ','
-    - explain_option:
-        keyword: buffers
-        literal: 'true'
-    - comma: ','
-    - explain_option:
-      - keyword: format
-      - keyword: xml
-    - end_bracket: )
-    - select_statement:
+      keyword: explain
+      bracketed:
+      - start_bracket: (
+      - explain_option:
+          keyword: analyze
+          literal: 'true'
+      - comma: ','
+      - explain_option:
+          keyword: costs
+          literal: 'false'
+      - comma: ','
+      - explain_option:
+          keyword: verbose
+          literal: 'true'
+      - comma: ','
+      - explain_option:
+          keyword: buffers
+          literal: 'true'
+      - comma: ','
+      - explain_option:
+        - keyword: format
+        - keyword: xml
+      - end_bracket: )
+      select_statement:
         select_clause:
           keyword: select
           select_clause_element:
@@ -53,11 +54,12 @@ file:
 - statement:
     explain_statement:
       keyword: explain
-      start_bracket: (
-      explain_option:
-      - keyword: format
-      - keyword: text
-      end_bracket: )
+      bracketed:
+        start_bracket: (
+        explain_option:
+        - keyword: format
+        - keyword: text
+        end_bracket: )
       select_statement:
         select_clause:
           keyword: select
@@ -67,11 +69,12 @@ file:
 - statement:
     explain_statement:
       keyword: explain
-      start_bracket: (
-      explain_option:
-      - keyword: format
-      - keyword: json
-      end_bracket: )
+      bracketed:
+        start_bracket: (
+        explain_option:
+        - keyword: format
+        - keyword: json
+        end_bracket: )
       select_statement:
         select_clause:
           keyword: select
@@ -81,11 +84,12 @@ file:
 - statement:
     explain_statement:
       keyword: explain
-      start_bracket: (
-      explain_option:
-      - keyword: format
-      - keyword: yaml
-      end_bracket: )
+      bracketed:
+        start_bracket: (
+        explain_option:
+        - keyword: format
+        - keyword: yaml
+        end_bracket: )
       select_statement:
         select_clause:
           keyword: select
diff --git a/test/fixtures/parser/postgres/postgres_filter.yml b/test/fixtures/parser/postgres/postgres_filter.yml
index e15f06d4958..e3008b3e5ea 100644
--- a/test/fixtures/parser/postgres/postgres_filter.yml
+++ b/test/fixtures/parser/postgres/postgres_filter.yml
@@ -7,18 +7,20 @@ file:
           function:
           - function_name:
               function_name_identifier: COUNT
-          - start_bracket: (
-          - star: '*'
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              star: '*'
+              end_bracket: )
           - keyword: FILTER
-          - start_bracket: (
-          - keyword: WHERE
-          - expression:
-              column_reference:
-                identifier: c_expires
-              comparison_operator: '>'
-              bare_function: CURRENT_TIMESTAMP
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              keyword: WHERE
+              expression:
+                column_reference:
+                  identifier: c_expires
+                comparison_operator: '>'
+                bare_function: CURRENT_TIMESTAMP
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: c_active
diff --git a/test/fixtures/parser/postgres/postgres_join_no_space.yml b/test/fixtures/parser/postgres/postgres_join_no_space.yml
index 0c3e29a61ed..41ed112f6df 100644
--- a/test/fixtures/parser/postgres/postgres_join_no_space.yml
+++ b/test/fixtures/parser/postgres/postgres_join_no_space.yml
@@ -27,15 +27,16 @@ file:
                 - identifier: '"my_table"'
           - join_on_condition:
               keyword: 'ON'
-              start_bracket: (
-              expression:
-              - column_reference:
-                - identifier: '"my_table2"'
-                - dot: .
-                - identifier: foo
-              - comparison_operator: '='
-              - column_reference:
-                - identifier: '"my_table"'
-                - dot: .
-                - identifier: foo
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                - column_reference:
+                  - identifier: '"my_table2"'
+                  - dot: .
+                  - identifier: foo
+                - comparison_operator: '='
+                - column_reference:
+                  - identifier: '"my_table"'
+                  - dot: .
+                  - identifier: foo
+                end_bracket: )
diff --git a/test/fixtures/parser/postgres/postgres_within_group.yml b/test/fixtures/parser/postgres/postgres_within_group.yml
index a2f41da1b28..af0059a2322 100644
--- a/test/fixtures/parser/postgres/postgres_within_group.yml
+++ b/test/fixtures/parser/postgres/postgres_within_group.yml
@@ -7,22 +7,24 @@ file:
           function:
             function_name:
               function_name_identifier: ARRAY_AGG
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: o_orderkey
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: o_orderkey
+              end_bracket: )
             withingroup_clause:
             - keyword: WITHIN
             - keyword: GROUP
-            - start_bracket: (
-            - orderby_clause:
-              - keyword: ORDER
-              - keyword: BY
-              - column_reference:
-                  identifier: o_orderkey
-              - keyword: ASC
-            - end_bracket: )
+            - bracketed:
+                start_bracket: (
+                orderby_clause:
+                - keyword: ORDER
+                - keyword: BY
+                - column_reference:
+                    identifier: o_orderkey
+                - keyword: ASC
+                end_bracket: )
       from_clause:
         keyword: FROM
         from_expression:
diff --git a/test/fixtures/parser/snowflake/snowflake_col_position.yml b/test/fixtures/parser/snowflake/snowflake_col_position.yml
index bbc78e7a7de..9f2bc6260fe 100644
--- a/test/fixtures/parser/snowflake/snowflake_col_position.yml
+++ b/test/fixtures/parser/snowflake/snowflake_col_position.yml
@@ -21,24 +21,30 @@ file:
         from_expression:
           from_expression_element:
             table_expression:
-              start_bracket: (
-              values_clause:
-              - keyword: values
-              - start_bracket: (
-              - literal: "'toffee'"
-              - comma: ','
-              - literal: '5'
-              - end_bracket: )
-              - comma: ','
-              - start_bracket: (
-              - literal: "'starburst'"
-              - comma: ','
-              - literal: '8'
-              - end_bracket: )
-              - comma: ','
-              - start_bracket: (
-              - literal: "'flying_saucer'"
-              - comma: ','
-              - literal: '1'
-              - end_bracket: )
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                values_clause:
+                - keyword: values
+                - bracketed:
+                  - start_bracket: (
+                  - expression:
+                      literal: "'toffee'"
+                  - comma: ','
+                  - expression:
+                      literal: '5'
+                  - end_bracket: )
+                - comma: ','
+                - bracketed:
+                  - start_bracket: (
+                  - literal: "'starburst'"
+                  - comma: ','
+                  - literal: '8'
+                  - end_bracket: )
+                - comma: ','
+                - bracketed:
+                  - start_bracket: (
+                  - literal: "'flying_saucer'"
+                  - comma: ','
+                  - literal: '1'
+                  - end_bracket: )
+                end_bracket: )
diff --git a/test/fixtures/parser/snowflake/snowflake_create_database.sql b/test/fixtures/parser/snowflake/snowflake_create_database.sql
new file mode 100644
index 00000000000..6ad7165bf34
--- /dev/null
+++ b/test/fixtures/parser/snowflake/snowflake_create_database.sql
@@ -0,0 +1,2 @@
+CREATE DATABASE MY_DATABASE;
+CREATE DATABASE IF NOT EXISTS MY_DATABASE;
\ No newline at end of file
diff --git a/test/fixtures/parser/snowflake/snowflake_create_database.yml b/test/fixtures/parser/snowflake/snowflake_create_database.yml
new file mode 100644
index 00000000000..7d00205ef7b
--- /dev/null
+++ b/test/fixtures/parser/snowflake/snowflake_create_database.yml
@@ -0,0 +1,18 @@
+file:
+- statement:
+    create_database_statement:
+    - keyword: CREATE
+    - keyword: DATABASE
+    - database_reference:
+        identifier: MY_DATABASE
+- statement_terminator: ;
+- statement:
+    create_database_statement:
+    - keyword: CREATE
+    - keyword: DATABASE
+    - keyword: IF
+    - keyword: NOT
+    - keyword: EXISTS
+    - database_reference:
+        identifier: MY_DATABASE
+- statement_terminator: ;
diff --git a/test/fixtures/parser/snowflake/snowflake_create_role.sql b/test/fixtures/parser/snowflake/snowflake_create_role.sql
index 59d2add5db2..0ea429144c0 100644
--- a/test/fixtures/parser/snowflake/snowflake_create_role.sql
+++ b/test/fixtures/parser/snowflake/snowflake_create_role.sql
@@ -1 +1,3 @@
+CREATE ROLE MY_ROLE;
+CREATE ROLE "my_role";
 CREATE OR REPLACE ROLE IF NOT EXISTS foo_role COMMENT = 'this is a fake role'
\ No newline at end of file
diff --git a/test/fixtures/parser/snowflake/snowflake_create_role.yml b/test/fixtures/parser/snowflake/snowflake_create_role.yml
index e2d5e9f656e..afcb34aed3d 100644
--- a/test/fixtures/parser/snowflake/snowflake_create_role.yml
+++ b/test/fixtures/parser/snowflake/snowflake_create_role.yml
@@ -1,5 +1,19 @@
 file:
-  statement:
+- statement:
+    create_role_statement:
+    - keyword: CREATE
+    - keyword: ROLE
+    - object_reference:
+        identifier: MY_ROLE
+- statement_terminator: ;
+- statement:
+    create_role_statement:
+    - keyword: CREATE
+    - keyword: ROLE
+    - object_reference:
+        identifier: '"my_role"'
+- statement_terminator: ;
+- statement:
     create_role_statement:
     - keyword: CREATE
     - binary_operator: OR
diff --git a/test/fixtures/parser/snowflake/snowflake_create_schema.sql b/test/fixtures/parser/snowflake/snowflake_create_schema.sql
new file mode 100644
index 00000000000..c6ced03f429
--- /dev/null
+++ b/test/fixtures/parser/snowflake/snowflake_create_schema.sql
@@ -0,0 +1,2 @@
+create schema mytestschema_clone_restore clone testschema;
+create schema mytestschema_clone_restore clone testschema before (timestamp => to_timestamp(40*365*86400));
\ No newline at end of file
diff --git a/test/fixtures/parser/snowflake/snowflake_create_schema.yml b/test/fixtures/parser/snowflake/snowflake_create_schema.yml
new file mode 100644
index 00000000000..32ca05edde9
--- /dev/null
+++ b/test/fixtures/parser/snowflake/snowflake_create_schema.yml
@@ -0,0 +1,37 @@
+file:
+- statement:
+    create_clone_statement:
+    - keyword: create
+    - keyword: schema
+    - identifier: mytestschema_clone_restore
+    - keyword: clone
+    - identifier: testschema
+- statement_terminator: ;
+- statement:
+    create_clone_statement:
+    - keyword: create
+    - keyword: schema
+    - identifier: mytestschema_clone_restore
+    - keyword: clone
+    - identifier: testschema
+    - from_before_expression:
+        keyword: before
+        bracketed:
+          start_bracket: (
+          keyword: timestamp
+          parameter_assigner: =>
+          expression:
+            function:
+              function_name:
+                function_name_identifier: to_timestamp
+              bracketed:
+                start_bracket: (
+                expression:
+                - literal: '40'
+                - binary_operator: '*'
+                - literal: '365'
+                - binary_operator: '*'
+                - literal: '86400'
+                end_bracket: )
+          end_bracket: )
+- statement_terminator: ;
diff --git a/test/fixtures/parser/snowflake/snowflake_first_value_ignore_nulls.yml b/test/fixtures/parser/snowflake/snowflake_first_value_ignore_nulls.yml
index a444eb9f787..e582ae78a26 100644
--- a/test/fixtures/parser/snowflake/snowflake_first_value_ignore_nulls.yml
+++ b/test/fixtures/parser/snowflake/snowflake_first_value_ignore_nulls.yml
@@ -9,36 +9,38 @@ file:
       - comma: ','
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: coalesce
-          - start_bracket: (
-          - expression:
-              function:
-              - function_name:
-                  function_name_identifier: first_value
-              - start_bracket: (
-              - expression:
-                  case_expression:
-                  - keyword: case
-                  - keyword: when
+            bracketed:
+            - start_bracket: (
+            - expression:
+                function:
+                  function_name:
+                    function_name_identifier: first_value
+                  bracketed:
+                  - start_bracket: (
                   - expression:
-                      column_reference:
-                        identifier: a
-                  - keyword: then
-                  - expression:
-                      column_reference:
-                        identifier: b
-                  - keyword: else
-                  - expression:
-                      literal: 'null'
-                  - keyword: end
-              - keyword: ignore
-              - keyword: nulls
-              - end_bracket: )
-          - comma: ','
-          - expression:
-              literal: 'false'
-          - end_bracket: )
+                      case_expression:
+                      - keyword: case
+                      - keyword: when
+                      - expression:
+                          column_reference:
+                            identifier: a
+                      - keyword: then
+                      - expression:
+                          column_reference:
+                            identifier: b
+                      - keyword: else
+                      - expression:
+                          literal: 'null'
+                      - keyword: end
+                  - keyword: ignore
+                  - keyword: nulls
+                  - end_bracket: )
+            - comma: ','
+            - expression:
+                literal: 'false'
+            - end_bracket: )
           alias_expression:
             keyword: as
             identifier: c
diff --git a/test/fixtures/parser/snowflake/snowflake_grant_revoke.sql b/test/fixtures/parser/snowflake/snowflake_grant_revoke.sql
new file mode 100644
index 00000000000..d998898de32
--- /dev/null
+++ b/test/fixtures/parser/snowflake/snowflake_grant_revoke.sql
@@ -0,0 +1,29 @@
+GRANT OWNERSHIP ON SCHEMA MY_DATABASE.MY_SCHEMA TO ROLE MY_ROLE;
+
+GRANT ROLE MY_ROLE TO ROLE MY_OTHER_ROLE;
+
+grant use_any_role on integration external_oauth_1 to role1;
+
+grant ownership on table myschema.mytable to role analyst;
+
+grant ownership on all tables in schema public to role analyst;
+
+grant ownership on all tables in schema mydb.public to role analyst;
+
+grant ownership on all tables in schema mydb.public to role analyst copy current grants;
+
+revoke role analyst from role sysadmin;
+
+revoke select,insert on future tables in schema mydb.myschema from role role1;
+
+revoke all privileges on function add5(number) from role analyst;
+
+revoke grant option for operate on warehouse report_wh from role analyst;
+
+revoke select on all tables in schema mydb.myschema from role analyst;
+
+revoke operate on warehouse report_wh from role analyst;
+
+revoke reference_usage on database database2 from share share1;
+
+GRANT OWNERSHIP ON ROLE TEST_ROLE TO ROLE DIFFERENT_ROLE;
diff --git a/test/fixtures/parser/snowflake/snowflake_grant_revoke.yml b/test/fixtures/parser/snowflake/snowflake_grant_revoke.yml
new file mode 100644
index 00000000000..ec616dda95b
--- /dev/null
+++ b/test/fixtures/parser/snowflake/snowflake_grant_revoke.yml
@@ -0,0 +1,233 @@
+file:
+- statement:
+    access_statement:
+    - keyword: GRANT
+    - keyword: OWNERSHIP
+    - keyword: 'ON'
+    - keyword: SCHEMA
+    - object_reference:
+      - identifier: MY_DATABASE
+      - dot: .
+      - identifier: MY_SCHEMA
+    - keyword: TO
+    - keyword: ROLE
+    - object_reference:
+        identifier: MY_ROLE
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: GRANT
+    - keyword: ROLE
+    - object_reference:
+        identifier: MY_ROLE
+    - keyword: TO
+    - keyword: ROLE
+    - object_reference:
+        identifier: MY_OTHER_ROLE
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: grant
+    - keyword: use_any_role
+    - keyword: 'on'
+    - keyword: integration
+    - object_reference:
+        identifier: external_oauth_1
+    - keyword: to
+    - object_reference:
+        identifier: role1
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: grant
+    - keyword: ownership
+    - keyword: 'on'
+    - keyword: table
+    - object_reference:
+      - identifier: myschema
+      - dot: .
+      - identifier: mytable
+    - keyword: to
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: grant
+    - keyword: ownership
+    - keyword: 'on'
+    - keyword: all
+    - keyword: tables
+    - keyword: in
+    - keyword: schema
+    - object_reference:
+        identifier: public
+    - keyword: to
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: grant
+    - keyword: ownership
+    - keyword: 'on'
+    - keyword: all
+    - keyword: tables
+    - keyword: in
+    - keyword: schema
+    - object_reference:
+      - identifier: mydb
+      - dot: .
+      - identifier: public
+    - keyword: to
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: grant
+    - keyword: ownership
+    - keyword: 'on'
+    - keyword: all
+    - keyword: tables
+    - keyword: in
+    - keyword: schema
+    - object_reference:
+      - identifier: mydb
+      - dot: .
+      - identifier: public
+    - keyword: to
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+    - keyword: copy
+    - keyword: current
+    - keyword: grants
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+    - keyword: from
+    - keyword: role
+    - object_reference:
+        identifier: sysadmin
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: select
+    - comma: ','
+    - keyword: insert
+    - keyword: 'on'
+    - keyword: future
+    - keyword: tables
+    - keyword: in
+    - keyword: schema
+    - object_reference:
+      - identifier: mydb
+      - dot: .
+      - identifier: myschema
+    - keyword: from
+    - keyword: role
+    - object_reference:
+        identifier: role1
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: all
+    - keyword: privileges
+    - keyword: 'on'
+    - keyword: function
+    - object_reference:
+        identifier: add5
+    - base:
+        bracketed:
+          start_bracket: (
+          data_type:
+            data_type_identifier: number
+          end_bracket: )
+    - keyword: from
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: grant
+    - keyword: option
+    - keyword: for
+    - keyword: operate
+    - keyword: 'on'
+    - keyword: warehouse
+    - object_reference:
+        identifier: report_wh
+    - keyword: from
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: select
+    - keyword: 'on'
+    - keyword: all
+    - keyword: tables
+    - keyword: in
+    - keyword: schema
+    - object_reference:
+      - identifier: mydb
+      - dot: .
+      - identifier: myschema
+    - keyword: from
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: operate
+    - keyword: 'on'
+    - keyword: warehouse
+    - object_reference:
+        identifier: report_wh
+    - keyword: from
+    - keyword: role
+    - object_reference:
+        identifier: analyst
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: revoke
+    - keyword: reference_usage
+    - keyword: 'on'
+    - keyword: database
+    - object_reference:
+        identifier: database2
+    - keyword: from
+    - keyword: share
+    - object_reference:
+        identifier: share1
+- statement_terminator: ;
+- statement:
+    access_statement:
+    - keyword: GRANT
+    - keyword: OWNERSHIP
+    - keyword: 'ON'
+    - keyword: ROLE
+    - object_reference:
+        identifier: TEST_ROLE
+    - keyword: TO
+    - keyword: ROLE
+    - object_reference:
+        identifier: DIFFERENT_ROLE
+- statement_terminator: ;
diff --git a/test/fixtures/parser/snowflake/snowflake_lateral_flatten_after_join.yml b/test/fixtures/parser/snowflake/snowflake_lateral_flatten_after_join.yml
index b33b326a46c..1921d9e5081 100644
--- a/test/fixtures/parser/snowflake/snowflake_lateral_flatten_after_join.yml
+++ b/test/fixtures/parser/snowflake/snowflake_lateral_flatten_after_join.yml
@@ -16,41 +16,44 @@ file:
       - comma: ','
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: iff
-          - start_bracket: (
-          - expression:
-              function:
-                function_name:
-                  function_name_identifier: rank
-                start_bracket: (
-                end_bracket: )
-                over_clause:
-                  keyword: over
-                  start_bracket: (
-                  window_specification:
-                    partitionby_clause:
-                    - keyword: partition
-                    - keyword: by
-                    - expression:
-                        column_reference:
-                          identifier: id
-                    orderby_clause:
-                    - keyword: order
-                    - keyword: by
-                    - column_reference:
-                        identifier: t_id
-                    - keyword: desc
-                  end_bracket: )
-              comparison_operator: '='
-              literal: '1'
-          - comma: ','
-          - expression:
-              literal: 'true'
-          - comma: ','
-          - expression:
-              literal: 'false'
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                function:
+                  function_name:
+                    function_name_identifier: rank
+                  bracketed:
+                    start_bracket: (
+                    end_bracket: )
+                  over_clause:
+                    keyword: over
+                    bracketed:
+                      start_bracket: (
+                      window_specification:
+                        partitionby_clause:
+                        - keyword: partition
+                        - keyword: by
+                        - expression:
+                            column_reference:
+                              identifier: id
+                        orderby_clause:
+                        - keyword: order
+                        - keyword: by
+                        - column_reference:
+                            identifier: t_id
+                        - keyword: desc
+                      end_bracket: )
+                comparison_operator: '='
+                literal: '1'
+            - comma: ','
+            - expression:
+                literal: 'true'
+            - comma: ','
+            - expression:
+                literal: 'false'
+            - end_bracket: )
           alias_expression:
             keyword: as
             identifier: most_recent
@@ -70,18 +73,19 @@ file:
                   identifier: b
           - join_on_condition:
               keyword: 'on'
-              start_bracket: (
-              expression:
-              - column_reference:
-                - identifier: b
-                - dot: .
-                - identifier: c_id
-              - comparison_operator: '='
-              - column_reference:
-                - identifier: a
-                - dot: .
-                - identifier: c_id
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                - column_reference:
+                  - identifier: b
+                  - dot: .
+                  - identifier: c_id
+                - comparison_operator: '='
+                - column_reference:
+                  - identifier: a
+                  - dot: .
+                  - identifier: c_id
+                end_bracket: )
       - comma: ','
       - from_expression:
           from_expression_element:
@@ -90,12 +94,13 @@ file:
               function:
                 function_name:
                   function_name_identifier: flatten
-                start_bracket: (
-                snowflake_keyword_expression:
-                  parameter: input
-                  parameter_assigner: =>
-                  column_reference:
-                  - identifier: b
-                  - dot: .
-                  - identifier: cool_ids
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  snowflake_keyword_expression:
+                    parameter: input
+                    parameter_assigner: =>
+                    column_reference:
+                    - identifier: b
+                    - dot: .
+                    - identifier: cool_ids
+                  end_bracket: )
diff --git a/test/fixtures/parser/snowflake/snowflake_pivot.yml b/test/fixtures/parser/snowflake/snowflake_pivot.yml
index 02947bf87ff..ba0e99ef63f 100644
--- a/test/fixtures/parser/snowflake/snowflake_pivot.yml
+++ b/test/fixtures/parser/snowflake/snowflake_pivot.yml
@@ -15,32 +15,36 @@ file:
               table_reference:
                 identifier: my_tbl
           from_pivot_expression:
-          - keyword: PIVOT
-          - start_bracket: (
-          - function:
-              function_name:
-                function_name_identifier: min
-              start_bracket: (
-              expression:
-                column_reference:
-                  identifier: f_val
-              end_bracket: )
-          - keyword: FOR
-          - identifier: f_id
-          - keyword: IN
-          - start_bracket: (
-          - literal: '1'
-          - comma: ','
-          - literal: '2'
-          - end_bracket: )
-          - end_bracket: )
+            keyword: PIVOT
+            bracketed:
+            - start_bracket: (
+            - function:
+                function_name:
+                  function_name_identifier: min
+                bracketed:
+                  start_bracket: (
+                  expression:
+                    column_reference:
+                      identifier: f_val
+                  end_bracket: )
+            - keyword: FOR
+            - identifier: f_id
+            - keyword: IN
+            - bracketed:
+              - start_bracket: (
+              - literal: '1'
+              - comma: ','
+              - literal: '2'
+              - end_bracket: )
+            - end_bracket: )
           table_alias_expression:
             alias_expression:
               keyword: AS
               identifier: f
-              start_bracket: (
-              identifier_list:
-              - identifier: a
-              - comma: ','
-              - identifier: b
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                identifier_list:
+                - identifier: a
+                - comma: ','
+                - identifier: b
+                end_bracket: )
diff --git a/test/fixtures/parser/snowflake/snowflake_qualify.yml b/test/fixtures/parser/snowflake/snowflake_qualify.yml
index 73b51310f17..b855b09ecde 100644
--- a/test/fixtures/parser/snowflake/snowflake_qualify.yml
+++ b/test/fixtures/parser/snowflake/snowflake_qualify.yml
@@ -23,23 +23,25 @@ file:
           function:
             function_name:
               function_name_identifier: row_number
-            start_bracket: (
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              end_bracket: )
             over_clause:
               keyword: over
-              start_bracket: (
-              window_specification:
-                partitionby_clause:
-                - keyword: partition
-                - keyword: by
-                - expression:
-                    column_reference:
+              bracketed:
+                start_bracket: (
+                window_specification:
+                  partitionby_clause:
+                  - keyword: partition
+                  - keyword: by
+                  - expression:
+                      column_reference:
+                        identifier: col1
+                  orderby_clause:
+                  - keyword: order
+                  - keyword: by
+                  - column_reference:
                       identifier: col1
-                orderby_clause:
-                - keyword: order
-                - keyword: by
-                - column_reference:
-                    identifier: col1
-              end_bracket: )
+                end_bracket: )
           comparison_operator: '='
           literal: '1'
diff --git a/test/fixtures/parser/snowflake/snowflake_sample.yml b/test/fixtures/parser/snowflake/snowflake_sample.yml
index 8fdc3cfaf33..fc727d4d4ae 100644
--- a/test/fixtures/parser/snowflake/snowflake_sample.yml
+++ b/test/fixtures/parser/snowflake/snowflake_sample.yml
@@ -16,6 +16,7 @@ file:
                 identifier: real_data
           snowflake_sample_expression:
             keyword: sample
-            start_bracket: (
-            literal: '20'
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              literal: '20'
+              end_bracket: )
diff --git a/test/fixtures/parser/snowflake/snowflake_semi_structured.yml b/test/fixtures/parser/snowflake/snowflake_semi_structured.yml
index 9cefcb391ff..02d8c0f6ab8 100644
--- a/test/fixtures/parser/snowflake/snowflake_semi_structured.yml
+++ b/test/fixtures/parser/snowflake/snowflake_semi_structured.yml
@@ -108,10 +108,11 @@ file:
               function:
                 function_name:
                   function_name_identifier: flatten
-                start_bracket: (
-                snowflake_keyword_expression:
-                  parameter: INPUT
-                  parameter_assigner: =>
-                  column_reference:
-                    identifier: custom_fields
-                end_bracket: )
+                bracketed:
+                  start_bracket: (
+                  snowflake_keyword_expression:
+                    parameter: INPUT
+                    parameter_assigner: =>
+                    column_reference:
+                      identifier: custom_fields
+                  end_bracket: )
diff --git a/test/fixtures/parser/snowflake/snowflake_semi_structured_3.yml b/test/fixtures/parser/snowflake/snowflake_semi_structured_3.yml
index e704b83e1a4..153c4440a35 100644
--- a/test/fixtures/parser/snowflake/snowflake_semi_structured_3.yml
+++ b/test/fixtures/parser/snowflake/snowflake_semi_structured_3.yml
@@ -8,13 +8,14 @@ file:
           - function:
               function_name:
                 function_name_identifier: PARSE_JSON
-              start_bracket: (
-              expression:
-                column_reference:
-                - identifier: t
-                - dot: .
-                - identifier: metadata
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                  column_reference:
+                  - identifier: t
+                  - dot: .
+                  - identifier: metadata
+                end_bracket: )
           - array_accessor:
               start_square_bracket: '['
               expression:
@@ -33,13 +34,14 @@ file:
             function:
               function_name:
                 function_name_identifier: PARSE_JSON
-              start_bracket: (
-              expression:
-                column_reference:
-                - identifier: t
-                - dot: .
-                - identifier: metadata
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                  column_reference:
+                  - identifier: t
+                  - dot: .
+                  - identifier: metadata
+                end_bracket: )
             snowflake_semi_structured_expression:
               colon: ':'
               semi_structured_element: customer_id
diff --git a/test/fixtures/parser/snowflake/snowflake_use.sql b/test/fixtures/parser/snowflake/snowflake_use.sql
index 8f2d49e6e28..12b649867a1 100644
--- a/test/fixtures/parser/snowflake/snowflake_use.sql
+++ b/test/fixtures/parser/snowflake/snowflake_use.sql
@@ -5,3 +5,17 @@ use warehouse my_warehouse;
 use database my_database;
 
 use schema my_schema;
+
+USE ROLE "MY_ROLE";
+
+USE WAREHOUSE "MY_WAREHOUSE";
+
+USE DATABASE "MY_DATABASE";
+
+USE "MY_DATABASE";
+
+USE SCHEMA "MY_DATABASE"."MY_SCHEMA";
+
+USE SCHEMA "MY_SCHEMA";
+
+USE "MY_DATABASE"."MY_SCHEMA";
diff --git a/test/fixtures/parser/snowflake/snowflake_use.yml b/test/fixtures/parser/snowflake/snowflake_use.yml
index 0474c41c3ae..a7654bc2a1f 100644
--- a/test/fixtures/parser/snowflake/snowflake_use.yml
+++ b/test/fixtures/parser/snowflake/snowflake_use.yml
@@ -27,3 +27,54 @@ file:
     - object_reference:
         identifier: my_schema
 - statement_terminator: ;
+- statement:
+    use_statement:
+    - keyword: USE
+    - keyword: ROLE
+    - object_reference:
+        identifier: '"MY_ROLE"'
+- statement_terminator: ;
+- statement:
+    use_statement:
+    - keyword: USE
+    - keyword: WAREHOUSE
+    - object_reference:
+        identifier: '"MY_WAREHOUSE"'
+- statement_terminator: ;
+- statement:
+    use_statement:
+    - keyword: USE
+    - keyword: DATABASE
+    - object_reference:
+        identifier: '"MY_DATABASE"'
+- statement_terminator: ;
+- statement:
+    use_statement:
+      keyword: USE
+      object_reference:
+        identifier: '"MY_DATABASE"'
+- statement_terminator: ;
+- statement:
+    use_statement:
+    - keyword: USE
+    - keyword: SCHEMA
+    - object_reference:
+      - identifier: '"MY_DATABASE"'
+      - dot: .
+      - identifier: '"MY_SCHEMA"'
+- statement_terminator: ;
+- statement:
+    use_statement:
+    - keyword: USE
+    - keyword: SCHEMA
+    - object_reference:
+        identifier: '"MY_SCHEMA"'
+- statement_terminator: ;
+- statement:
+    use_statement:
+      keyword: USE
+      object_reference:
+      - identifier: '"MY_DATABASE"'
+      - dot: .
+      - identifier: '"MY_SCHEMA"'
+- statement_terminator: ;
diff --git a/test/fixtures/parser/snowflake/snowflake_window_function_ignore_nulls.yml b/test/fixtures/parser/snowflake/snowflake_window_function_ignore_nulls.yml
index 691551486b7..9cc6477701b 100644
--- a/test/fixtures/parser/snowflake/snowflake_window_function_ignore_nulls.yml
+++ b/test/fixtures/parser/snowflake/snowflake_window_function_ignore_nulls.yml
@@ -7,37 +7,39 @@ file:
           function:
           - function_name:
               function_name_identifier: FIRST_VALUE
-          - start_bracket: (
-          - expression:
-              column_reference:
-                identifier: foo
-          - end_bracket: )
+          - bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: foo
+              end_bracket: )
           - keyword: IGNORE
           - keyword: NULLS
           - over_clause:
               keyword: over
-              start_bracket: (
-              window_specification:
-                partitionby_clause:
-                - keyword: PARTITION
-                - keyword: BY
-                - expression:
-                    column_reference:
-                      identifier: buzz
-                orderby_clause:
-                - keyword: ORDER
-                - keyword: BY
-                - column_reference:
-                    identifier: bar
-                frame_clause:
-                - keyword: ROWS
-                - raw: BETWEEN
-                - raw: UNBOUNDED
-                - raw: PRECEDING
-                - raw: AND
-                - raw: CURRENT
-                - raw: ROW
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                window_specification:
+                  partitionby_clause:
+                  - keyword: PARTITION
+                  - keyword: BY
+                  - expression:
+                      column_reference:
+                        identifier: buzz
+                  orderby_clause:
+                  - keyword: ORDER
+                  - keyword: BY
+                  - column_reference:
+                      identifier: bar
+                  frame_clause:
+                  - keyword: ROWS
+                  - raw: BETWEEN
+                  - raw: UNBOUNDED
+                  - raw: PRECEDING
+                  - raw: AND
+                  - raw: CURRENT
+                  - raw: ROW
+                end_bracket: )
           alias_expression:
             keyword: AS
             identifier: bat
diff --git a/test/fixtures/parser/snowflake/snowflake_within_group.yml b/test/fixtures/parser/snowflake/snowflake_within_group.yml
index 09644908f73..65a4ce43351 100644
--- a/test/fixtures/parser/snowflake/snowflake_within_group.yml
+++ b/test/fixtures/parser/snowflake/snowflake_within_group.yml
@@ -5,68 +5,78 @@ file:
       common_table_expression:
         identifier: favourite_fruits
         keyword: as
-        start_bracket: (
-        select_statement:
-          select_clause:
-          - keyword: select
-          - select_clause_element:
-              column_reference:
-                identifier: column1
-              alias_expression:
-                keyword: as
-                identifier: name
-          - comma: ','
-          - select_clause_element:
-              column_reference:
-                identifier: column2
-              alias_expression:
-                keyword: as
-                identifier: colour
-          from_clause:
-            keyword: from
-            from_expression:
-              from_expression_element:
-                table_expression:
-                  start_bracket: (
-                  values_clause:
-                  - keyword: values
-                  - start_bracket: (
-                  - literal: "'apple'"
-                  - comma: ','
-                  - literal: "'green'"
-                  - end_bracket: )
-                  - comma: ','
-                  - start_bracket: (
-                  - literal: "'unripe banana'"
-                  - comma: ','
-                  - literal: "'green'"
-                  - end_bracket: )
-                  - comma: ','
-                  - start_bracket: (
-                  - literal: "'kiwi'"
-                  - comma: ','
-                  - literal: "'green'"
-                  - end_bracket: )
-                  - comma: ','
-                  - start_bracket: (
-                  - literal: "'blueberry'"
-                  - comma: ','
-                  - literal: "'blue'"
-                  - end_bracket: )
-                  - comma: ','
-                  - start_bracket: (
-                  - literal: "'strawberry'"
-                  - comma: ','
-                  - literal: "'red'"
-                  - end_bracket: )
-                  - comma: ','
-                  - start_bracket: (
-                  - literal: "'grape'"
-                  - comma: ','
-                  - literal: "'red'"
-                  - end_bracket: )
-                  end_bracket: )
-        end_bracket: )
+        bracketed:
+          start_bracket: (
+          select_statement:
+            select_clause:
+            - keyword: select
+            - select_clause_element:
+                column_reference:
+                  identifier: column1
+                alias_expression:
+                  keyword: as
+                  identifier: name
+            - comma: ','
+            - select_clause_element:
+                column_reference:
+                  identifier: column2
+                alias_expression:
+                  keyword: as
+                  identifier: colour
+            from_clause:
+              keyword: from
+              from_expression:
+                from_expression_element:
+                  table_expression:
+                    bracketed:
+                      start_bracket: (
+                      values_clause:
+                      - keyword: values
+                      - bracketed:
+                        - start_bracket: (
+                        - expression:
+                            literal: "'apple'"
+                        - comma: ','
+                        - expression:
+                            literal: "'green'"
+                        - end_bracket: )
+                      - comma: ','
+                      - bracketed:
+                        - start_bracket: (
+                        - literal: "'unripe banana'"
+                        - comma: ','
+                        - literal: "'green'"
+                        - end_bracket: )
+                      - comma: ','
+                      - bracketed:
+                        - start_bracket: (
+                        - literal: "'kiwi'"
+                        - comma: ','
+                        - literal: "'green'"
+                        - end_bracket: )
+                      - comma: ','
+                      - bracketed:
+                        - start_bracket: (
+                        - literal: "'blueberry'"
+                        - comma: ','
+                        - literal: "'blue'"
+                        - end_bracket: )
+                      - comma: ','
+                      - bracketed:
+                        - start_bracket: (
+                        - literal: "'strawberry'"
+                        - comma: ','
+                        - literal: "'red'"
+                        - end_bracket: )
+                      - comma: ','
+                      - bracketed:
+                        - start_bracket: (
+                        - literal: "'grape'"
+                        - comma: ','
+                        - literal: "'red'"
+                        - end_bracket: )
+                      end_bracket: )
+          end_bracket: )
       select_statement:
         select_clause:
         - keyword: select
@@ -76,26 +86,28 @@ file:
         - comma: ','
         - select_clause_element:
             function:
-            - function_name:
+              function_name:
                 function_name_identifier: listagg
-            - start_bracket: (
-            - expression:
-                column_reference:
-                  identifier: name
-            - comma: ','
-            - expression:
-                literal: "', '"
-            - end_bracket: )
-            - withingroup_clause:
-              - keyword: within
-              - keyword: group
+              bracketed:
               - start_bracket: (
-              - orderby_clause:
-                - keyword: order
-                - keyword: by
-                - column_reference:
+              - expression:
+                  column_reference:
                     identifier: name
+              - comma: ','
+              - expression:
+                  literal: "', '"
               - end_bracket: )
+              withingroup_clause:
+              - keyword: within
+              - keyword: group
+              - bracketed:
+                  start_bracket: (
+                  orderby_clause:
+                  - keyword: order
+                  - keyword: by
+                  - column_reference:
+                      identifier: name
+                  end_bracket: )
             alias_expression:
               keyword: as
               identifier: fruits
diff --git a/test/fixtures/parser/teradata/collect_stats.yml b/test/fixtures/parser/teradata/collect_stats.yml
index 0fc3f4be717..7f428e56403 100644
--- a/test/fixtures/parser/teradata/collect_stats.yml
+++ b/test/fixtures/parser/teradata/collect_stats.yml
@@ -4,10 +4,11 @@ file:
     - keyword: COLLECT
     - keyword: STATISTICS
     - keyword: COLUMN
-    - start_bracket: (
-    - object_reference:
-        identifier: IND_TIPO_TARJETA
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        object_reference:
+          identifier: IND_TIPO_TARJETA
+        end_bracket: )
     - keyword: 'ON'
     - object_reference:
       - identifier: DB_1
@@ -19,19 +20,20 @@ file:
     - keyword: COLLECT
     - keyword: STATISTICS
     - keyword: INDEX
-    - start_bracket: (
-    - object_reference:
-        identifier: COD_TARJETA
-    - comma: ','
-    - object_reference:
-        identifier: COD_EST
-    - comma: ','
-    - object_reference:
-        identifier: IND_TIPO_TARJETA
-    - comma: ','
-    - object_reference:
-        identifier: FEC_ANIO_MES
-    - end_bracket: )
+    - bracketed:
+      - start_bracket: (
+      - object_reference:
+          identifier: COD_TARJETA
+      - comma: ','
+      - object_reference:
+          identifier: COD_EST
+      - comma: ','
+      - object_reference:
+          identifier: IND_TIPO_TARJETA
+      - comma: ','
+      - object_reference:
+          identifier: FEC_ANIO_MES
+      - end_bracket: )
     - keyword: 'ON'
     - object_reference:
       - identifier: DB_1
diff --git a/test/fixtures/parser/teradata/create_table_stmt.yml b/test/fixtures/parser/teradata/create_table_stmt.yml
index da6740a38e2..9e3acbee383 100644
--- a/test/fixtures/parser/teradata/create_table_stmt.yml
+++ b/test/fixtures/parser/teradata/create_table_stmt.yml
@@ -25,21 +25,24 @@ file:
       - comma: ','
       - keyword: DEFAULT
       - keyword: MERGEBLOCKRATIO
-    - start_bracket: (
-    - column_definition:
-        column_reference:
-          identifier: FIELD1
-        td_internal_data_type:
-          data_type_identifier: CHAR
-          start_bracket: (
-          expression:
-            literal: '9'
-          end_bracket: )
-    - end_bracket: )
+    - bracketed:
+        start_bracket: (
+        column_definition:
+          column_reference:
+            identifier: FIELD1
+          td_internal_data_type:
+            data_type_identifier: CHAR
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '9'
+              end_bracket: )
+        end_bracket: )
     - td_table_constraint:
       - keyword: PRIMARY
       - keyword: INDEX
-      - start_bracket: (
-      - identifier: FIELD1
-      - end_bracket: )
+      - bracketed:
+          start_bracket: (
+          identifier: FIELD1
+          end_bracket: )
   statement_terminator: ;
diff --git a/test/fixtures/parser/teradata/create_table_stmt_2.yml b/test/fixtures/parser/teradata/create_table_stmt_2.yml
index 234066e9383..f4bcc75ca48 100644
--- a/test/fixtures/parser/teradata/create_table_stmt_2.yml
+++ b/test/fixtures/parser/teradata/create_table_stmt_2.yml
@@ -6,114 +6,120 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: TABLE_2
-    - start_bracket: (
-    - column_definition:
-      - column_reference:
-          identifier: CHAR_FIELD
-      - td_internal_data_type:
-          data_type_identifier: CHAR
-          start_bracket: (
-          expression:
-            literal: '19'
-          end_bracket: )
-      - td_column_attribute_constraint:
-        - keyword: CHARACTER
-        - keyword: SET
-        - identifier: LATIN
-      - td_column_attribute_constraint:
-        - keyword: NOT
-        - keyword: CASESPECIFIC
-      - column_constraint:
-        - keyword: NOT
-        - keyword: 'NULL'
-    - comma: ','
-    - column_definition:
-        column_reference:
-          identifier: DATE_FIELD
-        td_internal_data_type:
-          data_type_identifier: DATE
-          keyword: FORMAT
-          literal: "'YYYY-MM-DD'"
-        column_constraint:
-        - keyword: NOT
-        - keyword: 'NULL'
-    - comma: ','
-    - column_definition:
-        column_reference:
-          identifier: BYTE_FIELD
-        td_internal_data_type:
-          data_type_identifier: BYTEINT
-        td_column_attribute_constraint:
-          keyword: COMPRESS
-          literal: '0'
-    - comma: ','
-    - column_definition:
-        column_reference:
-          identifier: DECIMAL_FIELD
-        td_internal_data_type:
-        - data_type_identifier: DECIMAL
-        - start_bracket: (
-        - expression:
-            literal: '15'
-        - comma: ','
-        - expression:
-            literal: '2'
-        - end_bracket: )
-        td_column_attribute_constraint:
-        - keyword: COMPRESS
-        - start_bracket: (
-        - literal: '50.00'
-        - comma: ','
-        - literal: '45.50'
-        - comma: ','
-        - literal: '40.00'
-        - comma: ','
-        - literal: '30.00'
-        - comma: ','
-        - literal: '27.80'
-        - comma: ','
-        - literal: '27.05'
-        - comma: ','
-        - literal: '20.00'
-        - comma: ','
-        - literal: '17.87'
-        - comma: ','
-        - literal: '17.56'
-        - comma: ','
-        - literal: '17.41'
-        - comma: ','
-        - literal: '17.26'
-        - comma: ','
-        - literal: '17.11'
-        - comma: ','
-        - literal: '16.96'
-        - comma: ','
-        - literal: '16.82'
-        - comma: ','
-        - literal: '16.68'
-        - end_bracket: )
-    - comma: ','
-    - column_definition:
-        column_reference:
-          identifier: TIMESTAMP_FIELD
-        td_internal_data_type:
-          data_type_identifier: TIMESTAMP
-          start_bracket: (
-          expression:
-            literal: '6'
-          end_bracket: )
-        column_constraint:
-        - keyword: NOT
-        - keyword: 'NULL'
-    - end_bracket: )
-    - td_table_constraint:
-      - keyword: PRIMARY
-      - keyword: INDEX
+    - bracketed:
       - start_bracket: (
-      - identifier: CHAR_FIELD
+      - column_definition:
+        - column_reference:
+            identifier: CHAR_FIELD
+        - td_internal_data_type:
+            data_type_identifier: CHAR
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '19'
+              end_bracket: )
+        - td_column_attribute_constraint:
+          - keyword: CHARACTER
+          - keyword: SET
+          - identifier: LATIN
+        - td_column_attribute_constraint:
+          - keyword: NOT
+          - keyword: CASESPECIFIC
+        - column_constraint:
+          - keyword: NOT
+          - keyword: 'NULL'
+      - comma: ','
+      - column_definition:
+          column_reference:
+            identifier: DATE_FIELD
+          td_internal_data_type:
+            data_type_identifier: DATE
+            keyword: FORMAT
+            literal: "'YYYY-MM-DD'"
+          column_constraint:
+          - keyword: NOT
+          - keyword: 'NULL'
+      - comma: ','
+      - column_definition:
+          column_reference:
+            identifier: BYTE_FIELD
+          td_internal_data_type:
+            data_type_identifier: BYTEINT
+          td_column_attribute_constraint:
+            keyword: COMPRESS
+            literal: '0'
       - comma: ','
-      - identifier: DATE_FIELD
+      - column_definition:
+          column_reference:
+            identifier: DECIMAL_FIELD
+          td_internal_data_type:
+            data_type_identifier: DECIMAL
+            bracketed:
+            - start_bracket: (
+            - expression:
+                literal: '15'
+            - comma: ','
+            - expression:
+                literal: '2'
+            - end_bracket: )
+          td_column_attribute_constraint:
+            keyword: COMPRESS
+            bracketed:
+            - start_bracket: (
+            - literal: '50.00'
+            - comma: ','
+            - literal: '45.50'
+            - comma: ','
+            - literal: '40.00'
+            - comma: ','
+            - literal: '30.00'
+            - comma: ','
+            - literal: '27.80'
+            - comma: ','
+            - literal: '27.05'
+            - comma: ','
+            - literal: '20.00'
+            - comma: ','
+            - literal: '17.87'
+            - comma: ','
+            - literal: '17.56'
+            - comma: ','
+            - literal: '17.41'
+            - comma: ','
+            - literal: '17.26'
+            - comma: ','
+            - literal: '17.11'
+            - comma: ','
+            - literal: '16.96'
+            - comma: ','
+            - literal: '16.82'
+            - comma: ','
+            - literal: '16.68'
+            - end_bracket: )
       - comma: ','
-      - identifier: BYTE_FIELD
+      - column_definition:
+          column_reference:
+            identifier: TIMESTAMP_FIELD
+          td_internal_data_type:
+            data_type_identifier: TIMESTAMP
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '6'
+              end_bracket: )
+          column_constraint:
+          - keyword: NOT
+          - keyword: 'NULL'
       - end_bracket: )
+    - td_table_constraint:
+      - keyword: PRIMARY
+      - keyword: INDEX
+      - bracketed:
+        - start_bracket: (
+        - identifier: CHAR_FIELD
+        - comma: ','
+        - identifier: DATE_FIELD
+        - comma: ','
+        - identifier: BYTE_FIELD
+        - end_bracket: )
   statement_terminator: ;
diff --git a/test/fixtures/parser/teradata/create_table_stmt_3.yml b/test/fixtures/parser/teradata/create_table_stmt_3.yml
index 1b93155383d..e0d13cf2a71 100644
--- a/test/fixtures/parser/teradata/create_table_stmt_3.yml
+++ b/test/fixtures/parser/teradata/create_table_stmt_3.yml
@@ -6,79 +6,85 @@ file:
     - keyword: TABLE
     - table_reference:
         identifier: NUM_LTR_DESVINCULADOS_ADH
-    - start_bracket: (
-    - column_definition:
-      - column_reference:
-          identifier: DES_EVENTO
-      - td_internal_data_type:
-          data_type_identifier: VARCHAR
-          start_bracket: (
-          expression:
-            literal: '255'
-          end_bracket: )
-      - td_column_attribute_constraint:
-        - keyword: CHARACTER
-        - keyword: SET
-        - identifier: LATIN
-      - td_column_attribute_constraint:
-        - keyword: NOT
-        - keyword: CASESPECIFIC
-      - td_column_attribute_constraint:
-        - keyword: COMPRESS
-        - start_bracket: (
-        - literal: "'Cambio de bandera'"
-        - comma: ','
-        - literal: "'Cierre'"
-        - end_bracket: )
-    - comma: ','
-    - column_definition:
-        column_reference:
-          identifier: IND_CONTINUA
-        td_internal_data_type:
-          data_type_identifier: BYTEINT
-        td_column_attribute_constraint:
-          keyword: COMPRESS
-    - end_bracket: )
-    - td_table_constraint:
-      - keyword: PRIMARY
-      - keyword: INDEX
+    - bracketed:
       - start_bracket: (
-      - identifier: COD_TARJETA
-      - comma: ','
-      - identifier: COD_EST
-      - comma: ','
-      - identifier: FEC_CIERRE_EST
+      - column_definition:
+        - column_reference:
+            identifier: DES_EVENTO
+        - td_internal_data_type:
+            data_type_identifier: VARCHAR
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: '255'
+              end_bracket: )
+        - td_column_attribute_constraint:
+          - keyword: CHARACTER
+          - keyword: SET
+          - identifier: LATIN
+        - td_column_attribute_constraint:
+          - keyword: NOT
+          - keyword: CASESPECIFIC
+        - td_column_attribute_constraint:
+            keyword: COMPRESS
+            bracketed:
+            - start_bracket: (
+            - literal: "'Cambio de bandera'"
+            - comma: ','
+            - literal: "'Cierre'"
+            - end_bracket: )
       - comma: ','
-      - identifier: IND_TIPO_TARJETA
+      - column_definition:
+          column_reference:
+            identifier: IND_CONTINUA
+          td_internal_data_type:
+            data_type_identifier: BYTEINT
+          td_column_attribute_constraint:
+            keyword: COMPRESS
       - end_bracket: )
+    - td_table_constraint:
+      - keyword: PRIMARY
+      - keyword: INDEX
+      - bracketed:
+        - start_bracket: (
+        - identifier: COD_TARJETA
+        - comma: ','
+        - identifier: COD_EST
+        - comma: ','
+        - identifier: FEC_CIERRE_EST
+        - comma: ','
+        - identifier: IND_TIPO_TARJETA
+        - end_bracket: )
       - keyword: PARTITION
       - keyword: BY
       - td_partitioning_level:
-        - function_name:
+          function_name:
             function_name_identifier: RANGE_N
-        - start_bracket: (
-        - raw: FEC_OPERACION
-        - raw: BETWEEN
-        - raw: DATE
-        - raw: "'2007-01-01'"
-        - raw: AND
-        - raw: DATE
-        - raw: "'2022-01-01'"
-        - raw: EACH
-        - raw: INTERVAL
-        - raw: "'1'"
-        - raw: MONTH
-        - comma: ','
-        - raw: 'NO'
-        - raw: RANGE
-        - raw: OR
-        - raw: UNKNOWN
-        - end_bracket: )
+          bracketed:
+          - start_bracket: (
+          - raw: FEC_OPERACION
+          - raw: BETWEEN
+          - raw: DATE
+          - raw: "'2007-01-01'"
+          - raw: AND
+          - raw: DATE
+          - raw: "'2022-01-01'"
+          - raw: EACH
+          - raw: INTERVAL
+          - raw: "'1'"
+          - raw: MONTH
+          - comma: ','
+          - raw: 'NO'
+          - raw: RANGE
+          - raw: OR
+          - raw: UNKNOWN
+          - end_bracket: )
       - keyword: INDEX
       - object_reference:
           identifier: HOPR_TRN_TRAV_SIN_MP_I
-      - start_bracket: (
-      - column_reference:
-          identifier: IND_TIPO_TARJETA
-      - end_bracket: )
+      - bracketed:
+          start_bracket: (
+          column_reference:
+            identifier: IND_TIPO_TARJETA
+          end_bracket: )
   statement_terminator: ;
diff --git a/test/fixtures/parser/teradata/select_stmt.yml b/test/fixtures/parser/teradata/select_stmt.yml
index 94c3dd4b00f..9c5deb04c42 100644
--- a/test/fixtures/parser/teradata/select_stmt.yml
+++ b/test/fixtures/parser/teradata/select_stmt.yml
@@ -5,20 +5,21 @@ file:
       - keyword: SELECT
       - select_clause_element:
           function:
-          - function_name:
+            function_name:
               function_name_identifier: ADD_MONTHS
-          - start_bracket: (
-          - expression:
-              column_reference:
-              - identifier: abandono
-              - dot: .
-              - identifier: FEC_CIERRE_EST
-          - comma: ','
-          - expression:
-              numeric_literal:
-                binary_operator: '-'
-                literal: '12'
-          - end_bracket: )
+            bracketed:
+            - start_bracket: (
+            - expression:
+                column_reference:
+                - identifier: abandono
+                - dot: .
+                - identifier: FEC_CIERRE_EST
+            - comma: ','
+            - expression:
+                numeric_literal:
+                  binary_operator: '-'
+                  literal: '12'
+            - end_bracket: )
           alias_expression:
             keyword: AS
             identifier: FEC_CIERRE_EST_ULT12
@@ -27,15 +28,16 @@ file:
           function:
             function_name:
               function_name_identifier: CAST
-            start_bracket: (
-            expression:
-              literal: "'200010'"
-            keyword: AS
-            td_internal_data_type:
-              data_type_identifier: DATE
-              keyword: FORMAT
-              literal: "'YYYYMM'"
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                literal: "'200010'"
+              keyword: AS
+              td_internal_data_type:
+                data_type_identifier: DATE
+                keyword: FORMAT
+                literal: "'YYYYMM'"
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: CAST_STATEMENT_EXAMPLE
diff --git a/test/fixtures/parser/teradata/select_stmt_cast.yml b/test/fixtures/parser/teradata/select_stmt_cast.yml
index b43a638ae25..f5ae8960901 100644
--- a/test/fixtures/parser/teradata/select_stmt_cast.yml
+++ b/test/fixtures/parser/teradata/select_stmt_cast.yml
@@ -7,30 +7,33 @@ file:
           expression:
             literal: "'9999-12-31'"
             cast_expression:
-              start_bracket: (
-              td_internal_data_type:
-                data_type_identifier: DATE
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                td_internal_data_type:
+                  data_type_identifier: DATE
+                end_bracket: )
       - comma: ','
       - select_clause_element:
           expression:
             literal: "'9999-12-31'"
             cast_expression:
-              start_bracket: (
-              td_internal_data_type:
-                data_type_identifier: DATE
-                keyword: FORMAT
-                literal: "'YYYY-MM-DD'"
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                td_internal_data_type:
+                  data_type_identifier: DATE
+                  keyword: FORMAT
+                  literal: "'YYYY-MM-DD'"
+                end_bracket: )
       - comma: ','
       - select_clause_element:
           expression:
             literal: "'100000'"
             cast_expression:
-              start_bracket: (
-              td_internal_data_type:
-                data_type_identifier: SMALLINT
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                td_internal_data_type:
+                  data_type_identifier: SMALLINT
+                end_bracket: )
       from_clause:
         keyword: from
         from_expression:
diff --git a/test/fixtures/parser/teradata/update_from.yml b/test/fixtures/parser/teradata/update_from.yml
index cca483fbec0..dcaed871042 100644
--- a/test/fixtures/parser/teradata/update_from.yml
+++ b/test/fixtures/parser/teradata/update_from.yml
@@ -8,59 +8,60 @@ file:
         keyword: FROM
         from_expression_element:
           table_expression:
-            start_bracket: (
-            select_statement:
-              select_clause:
-              - keyword: SELECT
-              - select_clause_element:
-                  column_reference:
-                    identifier: a
-              - comma: ','
-              - select_clause_element:
-                  column_reference:
-                    identifier: b
-              - comma: ','
-              - select_clause_element:
-                  column_reference:
-                    identifier: c
-              - comma: ','
-              - select_clause_element:
-                  column_reference:
-                    identifier: d
-              from_clause:
-                keyword: FROM
-                from_expression:
-                  from_expression_element:
-                    table_expression:
-                      table_reference:
-                        identifier: t_b
-                  join_clause:
-                  - keyword: INNER
-                  - keyword: JOIN
-                  - from_expression_element:
+            bracketed:
+              start_bracket: (
+              select_statement:
+                select_clause:
+                - keyword: SELECT
+                - select_clause_element:
+                    column_reference:
+                      identifier: a
+                - comma: ','
+                - select_clause_element:
+                    column_reference:
+                      identifier: b
+                - comma: ','
+                - select_clause_element:
+                    column_reference:
+                      identifier: c
+                - comma: ','
+                - select_clause_element:
+                    column_reference:
+                      identifier: d
+                from_clause:
+                  keyword: FROM
+                  from_expression:
+                    from_expression_element:
                       table_expression:
                         table_reference:
-                          identifier: t_c
-                  - join_on_condition:
-                      keyword: 'ON'
-                      expression:
-                      - column_reference:
-                        - identifier: t_b
-                        - dot: .
-                        - identifier: d
-                      - comparison_operator: '='
-                      - column_reference:
-                        - identifier: t_c
-                        - dot: .
-                        - identifier: d
-              where_clause:
-                keyword: WHERE
-                expression:
-                  column_reference:
-                    identifier: b
-                  comparison_operator: '='
-                  literal: "'F'"
-            end_bracket: )
+                          identifier: t_b
+                    join_clause:
+                    - keyword: INNER
+                    - keyword: JOIN
+                    - from_expression_element:
+                        table_expression:
+                          table_reference:
+                            identifier: t_c
+                    - join_on_condition:
+                        keyword: 'ON'
+                        expression:
+                        - column_reference:
+                          - identifier: t_b
+                          - dot: .
+                          - identifier: d
+                        - comparison_operator: '='
+                        - column_reference:
+                          - identifier: t_c
+                          - dot: .
+                          - identifier: d
+                where_clause:
+                  keyword: WHERE
+                  expression:
+                    column_reference:
+                      identifier: b
+                    comparison_operator: '='
+                    literal: "'F'"
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: t_d
diff --git a/test/fixtures/rules/std_rule_cases/L015.yml b/test/fixtures/rules/std_rule_cases/L015.yml
index cc8aa5e115e..33994f28034 100644
--- a/test/fixtures/rules/std_rule_cases/L015.yml
+++ b/test/fixtures/rules/std_rule_cases/L015.yml
@@ -10,8 +10,8 @@ test_2:
   fix_str: SELECT DISTINCT (a + b) * c
 
 test_3:
-  # Space after DISTINCT makes it okay(-ish)...
-  pass_str: SELECT DISTINCT (a)
+  fail_str: SELECT DISTINCT (a)
+  fix_str: SELECT DISTINCT a
 
 test_4:
   pass_str: SELECT DISTINCT (a + b) * c
diff --git a/test/fixtures/templater/jinja_f/jinja.yml b/test/fixtures/templater/jinja_f/jinja.yml
index 61ee2bfa839..32fe3c950bb 100644
--- a/test/fixtures/templater/jinja_f/jinja.yml
+++ b/test/fixtures/templater/jinja_f/jinja.yml
@@ -11,24 +11,25 @@ file:
           function:
             function_name:
               function_name_identifier: MAX
-            start_bracket: (
-            expression:
-              case_expression:
-              - keyword: CASE
-              - keyword: WHEN
-              - expression:
-                  column_reference:
-                    identifier: word
-                  comparison_operator: "="
-                  literal: "'shop'"
-              - keyword: THEN
-              - expression:
-                  literal: "1"
-              - keyword: ELSE
-              - expression:
-                  literal: "0"
-              - keyword: END
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                case_expression:
+                - keyword: CASE
+                - keyword: WHEN
+                - expression:
+                    column_reference:
+                      identifier: word
+                    comparison_operator: "="
+                    literal: "'shop'"
+                - keyword: THEN
+                - expression:
+                    literal: "1"
+                - keyword: ELSE
+                - expression:
+                    literal: "0"
+                - keyword: END
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: shop_word
@@ -37,24 +38,25 @@ file:
           function:
             function_name:
               function_name_identifier: MAX
-            start_bracket: (
-            expression:
-              case_expression:
-              - keyword: CASE
-              - keyword: WHEN
-              - expression:
-                  column_reference:
-                    identifier: word
-                  comparison_operator: "="
-                  literal: "'products'"
-              - keyword: THEN
-              - expression:
-                  literal: "1"
-              - keyword: ELSE
-              - expression:
-                  literal: "0"
-              - keyword: END
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                case_expression:
+                - keyword: CASE
+                - keyword: WHEN
+                - expression:
+                    column_reference:
+                      identifier: word
+                    comparison_operator: "="
+                    literal: "'products'"
+                - keyword: THEN
+                - expression:
+                    literal: "1"
+                - keyword: ELSE
+                - expression:
+                    literal: "0"
+                - keyword: END
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: products_word
@@ -63,24 +65,25 @@ file:
           function:
             function_name:
               function_name_identifier: MAX
-            start_bracket: (
-            expression:
-              case_expression:
-              - keyword: CASE
-              - keyword: WHEN
-              - expression:
-                  column_reference:
-                    identifier: word
-                  comparison_operator: "="
-                  literal: "'code'"
-              - keyword: THEN
-              - expression:
-                  literal: "1"
-              - keyword: ELSE
-              - expression:
-                  literal: "0"
-              - keyword: END
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                case_expression:
+                - keyword: CASE
+                - keyword: WHEN
+                - expression:
+                    column_reference:
+                      identifier: word
+                    comparison_operator: "="
+                    literal: "'code'"
+                - keyword: THEN
+                - expression:
+                    literal: "1"
+                - keyword: ELSE
+                - expression:
+                    literal: "0"
+                - keyword: END
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: code_word
@@ -89,25 +92,27 @@ file:
           function:
             function_name:
               function_name_identifier: safe_cast
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: vector_array
-              array_accessor:
-                start_square_bracket: "["
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: ORDINAL
-                    start_bracket: (
-                    expression:
-                      literal: "0"
-                    end_bracket: )
-                end_square_bracket: "]"
-            keyword: AS
-            data_type:
-              data_type_identifier: FLOAT64
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: vector_array
+                array_accessor:
+                  start_square_bracket: "["
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: ORDINAL
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: "0"
+                        end_bracket: )
+                  end_square_bracket: "]"
+              keyword: AS
+              data_type:
+                data_type_identifier: FLOAT64
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: v0
@@ -116,25 +121,27 @@ file:
           function:
             function_name:
               function_name_identifier: safe_cast
-            start_bracket: (
-            expression:
-              column_reference:
-                identifier: vector_array
-              array_accessor:
-                start_square_bracket: "["
-                expression:
-                  function:
-                    function_name:
-                      function_name_identifier: ORDINAL
-                    start_bracket: (
-                    expression:
-                      literal: "1"
-                    end_bracket: )
-                end_square_bracket: "]"
-            keyword: AS
-            data_type:
-              data_type_identifier: FLOAT64
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+                column_reference:
+                  identifier: vector_array
+                array_accessor:
+                  start_square_bracket: "["
+                  expression:
+                    function:
+                      function_name:
+                        function_name_identifier: ORDINAL
+                      bracketed:
+                        start_bracket: (
+                        expression:
+                          literal: "1"
+                        end_bracket: )
+                  end_square_bracket: "]"
+              keyword: AS
+              data_type:
+                data_type_identifier: FLOAT64
+              end_bracket: )
           alias_expression:
             keyword: AS
             identifier: v1
diff --git a/test/fixtures/templater/jinja_g_macros/jinja.yml b/test/fixtures/templater/jinja_g_macros/jinja.yml
index 5ade38c2e15..288186b633d 100644
--- a/test/fixtures/templater/jinja_g_macros/jinja.yml
+++ b/test/fixtures/templater/jinja_g_macros/jinja.yml
@@ -6,22 +6,24 @@ file:
       - select_clause_modifier:
         - keyword: distinct
         - keyword: 'on'
-        - start_bracket: (
-        - expression:
-            column_reference:
-              identifier: id
-        - end_bracket: )
+        - bracketed:
+          - start_bracket: (
+          - expression:
+              column_reference:
+                identifier: id
+          - end_bracket: )
       - select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - column_reference:
-                identifier: json
-            - binary_operator: ->
-            - literal: "'type'"
-            - binary_operator: ->>
-            - literal: "'id'"
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - column_reference:
+                  identifier: json
+              - binary_operator: ->
+              - literal: "'type'"
+              - binary_operator: ->>
+              - literal: "'id'"
+              end_bracket: )
             cast_expression:
               casting_operator: '::'
               data_type:
@@ -32,15 +34,16 @@ file:
       - comma: ','
       - select_clause_element:
           expression:
-            start_bracket: (
-            expression:
-            - column_reference:
-                identifier: json
-            - binary_operator: ->
-            - literal: "'type'"
-            - binary_operator: ->>
-            - literal: "'name'"
-            end_bracket: )
+            bracketed:
+              start_bracket: (
+              expression:
+              - column_reference:
+                  identifier: json
+              - binary_operator: ->
+              - literal: "'type'"
+              - binary_operator: ->>
+              - literal: "'name'"
+              end_bracket: )
           alias_expression:
             keyword: as
             identifier: name
@@ -49,53 +52,56 @@ file:
         from_expression:
           from_expression_element:
             table_expression:
-              start_bracket: (
-              select_statement:
-                select_clause:
-                  keyword: select
-                  select_clause_element:
-                    wildcard_expression:
-                      wildcard_identifier:
-                        star: '*'
-                from_clause:
-                  keyword: from
-                  from_expression:
-                    from_expression_element:
-                      table_expression:
-                        table_reference:
-                          identifier: sb_route_events
-                      alias_expression:
-                        keyword: as
-                        identifier: s
-                where_clause:
-                  keyword: where
-                  start_bracket: (
-                  expression:
-                  - column_reference:
-                    - identifier: s
-                    - dot: .
-                    - identifier: match_id
-                  - keyword: not
-                  - keyword: in
-                  - start_bracket: (
-                  - select_statement:
-                      select_clause:
-                        keyword: select
-                        select_clause_modifier:
-                          keyword: distinct
-                        select_clause_element:
-                          column_reference:
-                            identifier: match_id
-                      from_clause:
-                        keyword: from
-                        from_expression:
-                          from_expression_element:
-                            table_expression:
-                              table_reference:
-                                identifier: this_model
-                  - end_bracket: )
-                  end_bracket: )
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                select_statement:
+                  select_clause:
+                    keyword: select
+                    select_clause_element:
+                      wildcard_expression:
+                        wildcard_identifier:
+                          star: '*'
+                  from_clause:
+                    keyword: from
+                    from_expression:
+                      from_expression_element:
+                        table_expression:
+                          table_reference:
+                            identifier: sb_route_events
+                        alias_expression:
+                          keyword: as
+                          identifier: s
+                  where_clause:
+                    keyword: where
+                    bracketed:
+                      start_bracket: (
+                      expression:
+                      - column_reference:
+                        - identifier: s
+                        - dot: .
+                        - identifier: match_id
+                      - keyword: not
+                      - keyword: in
+                      - bracketed:
+                        - start_bracket: (
+                        - select_statement:
+                            select_clause:
+                              keyword: select
+                              select_clause_modifier:
+                                keyword: distinct
+                              select_clause_element:
+                                column_reference:
+                                  identifier: match_id
+                            from_clause:
+                              keyword: from
+                              from_expression:
+                                from_expression_element:
+                                  table_expression:
+                                    table_reference:
+                                      identifier: this_model
+                        - end_bracket: )
+                      end_bracket: )
+                end_bracket: )
             alias_expression:
               keyword: as
               identifier: e
\ No newline at end of file
diff --git a/test/fixtures/templater/jinja_i_raw/raw_tag_2.yml b/test/fixtures/templater/jinja_i_raw/raw_tag_2.yml
index 99b2b104658..f24fea73a80 100644
--- a/test/fixtures/templater/jinja_i_raw/raw_tag_2.yml
+++ b/test/fixtures/templater/jinja_i_raw/raw_tag_2.yml
@@ -8,11 +8,12 @@ file:
           - function:
               function_name:
                 function_name_identifier: lower
-              start_bracket: (
-              expression:
-                column_reference:
-                  identifier: note_text
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                  column_reference:
+                    identifier: note_text
+                end_bracket: )
           - keyword: NOT
           - keyword: LIKE
           - literal: "'%daycare: {%'"
@@ -20,11 +21,12 @@ file:
           - function:
               function_name:
                 function_name_identifier: lower
-              start_bracket: (
-              expression:
-                column_reference:
-                  identifier: note_text
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                  column_reference:
+                    identifier: note_text
+                end_bracket: )
           - keyword: NOT
           - keyword: LIKE
           - literal: "'%grade/ school name:  {%'"
@@ -32,11 +34,12 @@ file:
           - function:
               function_name:
                 function_name_identifier: lower
-              start_bracket: (
-              expression:
-                column_reference:
-                  identifier: note_text
-              end_bracket: )
+              bracketed:
+                start_bracket: (
+                expression:
+                  column_reference:
+                    identifier: note_text
+                end_bracket: )
           - keyword: NOT
           - keyword: LIKE
           - literal: "'%social history:  {%'"


Code review comments:
diff_hunk: @@ -604,16 +641,26 @@ def _bracket_sensitive_look_ahead_match(
                                 v_level=3,
                                 got=matcher,
                             )
-                            return ((), MatchResult.from_unmatched(segments), None)
+                            # We return with the mutated segments so we can reuse any bracket matching.
+                            return (
+                                (),
+                                MatchResult.from_unmatched(pre_seg_buff + seg_buff),
+                                None,
+                            )
                         else:
                             # This shouldn't happen!?
                             raise NotImplementedError(
                                 "This shouldn't happen. Panic in _bracket_sensitive_look_ahead_match."
                             )
                     else:
                         # Not in a bracket stack, but no match. This is a happy
-                        # unmatched exit.
-                        return ((), MatchResult.from_unmatched(segments), None)
+                        # unmatched exit. We return with the mutated segments so we can
+                        # reuse any bracket matching.
+                        return (
path: src/sqlfluff/core/parser/grammar/base.py
text: @user1:
This duplicates code from around line 645. Possible to eliminate the duplication somehow and simplify the code?

@author:
Good shout - I'll see what I can do...

@author:
Yep - I've managed to combine the _three_ instances of this code into a single code path. Great idea! 🎉

diff_hunk: @@ -295,43 +310,59 @@ def match(
             pre_nc = ()
             post_nc = ()
 
-        # If we don't have anything left after trimming, act accordingly.
+        # If we've got a case of empty brackets check whether that is allowed.
         if not content_segs:
             if not self._elements or (
-                all(e.is_optional() for e in self._elements) and self.allow_gaps
+                all(e.is_optional() for e in self._elements)
+                and (self.allow_gaps or (not pre_nc and not post_nc))
             ):
                 return MatchResult(
-                    start_match.matched_segments
-                    + pre_nc
-                    + post_nc
-                    + end_match.matched_segments,
-                    end_match.unmatched_segments,
+                    (bracket_segment,)
+                    if bracket_persists
+                    else bracket_segment.segments,
+                    trailing_segments,
                 )
             else:
                 return MatchResult.from_unmatched(segments)
 
-        # Match using super. Sequence will interpret the content of the elements.
+        # Match the content using super. Sequence will interpret the content of the elements.
         with parse_context.deeper_match() as ctx:
             content_match = super().match(content_segs, parse_context=ctx)
 
         # We require a complete match for the content (hopefully for obvious reasons)
         if content_match.is_complete():
+            # Reconstruct the bracket segment post match.
+            # We need to realign the meta segments so the pos markers are correct.
+            # Have we already got indents?
+            meta_idx = None
+            for idx, seg in enumerate(bracket_segment.segments):
+                if seg.is_meta and seg.indent_val > 0:  # type: ignore
+                    meta_idx = idx
+                    break
+            # If we've already go indents, don't add more.
path: src/sqlfluff/core/parser/grammar/sequence.py
text: @user1:
```suggestion
            # If we've already got indents, don't add more.
```

diff_hunk: @@ -1033,6 +1037,53 @@ def iter_patches(self, templated_str: str) -> Iterator[FixPatch]:
                 )
 
 
+class BracketedSegment(BaseSegment):
+    """A segment containing a bracketed expression."""
+
+    type = "bracketed"
+    additional_kwargs = ["start_bracket", "end_bracket"]
+
+    def __init__(
+        self,
+        *args,
+        start_bracket: Tuple[BaseSegment] = None,
path: src/sqlfluff/core/parser/segments/base.py
text: @user1:
Why is it a tuple rather than just a `BaseSegment`?

@author:
Good question. I did this initially so that `tuple` arithmetic was easy, but these should always be single segments 🤔. For someone reading the code raw, do you think `BaseSegment` would make more sense? If so I make change it to do that instead.

@user1:
I'm torn, because the syntax for creating a tuple "on the fly" is really obtuse and easy to overlook. Let's stick with the current code, but maybe add a clarifying comment that there'll be only one?

diff_hunk: @@ -67,17 +69,22 @@ def wrapped_match_method(self, segments: tuple, parse_context):
             # Reset the ephemeral name on the new version of the grammar otherwise
             # we get infinite recursion.
             new_grammar.ephemeral_name = None
-            return MatchResult.from_matched(
-                (
-                    EphemeralSegment(
-                        segments=segments,
-                        pos_marker=None,
-                        # Ephemeral segments get a copy of the parent grammar.
-                        parse_grammar=new_grammar,
-                        name=self.ephemeral_name,
-                    ),
+            # We shouldn't allow nested ephemerals. If they're present. Don't create another.
path: src/sqlfluff/core/parser/segments/ephemeral.py
text: @user1:
```suggestion
            # We shouldn't allow nested ephemerals. If they're present, don't create another.
```

diff_hunk: @@ -335,9 +335,7 @@ class GroupByClauseSegment(BaseSegment):
                 Ref("ExpressionSegment"),
                 Ref("CubeRollupClauseSegment"),
                 Ref("GroupingSetsClauseSegment"),
-                Sequence(
-                    Ref("StartBracketSegment"), Ref("EndBracketSegment")
-                ),  # () possible
+                Bracketed(),  # () possible
path: src/sqlfluff/dialects/dialect_exasol.py
text: @user1:
The `() possible` comment is a bit cryptic. Does this mean "Empty parentheses are possible"?

@author:
It does. I'm going to change it. 👍

diff_hunk: @@ -81,13 +81,18 @@ def indent_size_up_to(segs):
 
             balance = 0
             with_indent, with_indent_str = indent_size_up_to(raw_stack_buff)
-            for seg in segment.iter_segments(expanding=["common_table_expression"]):
+            print("SEG", segment, with_indent, repr(with_indent_str))
path: src/sqlfluff/rules/L018.py
text: @user1:
Looks like debugging code -- should this `print()` call be removed?

diff_hunk: @@ -295,43 +310,59 @@ def match(
             pre_nc = ()
             post_nc = ()
 
-        # If we don't have anything left after trimming, act accordingly.
+        # If we've got a case of empty brackets check whether that is allowed.
         if not content_segs:
             if not self._elements or (
-                all(e.is_optional() for e in self._elements) and self.allow_gaps
+                all(e.is_optional() for e in self._elements)
+                and (self.allow_gaps or (not pre_nc and not post_nc))
             ):
                 return MatchResult(
-                    start_match.matched_segments
-                    + pre_nc
-                    + post_nc
-                    + end_match.matched_segments,
-                    end_match.unmatched_segments,
+                    (bracket_segment,)
+                    if bracket_persists
+                    else bracket_segment.segments,
+                    trailing_segments,
                 )
             else:
                 return MatchResult.from_unmatched(segments)
 
-        # Match using super. Sequence will interpret the content of the elements.
+        # Match the content using super. Sequence will interpret the content of the elements.
         with parse_context.deeper_match() as ctx:
             content_match = super().match(content_segs, parse_context=ctx)
 
         # We require a complete match for the content (hopefully for obvious reasons)
         if content_match.is_complete():
+            # Reconstruct the bracket segment post match.
+            # We need to realign the meta segments so the pos markers are correct.
+            # Have we already got indents?
+            meta_idx = None
+            for idx, seg in enumerate(bracket_segment.segments):
+                if seg.is_meta and seg.indent_val > 0:  # type: ignore
path: src/sqlfluff/core/parser/grammar/sequence.py
text: @user1:
```suggestion
                if seg.is_meta and cast(MetaSegment, seg).indent_val > 0:
```

diff_hunk: @@ -245,48 +251,57 @@ def match(
             seg_buff = segments
 
         # Rehydrate the bracket segments in question.
-        start_bracket, end_bracket = self.get_bracket_from_dialect(parse_context)
+        # bracket_persits controls whether we make a BracketedSegment or not.
+        start_bracket, end_bracket, bracket_persists = self.get_bracket_from_dialect(
+            parse_context
+        )
         # Allow optional override for special bracket-like things
         start_bracket = self.start_bracket or start_bracket
         end_bracket = self.end_bracket or end_bracket
 
-        # Look for the first bracket
-        with parse_context.deeper_match() as ctx:
-            start_match = start_bracket.match(seg_buff, parse_context=ctx)
-        if start_match:
-            seg_buff = start_match.unmatched_segments
+        # Are we dealing with a pre-existing BracketSegment?
+        if seg_buff[0].is_type("bracketed"):
+            seg: BracketedSegment = seg_buff[0]  # type: ignore
path: src/sqlfluff/core/parser/grammar/sequence.py
text: @user1:
```suggestion
            seg: BracketedSegment = cast(BracketedSegment, seg_buff[0])
```

diff_hunk: @@ -295,43 +310,59 @@ def match(
             pre_nc = ()
             post_nc = ()
 
-        # If we don't have anything left after trimming, act accordingly.
+        # If we've got a case of empty brackets check whether that is allowed.
         if not content_segs:
             if not self._elements or (
-                all(e.is_optional() for e in self._elements) and self.allow_gaps
+                all(e.is_optional() for e in self._elements)
+                and (self.allow_gaps or (not pre_nc and not post_nc))
path: src/sqlfluff/core/parser/grammar/sequence.py
text: @user1:
I should probably know this, but what's `nc`?

@author:
ah, _non code_. I'll add some comments

@author:
Actually.... I'll just rename them to `pre_segs` and `post_segs` 👍