File: Util\WriteCsvNames.vb
Web Access
Project: src\src\Tools\Source\CompilerGeneratorTools\Source\VisualBasicSyntaxGenerator\VisualBasicSyntaxGenerator.vbproj (VisualBasicSyntaxGenerator)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
'-----------------------------------------------------------------------------------------------------------
' This is the code that actually outputs the VB code that defines the tree. It is passed a read and validated
' ParseTree, and outputs the code to defined the node classes for that tree, and also additional data
' structures like the kinds, visitor, etc.
'-----------------------------------------------------------------------------------------------------------
 
Imports System.IO
 
' Class to write out the names in the tree as a CSV file for Excel.
 
Friend Class WriteCsvNames
    Inherits WriteUtils
 
    Private _writer As TextWriter    'output is sent here.
 
    ' Initialize the class with the parse tree to write.
    Public Sub New(parseTree As ParseTree)
        MyBase.New(parseTree)
    End Sub
 
    ' Write out the CSV with the names.
    Public Sub WriteCsv(filename As String)
        _writer = New StreamWriter(New FileStream(filename, FileMode.Create, FileAccess.Write))
 
        Using _writer
            WriteEnums()
            WriteNodeStructures()
            WriteFactories()
        End Using
    End Sub
 
    Private Sub WriteCsvLine(val1 As String, val2 As String, val3 As String)
        _writer.WriteLine("{0},{1},{2}", val1, val2, val3)
    End Sub
 
    Private Sub WriteBlankLine()
        WriteCsvLine("", "", "")
    End Sub
 
    Private Sub WriteEnums()
        For Each enumerationType In _parseTree.Enumerations.Values
            WriteEnum(enumerationType)
        Next
    End Sub
 
    Private Sub WriteNodeStructures()
        For Each nodeStructure In _parseTree.NodeStructures.Values
            WriteNodeStructure(nodeStructure)
        Next
    End Sub
 
    ' Generate an enumeration type
    Private Sub WriteEnum(enumeration As ParseEnumeration)
        WriteCsvLine("enum", EnumerationTypeName(enumeration), "")
 
        For Each enumerator In enumeration.Enumerators
            WriteEnumeratorVariable(enumerator, enumeration)
        Next
 
        WriteBlankLine()
    End Sub
 
    Private Sub WriteEnumeratorVariable(enumerator As ParseEnumerator, enumeration As ParseEnumeration)
        WriteCsvLine(NameOf(enumerator), EnumerationTypeName(enumeration), enumerator.Name)
    End Sub
 
    Private Sub WriteNodeStructure(nodeStructure As ParseNodeStructure)
        WriteCsvLine("class", StructureTypeName(nodeStructure), "")
 
        For Each kind In nodeStructure.NodeKinds
            WriteKind(kind)
        Next
 
        Dim allFields = GetAllFieldsOfStructure(nodeStructure)
        For i = 0 To allFields.Count - 1
            WriteField(allFields(i))
        Next
 
        Dim allChildren = GetAllChildrenOfStructure(nodeStructure)
        For i = 0 To allChildren.Count - 1
            WriteChild(allChildren(i))
        Next
 
        WriteBlankLine()
    End Sub
 
    Private Sub WriteKind(kind As ParseNodeKind)
        WriteCsvLine(NameOf(kind), StructureTypeName(kind.NodeStructure), Ident(kind.Name))
    End Sub
 
    Private Sub WriteField(field As ParseNodeField)
        WriteCsvLine(NameOf(field), StructureTypeName(field.ContainingStructure), FieldPropertyName(field))
    End Sub
 
    Private Sub WriteChild(child As ParseNodeChild)
        WriteCsvLine(NameOf(child), StructureTypeName(child.ContainingStructure), ChildPropertyName(child))
    End Sub
 
    Private Sub WriteFactories()
        WriteCsvLine("class", Ident(_parseTree.FactoryClassName), "")
        For Each nodeStructure In _parseTree.NodeStructures.Values
            GenerateFactoryMethodsForStructure(nodeStructure)
        Next
    End Sub
 
    Private Sub GenerateFactoryMethodsForStructure(nodeStructure As ParseNodeStructure)
        If _parseTree.IsAbstract(nodeStructure) Then Return ' abstract structures don't have factory methods
 
        For Each nodeKind In nodeStructure.NodeKinds
            GenerateFactoryMethods(nodeStructure, nodeKind)
        Next
 
        ' Only generate one a structure-level factory method if >= 2 kinds, and the nodeStructure name doesn't conflict with a kind name.
        If nodeStructure.NodeKinds.Count >= 2 And Not _parseTree.NodeKinds.ContainsKey(FactoryName(nodeStructure)) Then
            GenerateFactoryMethods(nodeStructure, Nothing)
        End If
    End Sub
 
    Private Sub GenerateFactoryMethods(nodeStructure As ParseNodeStructure, nodeKind As ParseNodeKind)
        GenerateFactoryMethod(nodeStructure, nodeKind, False)
        If HasSimplifiedFactory(nodeStructure, nodeKind) Then
            GenerateFactoryMethod(nodeStructure, nodeKind, True)
        End If
    End Sub
 
    ' Should we generator a simplified factory method also?
    Private Function HasSimplifiedFactory(nodeStructure As ParseNodeStructure, nodeKind As ParseNodeKind) As Boolean
        ' Currently, all tokens have simplified factories.
        Return nodeStructure.IsToken
    End Function
 
    ' Generate the factory method for a node structure, possibly customized to a particular kind.
    ' If kind is Nothing, generate a factory method that takes a Kind parameter, and can create any kind.
    ' If kind is not Nothing, generator a factory method customized to that particular kind.
    ' The simplified form is:
    '   Defaults the text for any token with token-text defined
    '   Defaults the trivia to a single trailing space for any token
    Private Sub GenerateFactoryMethod(nodeStructure As ParseNodeStructure, nodeKind As ParseNodeKind, simplifiedForm As Boolean)
        Dim factoryFunctionName As String       ' name of the factory method.
 
        If nodeKind IsNot Nothing Then
            If nodeKind.NoFactory Then Return
 
            factoryFunctionName = FactoryName(nodeKind)
        Else
            If nodeStructure.NoFactory Then Return
 
            factoryFunctionName = FactoryName(nodeStructure)
        End If
 
        WriteCsvLine("factory", Ident(_parseTree.FactoryClassName), Ident(factoryFunctionName))
 
    End Sub
 
End Class