03 关于工作 当时发的offer是测试,后来入职后发现是个运维的活。组长是测试经理,算我就俩测试,刚开始写过验收文档,用户操作手册,测试用例,测试计划,写完就写完了,并没人告诉我对不对。...在公司一年下来我发现自己黑眼圈明显严重不少,而且下不去了,直到现在也是如此,后来总有朋友打趣说我是不是纵欲过度了,然后我们就是哈哈大笑… 04 关于爱情 我是毕业就分手了,也许是作为毕业后,必须经历的,...…… 依稀还记得,我师父在年会喝酒喝多了说的一句话。...,我做.net开发?...但如果不坚持下去,永远没有能得到自信的那一天,一辈子都会有挫败感。 坚持做自己认为对的事,至于是对是错,并不重要,时间长了,自然就会有有分晓。
它的主要作用就是你可以用巴科斯范式来描述语法规则,然后它帮你生成对应的解析器。 大家都知道实践是最好的学习方式,要快速深刻地理解antlr的操作和相关接口就不得不找一个练手的东西。...咱写不出来比fastjson更快、bug更少、更安全的json解析器,难道还写不出来一个bug更多、更慢、更不安全的解析器吗,正面拼不赢咱反其道而行。...为了对标阿里的fastjson,我给它起名 slowjson,源码已在github slowjson 欢迎star。为了推广slowjson,我都想好广告词了。 你想升职加薪吗?...你想拿年终奖吗? 你想成为同事眼中的性能优化小能手吗? 今天用slowjson,年底做性能优化换回fastjson,十倍性能不是梦,升职加薪准能成。...,而且简单多了,我的封装如下。
我是锋小刀! 在上一期视频中,我们讲解了excel如何按指定名称快速创建工作表,没有看的可以看一下:excel按指定名称快速创建工作表。...而python其实也是可以做到的,而且很简单,只需要几行代码即可。而python代码是可以重复利用,能节省很多时间,做到解放双手,拒绝做重复的事情。...xlwt库 今天主要用到xlwt库来操作,xlwt是Python中操作Excel的一个库,可以将进行创建工作簿、工作表、数据写入Excel。在写爬虫时我们也用过,主要是用来保存爬取的数据的。...xlwt库是python的第三方库,需要安装,安装命令: pip install xlwt 实战代码 这里我创建了一个名为"名称"的文件,里面一共有996条数据。 ? 先导入xlwt库。...批量操作文件,解放双手,拒绝做重复的事情,让一些重复的事情不再重复! THE END
使用代码生成代码是一件十分美妙的事情,于是有了各种代码生成器。但是生成代码,意味着要有对生成规则的分析和处理。 Boost.Spirit 就是这么一个语法分析工具,它实现了对上下文无关文法的LL分析。...Boost.Spirit 的使用真的是把模板嵌套用到了极致。确实这么做造成了非常强的扩展性,生成的代码也非常高效,但是嵌套的太复杂了,对于初学者而言真心难看懂。...你能想象在学习阶段一个不是太明白的错误导致编译器报出的几十层模板嵌套错误信息的感受吗?而且,这么复杂的模板嵌套还直接导致了编译速度的巨慢无比。...其实在之前,我已经使用过Spirit的Classic版本,即1.X版本,但是过多的复制操作让我觉得当时用得很低效,还好分析的内容并不复杂所以没。体现出来 这回就来研究下功能更强劲的2.X 版本。...而Boost.Spirit的Lex库的很多地方和它很像(我也没用过Flex,官方是这么说的)。 Lex的好处呢,就是可以用正则表达式描述一个规则,而且可以动态生成。而且可以可Qi混合起来使用。
Boost.Spirit 就是这么一个语法分析工具,它实现了对上下文无关文法的LL分析。支持EBNF(扩展巴科斯范式)。 Boost.Spirit 的使用真的是把模板嵌套用到了极致。...确实这么做造成了非常强的扩展性,生成的代码也非常高效,但是嵌套的太复杂了,对于初学者而言真心难看懂。 你能想象在学习阶段一个不是太明白的错误导致编译器报出的几十层模板嵌套错误信息的感受吗?...其实在之前,我已经使用过Spirit的Classic版本,即1.X版本,但是过多的复制操作让我觉得当时用得很低效,还好分析的内容并不复杂所以没。体现出来 这回就来研究下功能更强劲的2.X 版本。...这里面也描述了Qi的解析器支持的操作符。...而Boost.Spirit的Lex库的很多地方和它很像(我也没用过Flex,官方是这么说的)。 Lex的好处呢,就是可以用正则表达式描述一个规则,而且可以动态生成。而且可以可Qi混合起来使用。
”-5”后才能参与运算,并且编译器要知道,add(6,7)是一个函数调用,它需要执行add(6,7),获得函数运行后返回值才能继续参与算术表达式的运算。...好在普拉特解析法有别与传统的编译原理语法解析算法,它简单,精致,易理解,我们看看普拉特解析法是如何巧妙的解决上面复杂算术表达式的解析的。...,它表示做取反操作,this.lexer.MINUS_SIGN 对应表达式中的”-“,它表示做取负操作。上面代码表示,一旦语法解析器解析到符号”!”...然后前序表达式在去掉前序操作符后,接着的确是一个算术表达式,也就是说前序表达式包含了算术表达式,这就形成一个概念定义上的反复包含,我包含你与此同时你又包含我,这种成分的互相包含性是编译原理理解起来的难点所在...,也就是解析器会先处理”56”,再把所得结果与前面的表达式”4”做加法运算。
想要验证这个其实并不难,我们找到 Kotlin 的源码,找到 lexer 相关的源码: ?...我们看下调用堆栈,解析器被调用的地方实际上是 PsiElement 构造的过程中。我们再来看看 doParseContents 这个方法是干什么的: ?...3 对比看看其他语言 能够出现类似语法的,我们可以对照一下 Swfit 和 Scala。 先说说 Scala,它的解析器应该是极其强大的,毕竟人家允许各种字符作为运算符啊。。 ?...好啦,其实这都不是什么大问题了,这篇文章探讨的那句代码本身就比较蛋疼: val list: ArrayList= ArrayList() 我就问你为什么不去掉前面的类型,类型推导难道还不够吗...还有我觉得Scala 用[ ]来表示泛型比好多了我以前看一个人说后者写起来感觉很反人类或者看上去很奇怪,我很赞同。
编译原理也是如此,为了打破这些虚有其表的假道学,我开启了一个用java开发一个实打实的C语言编译器课程,这个编译器能把C语言转换成java字节码,在java虚拟机上执行,我相信这点我绝对是国内首创。...然而让我意象不到的是,原本看似极为复杂的工程实践,原来还存在着相当优美简洁的实现办法,我们这几节所讲的普拉特解析法就是典型实例,原来我需要花几千行代码,费时费力,绞尽脑汁好几天才能完成的事情,在普拉特解析法里就能轻而易举的处理掉...在该函数中,它判断当前解读到的token是否是true,如果是,它会创建一个Boolean类,把它的value值设置成1,若不然,把value值设置成0,上面代码完成后,程序运行结果如下: ?...,它先判断关键字”fn” 之后是不是跟着左括号,如果是,那么根据函数定义,接下来就是以逗号分隔开的参数列表,参数列表的解析由函数parseFunctionParameters负责,由于函数可以没有参数,...因此在它的执行中,先判断左括号后面是不是直接跟着右括号,如果是那就直接返回。
包含太多特殊规则了,对于一个不了解 ply 的人来说,这可能太糟糕了,我们需要一些办法来稍稍改善它。...你可以在单独的模块中定义规则,以此保证分析器主代码干净,这需要你在创建 lexer 时显式地指定 module: lexer = lex.lex(module=tokrules) 面向对象:有时面向对象不失是一个封装的好办法...# or parser = yacc.yacc(start="foo") 移入/规约 上面给出的语法规则是经过规约的规则,对解析器来说,它更容易处理,因为它几乎不存在歧义,但从编程的角度来说,我们可能会以一种更符合人类直觉的方式定义语法规则...解析器是依赖堆栈工作的,阅读时注意栈顶在靠右 文件中用 ! 标注出了冲突的地方,虽然这些冲突不见得都是不好的。...其他 一个良好的解析器不应该遇到错误就立刻返回,你应该尽可能返回所有的错误以便用户排查错误,你可以定义 p_error 来处理异常,它将以发生错误的 TOKEN 作为参数,在这里你可以做一些恢复错误的操作
例如下面这条语句: let foo = 1234; 语句经过词法解析器解析后,就会转变为: LET IDENTIFIER ASSIGN_SIGN INTEGER SEMI 完成上面工作后,词法解析器的任务就完成了...我们本节将实现一个简单的语法解析器,它的作用是能解析let 语句,例如: let foo = 1234; let x = y; 语法解析器在实现语法解析时,一般有两种策略,一种叫自顶向下,一种是自底向上...,需要传入词法解析器,因为解析器解析的内容是经过词法解析器处理后的结果,也就是一系列token的组合。...this.expectPeek(this.lexer.IDENTIFIER)) { return null } 上面代码用于判断,跟着关键字let 后面的是不是变量字符串...如果是就用当前的token构建一个Identifier类,并把它作为初始化LetStatement类的一部分。接下来就得判断跟着的是否是等号了: if (!
词法器的职责是读取 INI 文件内容、分析创建 Token,以及通过 channel 将 Token 发送给解析器。...接着,将 Token 和 Token 类型通过 channel 发送给解析器。 最后,判断下一个期望的状态函数,并返回。 我们先定义一个启动函数。它同样是解析器(下篇文章)的启动入口。...它初始化了一个 Lexer,赋予它第一个状态函数。 第一个期望的 Token 可能是什么?一个特殊符号还是一个关键词?...LexSection 返回的状态函数是 LexerRightBracket,逻辑与 LexerLeftBracket 类似,不同的是,它返回的状态函数是 LexBegin, 原因是 Section 可能是空...它会在遇到换行符时确认一个完整的Value。它返回的状态函数是 LexBegin,以此继续下一轮的分析。
如果从这个角度上看,有些人肯定会认为我是PUA了他。但真的是这样的吗? 03 我只是想把事做得更好而已,有错吗?上级对自己的要求多一些,高一些,真的是在PUA我吗?想了很久,终于想通问题出在哪里了。...问题就在于:是谁来做PUA这个动作!! 如果是上级强制要求测试来做质量内建,做不好就滚蛋,那这个就是在PUA了。但如果是我自己想把事做得更好些,让团队质量更好些,就不算是PUA了吧。...04 回想自己的成长历程,虽然不能说是把工作当成了义务,但至少也是会经常思考如何把事做得更好,很少去想这件是不是应该我去做。 功能测试人员要学性能测试吗?...05 有一位教练和我说,在团队,要做到“职责是明确的,边界是模糊的”,什么意思呢,就是每个岗位都是自己明确的工作职责,但是,谁来做这事,可以是模糊的。...不要因为角色结束了自己,也不要计较一时的付出是多还是少,事就在哪,你不做,总有人来做。那为什么不是你去做呢?你的付出团队是看得见的,它总能在某个关键时刻帮助到你。 教练说得对!
一种直观的做法是我们依次读入字符然后做即时判断,例如首先看第一个读到的字符是不是数字,或者是不是左括号,然后根据读入的前一个字符看看接下来读入的字符是否合法,你可以尝试用代码来实现试试,你很快会发现代码非常难写...算法的基本做法是选择相应的生产式进行”套用“,直到生产式解析为终结符为止。于是对应表达式3+2,我们可以猜到可以使用list -> list + list, 因为只有它含有符号”+”。...我个人觉得很难用语言来描述什么叫语法,但我发现如果使用代码的话,或许能让人有“心领神会”的感觉。...由于语法解析不好用语言说明,有意思的是使用代码反而能描述更清楚,因此我们直接通过代码来理解如何使用生产式来匹配给定的字符串,首先我们对上次完成的lexer做一些修改: package lexer import...,例如在使用list -> “(“ list “)”,时,代码首先判断读入的是不是左括号,然后递归的调用list函数字节,最后再判断最终读入的是不是右括号,所以生产式本质上是指导我们代码如何实现,代码对读入字符的判断
解析器还得考虑不同操作符产生不同含义的表达式,例如 -5 表示的是一个数值也就是负五,而—5 表示的是一次算术操作,意思是计算5-1所得的值,也就是4....,由于算术表达式展现形式多种多样,要通过它光怪陆离的表象识别它的本质是一件很困难的事情,因此,语法解析器对算术表达式解析算法的发明和实现是计算机科学发展史上光辉的一页。...} } 我们提到的函数表就是prefixParseFns, 从代码可以看成,如果解析器当前遇到的token类型是变量字符串,也就是lexer.IDENTIFIER,时,解析器就从该表中拿出...parseIdentifier这个函数来执行,如果解析器当前遇到的token类型是数组字符串,那么它便从该表中拿出函数parseIntegerLiteral来执行。...如果当前解析器读取到的是数字字符串,那么它会从表中找到函数parseIntegerLiteral来执行,该函数根据当前token,把它的内容解析成整形数值后,创建一个IntegerLiteral的类实例
最近,我发了一条推特,我喜欢上 lambda 演算了,它简单、强大。...已经有许多编译器/解析器/解释器(compiler / parser / interpreter)的教程,但大多数不会引导你完整实现一种语言,因为实现完全的语言语义,通常需要很多工作。...词法分析器( Lexer ) 现在我们可以拿上面定义的 token 来写 词法分析器(Lexer) 了, 为解析器解析程序提供一个很棒的 API。...解析器 解析器基本上是语法的一个副本。...最后,如果没有规则适用于AST,这意味着它已经是一个 value,我们将它返回。 另外一个值得提出的是上下文(context)。
,可以借助如 yacc 这样的工具,但是为了追求效率,也可以完全手写(promql 就是手写,如果是手写,没有太大必要把词解析和语法解析两者分割得太清楚) 执行我们只看即时执行的情况,一般来说可以对上一步的语法树直接执行...,也可以做进一步编译,以虚拟机(类似 lua、python 等)的方式执行。...先编译的好处是可以做一些优化,执行效率会更高。...yyLexer 做解释操作。...,【这个解释器做得比较简单,并无完全符合 json 标准】 这个例子的关键在于写出 json 的 表达式树, 简化如下 %{ package jsonparser type pair struct {
下面我们完成一个基本功能的词法解析器,在lexer文件夹下面新建一个文件为lexer.go,输入内容如下: package lexer type Lexer struct { input string...byte //读取的字符 } func New(input string) *Lexer { //生成一个词法解析器 l := &Lexer{input: input} return...int //下一个要读取的字符位置,也就是position + 1 ch byte //读取的字符 } func New(input string) *Lexer { //生成一个词法解析器...,后面跟着数字或者是下划线,因此解析逻辑就是,当我们读取到字符时,我们就进入到变量名的识别流程,也就是读取到字符后,如果接下来读取的还是字符,数字或者是下划线,我们就不断的往下走,直到遇到不是字符,数字或下划线的符号为止...Python代码做初步的解析了。
好像以前做的那个数据库设计大家都没太看懂,究其原因似乎大家都比较习惯使用PowerDesinger来设计。...我们可以建立一个业务员角色,设置业务员角色可以做的事情,然后把五个业务员和业务员角色关联起来。这样就方便了,业务员可以做得事情有变化的时候,我只需要修改业务员角色可以做得事情就可以了。...而且也可以适合很大的范围,因为那个资源的定义实在是太广泛了,到了无所不包的程度了。但是这个设计真的好吗?或者是实用吗?...我还是觉得看中文舒服:) 3、写这个的目的: 给自己用,工作7年的工作总结、思路总结,四、五个项目的权限的总结。 和大家分享,交流。看看大家的意见,否则不就更是闭门造车吗?...是不是要修改表结构了呢?我是不想改的,还是用角色绑定的方法来处理,增加一个“张三专用角色”,这个角色是“隐藏”的,不和其他的角色一样的管理,需要通过对“张三”来管理。
译者前言 最近发现我的翻译是越来越随性了,刚开始文章翻译的时候比较拘束,现在更多强调可读性,比如有些对文章大意没有什么影响的文字我现在都会选择直接跳过。...第二篇文章,英文原版,因主要聚焦在 Lexer 的实现。它完成了将输入文本转化为 Token 的过程。 今天是本系列的最后一篇文章,最终完成我们的解释器。...解析器 解析器的编写,我们要做的第一件事是,创建一个用于存放解析结构的变量,即一个 IniFile 结构体类型变量。...,还有解析器当前的状态。...词法分析与解析是一个非常复杂的话题,有太多内容需要学习。我们可以看到,即使像上面 INI 文件解析这样简单的工作,我们也需要花费一些精力才能完成。
当我准备再新增一个 % 取模的运算符时,会发现工作很繁琐而且几乎都是重复的;主要是两步: 需要在词法解析器中新增对 % 符号的支持。 在语法解析器遍历 AST 时对 % token 实现具体逻辑。...其中的词法解析和遍历 AST 完全是重复工作,所以我们可否能够简化这两步呢?...Antlr Antlr 就是做帮我们解决这些问题的常用工具,利用它我们只需要编写词法文件,然后就可以自动生成词法、语法解析器,并且可以生成不同语言的代码。...下面以 GScript 的示例来看看 antlr 是如何帮我们生成词法分析器的。...(默认是 Java),关于 Antlr 的词法、文法规则以及安装步骤请参考官网。
领取专属 10元无门槛券
手把手带您无忧上云