一、语法分析

通过将词法分析获取的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篇】静态代码扫描分析(三)语法分析的更多相关文章

  1. 【Lua篇】静态代码扫描分析(一)初步介绍

    一.静态代码分析         静态代码分析是一种通过检查代码而不是执行程序来发现源代码中错误的手段.通常可以帮助我们发现常见的编码错误,例如: 语法错误 违反制定的标准编码 未定义的变量 安全性问 ...

  2. 【Lua篇】静态代码扫描分析(四)规则检查

    一.前言 通过前面三篇文章已经初步实现了将Lua源代码文件读取解析成语法树,现在就可以通过得到的语法树进行指定规则的代码扫描检查.下图简单列举了一下单个Lua文件内部的语法关系情况(注意并非真正的类图 ...

  3. 【Lua篇】静态代码扫描分析(二)词法分析

    一.词法分析 词法分析(英语:lexical analysis)是计算机科学中将字符序列转换为单词(Token)序列的过程.进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer, ...

  4. 静态代码扫描工具PMD定制xml的规则(一)操作篇

    0.前言 PMD作为开源的静态代码扫描工具有很强的扩展能力,可使用java或xpath定制rule.第一篇从操作上讲解如何定制一个用于扫描xml是否规范的规则.首先我们知道xml格式的文件在java工 ...

  5. DEVOPS技术实践_05:sonar静态代码扫描

    一.SonarQube静态代码扫描平台 1.1 安装 https://www.sonarqube.org/官网 1.2 下载软件包 https://www.sonarqube.org/download ...

  6. 使用OClint进行iOS项目的静态代码扫描

    使用OClint进行iOS项目的静态代码扫描 原文链接:http://blog.yourtion.com/static-code-analysis-ios-using-oclint.html 最近需要 ...

  7. Lint——Android SDK提供的静态代码扫描工具

    Lint和FindBugs一样,都是静态代码扫描工具,区别在于它是Android SDK提供的,会检查Android项目源文件的正确性.安全性.性能.可用性等潜在的bug并优化改进. 下图简单地描述了 ...

  8. Objective C静态代码扫描和代码质量管理 OClint + SonarQube

    OClint是针对C, C++及Objective C代码的静态扫描分析工具,而SonarQube是一个开源的代码质量管理平台.本文将实现将OClint的扫描结果导入到SonarQube中,已实现对O ...

  9. Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序

    静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行.执行顺序优先级:静态块,main(),构造块,构造方法. 构造函数 public H ...

随机推荐

  1. 10、pfile和spfile文件详解

    10.1.介绍: 1.Oracle中的参数文件是一个包含一系列参数以及参数对应值的操作系统文件.它们是在数据库实例启动时候加载的, 决定了数据库的物理结构.内存.数据库的限制及系统大量的默认值.数据库 ...

  2. csu-acm 1503: 点到圆弧的距离

    1503: 点到圆弧的距离 分析: 先判断点和圆心的连线是否在圆弧范围内,如果在,最短距离即到圆心的距离减去半径的绝对值:反之,为到端点的最短距离. 具体看注释 #include <bits/s ...

  3. 9、SpringBoot整合之SpringBoot整合SpringSecurity

    SpringBoot整合SpringSecurity 一.创建项目,选择依赖 选择Spring Web.Thymeleaf即可 二.在pom文件中导入相关依赖 <!-- 导入SpringSecu ...

  4. 全局获取HttpContext

    全局获取HttpContext 在我们平常开发中会有这样的需求,我们的Service业务层需要获取请求上下文中的用户信息,一般我们从控制器参数传递过来.如果你觉得这样就可以了,请您关闭文章. 场景 但 ...

  5. Spring中这么重要的AnnotationAwareAspectJAutoProxyCreator类是干嘛的?

    大家好,我是冰河~~ 停更了很久的[Spring注解系列]专题,终于重新更新了,我们还是接着之前的文章继续往下更新.在<[Spring注解驱动开发]二狗子让我给他讲讲@EnableAspectJ ...

  6. c语言:逗号运算符

    #include <stdio.h> main() { int a,s,d; s=2,d=3; a=12+(s+2,d+4); printf("%d\n",a); in ...

  7. deepin使用synergy鼠标越界软件实现和另一台windows系统共享鼠标

    1,搜索synergy就能找到很多安装和配置的博客文章. 2,我遇到的问题: 1,在linux(deepin)上安装1.8.8版本报出找不到依赖libssl.so.1.0.0的错误,导致无法成功启动软 ...

  8. Jmeter任在运行,线程数上不去

    问题 jmeter在运行,但是线程数上不去(本来模型设计了100个总线程,但运行时线程只能上到5,根据图上观察总共也只能运行5个线程) 之前更新了random csv插件 解决办法 查看jmeter. ...

  9. 【对线面试官】CountDownLatch和CyclicBarrier的区别

    <对线面试官>系列目前已经连载31篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...

  10. 记一次错误:mid=front+(rear-front)>>1;

    设rear=6,front=4,mid=front+(rear-front)>>1; mid应该等于5的,但结果却是3. 错误原因:"+"运算符的优先级高于" ...