前言前些天偶然看到以前写的一份代码,注意有一段尘封的代码,被我遗忘了。这段代码是一个简单的解析器,当时是为了解析日志而做的。最初解析日志时,我只是简单的正则加上分割,写着写着,我想,能不能用一个简单的方案做个解析器,这样可以解析多种日志。于是就有了这段代码,后来日志解析完了,没有解析其它日志就给忘了。再次看到这段代码,用非常简单易读的代码就实现了一个解析器,觉得非常值得分享。思路言归正传,这个简单的解析器是怎么构思的呢?那要先从模式匹配开始。解析与模式匹配有很多相似之处,比如解析一个整数,跟匹配一个整数就是相似的。都需要根据整数的文法0|[1-9]\d*把文本中满足文法的部分找出来,不同的是,
前言前些天偶然看到以前写的一份代码,注意有一段尘封的代码,被我遗忘了。这段代码是一个简单的解析器,当时是为了解析日志而做的。最初解析日志时,我只是简单的正则加上分割,写着写着,我想,能不能用一个简单的方案做个解析器,这样可以解析多种日志。于是就有了这段代码,后来日志解析完了,没有解析其它日志就给忘了。再次看到这段代码,用非常简单易读的代码就实现了一个解析器,觉得非常值得分享。思路言归正传,这个简单的解析器是怎么构思的呢?那要先从模式匹配开始。解析与模式匹配有很多相似之处,比如解析一个整数,跟匹配一个整数就是相似的。都需要根据整数的文法0|[1-9]\d*把文本中满足文法的部分找出来,不同的是,
前言在日常工作中,偶尔需要调查一些诡异的问题,而业务代码经过长时间的演化,很可能已经变得错综复杂,流程、分支众多,如果能在关键方法的日志里添加上调用者的信息,将对定位问题非常有帮助。介绍StackTrace,位于System.Diagnostics命名空间下,名字很直观,它代表一个方法调用的跟踪堆栈,里面存放着按顺序排列的栈帧对象(StackFrame),每当发生一次调用,就会压入一个栈帧;而一个栈帧,则拥有本次调用的各种信息,除了MethodBase,还包括所在的文件名、行、列等。演示下面代码演示了如何获取调用者的方法名、所在文件、行号、列号等信息。publicstaticstringGet
前言在日常工作中,偶尔需要调查一些诡异的问题,而业务代码经过长时间的演化,很可能已经变得错综复杂,流程、分支众多,如果能在关键方法的日志里添加上调用者的信息,将对定位问题非常有帮助。介绍StackTrace,位于System.Diagnostics命名空间下,名字很直观,它代表一个方法调用的跟踪堆栈,里面存放着按顺序排列的栈帧对象(StackFrame),每当发生一次调用,就会压入一个栈帧;而一个栈帧,则拥有本次调用的各种信息,除了MethodBase,还包括所在的文件名、行、列等。演示下面代码演示了如何获取调用者的方法名、所在文件、行号、列号等信息。publicstaticstringGet
Python3.9中的PEG语法分析算法0题外话若文章有后续更新,可以在我的博客上看到。pre视频在这里。1PEG:ParsingExpressionGrammar1.1定义1.1.1语法形式上,一个解析表达文法由以下部分组成:一个有限的非终结符的集合\(N\)一个有限的终结符的集合\(\Sigma\),和\(N\)没有交集一个有限的解析规则的集合\(P\)一个被称作开始表达式的解析表达式\(e_s\)1.1.2语义PEG与CFG最关键的不同是,PEG的选择操作符是有序的。如果第一个选项匹配成功,则忽略第二个(以及之后的)选项。因此PEG的有序选择是不可交换的。1.2解释解析表达文法里每一个非
Python3.9中的PEG语法分析算法0题外话若文章有后续更新,可以在我的博客上看到。pre视频在这里。1PEG:ParsingExpressionGrammar1.1定义1.1.1语法形式上,一个解析表达文法由以下部分组成:一个有限的非终结符的集合\(N\)一个有限的终结符的集合\(\Sigma\),和\(N\)没有交集一个有限的解析规则的集合\(P\)一个被称作开始表达式的解析表达式\(e_s\)1.1.2语义PEG与CFG最关键的不同是,PEG的选择操作符是有序的。如果第一个选项匹配成功,则忽略第二个(以及之后的)选项。因此PEG的有序选择是不可交换的。1.2解释解析表达文法里每一个非
大家都知道,在dotnet里的Debug下和Release下的一个最大的不同是在Release下开启了代码优化。启用代码优化,将会对生成的IL代码进行优化,同时优化后的IL也会有一些运行时的更多优化。内联是一个非常常用的优化手段,内联将会让StackTrace获取的调用堆栈存在Debug下和Release下的差异,从而导致获取方法标记的Attribute特性不能符合预期工作这一个坑是来源于我所在团队开源的CUnit(中文单元测试框架)仓库的一次单元测试过程,我发现了在Debug下能通过测试,但是在Release下失败。详细请看:https://github.com/dotnet-campus/
大家都知道,在dotnet里的Debug下和Release下的一个最大的不同是在Release下开启了代码优化。启用代码优化,将会对生成的IL代码进行优化,同时优化后的IL也会有一些运行时的更多优化。内联是一个非常常用的优化手段,内联将会让StackTrace获取的调用堆栈存在Debug下和Release下的差异,从而导致获取方法标记的Attribute特性不能符合预期工作这一个坑是来源于我所在团队开源的CUnit(中文单元测试框架)仓库的一次单元测试过程,我发现了在Debug下能通过测试,但是在Release下失败。详细请看:https://github.com/dotnet-campus/
1.算术运算表达式求值在上一篇博文《Python技法:用re模块实现简易tokenizer》中,我们介绍了用正则表达式来匹配对应的模式,以实现简单的分词器。然而,正则表达式不是万能的,它本质上是一种有限状态机(finitestatemachine,FSM),无法处理含有递归语法的文本,比如算术运算表达式。要解析这类文本,需要另外一种特定的语法规则。我们这里介绍可以表示上下文无关文法(contextfreegrammer)的语法规则巴科斯范式(BNF)和扩展巴科斯范式(EBNF)。实际上,小到一个算术运算表达式,大到几乎所有程序设计语言,都是通过上下文无关文法来定义的。对于简单的算术运算表达式,
1.算术运算表达式求值在上一篇博文《Python技法:用re模块实现简易tokenizer》中,我们介绍了用正则表达式来匹配对应的模式,以实现简单的分词器。然而,正则表达式不是万能的,它本质上是一种有限状态机(finitestatemachine,FSM),无法处理含有递归语法的文本,比如算术运算表达式。要解析这类文本,需要另外一种特定的语法规则。我们这里介绍可以表示上下文无关文法(contextfreegrammer)的语法规则巴科斯范式(BNF)和扩展巴科斯范式(EBNF)。实际上,小到一个算术运算表达式,大到几乎所有程序设计语言,都是通过上下文无关文法来定义的。对于简单的算术运算表达式,