用java实现一个简易编译器-语法解析

语法和解析树:

举个例子看看,语法解析的过程。句子:“我看到刘德华唱歌”。在计算机里,怎么用程序解析它呢。从语法上看,句子的组成是由主语,动词,和谓语从句组成,主语是“我”,动词是“看见”, 谓语从句是”刘德华唱歌“。因此一个句子可以分解成 主语 + 动词 + 谓语从句:

句子-->主语+动词 + 谓语从句

主语是名词,因此有 :

主语->名词

句子里的名词有: “我”, “刘德华”,因此有解析规则:

名词-> "我“  |  "刘德华".

句子里的动词是“看见”, “唱歌”,由此有解析规则:

动词-> “看见” | “唱歌”

再看谓语从句,谓语从句由宾语和谓语动词组成, 宾语是 “刘德华”, 谓语动词是“唱歌", 谓语从句的解析规则就是:

谓语从句 -> 宾语 + 谓语动词

谓语动词是属于动词,于是又有:

谓语动词-> 动词

动词->”看见” | "唱歌"

这样,整个句子的解析规则就有:

1.句子-->主语+动词 + 谓语从句

2.谓语从句 -> 宾语 + 谓语动词

3.主语->名词

4.谓语动词->动词

5.动词-> “看见” | “唱歌”

6.名词-> "我“  |  "刘德华".

上面这组解析规则就是在计算机中用来解析句子的算法,接下来我们通过一系列替换,从这组规则还原回句子,首先从第一个规则开始,用右边的式子替换左边的符号,

1. 句子 通过规则 :句子-->主语+动词 + 谓语从句 替换得到:

2. 主语+动词 + 谓语从句, 通过规则 主语->名词 替换得到:

3. 名词 + 动词 + 谓语从句, 通过规则 名词-> "我“  |  "刘德华" 替换得到

4. 我 + 动词 + 谓语从句, 通过规则 动词-> "看见" 替换得到:

5. 我 看见 + 谓语从句, 通过规则 谓语从句 -> 宾语 + 谓语动词 替换得到:

6. 我 看见 宾语+谓语动词, 通过规则 宾语->名词 替换得到:

7. 我 看见 名词+谓语动词, 通过规则 名词-> "我“  |  "刘德华" 替换得到:

8. 我 看见 刘德华 + 谓语动词, 通过规则 谓语动词->动词 替换得到:

9. 我 看见 刘德华 动词。通过规则 动词-> “唱歌” 替换得到

10 我 看见 刘德华 唱歌

至此,我们已经没有可替换的地方,于是语法解析完成。 由此可见,语法解析就是通过设立一组规则,然后判断输入的文本是否符合给定规则的过程。我们看到,最底层的一些规则是这样的:

名词-> "我“  |  "刘德华", 动词-> “看见” |“唱歌“

这几条规则,其实就是以前(http://blog.csdn.net/tyler_download/article/details/50668983)所说的词法分析,-> 左边就是标签,右边就是词法分析的字符串。整个解析过程,形成了一种树状结构,这个结构就叫语法解析树:

设想,由文字组成的文本,其形式是无穷的,语法解析的规则是将无穷的文本中,选取出组合形式符合语法规则的文本,例如对于上述语法,句子:“我看见张学友唱歌” 就无法通过语法规则,按照上面的替换过程,我们发现,到第7步时 解析到宾语,宾语替换成名词后无法将名词替换成“张学友”, 因此“我看见张学友唱歌”对于上面的语法规则而言,是非法输入。

当然,语法规则所限定的文本输入也不是唯一的,句子:“刘德华看见我唱歌” 也符合上面的语法规则,大家可以仿照上面的替换过程验证一下。

如果想要语法识别“我看见张学友唱歌”, 那么只要将规则改一下:名词->”我“ | ”刘德华” | “张学友” 即可。

我们看看,将上述替代过程转成计算机伪码是怎样的:

假定“我看见刘德华唱歌” 这歌句子存在缓冲区buffer 里,那么代码表述如下:

句子(buffer) {

//主语 + 动词 + 谓语从句 替换 句子

主语(buffer);

动词(buffer);

谓语从句(buffer);

}

主语(buffer) {

//名词 替换 主语

名词(buffer);

}

名词(buffer) {

// “我” | “刘德华” 替换 名词

if (buffer[0] == “我”) {

buffer = buffer.substring(1);

return;

}

if (buffer[0,1,2] == “刘德华”) {

buffer = buffer.substring(3);

return;

}

throw new Exception (“该语句不符合语法”);

}

动词(buffer) {

// “看见” | “唱歌“ 替换 动词

if (buffer[0,1]== “看见” || buffer[0,1] == “唱歌") {

buffer = buffer.substring(2);

return;

}

throw new Exception (“该语句不符合语法”);

}

谓语从句(buffer) {

//宾语 谓语动词 替换 谓语从句

宾语(buffer);

谓语动词(buffer);

}

宾语(buffer) {

//名词 替换 宾语

名词(buffer);

}

谓语动词(buffer) {

//动词 替换 谓语动词

动词(buffer);

}

在下一篇,我们看看,如何对带有加好和乘号的算术表达式,如何制定一套语法规则以及相应的语法替换代码。

时间: 2024-11-06 07:29:21

用java实现一个简易编译器-语法解析的相关文章

用java实现一个简易编译器1-词法解析入门

本文对应代码下载地址为: http://download.csdn.net/detail/tyler_download/9435103 视频地址: http://v.youku.com/v_show/id_XMTQ3NTQwMDkxMg==.html?from=s1.8-1-1.2 技术的发展可谓是日新月异,层出不穷,但无论是炙手可热的大数据,还是火烧鸟了的人工智能,所有这些高大上的尖端科技无不建立在基础技术的根基之上.编译原理,计算机网络,操作系统,便是所有软件技术的基石.在这三根支柱中,维编

Java实现一个简易HTTP服务器 (二) -- 多线程

Java实现一个简易HTTP服务器 (二) -- 多线程 运行方法:新建项目后在目录下创建index.html. favicon为可选项,作为网站图标 public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(80); System.out.println("Server started at &quo

Java实现一个简易HTTP服务器(一)-- socket

Java实现一个简易HTTP服务器(一)-- socket -----2019-9-29---------- public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(89); System.out.println("Server started at " + new Date() + &qu

Java实现一个简易HTTP服务器(三)

从InputStream读取数据,构造Request.Request包含Http请求的参数. public class Request { public String method; // 请求方法 public String path; // 请求路径 public String portal; // 协议名称 public Map<String, String> map; // 请求头中的附加参数 public String payload; // 请求体 private int BUFF

java 实现一个简易计算器

import java.util.Scanner;public class Test { public static void main(String[] args) { count(); } public static void count() { Scanner input1 = new Scanner(System.in); System.out.println("输入一个数"); double a = input1.nextDouble(); while (true) { Sc

学了编译原理能否用 Java 写一个编译器或解释器?

16 个回答 默认排序? RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和解释器.其实用什么语言来实现编译器并不是最重要的部分(虽然Java也不是实现编译器最方便的语言),最初用啥语言都可以. 我在大学的时候,我们的软件工程和计算机科学的编译原理课的作业好像都是可以用Java来写的.反正我印象中我给这两门课写的作业都是用的Java. ===================

Atitit.sql&#160;ast&#160;表达式&#160;语法树&#160;语法&#160;解析原理与实现&#160;java&#160;php&#160;c#.net&#160;js&#160;python

Atitit.sql ast 表达式 语法树 语法 解析原理与实现 java php c#.net js python 1.1. Sql语法树 ast 如下图锁死1 2. SQL语句解析的思路和过程3 2.1. lexer作为一个工具,完成了对SQL字符串的切割,将语句转化成一个tokens数组.3 2.2. Parser完成了SQL解析的后序部分:使用一个lexer对象作为工具,切出tokens,然后解析语义,绑定相关的系统接口.3 2.3. 关系数据和XML数据库下其抽象语法树分别为: 如图

从零开始实现一个简易的Java MVC框架(三)--实现IOC

Spring中的IOC IoC全称是Inversion of Control,就是控制反转,他其实不是spring独有的特性或者说也不是java的特性,他是一种设计思想.而DI(Dependency Injection),即依赖注入就是Ioc的一种实现方式.关于Ioc和DI的具体定义和优缺点等大家可以自行查找资料了解一下,这里就不详细赘述,总之spring的IoC功能很大程度上便捷了我们的开发工作. 在实现我们的Ioc之前,我们先了解一下spring的依赖注入,在spring中依赖注入有三种方式

C 实现一个简易的Http服务器

引言 做一个老实人挺好的,至少还觉得自己挺老实的. 再分享一首 自己喜欢的诗人的一首 情景诗. 每个人总会有问题,至少喜欢就好, 本文 参照 http 协议   http://www.cnblogs.com/rayray/p/3729533.html html格式   http://blog.csdn.net/allenjy123/article/details/7375029 tinyhttpd 源码    https://github.com/EZLippi/Tinyhttpd 附录 本文最