网站 建设设计方案,做网站好公司哪家好,大连网页制作wordpress,wordpress分类目录代码在上一篇博文 LogoSharp#xff1a;Logo语言的C#实现中#xff0c;我介绍了LOGO语言的C#实现#xff0c;在该项目中#xff0c;我使用了.NET下的语法解析框架#xff1a;Irony。Irony框架最开始的时候是由Roman Ivantsov发布在codeplex上的一个开源项目#xff0c;它使用… 在上一篇博文 LogoSharpLogo语言的C#实现中我介绍了LOGO语言的C#实现在该项目中我使用了.NET下的语法解析框架Irony。Irony框架最开始的时候是由Roman Ivantsov发布在codeplex上的一个开源项目它使用MIT协议开源。由于2017年的时候微软关闭了codeplex服务为了让这个优秀的项目能够继续为人所用我将其复制到了我的Github账号下并将其移植到NET Standard 2.0地址是https://github.com/daxnet/irony。于是Irony目前可以在.NET Core下使用了。事实上Github中有很多Irony的版本但大多数都不支持.NET Core。不仅如此我还在Azure DevOps上配置了持续集成因此你可以通过NuGet很方便地使用Irony。Irony相关的NuGet包有两个你需要在你的项目中同时安装以下两个NuGet包12Install-Package Irony.NetCore -Version 1.1.11Install-Package Irony.Interpreter.NetCore -Version 1.1.11接下来我介绍一下如何用Irony实现一个语法解析器我们以SQL语句为例进行介绍。所有使用Irony框架的语法定义都必须继承于Grammar类并加上Language特性。以下就是我定义的一个SQL语句的语法我称之为“Mini SQL”因为它目前只支持SELECT语句而且不支持WHERE子句。12345678910111213141516171819[Language(Mini SQL, 1.0, A SQL Sample)]public class MiniSqlGrammar : Grammar{ public MiniSqlGrammar() : base(false) { var identifier new IdentifierTerminal(Identifier); var table new NonTerminal(table); var fields new NonTerminal(fields); var sql_statement new NonTerminal(SQL); table.Rule identifier; fields.Rule * | MakePlusRule(fields, ToTerm(,), identifier); sql_statement.Rule SELECT fields FROM table; Root sql_statement; }}代码非常简单也很容易理解它可以使用人类比较容易读懂的语法定义规则进行语法定义。这里简单介绍一下上面的代码Language特性用于描述我们自定义的语法语法类需要继承于Grammar类基类构造函数的false参数表示我们的语言是大小写不敏感的所有的程序语言标识符都可以用IdentifierTerminal进行定义Irony已经自带了标识符的识别逻辑非常简单table是一个标识符fields可以是*也可以是由一些标识符通过逗号分隔的一个列表SQL语句由四个部分组成SELECT关键字、fields字段列表、FROM关键字以及table数据表名Rootsql_statement表示语言的解析入口就是SQL语句编译通过后我们就可以使用这个语法进行SELECT语句的解析了。Irony有一个非常不错的功能就是它提供一个用户界面用来测试我们定义的语法。这个用户界面是一个Windows Forms的应用程序我也将其发布到我的Github账号下地址是https://github.com/daxnet/irony-explorer。下载以后编译执行GrammarExplorer项目就可以打开这个测试界面。在测试界面中打开包含有自定义语法的.NET DLL就可以将其添加到Grammar Explorer中。例如下图展示了我用Grammar Explorer测试上面的SQL语法的界面效果在Grammar Explorer中你可以看到我们自定义语法是否存在错误还可以使用一个具有代码着色功能的编辑器进行测试点击Parse按钮即可生成语法解析树。使用Irony进行语法解析的基本步骤是基于语法Grammar定义创建语言数据Language Data基于语言数据产生解析器Parser使用解析器解析输入的字符串生成语法树遍历语法树执行相应的程序逻辑下面的代码展示了这一过程123456789101112131415161718192021222324252627282930313233343536373839404142sealed class SqlParser{ private static readonly LanguageData languageData new LanguageData(new MiniSqlGrammar()); private static readonly Parser parser new Parser(languageData); private readonly Liststring parsedFields new Liststring(); public void Execute(string command) { var tree parser.Parse(command); if (tree.HasErrors()) { return; } ParseTree(tree.Root); } private void ParseTree(ParseTreeNode node) { switch (node.Term.Name) { case SQL: foreach (var child in node.ChildNodes) { ParseTree(child); } break; case fields: foreach (var child in node.ChildNodes) { parsedFields.Add(child.Token.Text); } break; case table: ParsedTable node.ChildNodes[0].Token.Text; break; } } public IEnumerablestring ParsedFields parsedFields; public string ParsedTable { get; private set; }}SqlParser会基于我们自定义的语法类生成一个Irony的Parser对象然后使用Parse方法来解析传入的SQL语句并产生语法解析树。之后就可以根据树状结构来解析语句中的每一个部分并执行相应的操作。最后就是使用这个SqlParser类来解析SQL语句并得到结果。代码如下123456789101112static void Main(string[] args){ var sqlParser new SqlParser(); sqlParser.Execute(SELECT firstName, LastName FROM tbl_students); Console.WriteLine($获得的数据表: {sqlParser.ParsedTable}); Console.WriteLine(获得的字段:); foreach (var field in sqlParser.ParsedFields) { Console.WriteLine(field); }}代码很简单调用SqlParser的Execute方法来解析给定的SQL语句解析结果会分别保存在SqlParser的ParsedTable和ParsedFields两个属性中上面的控制台程序只需要输出这两个结果就行了。在实际应用中可以通过ParsedTable来获取某一种类型的对象列表然后通过ParsedFields来投影列表中每个对象的属性从而得到基于C#的一系列对象来执行SQL查询的效果。本案例执行结果如下本文简要介绍了.NET语法解析框架Irony的使用并通过SQL语句解析的案例介绍了Irony使用的一些技巧与步骤。就SQL语句而言它的定义还是相对比较复杂的不可能单靠一篇博客就能完全覆盖所有内容也是因为这个原因本文也没有涉及WHERE子句的设计但Irony框架是完全可以做到这一点的。事实上在Irony Explorer项目中就有一个IronyExplorer.Samples的工程其中包含了很多编程语言语法定义的案例代码比如Java、C#、SQL等有兴趣的可以参考。Irony框架本身已经帮我们做了很多工作比如大小写敏感的特性比如运算符优先级的定义比如标识符、整数、小数、正负数的定义再比如块注释与行注释的处理等等。在我用C#实现LOGO语言时基本上也是按照上面所述步骤进行编写和测试因此我就不再另起篇幅来介绍LOGO语言的语法定义了。原文地址https://sunnycoding.cn/2019/07/11/sql-parser-with-irony-in-csharp/.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com