一个JavaScript版本的bison
jison是一个 JavaScript 编写的解析器生成器,可以用来生成自定义的编程语言解析器。它的令人兴奋的点在于,它允许开发人员使用 JavaScript 语言来定义语法规则,然后将其转换为解析器,从而支持自定义的编程语言。
在前端应用方面,Jison 可以用于实现自定义的模版引擎,例如类似于 Handlebars 或者 Mustache 的模版引擎。通过使用 Jison,开发人员可以定义自己的模版语法规则,然后将其转换为解析器,从而实现对自定义模版语法的支持。
(资料图)
此外,Jison 还可以用于实现自定义的 DSL(领域特定语言),例如在前端应用中实现一些特定的业务逻辑,例如表单验证、数据格式化等等。通过使用 Jison,开发人员可以定义自己的 DSL 语法规则,然后将其转换为解析器,从而实现对自定义 DSL 的支持。
jison有很多demo可以供参考,比如 写一个计算器 https://gerhobbelt.github.io/jison/try/
要实现这个计算器,你的代码不再是手写解析算术表达式,手写语法树解析,然后计算结果,而是只用定义规则,剩下的事让机器帮你搞定就好了:
cala.bison
/* description: Parses end executes mathematical expressions. *//* lexical grammar */%lex%%\s+ /* skip whitespace */[0-9]+("."[0-9]+)?\b return "NUMBER""*" return "*""/" return "/""-" return "-""+" return "+""^" return "^""(" return "("")" return ")""PI" return "PI""E" return "E"<> return "EOF". return "INVALID"/lex/* operator associations and precedence */%left "+" "-"%left "*" "/"%left "^"%left UMINUS%start expressions%% /* language grammar */expressions : e EOF {return $1;} ;e : e "+" e {$$ = $1+$3;} | e "-" e {$$ = $1-$3;} | e "*" e {$$ = $1*$3;} | e "/" e {$$ = $1/$3;} | e "^" e {$$ = Math.pow($1, $3);} | "-" e %prec UMINUS {$$ = -$2;} | "(" e ")" {$$ = $2;} | NUMBER {$$ = Number(yytext);} | E {$$ = Math.E;} | PI {$$ = Math.PI;} ;
要了解jison的强大,就必须了解下DSL,以及它能够高效的解决哪些问题:
DSL(Domain-Specific Language)是一种用于特定领域的编程语言,它是为了解决某些领域特定的问题而设计的。与通用编程语言相比,DSL更加专注于特定领域,因此在该领域内更易于使用和理解。DSL可以通过语法、关键字或标记等方式来描述特定领域内的问题,并提供相应的解决方案。常见的DSL包括配置文件语言、领域特定脚本语言、数据流语言等。DSL的好处在于可以提高编程效率和代码可读性,同时也使得非程序员能够更容易地理解和维护代码。
简单的实现一个DSL的步骤
要完整实现一个DSL,需要以下步骤:
1.定义DSL的语法和语义:DSL语言需要有自己的语法和语义,以便用户能够使用该语言来表达自己的意图。语法定义通常使用BNF或EBNF表示。
2.实现DSL的解析器:DSL解析器是将DSL代码解析为计算机可执行的指令的程序。解析器通常使用词法分析器和语法分析器来实现。
3.实现DSL的执行器:DSL执行器是将DSL代码转化为实际的计算机操作的程序。执行器通常使用解释器或编译器实现。
其中词法分析器,语法分析器这些都有非常稳定的工具,比如,如果有定义好的BNF范式,直接丢给 flex 就可以解决词法分析的这个过程,然后在丢给 yacc,就可以按照这个规则编译出可执行程序,也许你会觉得这个非常不可思议,怎么写一堆规则就可以变成可执行程序呢?但实际上,你好好思考下,你写程序部也是在规定一些规则吗?
if/else/while/... ,这部都是在告诉计算机如何理解并执行你的意图吗?OK,立即这些,就看看其中的一些概念,对于新手可能需要科普一下:
BNF或EBNF简单的描述
BNF(巴克斯-诺尔范式)和 EBNF(扩展巴克斯-诺尔范式)是一种用于描述编程语言结构的形式语法。例如,下面是一个使用BNF表示的简单数学表达式:
::= | "+" | "-" ::= | "*" | "/" ::= | "(" ")"
这个BNF描述了一个数学表达式可以由一个项(term)或一个表达式(expr)加减一个项(term)组成。一个项可以由一个因子(factor)或一个项(term)乘除一个因子(factor)组成。一个因子可以是一个数字(number)或者一个表达式(expr)。
EBNF是BNF的一个扩展,添加了更多的元素来描述更复杂的语言结构。例如,下面是一个使用EBNF描述的简单的JSON对象:
这个EBNF描述了一个JSON对象由大括号包围着若干个属性(property)组成。每个属性包含一个字符串键(string)和一个值(value),用冒号分隔。字符串是由双引号包围的任意字符的序列(char)。值可以是一个字符串,一个数字,一个JSON对象,一个JSON数组,或者true/false/null中的一个。数字是由一个或多个数字(digit)和一个可选的小数点以及一个可选的指数部分组成。
上面这一堆精准定义的规则都是一些上下文无关文法,要准确写出flex可以用的规则,必须对上下文无关文法比较熟悉,比如不能出现左递归、不能出现空规则等等:
上下文无关文法
上下文无关文法(Context-Free Grammar)指的是一种形式文法,其中所有规则的左部只包含一个非终结符号,而右部可以是任意长度的终结符和非终结符序列。上下文无关文法是自然语言处理、编译原理和计算机语言设计等领域中广泛使用的一种形式化表示方法。
要轻松写一个上下文无关文法,可以按照以下步骤进行:
1. 确定终结符号集和非终结符号集。终结符号是指语言中的基本符号,如字母、数字、标点符号等;非终结符号是指可以被分解为其他符号序列的符号,如句子、短语、单词等。2. 编写规则。规则由两部分组成,左部为非终结符号,右部为终结符号和/或非终结符号的序列。例如,一个简单的规则可以写为:S -> aSb,表示S可以被替换为一个"a",后面跟着S,再后面跟着一个"b"。3. 定义起始符号。起始符号是文法中唯一的一个非终结符号,表示整个文法的起点。通常用大写字母来表示起始符号。4. 检查文法的合法性。文法需要满足一些条件,如不能存在左递归、不能出现空规则等。例如,一个简单的上下文无关文法可以表示一个简单的算术表达式:
1. 终结符号集:数字(0-9)、加号(+)、减号(-)、左括号(()、右括号())
2. 非终结符号集:表达式(E)、项(T)、因子(F)
3. 规则:
E -> E+T | E-T | T T -> T*F | T/F | F F -> (E) | num
4. 起始符号:E
这个文法可以生成类似于“3+4*5”的算术表达式。
左递归和空规则
左递归:在一个产生式的右部出现了该产生式本身作为左部的情况,例如:A->Aα(α为任意串)。这种产生式会导致递归调用,容易陷入死循环,因此需要消除左递归。
空规则:也称ε规则,表示产生式右部可以为空,例如:A->ε。如果某个非终结符的所有产生式都是空规则,那么这个非终结符可以被省略,也就没有必要存在了。但是,如果存在空规则,那么在语法分析时需要进行特殊处理,增加算法的复杂度。因此,尽量避免使用空规则。
DSL擅长解决哪些领域的问题
DSL(领域特定语言)擅长解决领域特定问题,即在特定领域中使用的编程语言。以下是一些DSL可以解决的问题的例子:
1. SQL:SQL是一种DSL,用于在关系数据库中查询和操作数据。它是用于数据管理和查询的最常用的DSL之一。2. HTML和CSS:HTML和CSS是用于构建Web页面的DSL。HTML用于定义页面的结构和内容,CSS用于定义页面的外观和样式。3. LaTeX:LaTeX是一种DSL,用于创建高质量的科学文档和出版物。它提供了丰富的排版控制,使得用户可以创建复杂的数学公式,图表和图形。4. R:R是一种DSL,用于数据分析和统计。它提供了许多内置函数和库,可以用于数据可视化,机器学习和预测建模等任务。5. Regex:正则表达式是一种DSL,用于匹配和操作文本。它在许多编程语言中都得到了广泛的应用,可以用于文本搜索,替换和解析。DSL可以用于在特定领域中更有效地解决问题,提高开发效率和代码质量。
关键词:
-
全球头条:懂前端的你也可以轻松定义自己业务的DSL
jison是一个JavaScript编写的解析器生成器,可以用来生成自定义的编程语言解析器。它的令人兴奋的点在于,它允许开发人员使用JavaScript
-
全球快消息!当务之急是找到关键的问题_当务之急
1、【解释】:当务:指应当办理的事。2、当前任务中最急切要办的事。3、【出自】:《孟子·尽心上》:“知者无不知也,当务之
-
地下城堡2图15攻略教团骑士_地下城堡2图15攻略
1、阵容:法师X2、圣骑、祭祀;也可以用一般的圣龙代替其中一个法师。2、通关方式:在装备选择上,双铁臂消防服4件(也可以
-
环球讯息:国内首座最大直径22万方储罐机械完工
【国内首座最大直径22万方储罐机械完工】新华社消息,3月17日,由海油工程牵头总承包的国家管网天津LNG二期项目4号储罐及配套设施成功实现机械
-
海亮股份董事长曹建国:锂电铜箔供需趋稳 产品价格下降可预见|全球播报
3月17日,海亮股份(SZ002203,股价11 77元,市值233 62亿元)召开了2023年第二次临时股东大会。在股东交流环节,董事长曹建国表示,铜加工费下
-
勇士不敌老鹰客场十连败 库里31+6+5杨25+12 观速讯
勇士不敌老鹰客场十连败库里31+6+5杨25+12,库里,勇士,老鹰,特雷-杨
-
范闲何时知道五竹是机器人_五竹是机器人吗-天天速讯
1、与其说是在玩主角光环的把戏,不如说是范贤母亲的光环太强了,所以范贤从出生开始就被光环笼罩着。所谓的试炼,其实一路都有强大的后台支持
-
濮存晰的老婆_濮存晰个人资料 世界热点评
1、濮存昕,1953年7月31日出生在北京市东城区,汉族。2、祖籍南京市溧水区,中国男演员。本文就为大家分享到这里,希望
-
所属街道社区怎么查询 郑州市街道办事处划分
今天来聊聊关于所属街道社区怎么查询,郑州市街道办事处划分的文章,现在就为大家来简单介绍下所属街道社区怎么查询,郑州市街道
-
AI助力智媒时代!海报新闻成为文心一言首批生态合作伙伴
大众网·海报新闻记者冯媛媛济南报道3月16日下午,百度正式发布国内首款大语言模型——文心一言,山东省互联网传媒集团旗下海报新闻成为文心一
-
每日播报!福州赏羊蹄甲指南(地点+简介)
工业路羊蹄甲又开啦首选赏花地:工业路(附近还有宝龙城市广场和万象城可以逛哦)次选赏花地:温泉支路、金泉路、朝阳路、高桥路、芳沁路、左
-
日媒:日本“少年诈骗犯”增加,网络招募成陷阱 天天关注
参考消息网3月17日报道据日本《朝日新闻》网站3月16日报道,据悉,去年日本有477名未满20岁的青少年因参与诈骗被捕或被送检,比上年增加44人(
-
这款36K英里1976 AMC大黄蜂Sportabout保留了马拉伊斯时代的“豪华” 全球讯息
有时您正在寻找时间记录,而不是跟踪时间。如果您想在过去的时代里度过一段时间,那么没有什么比AMC产品更能囊括1970年代
-
今日快讯:未来5年粵港澳大湾区将引领全球湾区发展 “广东制造”抢抓全面注册制改革机遇促发展
“跨国公司巨头在广东投资100多亿美元,释放的信号就是看好广东,看中大湾区投资的热土。”3月16日,中国首席经济学家论坛暨第二届大湾区经济
-
今日时讯:罗马远征球迷赛后高唱穆帅名字 穆帅从一项欧战出局不该踢次级别拉齐奥没有更低级别可踢了吧-每日热点
小伙伴们好,带大家回顾下罗马远征球迷赛后高唱穆帅名字穆帅从一项欧战出局不该踢次级别拉齐奥没有更低级别可踢了吧,那么小纵
-
全球快报:离职了怎么自己交社保_失业期间社保怎么交
1、根据不同的失业情况,具体失业后缴纳社保也是有区别的。2、按规定,领取失业保险金人员应参加其失业前的职工社保,由失业保
-
世界观点:5月底奥迪A6L优惠完22万,A4L优惠完15万,到底是不是真的
相信关注汽车圈的朋友肯定都知道的一件事情,有人预测奥迪会降价,A6L会到22万,A4L会到十五六万,说是有600多万辆库存车,因为国6B马上要实施
-
汉中市社保卡进度_汉中社保卡制卡进度查询
1、可以在支付宝里面查。2、打开支付宝,搜索市民服务,打开后点击里面的社保,然后就有社保卡制卡进度查询,然后点击进去输入
-
当前热门:世贸组织讨论环境政策贸易影响 中方提案受关注
会议期间,各方就环境政策的贸易影响展开讨论,中方要求对欧盟碳边境调节机制开展多边专题讨论的提案受到世贸组织成员广泛关注
-
中环海陆董秘回复:公司可转债转股价格是否下修,请您关注届时公司披露的相关公告! 2023年风电行业整体向好
中环海陆(301040)03月16日在投资者关系平台上答复了投资者关心的问题。