@@ -292,6 +292,7 @@ local err_msg = "Failed to parse:%s\n [%d] >> %s"
292292
293293local build_grammar = wrap_env (function ()
294294 local _indent = Stack (0 ) -- current indent
295+ local _do_stack = Stack (0 )
295296
296297 local last_pos = 0 -- used to know where to report error
297298 local function check_indent (str , pos , indent )
@@ -317,6 +318,34 @@ local build_grammar = wrap_env(function()
317318 return true
318319 end
319320
321+
322+ local function check_do (str , pos , do_node )
323+ local top = _do_stack :top ()
324+ if top == nil or top then
325+ return true , do_node
326+ end
327+ return false
328+ end
329+
330+ local function disable_do (str_pos )
331+ _do_stack :push (false )
332+ return true
333+ end
334+
335+ local function enable_do (str_pos )
336+ _do_stack :push (true )
337+ return true
338+ end
339+
340+ local function pop_do (str , pos )
341+ if nil == _do_stack :pop () then error (" unexpected do pop" ) end
342+ return true
343+ end
344+
345+ local DisableDo = Cmt (" " , disable_do )
346+ local EnableDo = Cmt (" " , enable_do )
347+ local PopDo = Cmt (" " , pop_do )
348+
320349 local keywords = {}
321350 local function key (chars )
322351 keywords [chars ] = true
@@ -384,9 +413,9 @@ local build_grammar = wrap_env(function()
384413
385414 Return = key " return" * (ExpListLow / mark " explist" + C " " ) / mark " return" ,
386415
387- With = key " with" * Exp * key " do" ^- 1 * Body / mark " with" ,
416+ With = key " with" * DisableDo * ensure ( Exp , PopDo ) * key " do" ^- 1 * Body / mark " with" ,
388417
389- Switch = key " switch" * Exp * key " do" ^- 1 * Space ^- 1 * Break * SwitchBlock / mark " switch" ,
418+ Switch = key " switch" * DisableDo * ensure ( Exp , PopDo ) * key " do" ^- 1 * Space ^- 1 * Break * SwitchBlock / mark " switch" ,
390419
391420 SwitchBlock = EmptyLine ^ 0 * Advance * Ct (SwitchCase * (Break ^ 1 * SwitchCase )^ 0 * (Break ^ 1 * SwitchElse )^- 1 ) * PopIndent ,
392421 SwitchCase = key " when" * Exp * key " then" ^- 1 * Body / mark " case" ,
@@ -401,13 +430,15 @@ local build_grammar = wrap_env(function()
401430 Unless = key " unless" * IfCond * key " then" ^- 1 * Body *
402431 ((Break * CheckIndent )^- 1 * EmptyLine ^ 0 * key " else" * Body / mark " else" )^- 1 / mark " unless" ,
403432
404- While = key " while" * Exp * key " do" ^- 1 * Body / mark " while" ,
433+ While = key " while" * DisableDo * ensure ( Exp , PopDo ) * key " do" ^- 1 * Body / mark " while" ,
405434
406- For = key " for" * (Name * sym " =" * Ct (Exp * sym " ," * Exp * (sym " ," * Exp )^- 1 )) *
435+ For = key " for" * DisableDo * ensure (Name * sym " =" * Ct (Exp * sym " ," * Exp * (sym " ," * Exp )^- 1 ), PopDo ) *
407436 key " do" ^- 1 * Body / mark " for" ,
408437
409438 ForEach = key " for" * Ct (NameList ) * key " in" * Ct (sym " *" * Exp / mark " unpack" + ExpList ) * key " do" ^- 1 * Body / mark " foreach" ,
410439
440+ Do = key " do" * Body / mark " do" ,
441+
411442 Comprehension = sym " [" * Exp * CompInner * sym " ]" / mark " comprehension" ,
412443
413444 TblComprehension = sym " {" * Ct (Exp * (sym " ," * Exp )^- 1 ) * CompInner * sym " }" / mark " tblcomprehension" ,
@@ -436,6 +467,7 @@ local build_grammar = wrap_env(function()
436467 Switch +
437468 With +
438469 ForEach + For + While +
470+ Cmt (Do , check_do ) +
439471 sym " -" * - SomeSpace * Exp / mark " minus" +
440472 sym " #" * Exp / mark " length" +
441473 key " not" * Exp / mark " not" +
0 commit comments