【Lua篇】静态代码扫描分析(三)语法分析
一、语法分析
通过将词法分析获取的Token流按照目标语言的语法进行解析的过程,例如解析函数声明、函数调用、变量声明、各种语句等。
二、Lua语法分析
在写语法分析程序前,先需要了解Lua的语句和语法,然后进行逐个解析。
下面简单列举一下Lua的语句:
1. 函数定义
1 -- 普通的函数声明
2 function demo1()
3 -- <函数体>
4 end
5 -- 类方法
6 function t.demo2(self)
7 -- <函数体>
8 end
9 -- 方法调用中的匿名函数(其实还有很多)
10 some_method_call(arg1, function() <callback> end)
2. 函数调用
1 -- 普通的函数调用
2 print("Hello Lua")
3 -- 模块方法
4 math.random(1,2)
5 -- 类方法
6 obj:set_id(xx)
3. 赋值语句
1 -- 带local局部变量声明赋值
2 local a = 1
3 -- 多变量
4 local a,b,c = 2,3
5 -- 全局的变量
6 g_a = 3
7 -- 赋值可以是函数、函数调用、表等
8 g_c,g_b = {}, function() end
4. 条件分支
1 -- if条件分支
2 if a > 1 then
3 elseif a > 2 then
4 else
5 end
5. for循环
1 -- for循环
2 for i=1,10,2 do
3 end
6. for迭代器
1 -- 迭代包含in pairs 和 in ipairs
2 for k,v in pairs(tb) do
3 end
7. while循环
1 -- while循环,条件可以很复杂
2 while a >1 and b > 1 do
3 end
8. repeat until 循环
1 repeat
2 until a > 1
上面仅仅简单了进行了举例,实际上项目中的写法是千奇百怪的,因此需要确保包含所有的语法规则。在进行语法解析的时候,首先进行代码块的解析,可以把一个文件看作整个代码块,里面包含各种的语句。然后其实是逐语句解析,先取出一个Token,判断这个Token的类型,然后决定更细规则的解析,就像下面代码列举的过程一样。
1. 语法解析的入口,调用block解析。
1 def parse(self):
2 self._TokenNum = self.mTokens
3 block = self.on_block_parse()
4 return block
2. 对block解析的时候,实际是循环调用逐语句解析,直到匹配到语句块结束标记。
1 def on_block_parse(self):
2 token = self.get_token()
3 statements = []
4 while token is not None:
5 # until,else,elseif,end
6 if self.is_end_token(token):
7 self.put_token()
8 break
9 # 语句解析
10 statement = self.on_statement_parse(token)
11 if not statement:
12 break
13 statements.append(statement)
14 token = self.get_token()
15 return Block(statements)
3. 逐语句解析就是获取Token的类型,并调用对应类型的解析方法。
1 def on_statement_parse(self, token):
2 # 函数
3 if token.tokenType == T.FUNCTION:
4 return self.on_function_parse(token)
5 # for .. in .. do .. end
6 elif token.tokenType == T.FOR:
7 return self.on_for_parse(token)
8 # while .. do .. end
9 elif token.tokenType == T.WHILE:
10 return self.on_while_parse(token)
11 # repeat ... until xx
12 elif token.tokenType == T.REPEAT:
13 return self.on_repeat_parse(token)
14 # if .. elseif ... else .. end
15 elif token.tokenType == T.IF:
16 return self.on_if_parse(token)
17 # do ... end
18 elif token.tokenType == T.DO:
19 return self.on_do_parse(token)
20 # local xx
21 elif token.tokenType == T.LOCAL:
22 return self.on_local_parse(token)
23 # return xxx
24 elif token.tokenType == T.RETURN:
25 return self.on_return_parse(token)
26 else:
27 return self.on_expression_parse(token)
4. 列举一下while循环的解析,其中会调用表达式解析while的条件,调用block解析while的语句体,然后检查是否有end。基本上其他的语句也是按照这样的方式进行分析与解析。
1 def on_while_parse(self, token):
2 """ while 循环 """
3 # while <condition> do
4 exp = self.on_expression_parse(self.get_token())
5 if not exp:
6 self.print_syntax_error(token)
7 return None
8 next_token = self.get_token()
9 if next_token.text != 'do':
10 self.print_syntax_error(next_token)
11 return
12 body = self.on_block_parse()
13 next_token = self.get_token()
14 if next_token.text != 'end':
15 self.print_syntax_error(next_token)
16 return None
17 while_statement = LNodeWhile(token.lineno, exp, body)
18 return while_statement
三、总结
通过上面的简单介绍,不知可能上手写一写呢?将所有的语句都解析完成后,接下来就是进行静态代码扫描了。如果是使用C或者C++写的话,完全可以从Lua的源码中提取上面的词法和语法解析内容,而直接进行代码规则扫描检查的编写。
文章来自我的公众号,大家如果有兴趣可以关注,具体扫描关注下图。
【Lua篇】静态代码扫描分析(三)语法分析的更多相关文章
- 【Lua篇】静态代码扫描分析(一)初步介绍
一.静态代码分析 静态代码分析是一种通过检查代码而不是执行程序来发现源代码中错误的手段.通常可以帮助我们发现常见的编码错误,例如: 语法错误 违反制定的标准编码 未定义的变量 安全性问 ...
- 【Lua篇】静态代码扫描分析(四)规则检查
一.前言 通过前面三篇文章已经初步实现了将Lua源代码文件读取解析成语法树,现在就可以通过得到的语法树进行指定规则的代码扫描检查.下图简单列举了一下单个Lua文件内部的语法关系情况(注意并非真正的类图 ...
- 【Lua篇】静态代码扫描分析(二)词法分析
一.词法分析 词法分析(英语:lexical analysis)是计算机科学中将字符序列转换为单词(Token)序列的过程.进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer, ...
- 静态代码扫描工具PMD定制xml的规则(一)操作篇
0.前言 PMD作为开源的静态代码扫描工具有很强的扩展能力,可使用java或xpath定制rule.第一篇从操作上讲解如何定制一个用于扫描xml是否规范的规则.首先我们知道xml格式的文件在java工 ...
- DEVOPS技术实践_05:sonar静态代码扫描
一.SonarQube静态代码扫描平台 1.1 安装 https://www.sonarqube.org/官网 1.2 下载软件包 https://www.sonarqube.org/download ...
- 使用OClint进行iOS项目的静态代码扫描
使用OClint进行iOS项目的静态代码扫描 原文链接:http://blog.yourtion.com/static-code-analysis-ios-using-oclint.html 最近需要 ...
- Lint——Android SDK提供的静态代码扫描工具
Lint和FindBugs一样,都是静态代码扫描工具,区别在于它是Android SDK提供的,会检查Android项目源文件的正确性.安全性.性能.可用性等潜在的bug并优化改进. 下图简单地描述了 ...
- Objective C静态代码扫描和代码质量管理 OClint + SonarQube
OClint是针对C, C++及Objective C代码的静态扫描分析工具,而SonarQube是一个开源的代码质量管理平台.本文将实现将OClint的扫描结果导入到SonarQube中,已实现对O ...
- Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行.执行顺序优先级:静态块,main(),构造块,构造方法. 构造函数 public H ...
随机推荐
- PS 快速抠图
1.选择矩形选框工具-->选择图中要抠掉的地方-->右键填充-->确定
- 【译】GO语言:管理多个错误
原文:https://medium.com/a-journey-with-go/go-multiple-errors-management-a67477628cf1 关于开发者使用Go遇到的最大挑 ...
- 万字长文肝Git--全流程知识点包您满意【建议收藏】
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本文将首先介绍在本地搭建GitLab服务,然后重点介绍Git的常用命令,Git的核心概念以及冲突处理,最后介绍Git与SVN的区别 干货满满,建议 ...
- RabbitMQ消息可靠性传输
消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用kafka.rocketMQ或者rabbitMQ,那么在RabbitMQ中如何保证消息的可靠性投递呢? 先再看一下RabbitMQ消息传递的流 ...
- Springboot:@RequestMapping注解及属性详解
@RequestMapping 注解: @RequestMapping 是 Spring Web 应用程序中最常被用到的注解之一.这个注解会将 HTTP 请求映射到 MVC 和 REST 控制器的处理 ...
- SpringMVC(5)数据绑定-2
在SpringMVC(4)数据绑定-1中我们介绍了如何用@RequestParam来绑定数据,下面我们来看一下其它几个数据绑定注解的使用方法. 1.@PathVariable 用来绑定URL模板变量值 ...
- rz上传文件报错:rpm Read Signature failed: sigh blob(1268): BAD, read returned 0
上传文件报错: [root@www localdisk]# rpm -ivh cobbler* error: cobbler-2.8.4-4.el7.x86_64.rpm: rpm Read Si ...
- jenkins报错The goal you specified requires a project to execute but there is no POM inthis directory
报错截图及详细: 15:30:29[ERROR]The goal you specified requires a project to execute but there is no POM i ...
- 315M、433M和2.4G笔记
一.315M无线模块 315m无线模块广泛地运用在车辆监控.遥控.遥测.小型无线网络.无线抄表.门禁系统.小区传呼.工业数据采集系统.无线标签.身份识别.非接触RF智能卡.小型无线数据终端.安全防火系 ...
- 视图:DBA_TAB_PARTITIONS 分区表视图
Column Datatype 释义 Description TABLE_OWNER VARCHAR2(128) 表的owner Owner of the table TABLE_NAME VARCH ...