618618 OneOf (
619619 Ref ("SingleQuotedIdentifierSegment" ),
620620 Ref ("ReferencedVariableNameSegment" ),
621+ Ref ("BindVariableSegment" ),
621622 ),
622623 ),
623624 ),
@@ -1255,6 +1256,14 @@ class StatementSegment(ansi.StatementSegment):
12551256 """A generic segment, to any of its child subsegments."""
12561257
12571258 match_grammar = ansi .StatementSegment .match_grammar .copy (
1259+ # NOTE: The Scripting Block segment must be tried before
1260+ # we get to the transaction statement (from the ansi dialect)
1261+ # because they both start with BEGIN.
1262+ insert = [
1263+ Ref ("ScriptingBlockStatementSegment" ),
1264+ ],
1265+ before = Ref ("TransactionStatementSegment" ),
1266+ ).copy (
12581267 insert = [
12591268 Ref ("AccessStatementSegment" ),
12601269 Ref ("CreateStatementSegment" ),
@@ -1263,7 +1272,6 @@ class StatementSegment(ansi.StatementSegment):
12631272 Ref ("CreateCloneStatementSegment" ),
12641273 Ref ("CreateProcedureStatementSegment" ),
12651274 Ref ("AlterProcedureStatementSegment" ),
1266- Ref ("ScriptingBlockStatementSegment" ),
12671275 Ref ("ScriptingLetStatementSegment" ),
12681276 Ref ("ReturnStatementSegment" ),
12691277 Ref ("ShowStatementSegment" ),
@@ -1326,6 +1334,7 @@ class StatementSegment(ansi.StatementSegment):
13261334 Ref ("CreateExternalVolumeStatementSegment" ),
13271335 Ref ("DropExternalVolumeStatementSegment" ),
13281336 Ref ("AlterExternalVolumeStatementSegment" ),
1337+ Ref ("ForInLoopSegment" ),
13291338 ],
13301339 remove = [
13311340 Ref ("CreateIndexStatementSegment" ),
@@ -3119,14 +3128,33 @@ class ScriptingBlockStatementSegment(BaseSegment):
31193128 """
31203129
31213130 type = "scripting_block_statement"
3122- match_grammar = OneOf (
3131+ match_grammar = Sequence (
31233132 Sequence (
31243133 "BEGIN" ,
3125- Delimited (
3134+ Indent ,
3135+ Ref ("StatementSegment" ),
3136+ ),
3137+ AnyNumberOf (
3138+ Sequence (
3139+ Ref ("DelimiterGrammar" ),
31263140 Ref ("StatementSegment" ),
31273141 ),
3142+ terminators = [
3143+ OneOf (
3144+ Sequence (Ref ("DelimiterGrammar" ), "END" ),
3145+ # Don't terminate on an "END FOR", because that's a different
3146+ # expression.
3147+ exclude = Sequence (Ref ("DelimiterGrammar" ), "END" , "FOR" ),
3148+ ),
3149+ ],
3150+ # NOTE: We can't be greedy because there may be nested loops. This
3151+ # does make understanding any failed parsing loops difficult but I
3152+ # don't think there's an easy way around that.
31283153 ),
3129- Sequence ("END" ),
3154+ Ref ("DelimiterGrammar" ),
3155+ Dedent ,
3156+ "END" ,
3157+ reset_terminators = True ,
31303158 )
31313159
31323160
@@ -7132,6 +7160,8 @@ class TransactionStatementSegment(ansi.TransactionStatementSegment):
71327160 https://docs.snowflake.com/en/sql-reference/sql/begin.html
71337161 https://docs.snowflake.com/en/sql-reference/sql/commit.html
71347162 https://docs.snowflake.com/en/sql-reference/sql/rollback.html
7163+
7164+ NOTE: "END" is not currently a supported keyword here.
71357165 """
71367166
71377167 match_grammar = OneOf (
@@ -7828,3 +7858,48 @@ class AlterMaskingPolicySegment(BaseSegment):
78287858 Sequence ("UNSET" , "COMMENT" ),
78297859 ),
78307860 )
7861+
7862+
7863+ class ForInLoopSegment (BaseSegment ):
7864+ """FOR...IN...DO...END FOR statement.
7865+
7866+ https://docs.snowflake.com/en/developer-guide/snowflake-scripting/loops#for-loop
7867+ """
7868+
7869+ type = "for_in_statement"
7870+
7871+ match_grammar = Sequence (
7872+ Sequence (
7873+ Sequence (
7874+ "FOR" ,
7875+ Ref ("LocalVariableNameSegment" ),
7876+ "IN" ,
7877+ Ref ("LocalVariableNameSegment" ),
7878+ "DO" ,
7879+ Indent ,
7880+ ),
7881+ Delimited (
7882+ Ref ("StatementSegment" ),
7883+ delimiter = Ref ("DelimiterGrammar" ),
7884+ ),
7885+ parse_mode = ParseMode .GREEDY_ONCE_STARTED ,
7886+ reset_terminators = True ,
7887+ terminators = [Sequence (Ref ("DelimiterGrammar" ), "END" , "FOR" )],
7888+ ),
7889+ # There must be a trailing semicolon
7890+ Ref ("DelimiterGrammar" ),
7891+ Dedent ,
7892+ "END" ,
7893+ "FOR" ,
7894+ )
7895+
7896+
7897+ class BindVariableSegment (BaseSegment ):
7898+ """A :VARIABLE_NAME expression."""
7899+
7900+ type = "bind_variable"
7901+
7902+ match_grammar = Sequence (
7903+ Ref ("ColonSegment" ),
7904+ Ref ("LocalVariableNameSegment" ),
7905+ )
0 commit comments