vba - 为什么这段代码在粘贴时会编译,否则会失败?

标签 vba vb6 specifications vbe

friend 让我看this page ,并注意到一位论坛用户的签名中有一段奇怪的代码。

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

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

已移除滚动:

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



非常令人兴奋的是,如果您将代码按原样粘贴(然后不要再次触摸它!)到有效的过程级作用域中,则该代码可以编译(我没有尝试运行它,但这无关紧要)。

一些观察:
  • 如果指令分隔符/冒号被换行,它不再编译
  • On Local Error可以简化为On Error
  • 乍一看,嵌套转换并没有什么特别的兴趣,但结果证明用一个简单的 Debug.Assert True 代替了该系列的转换和比较。使代码始终如一地编译,因此其中的某些内容会弄乱编译器。
  • 如果代码被粘贴,则编译;如果在 VBE 验证该行后以任何方式修改它(甚至只是删除 Local ),它会停止编译,并且似乎没有任何东西让 VBA 理解它,除非该行被删除并重新粘贴。
  • 最新语法/解析器以实际 VBA 规范为模型,it parses and resolves just fine (老实说,这让我大吃一惊)
  • 如果已知该行无法编译,然后剪切/重新粘贴,则它不会编译……但是从 VBE 外部再次重新粘贴它,它会突然编译。

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

    我认为它与指令分隔符( : )和 inline-if 语法有关 - 鉴于没有 End If声明,事物是单行而不是块。

    但是,是什么让那个特定的代码成为薛定谔的代码呢?是什么让它同时合法和非法?

    如果代码被使用正式语法定义 (ANTLR) 生成的解析器正确解析,那么它一定是合法的构造吗?那么为什么当您仅返回到该行并按 ENTER 时它就不再合法了?

    最佳答案

    对于这么长的代码行,很难发现编译错误是从哪里潜入的,但是有一个微妙的区别,似乎是 VBE 在解析该行时或更可能在解析它之后对行应用自动更正。

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

    该行看起来像这样 直到 您将光标移动到另一行。
    注意冒号,粗体, Loop之间和 Else关键词 陈述:

    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



    这是将光标移动到另一行后的行:

    请注意,冒号已被 VBE 自动删除。似乎 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



    如果您将冒号添加回处于无效语法状态的行,则自动更正会再次启动,但您的行将恢复为有效但脆弱的代码。

    因此,似乎 VBE 解析该行,识别优化(冗余冒号),然后应用修复,但 VBE 并未意识到优化的行存在语法问题。

    但为什么这条线最终变得脆弱?行中有很多分散注意力和不相关的关键字,所以让我们大幅减少它:

    做 While..Loop

    If we minimize the complexity of the line, to isolate the problem, we can simplify the line to:
    If True Then Do While True: Beep: Loop: Else

    Which, again, VBE autocorrects to a fragile line:
    If True Then Do While True: Beep: Loop Else

    But we can go even further and reduce the line to an illogically short line:
    If True Then Do: Loop: Else

    And VBE, once again, dutifully removes the colon to produce this line: (DO NOT EXECUTE THIS LINE OR YOU WILL HANG EXCEL)
    If True Then Do: Loop Else



    而..温德

    Repeating the line, but swapping out the Do While Loop, for the older While Wend syntax:
    If True Then While True: Beep: Wend: Else

    Again, VBE optimizes away the colon, to give:
    If True Then While True: Beep: Wend Else

    But now the line is not fragile anymore!



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

    关键点:不要使用Do..Loop在单线If包含 Else 的语句陈述。

    关于vba - 为什么这段代码在粘贴时会编译,否则会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37147979/

    相关文章:

    xml - w3c 规范语法中的负号

    java - Excel VBA : Custom functions that return a range of data

    vb.net - VB6 中的 Attribute 关键字有什么作用?

    c++ - C++模板的问题

    c# - 'A field initializer cannot reference the non-static field, method, or property' CS0236 错误的概念原因

    vb6 - Jenkins 管道 : build steps not running concurrently?

    excel - 复制/粘贴到多个单元格后类型不匹配?

    vba - 文本比较在 VBA 中无法正常工作

    Excel VBA查找方法将搜索框 "Within"从工作簿重置为工作表

    vb6 - 将 Double 转换为 8 字节数组