当前位置: 首页 > news >正文

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

 

http://www.jsqmd.com/news/628680/

相关文章:

  • Intv_AI_MK11 自动化办公助手:Python 脚本生成与执行
  • 千问3.5-2B健身行业:运动姿势图识别、器械使用图理解与训练指导生成
  • 2026年佛山音乐品牌排名,德尚音乐音乐业务、服务及创新成果哪家强 - 工业品牌热点
  • Wnt/β-catenin信号通路在组织修复与再生中的关键作用及机制解析
  • MoveIt! IKFast插件配置避坑指南:从‘GetFreeParameters’报错到成功编译的完整流程
  • 终极指南:如何让Mac原生支持MKV等所有视频格式预览
  • Agent 的记忆机制
  • 告别误码:手把手教你配置GT收发器的8B10B编码与Comma对齐(附Vivado工程)
  • 电商人必备!用Qwen-Image-2512-SDNQ快速生成商品主图,提升工作效率
  • GHelper革命性硬件控制工具:解放华硕笔记本性能的终极解决方案
  • 万物识别镜像应用案例:电商商品自动分类、智能相册整理实战
  • 从模型到部署:四大推理引擎(ONNX Runtime、OpenVINO、TensorRT、ncnn)的选型实战指南
  • GHelper终极指南:三步掌握华硕笔记本性能优化,告别卡顿与高功耗!
  • 从SGM706看门狗芯片出发,详解硬件监控电路的设计要点与实战避坑
  • 2026年国内生成式引擎优化领域专业GEO优化工具服务商3家深度分析推荐 - 小白条111
  • EagleEye DAMO-YOLO TinyNAS:毫秒级目标检测,5分钟快速部署实战
  • Applied Intelligence投稿实战:Latex排版与文件提交的避坑指南
  • 性价比高的加密软件品牌企业如何选 - 工业品网
  • AI写专著的秘密武器!巧用工具,实现从构思到出版的飞跃
  • Qwen3-VL-8B多模态能力展示:数学公式识别、代码截图解释、手写体理解
  • VHDL交通信号灯实战:从零搭建Quartus仿真环境(含完整代码解析)
  • HarmonyOS应用开发深度解析:从移动端到PC端的技术实践
  • CHORD-X前端展示:微信小程序开发实时战术看板
  • 深入解析 DHCP 协议:从报文结构到实战抓包技巧
  • LeagueAkari:基于LCU API的英雄联盟客户端工具箱技术架构与实战指南
  • Multi-Agent 角色分工模板:产品经理+研发+测试智能体协作配置
  • IDEA NC NCC NCCloud U8C 开发插件:从零到一构建高效开发环境与补丁发布
  • 火杉互联GEO优化靠谱吗,广州地区有哪些成功案例? - 工业推荐榜
  • 从投影矩阵到视锥体剔除:OpenGL中的高效裁剪技术解析
  • 不用装软件!这款MicroPython浏览器 IDE :让你在手机上也能调试树莓派 Pico蘸