首页 > 基础资料 博客日记

AScript动态脚本多语言环境支持

2026-04-12 12:00:02基础资料围观1

这篇文章介绍了AScript动态脚本多语言环境支持,分享给大家做个参考,收藏极客资料网收获更多编程知识

AScript是一个开源的C#动态脚本解析执行库,支持扩展多种脚本语言。前一篇文章《AScript如何实现中文脚本引擎》中演示了扩展中文语言示例,本篇将更深入的理解AScript的多语言机制,以及如何在脚本中嵌入多种脚本语言。

一、自定义语法

AScript底层解析脚本生成token流,语法解析器对token流进行处理,就会调用ITokenHandler处理器,该接口定义如下:

1 public interface ITokenHandler
2 {
3     /// <summary>
4     /// token处理
5     /// </summary>
6     /// <param name="analyzer">语法分析器</param>
7     /// <param name="e">当前token、语法树及上下文信息</param>
8     void Build(DefaultSyntaxAnalyzer analyzer, TokenAnalyzingArgs e);
9 }

DefaultSyntaxAnalyzer参数为语法分析器,可以调用其中的BuildOneStatement或者BuildMultiStatement方法来读取一条或多条语句。

自定义语法就是对当前token以及前后语句进行处理,将结果添加到语法树,来实现期望的逻辑功能。

示例:定义sql条件语句的and语法

 1 /// <summary>
 2 /// <![CDATA[age>20 and age<50]]>
 3 /// </summary>
 4 public class AndTokenHandler : ITokenHandler
 5 {
 6     public static readonly AndTokenHandler Instance = new AndTokenHandler();
 7 
 8     public void Build(DefaultSyntaxAnalyzer analyzer, TokenAnalyzingArgs e)
 9     {
10         e.IsHandled = true;
11         if (!e.Ignore)
12         {
13             var op = new OperatorNode("and", DefaultSyntaxAnalyzer.OperatorPriorities["&&"], 2);
14             e.TreeBuilder.AddOperator(e.BuildContext, e.ScriptContext, e.Options, e.Control, op);
15         }
16     }
17 }

sql中的and语法等效于C#中的&&操作符,所以优先级取&&操作符的优先级,同时sql语言环境中需要注册and函数: AddFunc("and", AndAlsoOperator.Instance); 

二、定义语言

AScript中提供了ScriptLang类来扩展语言,该类包含类型、变量、函数、语法解析(ITokenHandler)管理。

多语言势必会带来语法兼容问题,比如sql条件中的"="号是相等的意思,等效于C#中的"==",跟C#中的赋值符号"="有冲突,可设置属性Compatible=false表示不兼容默认语言,在脚本或ScriptContext上下文中需要指定语言才能执行。

示例:定义Sql语言(这里只实现一个简单的条件判断功能)

 1 public class SqlLang : ScriptLang
 2 {
 3     public static readonly SqlLang Instance = new SqlLang();
 4 
 5     public SqlLang()
 6     {
 7         this.Compatible = false;
 8 
 9         AddFunc(".", DotOperator.Instance);
10         AddFunc("!", BoolNotOperator.Instance);
11         AddFunc("<", LessThanOperator.Instance);
12         AddFunc(">", GreaterThanOperator.Instance);
13         AddFunc("=", EqualOperator.Instance);
14         AddFunc(">=", GreaterThanOrEqualOperator.Instance);
15         AddFunc("<=", LessThanOrEqualOperator.Instance);
16         AddFunc("!=", NotEqualOperator.Instance);
17         AddFunc("and", AndAlsoOperator.Instance);
18         AddFunc("or", OrElseOperator.Instance);
19 
20         AddTokenHandler("and", AndTokenHandler.Instance);
21         AddTokenHandler("AND", AndTokenHandler.Instance);
22         AddTokenHandler("or", OrTokenHandler.Instance);
23         AddTokenHandler("OR", OrTokenHandler.Instance);
24         AddTokenHandler("=", EqualTokenHandler.Instance);
25         AddTokenHandler("like", LikeTokenHandler.Instance);
26         AddTokenHandler("LIKE", LikeTokenHandler.Instance);
27     }
28 }

由于AScript是区分大小写的,注册token时大小写都注册一下,便于sql语句中支持大小写语法,示例中的"or"、"like"等语法代码不一一列出了,感兴趣的同学可以到开源项目的单元测试中查看,后续可能会开发一个比较完备的sql语言脚本。

注册SqlLang: Script.Langs["sql"] = SqlLang.Instance; 

三、执行指定语言脚本

如果不指定语言,则使用默认且兼容的语言来执行脚本。

1、ScriptContext中设置Langs属性来指定脚本语言

 1 string s = "p.Name like 'to%' or p.Age>20 and p.Age<50";
 2 var script = new Script();
 3 script.Context.Langs = new[] { "sql" };
 4 var matchFunc = script.Compile<Person, bool>(s, "p");
 5 var list = new List<Person>
 6 {
 7     new Person("jim", 18),
 8     new Person("tony", 60),
 9     new Person("tom", 19),
10     new Person("san", 25),
11     new Person("lin", 70)
12 };
13 var matchedList = list.Where(matchFunc).ToList();
14 Assert.AreEqual(3, matchedList.Count);
15 Assert.AreEqual("tony", matchedList[0].Name);
16 Assert.AreEqual("tom", matchedList[1].Name);
17 Assert.AreEqual("san", matchedList[2].Name);

2、脚本中通过#lang语法嵌入其他语言

指定多个语言使用逗号","分隔,如: #lang 中文,CSharp 

 1 string s = @"
 2 bool isMatch(Person p) {
 3     #lang sql
 4     p.Age>20 and p.Age<50 or p.Name like 'to%' or p.Name='pen';
 5     #end
 6 }
 7 var matchedList = new List<Person>();
 8 foreach(var item in list) {
 9 if (isMatch(item)) matchedList.Add(item);
10 }
11 matchedList;
12 ";
13 var list = new List<Person>
14 {
15     new Person("jim", 18),
16     new Person("tony", 60),
17     new Person("tom", 19),
18     new Person("san", 25)
19 };
20 var script = new Script();
21 script.Context.AddType<Person>();
22 script.Context.SetVar("list", list);
23 var matchedList = script.Eval<List<Person>>(s);
24 Assert.AreEqual(3, matchedList.Count);
25 Assert.AreEqual("tony", matchedList[0].Name);
26 Assert.AreEqual("tom", matchedList[1].Name);
27 Assert.AreEqual("san", matchedList[2].Name);

四、结语

AScript 的多语言扩展能力,在同一脚本中嵌入不同脚本语言,让开发者和用户可以使用最合适的语言进行脚本配置,提高配置灵活性和产品体验。

AScript开源地址:https://gitee.com/rockey627/AScript

 


文章来源:https://www.cnblogs.com/rockey627/p/19854860
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云