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

我已经对此感到困惑了一段时间,并且四处张望,无法找到有关该主题的任何讨论。

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

写得非常类似。

do {

//Things happen here

} until (i == 15)

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

do {

//Things happen here

} while (!(i == 15))

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

回答:

Microsoft提出将Rolsyn

API作为带有公共API的C#编译器的实现。它为每个编译器管道阶段包含单独的API:语法分析,符号创建,绑定,MSIL发出。您可以提供自己的语法解析器实现或扩展现有的语法解析器实现,以便获得具有所需功能的C#编译器。

罗斯林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编译更新的语法树,或将语法Root.GetFullText()保存到文本文件并将其传递给csc.exe。

以上是 有没有办法在C#中实现自定义语言功能? 的全部内容, 来源链接: utcz.com/qa/409870.html

回到顶部