syntaxTree

简易Parser入门【一】:从树的递归开始

a 夏天 提交于 2020-02-26 21:22:29
Parser就是将字符串转化成AST(Abstract Syntax Tree)的程序 首先我们从树类的简单解析开始,假设有一个树节点(它是一个二叉树节点): class Tr: def __init__(self, val, left=None, right=None): self.val = val self.left = left self.right = right 我们用这个树节点构造一棵树: t_root = Tr(5, Tr(3, Tr(4), Tr(6)), Tr(1, Tr(2), Tr(7))) 它的结构如图所示,我们想打印从根节点到每个叶子节点的路径怎么办呢?遍历树一般都能想到用递归,但是递归到底递归什么东西呢?递归函数的参数如何选择?返回什么? 思考递归的时候,我们可以从问题点出发,先寻找停止递归的条件。我们需要打印从根节点到每个叶子节点的路径,所以停止条件就是到达叶子节点了。可以先用代码写出来: def print_leaf(tr_in): # type: (Tr) -> None if tr_in.left is None and tr_in.right is None: # todo: stop here and do something 我们达到停止条件需要做什么呢?需要打印。打印什么?打印从根节点到叶子节点的路径。好了,我们现在达到了叶子节点

教你如何用AST语法树对代码“动手脚”

流过昼夜 提交于 2019-12-17 14:16:22
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 作为程序猿,每天都在写代码,但是有没有想过通过代码对写好的代码”动点手脚”呢?今天就与大家分享——如何通过用AST语法树改写Java代码。 先抛一个问题:如何将图一代码改写为图二? void someMethod(){ String rst=callAnotherMethod(); LogUtil.log(TAG,”这里是一条非常非常长,比唐僧还啰嗦的日志信息描述,但是我短一点还不方便进行错误日志分析,调用callSomeMethod返回的结果是:”+rst); …… } 图一 void someMethod(){ String rst=callAnotherMethod(); LogUtil.log(TAG,”<-(1)->”+rst); …… } 图二 此题需要把代码中和程序逻辑无关的字符串提取出来,替换为id。比如个推日志输出类,缩短日志描述信息后,输出的日志就随之变短,根据映射表可以恢复真实原始日志。 通过何种方案改写? 你可能会想通过万能的“正则表达式”匹配替换,但当代码较为复杂时(如下图所示),使用“正则表达法”则会将问题复杂化,难以确保所有代码的完美覆盖并匹配。若通过AST语法树,可以很好地解决此问题。 import static Log.log; … log(“i am also the log

高德APP全链路源码依赖分析工程

一曲冷凌霜 提交于 2019-12-09 11:43:20
一、背景 高德 App 经过多年的发展,其代码量已达到数百万行级别,支撑了高德地图复杂的业务功能。但与此同时,随着团队的扩张和业务的复杂化,越来越碎片化的代码以及代码之间复杂的依赖关系带来诸多维护性问题,较为突出的问题包括: 不敢轻易修改或下线对外暴露的接口或组件,因为不知道有什么地方对自己有依赖、会受到影响,于是代码变得臃肿,包大小也变得越来越大; 模块在没有变动的情况下,发布到新版本的客户端时,需要全量回归测试整个功能,因为不知道所依赖的模块是否有变动; 难以判断 Native 从业务实现转变为底层支撑的趋势是否合理,治理是否有效; 这些问题已经达到了我们必须开始治理的程度了,而解决此类问题的关键在于需要了解代码间的依赖关系。 二、高德 APP 平台架构 为了消除一些疑惑,在讨论依赖分析的实现前,先简单说明一下高德 APP 的平台架构,以便对一些名词和场景有一些背景了解。 高德 APP 从语言平台上可以分为 4 个部分,JS 层主要负责业务逻辑和 UI 框架;中间有 C++层做高性能渲染(主要是地图渲染),同时实现了一些切面 API,这样可以在双端只维护一套逻辑了;Android 和 iOS 层主要作为适配层,做一些操作系统接口的对接和双端差异化的(尽可能)抹平。 这里的切面是指 JS 层与 Native/C++ 层的分界线,这里会实现一些切面 API,也就是 JS 层与