@@ -78,35 +78,61 @@ void accept(Token token, Token next) {
7878 }
7979
8080 private void acceptTopLevel (Token token , Token next ) {
81- int kind = token .kind ;
8281 if (afterDot ) {
8382 return ; // Qualified type/column names may use otherwise significant keywords.
8483 }
8584 // END IF/CASE/LOOP/WHILE/REPEAT is one terminator, not another opener.
86- if (previousKind == K_END && (kind == K_IF || kind == K_CASE || kind == K_LOOP
87- || keyword (token , "WHILE" ) || keyword (token , "REPEAT" ))) {
85+ if (previousKind == K_END && isEndQualifier (token )) {
8886 return ;
8987 }
88+ if (!acceptRoutineHeader (token )) {
89+ acceptBodyToken (token , next );
90+ }
91+ }
92+
93+ private boolean acceptRoutineHeader (Token token ) {
94+ int kind = token .kind ;
9095 if (kind == K_RETURNS && !bodyStarted ) {
9196 standardReturns = true ;
9297 returnTypeName = true ;
93- return ;
98+ return true ;
9499 }
95100 if (returnTypeName ) {
96101 returnTypeName = keyword (token , "SETOF" );
97- return ;
102+ return true ;
98103 }
99104 if (!compoundBody && (kind == K_AS || kind == K_IS )
100105 && (!bodyStarted || statementKind == K_RETURN && !standardReturns
101106 || statementKind == K_SET )) {
102107 declarations = true ;
103108 bodyStarted = false ;
109+ return true ;
110+ }
111+ return false ;
112+ }
113+
114+ private void acceptBodyToken (Token token , Token next ) {
115+ int kind = token .kind ;
116+ if (acceptStatementBoundary (kind )) {
104117 return ;
105118 }
106- if (kind == ST_SEMICOLON ) {
119+ if (!(hasParameters || declarations || bodyStarted )) {
120+ return ;
121+ }
122+ if (handlerAction && isSimpleStatementStart (kind )) {
107123 startStatement ();
124+ }
125+ if (acceptBeginOrCase (kind ) || declarations || acceptControlFlow (token )) {
108126 return ;
109127 }
128+ acceptStatementToken (token , next );
129+ }
130+
131+ private boolean acceptStatementBoundary (int kind ) {
132+ if (kind == ST_SEMICOLON ) {
133+ startStatement ();
134+ return true ;
135+ }
110136 if (kind == K_END ) {
111137 if (!blocks .isEmpty ()) {
112138 Block closed = blocks .pop ();
@@ -116,22 +142,20 @@ private void acceptTopLevel(Token token, Token next) {
116142 completed = true ;
117143 }
118144 statementStart = false ;
119- return ;
120- }
121- if (!(hasParameters || declarations || bodyStarted )) {
122- return ;
123- }
124- if (handlerAction && isSimpleStatementStart (kind )) {
125- startStatement ();
145+ return true ;
126146 }
147+ return false ;
148+ }
149+
150+ private boolean acceptBeginOrCase (int kind ) {
127151 if (kind == K_BEGIN
128152 && (!bodyStarted || statementStart || statementKind == K_DECLARE )) {
129153 blocks .push (Block .BEGIN );
130154 declarations = false ;
131155 compoundBody = true ;
132156 bodyStarted = true ;
133157 startStatement ();
134- return ;
158+ return true ;
135159 }
136160 if (kind == K_CASE ) {
137161 boolean statementCase = !declarations && (statementStart || handlerAction );
@@ -142,44 +166,56 @@ private void acceptTopLevel(Token token, Token next) {
142166 handlerAction = false ;
143167 }
144168 statementStart = false ;
145- return ;
146- }
147- if (declarations ) {
148- return ;
169+ return true ;
149170 }
150- if ((statementStart || handlerAction ) && (kind == K_IF || kind == K_LOOP
151- || keyword (token , "WHILE" ) || keyword (token , "REPEAT" ))) {
152- Block block = kind == K_IF ? Block .IF
153- : kind == K_LOOP ? Block .LOOP
154- : keyword (token , "WHILE" ) ? Block .WHILE : Block .REPEAT ;
171+ return false ;
172+ }
173+
174+ private boolean acceptControlFlow (Token token ) {
175+ int kind = token .kind ;
176+ Block block = controlBlock (token );
177+ if ((statementStart || handlerAction ) && block != null ) {
155178 blocks .push (block );
156179 bodyStarted = true ;
157180 compoundBody = true ;
158181 handlerAction = false ;
159182 statementKind = kind ;
160183 statementStart = block == Block .LOOP || block == Block .REPEAT ;
161- return ;
184+ return true ;
162185 }
186+ if (acceptOracleLoop (kind )) {
187+ return true ;
188+ }
189+ if (isStatementBranch (kind )) {
190+ startStatement ();
191+ return true ;
192+ }
193+ return false ;
194+ }
195+
196+ private boolean acceptOracleLoop (int kind ) {
163197 if (kind == K_LOOP && (statementKind == K_FOR || blocks .peek () == Block .WHILE )) {
164198 // Oracle FOR/WHILE ... LOOP shares the same END LOOP boundary.
165199 if (blocks .peek () != Block .WHILE ) {
166200 blocks .push (Block .LOOP );
167201 }
168202 startStatement ();
169- return ;
203+ return true ;
170204 }
171- if ((kind == K_THEN || kind == K_ELSE ) && !blocks .isEmpty ()
205+ return false ;
206+ }
207+
208+ private boolean isStatementBranch (int kind ) {
209+ return (kind == K_THEN || kind == K_ELSE ) && !blocks .isEmpty ()
172210 && blocks .peek () != Block .CASE_EXPRESSION
173- || kind == K_DO && blocks .peek () == Block .WHILE ) {
174- startStatement ();
175- return ;
176- }
177- if (previousKind == K_BEGIN && keyword (token , "ATOMIC" )) {
211+ || kind == K_DO && blocks .peek () == Block .WHILE ;
212+ }
213+
214+ private void acceptStatementToken (Token token , Token next ) {
215+ int kind = token .kind ;
216+ if (isStatementPrefix (token , next )) {
178217 return ;
179218 }
180- if (statementStart && (":" .equals (next .image ) || ":" .equals (token .image ))) {
181- return ; // A label precedes the statement it names.
182- }
183219 if (!bodyStarted ) {
184220 // SET may also be a PostgreSQL header option; AS remains recognizable above.
185221 if (!isSimpleStatementStart (kind )) {
@@ -196,6 +232,29 @@ private void acceptTopLevel(Token token, Token next) {
196232 statementStart = false ;
197233 }
198234
235+ private boolean isStatementPrefix (Token token , Token next ) {
236+ // ATOMIC and a label precede the statement they qualify.
237+ return previousKind == K_BEGIN && keyword (token , "ATOMIC" )
238+ || statementStart && (":" .equals (next .image ) || ":" .equals (token .image ));
239+ }
240+
241+ private static boolean isEndQualifier (Token token ) {
242+ return token .kind == K_CASE || controlBlock (token ) != null ;
243+ }
244+
245+ private static Block controlBlock (Token token ) {
246+ if (token .kind == K_IF ) {
247+ return Block .IF ;
248+ }
249+ if (token .kind == K_LOOP ) {
250+ return Block .LOOP ;
251+ }
252+ if (keyword (token , "WHILE" )) {
253+ return Block .WHILE ;
254+ }
255+ return keyword (token , "REPEAT" ) ? Block .REPEAT : null ;
256+ }
257+
199258 private void startStatement () {
200259 statementStart = true ;
201260 statementKind = -1 ;
0 commit comments