juggle语法规范如下:

类型:

bool         ->     in cpp bool
int          ->     in cpp int64
float        ->     in cpp double
string       ->     in cpp std::string
array        ->     in cpp std::vector
struct       ->     in cpp object

函数的定义则同c语言:void rpctest1(int argv1, bool argv2, string argv3, float argv4, array<int> argv5);

整体的juggle语法如下:

module juggle{void rpctest1(int argv1, bool argv2, string argv3, float argv4, array<int> argv5);void rpctest2(int argv1, bool argv2, string argv3, float argv4, array<int> argv5);}

其中module对应c++中的class,并且在服务器端会被codegen实现为一个单件,无需用户定义句柄有codegen生成对应的create代码。

codegen会依据module中函数定义,生成如下代码:

#include <juggle.h>class juggle: public module{
public:juggle() : module(ch, juggleuuid::UUID()){_service_handle->register_module_method(juggle_rpctest1,boost::bind(&juggle::call_rpctest1, this, _1));_service_handle->register_module_method(juggle_rpctest2,boost::bind(&juggle::call_rpctest2, this, _1));}~juggle(){}virtual void rpctest1(int64_t argv1,bool argv2,std::string argv3,double argv4,std::vector<int64_t>  argv5) = 0;void call_rpctest1(boost::shared_ptr<channel> ch, boost::shared_ptr<object> v){auto argv1 = (*v)["argv1"].asint();auto argv2 = (*v)["argv2"].asbool();auto argv3 = (*v)["argv3"].asstring();auto argv4 = (*v)["argv4"].asfloat();std::vector<int64_t> argv5;for(int i = 0; i < (*v)["argv5"].size(); i++){v.push_back((*v)["argv5"][i].asint());}auto ret = rpctest1(argv1, argv2, argv3, argv4, argv5);boost::shared_ptr<object> r = boost::make_shared<object>();(*r)["suuid"] = (*v)["suuid"];(*r)["method"] = (*value)["method"];(*r)["ret"] = ret;ch->push(r);}virtual void rpctest2(int64_t argv1,bool argv2,std::string argv3,double argv4,std::vector<int64_t>  argv5) = 0;void call_rpctest2(boost::shared_ptr<channel> ch, boost::shared_ptr<object> v){auto argv1 = (*v)["argv1"].asint();auto argv2 = (*v)["argv2"].asbool();auto argv3 = (*v)["argv3"].asstring();auto argv4 = (*v)["argv4"].asfloat();std::vector<int64_t> argv5;for(int i = 0; i < (*v)["argv5"].size(); i++){v.push_back((*v)["argv5"][i].asint());}auto ret = rpctest2(argv1, argv2, argv3, argv4, argv5);boost::shared_ptr<object> r = boost::make_shared<object>();(*r)["suuid"] = (*v)["suuid"];(*r)["method"] = (*value)["method"];(*r)["ret"] = ret;ch->push(r);  }};

可以看到,codegen实现了网络层面的消息响应、协议pack/unpack以及对rpc函数的调用,返回值封包发送的代码。用户只需要继承module并实现对应的rpc函数。

其中对于obejct的定义见 https://github.com/NetEase/fossilizid/blob/master/juggle/interface/object.h

我定义了一个纯虚类,用于规范一个通信协议参数入栈和访问的接口

然后定义了一个channel https://github.com/NetEase/fossilizid/blob/master/juggle/interface/channel.h

用于规范通信的接口

对于通信而言,push/pop是非常上层的一个接口,但是这样的设计目的在于提供一个宽泛的抽象,这里通信的可以是一个消息队列,一个基于共享内存的本地跨进程通信,同样也可以是socket。

btw:另一个原因是我自己封装的网络库的长相是这样的 https://github.com/NetEase/fossilizid/tree/master/remoteq, remotoq提供的通信句柄正是channel,而提供的访问接口则是push/pop。并且通过模板参数配置了网络协议的pack/unpack。我这么实现是为了方便代码复用。

然后是对dsl语言的编译:

juggle的语法定义的关键字,除了变量类型,就只有module和struct。对于一个module的定义,在module之后是是这个module的命名,之后是'{'表示此module定义开始,至'}'表示此module定义结束。module的分析代码如下:

class module(object):def __init__(self):self.keyworld = ''self.name = ''self.module = []self.machine = Nonedef push(self, ch):if ch == '}':self.machine = Nonereturn Trueif self.machine is not None:if self.machine.push(ch):self.module.append(self.machine.func)self.machine.clear()else:if ch == '{':self.name = deleteNoneSpacelstrip(self.keyworld)self.keyworld = ''self.machine = func()return Falseself.keyworld += chreturn False

在检索到'{'之后开始对module定义的分析,至'}'结束这个module的定义。

因为dsl语言本身的特性,module中只有函数定义,struct中变量定义。所以在module中,只需要分析函数定义。

self.machine = func(),对函数分析器的定义如下:

class func(object):def __init__(self):self.keyworld = ''self.func = []self.argvtuple = Nonedef clear(self):self.keyworld = ''self.func = []self.argvtuple = Nonedef push(self, ch):if ch == ' ' or ch == '\0':self.keyworld = deleteNoneSpacelstrip(self.keyworld)if self.keyworld != '':if self.argvtuple is None:self.func.append(self.keyworld)else:self.argvtuple.append(self.keyworld)self.keyworld = ''return Falseif ch == ',':if self.keyworld != '':self.argvtuple.append(deleteNoneSpacelstrip(self.keyworld))self.func.append(self.argvtuple)self.keyworld = ''self.argvtuple = []return Falseif ch == '(':self.func.append(deleteNoneSpacelstrip(self.keyworld))self.argvtuple = []self.keyworld = ''return Falseif ch == ')':if self.keyworld != '':self.argvtuple.append(deleteNoneSpacelstrip(self.keyworld))self.func.append(self.argvtuple)self.keyworld = ''return Falseif ch == ';':return Trueself.keyworld += chreturn False

因为无需考虑其他的语法要素的区分,函数定义的分析只需要考虑依次提取返回值类型,函数名,(,参数定义,),;函数定义结束。符号表示如下:

rettype funcname(argvlist...);

之后是对struct的分析,与module类似,在struct之后的既是struct name的定义,之后是'{'开始struct的定义,之'}'结束此struct的定义,代码如下:

class struct(object):def __init__(self):self.keyworld = ''self.name = ''self.struct = []self.argvdef = []def push(self, ch):if ch == ' ' or ch == '\0':if self.keyworld != '':self.argvdef.append(self.keyworld)if ch == '{':self.name = deleteNoneSpacelstrip(self.keyworld)self.keyworld = ''return Falseif ch == ';':self.struct.append(self.argvdef)self.argvdef = []if ch == '}':return Trueself.keyworld += chreturn False

对于struct中的变量定义,同样以'type name;'的方式直接分割。

之后是对jeggle文件的整体分析:

class statemachine(object):Moduledefine = 0Funcdefine = 1def __init__(self):self.keyworld = ''self.module = {}self.struct = {}self.machine = Nonedef push(self, ch):if self.machine is not None:if self.machine.push(ch):if isinstance(self.machine, module):self.module[self.machine.name] = self.machine.moduleself.machine = Noneif isinstance(self.machine, struct):self.struct[self.machine.name] = self.machine.structself.machine = Noneelse:self.keyworld += chif self.keyworld == 'module':self.machine = module()self.keyworld = ''if self.keyworld == 'struct':self.machine = struct()self.keyworld = ''def getmodule(self):return self.moduledef getstruct(self):return self.structdef syntaxanalysis(self, genfilestr):for str in genfilestr:for ch in str:self.push(ch)

检索到module和struct之后分别进入对应分支。

之后是codegen的代码见:

https://github.com/NetEase/fossilizid/blob/master/juggle/rpcmake/codegen.py

和之前的http://www.cnblogs.com/qianqians/p/4184441.html对比可以看到精简之后的dsl语法要方便分析许多,实作代码也要清晰不少。

和之前为c++添加rpccall的计划相比,现在的dsl语言便于提供其他语言的扩展,同时编译器也会好些很多。

btw:现在的dsl语法非常之强类型,尤其是带模板参数的array<int>,有用过protobuf和thrift的同学应该可以对比去其中的区别,希望大家能对如何设计一个好用的dsl展开讨论。

转载于:https://www.cnblogs.com/qianqians/p/4255034.html

juggle dsl语法介绍及codegen浅析相关推荐

  1. 【ES系列】ES的数据结构与DSL语法

    ES的数据结构与DSL语法 数据结构部分 正向索引与倒排索引 定义 结构 分词(keyword) DSL语句 常用DSL语句 索引部分 创建索引 查看es所有索引 查看单个索引 删除索引 文档部分 创 ...

  2. Markdown 语法介绍

    Markdown 语法介绍 from:https://coding.net/help/doc/project/markdown.html 文章内容 1 Markdown 语法介绍 1.1 标题 1.2 ...

  3. sql和mysql语法_SQL 与MySQL-基本语法介绍

    MySQL-基本语法介绍 简单说:msyql 就是一个仓库, sql就是如何从仓库取(查询.更改)东西,它们是一个组合,在一起亲密合作,缺一不合: MySQL 基本语法介绍 1. 什么是SQL SQL ...

  4. Elasticsearch之Query DSL语法入门

    1. query DSL入门 1.1 DSL query string 后边的参数原来越多,搜索条件越来越复杂,不能满足需求. GET /book/_search?q=name:java&si ...

  5. Swift翻译之-Swift语法入门 Swift语法介绍

    目录[-] Hello world - Swift 简单赋值 控制流 函数与闭包 对象和类 枚举与结构 协议和扩展 泛型 2014.6.3日,苹果公布最新编程语言Swift,Swift是一种新的编程语 ...

  6. php语法介绍,PHP语法介绍

    php7新特性是什么 php7新特性是什么?在PHP7中由于修改了底层引擎大部分代码,以及通过各种方式提高PHP的性能,所以在PHP7中也增加了一些新的语法,这些语法的使用也能对提高性能有帮助.下面给 ...

  7. php语法介绍,PHP 函数语法介绍一

    PHP 函数语法介绍一 复制代码 代码如下: function getAdder($x) { return function ($y) use ($x) { return $x + $y; }; } ...

  8. php 纯文本输出_关于PHP的语法介绍,新手必看

    作为一款最好用的PHP集成开发工具,它具有智能PHP代码编辑器,代码质量分析,简易代码导航和搜索.那么对于刚开始接触它的新手小白来说,它的入门语法对于你们来说一定很重要,那么就请跟我一起来看看吧. P ...

  9. c语言中建一个文件的语法,C语言语法介绍_文件.ppt

    C语言语法介绍_文件 第十三章 本章要点 文件的基本概念 文件的基本函数 文件的顺序读写 文件的随机读写 文件简单应用 主要内容 13.1 C文件概述 13.2 文件类型指针 13.3 文件的打开与关 ...

最新文章

  1. 计算机组成原理主存储器知识点,【考研】2020考研:计算机组成原理知识点主存储器与CPU的连接...
  2. SpringMVC学习系列(11) 之 表单标签
  3. UltraEdit常用配置搭建Java/C开发环境
  4. Linux微信运行错误,Ubuntu 16.04 运行微信开发者工具编译出错的解决办法
  5. CMake常用命令整理
  6. ax200无线网卡黑苹果_无线网卡AX200刷killer1650X
  7. OpenCV threshold 二值化
  8. Python基于迁移学习的手势识别实战【图像多分类任务】【实测准确度超过99.5%】
  9. app接口开发整理(1)
  10. java文件上传下载接口_java 文件上传下载
  11. 手机配置host的替代方案
  12. css:clac计算
  13. Springboot整合Redis实现腾讯云发送短信验证码并实现注册功能
  14. jsp大学生兼职信息管理系统
  15. CorelDRAW 2023版本更新内容及安装详细教程
  16. 如何设置Ubuntu 自动待机时间
  17. 金蝶生成凭证模板_【干货】金蝶云ERP教你凭证模版的引入引出
  18. OSAL系统框架专题
  19. 支持向量机原理(一) 线性支持向量机
  20. android平台下OpenGL ES 3.0绘制纯色背景

热门文章

  1. 值类型和引用类型在栈和堆中的分配
  2. 【GO语言】合理配置GOMAXPROCS提升一倍以上的性能
  3. javascript编程风格
  4. shell编程-条件判断
  5. 在Linux下轻松玩转Samba服务器
  6. 「AHOI / HNOI2018」转盘 解题报告
  7. ObservableCollection排序
  8. svnserve.conf: Option expected的问题解决方法
  9. java.math.BigDecimal()的用法
  10. php将中文插入数据库出现乱码