为什么这段代码在粘贴时编译但是否则失败?

Mat*_*don 12 vb6 vba specifications vbe

一位朋友让我看看这个页面,并注意到一个论坛用户的签名中有一段奇怪的代码.

代码是一个单行,如下所示:

On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Run Code Online (Sandbox Code Playgroud)

滚动删除:

关于本地错误恢复下一个:如果不为空则没有,然后做空:ReDim i(真假)作为货币:循环:其他Debug.Assert CCur(CLng(CInt(假冒错误真Xor假Eqv真))) ):停止:On Local Error GoTo 0

相当令人兴奋的是,代码编译(我没有尝试运行它,但这是无关紧要的)如果你只是按原样粘贴它(然后再不要再触摸它!)到一个有效的程序级范围.

一些观察:

  • 如果指令分隔符/冒号被新行替换,则不再编译
  • On Local Error 可以简化为 On Error
  • 嵌套转换初看起来没有任何特别的兴趣,但事实证明,取代一系列转换并与简单比较Debug.Assert True会使代码一致地编译,因此其中的某些东西会弄乱编译器.
  • 如果代码被粘贴,则编译; 如果Local在VBE验证了行之后以任何方式修改它(甚至只是删除),它就会停止编译,似乎没有任何东西让VBA理解它,除非该行被删除并重新粘贴.
  • 最新的语法/解析器是根据实际的VBA规范建立的,它解析并解析得很好(这真是让我)
  • 如果已知该行未编译,然后剪切/重新粘贴,则它不会编译...但是再次从VBE外部重新粘贴它,它会突然编译.

问题是,这段代码如何根据VB语言规范进行编译?这是VB [6 | A | E]实现中的错误吗?换句话说,为什么/如何运作

认为它是与指令分离器(:)和直列如果语法-考虑有没有End If说法,事情单线,而不是块.

但是,那些特定代码是什么使Schrödinger的代码?什么使它既合法又非法?

如果使用正式语法定义(ANTLR)生成的解析器正确解析代码,那么它必须是合法的构造吗?那么为什么当你回到那条线并点击ENTER时它就不再合法了?

Thu*_*ame 13

有了这么长的代码行,很难发现编译错误的位置,但是有一个微妙的区别,似乎是VBE对该行应用了一个自动更正,或者更有可能在解析之后.

这是原始行 - 从剪贴板粘贴

在您将光标移动到另一行之前,该行显示为这样.注意以及关键字语句之间的LoopElse粗体冒号:

在本地错误恢复下一个:如果不为空则没有,然后Loop: Else做空:ReDim i(真假)作为货币:Debug.Assert CCur(CLng(CInt(假冒错误真Xor假Eqv真)))):停止:On Local Error GoTo 0

这是该行后,您将光标移动到另一行:

请注意,VBE已自动删除冒号.似乎VBE解析器识别该语句,然后"优化""冗余"冒号.

在本地错误恢复下一个:如果不为空则没有,然后Loop Else做空:ReDim i(真假)作为货币:Debug.Assert CCur(CLng(CInt(假冒错误真Xor假Eqv真)))):停止:On Local Error GoTo 0

如果冒号添加回处于无效语法状态的行,则自动更正会再次启动,但您的行将返回有效但易碎的代码.

因此,似乎VBE解析行,识别优化(冗余冒号),然后应用修复,但VBE没有意识到优化行有语法问题.

但为什么这条线最终会变得脆弱?该行中有许多令人分心和不相关的关键字,所以让我们大幅减少它:

Do While.Loop

如果我们最小化线路的复杂性,为了隔离问题,我们可以将线路简化为:
If True Then Do While True: Beep: Loop: Else

再次,VBE自动修正到脆弱的线路:
If True Then Do While True: Beep: Loop Else

但我们可以更进一步,将线路减少到不合逻辑的短线:
If True Then Do: Loop: Else

和VBE ,再次,尽职尽责地删除冒号以产生这一行:( 不要执行此行或您将挂起)
If True Then Do: Loop Else

While..Wend

重复该行,但换掉Do While LoopWhile Wend语法:
If True Then While True: Beep: Wend: Else

再次,VBE优化掉冒号,给予:
If True Then While True: Beep: Wend Else

但现在该行不再脆弱了!

因此,While..Wend是较旧的构造,而Do..Loop构造是更新的(并且更灵活),但似乎VBE解析器(和语法优化器)与Do..Loop构造斗争.

关键点:不要Do..LoopIf包含Else语句的单行语句中使用.