有没有C#实现自定义语言功能的方法吗? [英] Is there a way to implement custom language features in C#?
问题描述
我一直在纳闷这一段时间,我已经绕了一下看了看,无法找到有关这个问题的讨论。
I've been puzzling about this for a while and I've looked around a bit, unable to find any discussion about the subject.
让我们假设我想实现一个简单的例子,像一个新的循环结构:do..until
Lets assume I wanted to implement a trivial example, like a new looping construct: do..until
写的很相似do..while
Written very similarly to do..while
do {
//Things happen here
} until (i == 15)
这可以通过这样转化成有效的csharp的:
This could be transformed into valid csharp by doing so:
do {
//Things happen here
} while (!(i == 15))
这显然是一个简单的例子,但有什么办法来增加这种性质的东西吗?理想的情况是作为一个Visual Studio扩展,使语法高亮等。
This is obviously a simple example, but is there any way to add something of this nature? Ideally as a Visual Studio extension to enable syntax highlighting etc.
推荐答案
微软提出Rolsyn API为C#编译器的公共API的实现。它包含了每个编译器流水线阶段的个人的API:语法分析,符号创建,绑定,MSIL排放。您可以提供自己的语法分析器或为了得到C#编译器瓦特/任何功能,你想扩展现有之一。
Microsoft proposes Rolsyn API as an implementation of C# compiler with public API. It contains individual APIs for each of compiler pipeline stages: syntax analysis, symbol creation, binding, MSIL emission. You can provide your own implementation of syntax parser or extend existing one in order to get C# compiler w/ any features you would like.
<一个href=\"https://blogs.msdn.microsoft.com/visualstudio/2011/10/19/introducing-the-microsoft-roslyn-ctp/\"相对=nofollow>罗斯林CTP
让我们使用罗斯林扩展C#语言!在我的例子,我做替换,直到声明W /对应的DO-而
Let's extend C# language using Roslyn! In my example I'm replacing do-until statement w/ corresponding do-while:
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));
// }
// }
现在,我们可以使用API罗丝琳最新编译语法树或保存syntaxRoot.GetFullText()为文本文件,并把它传递给CSC.EXE。
Now we can compile updated syntax tree using Roslyn API or save syntaxRoot.GetFullText() to text file and pass it to csc.exe.
这篇关于有没有C#实现自定义语言功能的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!