c# - 有没有办法在 C# 中实现自定义语言功能?

标签 c# syntactic-sugar language-construct

我已经对这个问题感到困惑了一段时间,我环顾四周,找不到关于这个主题的任何讨论。

假设我想实现一个简单的例子,比如一个新的循环结构:do..until

写的很像do..while

do {
    //Things happen here
} until (i == 15)

这样做可以将其转换为有效的 csharp:

do {
    //Things happen here
} while (!(i == 15))

这显然是一个简单的例子,但是有什么办法可以添加这种性质的东西吗?理想情况下作为 Visual Studio 扩展来启用语法突出显示等。

最佳答案

Microsoft 提议将 Rolsyn API 作为具有公共(public) API 的 C# 编译器的实现。它包含用于每个编译器管道阶段的单独 API:语法分析、符号创建、绑定(bind)、MSIL 发射。您可以提供自己的语法分析器实现或扩展现有语法分析器,以获得具有您想要的任何功能的 C# 编译器。

Roslyn CTP

让我们使用 Roslyn 扩展 C# 语言吧!在我的示例中,我正在用相应的 do-while 替换 do-until 语句:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Roslyn.Compilers.CSharp;

namespace RoslynTest
{

    class Program
    {
        static void Main(string[] args)
        {

            var code = @"

            using System;

            class Program {
                public void My() {
                    var i = 5;
                    do {
                        Console.WriteLine(""hello world"");
                        i++;
                    }
                    until (i > 10);
                }
            }
            ";



            //Parsing input code into a SynaxTree object.
            var syntaxTree = SyntaxTree.ParseCompilationUnit(code);

            var syntaxRoot = syntaxTree.GetRoot();

            //Here we will keep all nodes to replace
            var replaceDictionary = new Dictionary<DoStatementSyntax, DoStatementSyntax>();

            //Looking for do-until statements in all descendant nodes
            foreach (var doStatement in syntaxRoot.DescendantNodes().OfType<DoStatementSyntax>())
            {
                //Until token is treated as an identifier by C# compiler. It doesn't know that in our case it is a keyword.
                var untilNode = doStatement.Condition.ChildNodes().OfType<IdentifierNameSyntax>().FirstOrDefault((_node =>
                {
                    return _node.Identifier.ValueText == "until";
                }));

                //Condition is treated as an argument list
                var conditionNode = doStatement.Condition.ChildNodes().OfType<ArgumentListSyntax>().FirstOrDefault();

                if (untilNode != null && conditionNode != null)
                {

                    //Let's replace identifier w/ correct while keyword and condition

                    var whileNode = Syntax.ParseToken("while");

                    var condition = Syntax.ParseExpression("(!" + conditionNode.GetFullText() + ")");

                    var newDoStatement = doStatement.WithWhileKeyword(whileNode).WithCondition(condition);

                    //Accumulating all replacements
                    replaceDictionary.Add(doStatement, newDoStatement);

                }

            }

            syntaxRoot = syntaxRoot.ReplaceNodes(replaceDictionary.Keys, (node1, node2) => replaceDictionary[node1]);

            //Output preprocessed code
            Console.WriteLine(syntaxRoot.GetFullText());

        }
    }
}
///////////
//OUTPUT://
///////////
//            using System;

//            class Program {
//                public void My() {
//                    var i = 5;
//                    do {
//                        Console.WriteLine("hello world");
//                        i++;
//                    }
//while(!(i > 10));
//                }
//            }

现在我们可以使用 Roslyn API 编译更新的语法树或将 syntaxRoot.GetFullText() 保存到文本文件并将其传递给 csc.exe。

关于c# - 有没有办法在 C# 中实现自定义语言功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11749222/

相关文章:

c# - 重定向到页面 OnActionExecuting 方法 ASP.NET Core 5 MVC

c# - 我可以创建一个 SqlDataReader 并为其提供值,而不必从另一个对象返回 SqlDataReader 吗? SqlCommand.ExecuteReader()

for循环内的javascript添加

java - 双括号初始化和序列化

javascript - JavaScript 是否有类似于 php list 命令的语言结构?

c# - 如何在 Protobuf 中实现 VARIANT

c# - Assert.AreEqual(expected,actual) 中两个参数的顺序重要吗?

c# - 解构赋值 - C# 中变量的对象属性

c# - 在 C# 中是否有类似于 PHPs list() 的语言结构?

php - 使用字符串调用 PHP 语言构造