有没有办法在C#中实现自定义语言功能?
我对此困惑了一段时间,我环顾了一下四周,找不到任何关于这个主题的讨论 假设我想要实现一个简单的示例,比如一个新的循环构造:do..until 写得非常类似于做…而有没有办法在C#中实现自定义语言功能?,c#,syntactic-sugar,language-construct,C#,Syntactic Sugar,Language Construct,我对此困惑了一段时间,我环顾了一下四周,找不到任何关于这个主题的讨论 假设我想要实现一个简单的示例,比如一个新的循环构造:do..until 写得非常类似于做…而 do { //Things happen here } until (i == 15) 通过这样做,可以将其转换为有效的csharp: do { //Things happen here } while (!(i == 15)) 这显然是一个简单的例子,但有没有办法添加这种性质的内容?理想情况下,作为一个Visua
do {
//Things happen here
} until (i == 15)
通过这样做,可以将其转换为有效的csharp:
do {
//Things happen here
} while (!(i == 15))
这显然是一个简单的例子,但有没有办法添加这种性质的内容?理想情况下,作为一个Visual Studio扩展,可以启用语法突出显示等功能。不,没有办法实现您所说的内容 因为你要问的是定义新的语言结构,新的词汇分析,语言解析器,语义分析器,编译和优化生成的
IL
在这种情况下,您可以使用一些宏/函数
public bool Until(int val, int check)
{
return !(val == check);
}
像这样使用它
do {
//Things happen here
} while (Until(i, 15))
不,没有办法实现你所说的 因为你要问的是定义新的语言结构,新的词汇分析,语言解析器,语义分析器,编译和优化生成的
IL
在这种情况下,您可以使用一些宏/函数
public bool Until(int val, int check)
{
return !(val == check);
}
像这样使用它
do {
//Things happen here
} while (Until(i, 15))
你不能在C#中创建你自己的语法抽象,所以你能做的最好的事情就是创建你自己的高阶函数。您可以创建
操作
扩展方法:
public static void DoUntil(this Action act, Func<bool> condition)
{
do
{
act();
} while (!condition());
}
尽管这是否比直接使用
do..while
更可取值得怀疑。你不能在C#中创建自己的语法抽象,所以你最好创建自己的高阶函数。您可以创建操作
扩展方法:
public static void DoUntil(this Action act, Func<bool> condition)
{
do
{
act();
} while (!condition());
}
尽管这是否比直接使用
do..while
更可取还值得怀疑。微软提出Rolsyn API作为带有公共API的C#编译器的实现。它包含每个编译器管道阶段的单独API:语法分析、符号创建、绑定、MSIL发射。您可以提供自己的语法分析器实现,也可以扩展现有的语法分析器实现,以获得C#编译器和您想要的任何功能
让我们使用Roslyn来扩展C语言!在我的示例中,我将替换do直到语句w/相应的do,同时:
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));
// }
// }
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用Roslyn.Compilers.CSharp;
名称空间罗斯林测试
{
班级计划
{
静态void Main(字符串[]参数)
{
变量代码=@“
使用制度;
班级计划{
公开作废我的(){
var i=5;
做{
Console.WriteLine(“你好世界”);
i++;
}
直到(i>10);
}
}
";
//正在将输入代码解析为SynaxTree对象。
var syntaxTree=syntaxTree.ParseCompilationUnit(代码);
var syntaxRoot=syntaxTree.GetRoot();
//在这里,我们将保留所有要替换的节点
var replaceDictionary=newdictionary();
//在所有子代节点中查找do TILL语句
foreach(类型()的syntaxRoot.DegenantNodes()中的var doStatement)
{
//直到令牌被C#编译器视为标识符,它才知道在我们的例子中它是一个关键字。
var untilNode=doStatement.Condition.ChildNodes().OfType().FirstOrDefault((\u node=>
{
返回_node.Identifier.ValueText==“直到”;
}));
//条件被视为参数列表
var conditionNode=doStatement.Condition.ChildNodes().OfType().FirstOrDefault();
if(untilNode!=null&&conditionNode!=null)
{
//让我们替换标识符w/correct while关键字和条件
var whileNode=Syntax.ParseToken(“while”);
var condition=Syntax.ParseExpression(“(!”+conditionNode.GetFullText()+”);
var newDoStatement=doStatement.WithWhileKeyword(whileNode).WithCondition(condition);
//积累所有替代品
replaceDictionary.Add(doStatement,newDoStatement);
}
}
syntaxRoot=syntaxRoot.ReplaceNodes(replaceDictionary.Keys,(node1,node2)=>replaceDictionary[node1]);
//输出预处理代码
Console.WriteLine(syntaxRoot.GetFullText());
}
}
}
///////////
//输出://
///////////
//使用制度;
//班级计划{
//公开作废我的(){
//var i=5;
//做{
//Console.WriteLine(“你好世界”);
//i++;
// }
//而(!(i>10));
// }
// }
现在,我们可以使用Roslyn API编译更新后的语法树,或者将syntaxRoot.GetFullText()保存到文本文件中,并将其传递给csc.exe。微软建议将Rolsyn API作为带有公共API的C#编译器的实现。它包含每个编译器管道阶段的单独API:语法分析、符号创建、绑定、MSIL发射。您可以提供自己的语法分析器实现,也可以扩展现有的语法分析器实现,以获得C#编译器和您想要的任何功能 让我们使用Roslyn来扩展C语言!在我的示例中,我将替换do直到语句w/相应的do,同时:
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));
// }
// }
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用Roslyn.Compilers.CSharp;
名称空间罗斯林测试
{
班级计划
{
静态void Main(字符串[]参数)
{
变量代码=@“
使用制度;
班级计划{
公共v