有没有C#实现自定义语言功能的方法吗? [英] Is there a way to implement custom language features in C#?

查看:377
本文介绍了有没有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..un​​til

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆