非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

自由モノイドのイテレーター(39)

自由モノイドプログラミング言語の作成(MonIter バージョン1.2 仕様(23))

C# 構文木の調査

自由モノイドのイテレーター(16) - エレファント・ビジュアライザー調査記録」に書いた構文木を調べる方法についてまとめます。

C# 構文木の調査用のクラス
    /// <summary>
    /// C# 構文木の調査のためのクラス
    /// </summary>
    internal class CSStyleTreeScan
    {
        /// <summary>
        /// C# 構文木の調査の結果
        /// </summary>
        private string result = "";

        /// <summary>
        /// C# 構文木の調査の結果
        /// </summary>
        public string Result { get => result; set => result = value; }

        /// <summary>
        /// 調査結果を追加する
        /// </summary>
        /// <param name="text">追加するテキスト</param>
        private void WriteLine(string text)
        {
            result += text + "\r\n";
        }
        /// <summary>
        /// C# の構文木のノードを調べる
        /// </summary>
        /// <param name="node">C# の構文木のノード</param>
        /// <param name="n">階層の数</param>
        private void ScanSyntax(CSharpSyntaxNode node, int n)
        {
            string spc = " " + string.Concat(Enumerable.Repeat("- ", n).ToArray());
            WriteLine($"{spc}構文要素 {node.Kind()}");
            WriteLine($"{spc}  {node.ToFullString()}");
            WriteLine($"{spc}{node.GetType().Name}");
            if (node is LocalFunctionStatementSyntax localFunctionStatement)
            {
                WriteLine($"{spc}  文字列 Identifier.Text: {localFunctionStatement.Identifier.Text}");
            }
            else if (node is IdentifierNameSyntax identifierName)
            {
                WriteLine($"{spc}  文字列 Identifier.Text: {identifierName.Identifier.Text}");
            }
            else if (node is ParameterSyntax parameter)
            {
                WriteLine($"{spc}  文字列 Identifier.Text: {parameter.Identifier.Text}");
            }
            else if (node is LiteralExpressionSyntax literalExpression)
            {
                WriteLine($"{spc}  文字列 Token.Text: {literalExpression.Token.Text}");
            }
            else if (node is PredefinedTypeSyntax predefinedType)
            {
                WriteLine($"{spc}  文字列 Keyword.Text: {predefinedType.Keyword.Text}");
            }
            WriteLine($"{spc}  下位の要素数 {node.ChildNodes().Count()}");
            foreach (var child in node.ChildNodes())
            {
                if (child is CSharpSyntaxNode syntax_node)
                {
                    ScanSyntax(syntax_node, n + 1);
                }
            }
        }
        /// <summary>
        /// C# のコードの文字列から構文解析して構文木を調べる
        /// </summary>
        /// <param name="src">C# のコードの文字列</param>
        public void ScanSource(string src)
        {
            var tree = CSharpSyntaxTree.ParseText(src);
            var root = tree.GetCompilationUnitRoot();

            foreach (var child in root.Members)
            {
                ScanSyntax(child, 0);
            }
        }
    }

調査したい構文木のノードをこのクラスに追加していきます。

例:引数で渡すバージョン

C# スタイルのコード

    mon fib(int x, int y) => x & fib(y, x + y);
    fib(0, 1)

構文解析して C#構文木を調べるには以下のようにします。

        /// <summary>
        /// フィボナッチ数列 C# スタイルのコードの構文解析の結果を調べる(引数あり)
        /// </summary>
        /// <returns>構文解析の結果</returns>
        private string InfiniteFibpnacciPrmsCSStyleTreeScan()
        {
            string src = "mon fib(int x, int y) => x & fib(y, x + y); fib(0, 1)";
            CSStyleTreeScan scanner = new CSStyleTreeScan();
            scanner.ScanSource(src);
            return scanner.Result;
        }
例:Zip を使うバージョン

C# スタイルのコード

    mon fib(int x, int y) => x & y & zipsum(fib(x, y), tail(fib(x, y));
    fib(0, 1)

構文解析して C#構文木を調べるには以下のようにします。

        /// <summary>
        /// フィボナッチ数列 C# スタイルのコードの構文解析の結果を調べる(Zip)
        /// </summary>
        /// <returns>構文解析の結果</returns>
        private string InfiniteFibpnacciZipCSStyleTreeScan()
        {
            string src = "mon fib(int x, int y) => x & y & zipsum(fib(x, y), tail(fib(x, y)); fib(0, 1)";
            CSStyleTreeScan scanner = new CSStyleTreeScan();
            scanner.ScanSource(src);
            return scanner.Result;
        }