rubberduck-vba / Rubberduck

Every programmer needs a rubberduck. COM add-in for the VBA & VB6 IDE (VBE).

Home Page:https://rubberduckvba.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Parse error on Private Type definition

huaca2 opened this issue · comments

Write a Type Definition in a class module of the form:

Private Type Ficha
     FMT(0 To 2)
     AUT(0 To 2)
     ...

Throws a Parse Error at the end of FMT(0 To 2)

extraneous input '\r\n' expecting {WS.LINE_CONTINUATION}

Looks like an oversight in the parser grammar around UDT member definitions.
Thanks for the report!

Seems to be taken into account though:

// 5.2.3.3 User Defined Type Declarations
// member list includes trailing endOfStatement
udtDeclaration : (visibility whiteSpace)? TYPE whiteSpace untypedIdentifier endOfStatement udtMemberList END_TYPE;  
udtMemberList : (udtMember endOfStatement)+; 
udtMember : reservedNameMemberDeclaration | untypedNameMemberDeclaration;
untypedNameMemberDeclaration : untypedIdentifier whiteSpace? optionalArrayClause;
reservedNameMemberDeclaration : unrestrictedIdentifier whiteSpace asTypeClause;
optionalArrayClause : (arrayDim whiteSpace)? asTypeClause;

Specifically:

untypedNameMemberDeclaration : untypedIdentifier whiteSpace? optionalArrayClause;

Just to be sure, the END_TYPE token (i.e. End Type) is indeed present, yeah? The parse error is legit without that token, since the parser rule (which encodes section 5.2.3.3 of the language specifications) understands it's looking at a UDT definition by matching the source code against the grammar tokens:

udtDeclaration : (visibility whiteSpace)? TYPE whiteSpace untypedIdentifier endOfStatement udtMemberList END_TYPE;

In other words, in order to parse a udtDeclaration the source code must look like Type SomeIdentifierName with a mandatory udtMemberList on at least one more line, followed by End Type on another line.

Yes, my Type Definition ends correctly with the "End Type" token in the last line.

 Private Type Ficha
       FMT(0 To 2)
       AUT(0 To 2)
       ...
 End Type

It looks like the VBA language specification does not allow user defined types to include array members without an AS type clause at the end. However, the VBA editor does allow array members but only when declared using both explicit lower and upper bounds e.g. FM(0 to 2). In other words it won't accept FM(2) even though that is identical in meaning.

Private Type X
    A(2) As Variant         'This is fine
    B(0 To 2) As Variant    'This is fine
    C (2)                   'VBA will not compile this (the VBA editor inserts the space between the identifier and array)
    D(0 To 2)               'VBA will compile and work as expected but Rubberduck has a parse error
End Type

In the above example, the 4 members should be identical i.e. arrays of variants with lower bound 0 and upper bound 2. However, VBA will only allow cases A, B and D. Rubberduck only allows A and B.

So to support the reality of what works in VBA, we would need to change the VBAParser.g4 definition to explicitly allow UDT members to have an array with both lower and upper bounds but not a type. An odd special case.

So this is one of the few areas where the VBE implementation mismatches its own specifications.
In the spirit of RD being able to flag the untyped member declaration as such, indeed it would be necessary to address this, at least in 2.x (and then we carry the grammar into v3).
RD3 would merely be reporting a syntax error there if it's not addressed in the v3 grammar, so no biggie, but confusing enough to warrant aligning with the VBE implementation.

Submitted a fix which allow Rubberduck to parse cases where there is an array member of the UDT which doesn't have an explicit type declaration. It still requires a type declaration for non-array members as that is consistent with both the language specification and implementation.