ITADN

VisualBasic.Grammar.g4: required list children emitted as '*' instead of '+' (HandleList ignores optionality; C# generator honors MinCount)

#84636Opentinovyatkin 创建于 25 天前
help wantedLanguage-VBArea-Compilers
T
tinovyatkincommented
**Version Used:** `main` @ a213b74a81f3e66512c01d5e8f146cd05720cfe7 (file last regenerated in #47618) **Area:** VisualBasicSyntaxGenerator, output file [`VisualBasic.Grammar.g4`](https://github.com/dotnet/roslyn/blob/a213b74a81f3e66512c01d5e8f146cd05720cfe7/src/Compilers/VisualBasic/Portable/Generated/VisualBasic.Grammar.g4) ### Summary The VB grammar generator emits **every** plain (non-separated) list child as `*` (zero-or-more), ignoring whether the child is declared optional in `Syntax.xml`. The C# generator distinguishes these cases (`MinCount == 0 ? "*" : "+"`). As a result, eleven productions in the published VB grammar accept empty derivations the syntax model forbids, e.g.: ```antlr array_type : type array_rank_specifier* // an "array type" with no rank specifier is just `type` ; xml_text : xml_text_token* // an XML text node with no text ; query_expression : query_clause* // a query with no clauses — matches the empty string ; ``` Compare the C# grammar, generated from the equivalent model shape: [`array_type : type array_rank_specifier+`](https://github.com/dotnet/roslyn/blob/a213b74a81f3e66512c01d5e8f146cd05720cfe7/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4) (plus, not star; `ArrayTypeSyntax.RankSpecifiers` has `MinCount="1"` in the C# `Syntax.xml`). ### Root cause [`HandleList`, `GrammarGenerator.vb` L205–L207](https://github.com/dotnet/roslyn/blob/a213b74a81f3e66512c01d5e8f146cd05720cfe7/src/Tools/CompilerGeneratorTools/Source/VisualBasicSyntaxGenerator/Grammar/GrammarGenerator.vb#L205-L207): ```vb Private Function HandleList(structureNode As ParseNodeStructure, child As ParseNodeChild) As Production Return HandleChildKind(structureNode, child, child.ChildKind).Suffix("*") End Function ``` `Suffix("*")` is unconditional. The VB syntax model *does* make the distinction the generator discards: optional lists carry `optional="true"` (e.g. [`ModifiedIdentifierSyntax.ArrayRankSpecifiers`, Syntax.xml L5571](https://github.com/dotnet/roslyn/blob/a213b74a81f3e66512c01d5e8f146cd05720cfe7/src/Compilers/VisualBasic/Portable/Syntax/Syntax.xml#L5571)) while required lists do not (e.g. [`ArrayTypeSyntax.RankSpecifiers`](https://github.com/dotnet/roslyn/blob/a213b74a81f3e66512c01d5e8f146cd05720cfe7/src/Compilers/VisualBasic/Portable/Syntax/Syntax.xml#L7405)). The sibling `HandleSeparatedList` (L196–L203) already honors `child.MinCount`; plain lists should analogously emit `+` when the child is not optional — `Suffix(If(child.IsOptional, "*", "+"))`. Affected children (all plain-list, not `optional="true"`): `PropertyBlockSyntax.Accessors`, `EventBlockSyntax.Accessors`, `LocalDeclarationStatementSyntax.Modifiers`, `QueryExpressionSyntax.Clauses`, `XmlElementSyntax.Content`, `XmlTextSyntax.TextTokens`, `XmlCommentSyntax.TextTokens`, `XmlProcessingInstructionSyntax.TextTokens`, `XmlCDataSectionSyntax.TextTokens`, `ArrayTypeSyntax.RankSpecifiers`, `InterpolatedStringExpressionSyntax.Contents`. One caveat: honoring the flag will also surface a few `Syntax.xml` annotations that look inaccurate themselves — e.g. `XmlElementSyntax.Content` is not marked optional, yet `<a></a>` is legal and produces an empty `Content` list. So the complete fix is generator + an audit of the eleven annotations; today the generator makes the two cases indistinguishable, so such model inconsistencies are invisible. ### Why it matters Beyond fidelity, two of these make the grammar structurally degenerate for any consumer: `array_type : type array_rank_specifier*` lets `array_type` derive bare `type` (an epsilon unit-cycle inside the `type` hierarchy), and `query_expression`/`xml_text` matching the empty string produces empty-closure ambiguities everywhere they appear under `*`/`?` (ANTLR reports these as `error(153)`/`warning(154)` when the neighbouring issues are patched). ### Steps to Reproduce ```bash curl -sLo vb.g4 https://raw.githubusercontent.com/dotnet/roslyn/main/src/Compilers/VisualBasic/Portable/Generated/VisualBasic.Grammar.g4 grep -A2 -E '^(array_type|xml_text|query_expression)$' vb.g4 ``` ### Expected Behavior Required lists emitted as `+`; only `optional="true"` lists emitted as `*` — matching both the syntax model and the C# generator's behavior. ### Actual Behavior All plain lists emitted as `*`. Related: sibling reports from the same review: #84633; precedent #47594 / #47618.
0 条评论