用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);
}
在下一篇,我们看看,如何对带有加好和乘号的算术表达式,如何制定一套语法规则以及相应的语法替换代码。
用java实现一个简易编译器-语法解析的更多相关文章
- 用java实现一个简易编译器1-词法解析入门
本文对应代码下载地址为: http://download.csdn.net/detail/tyler_download/9435103 视频地址: http://v.youku.com/v_show/ ...
- 用java实现一个简易编译器2-语法解析
- 用java实现一个简易编译器
- Java实现 LeetCode 736 Lisp 语法解析(递归)
736. Lisp 语法解析 给定一个类似 Lisp 语句的表达式 expression,求出其计算结果. 表达式语法如下所示: 表达式可以为整数,let 语法,add 语法,mult 语法,或赋值的 ...
- java 实现一个简易计算器
import java.util.Scanner;public class Test { public static void main(String[] args) { count(); } pub ...
- 学了编译原理能否用 Java 写一个编译器或解释器?
16 个回答 默认排序 RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...
- Boost学习之语法解析器--Spirit
Boost.Spirit能使我们轻松地编写出一个简单脚本的语法解析器,它巧妙利用了元编程并重载了大量的C++操作符使得我们能够在C++里直接使用类似EBNF的语法构造出一个完整的语法解析器(同时也把C ...
- 用java实现编译器-算术表达式及其语法解析器的实现
大家在参考本节时,请先阅读以下博文,进行预热: http://blog.csdn.net/tyler_download/article/details/50708807 本节代码下载地址: http: ...
- 使用 java 实现一个简单的 markdown 语法解析器
1. 什么是 markdown Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的 ...
随机推荐
- Android-Xml文件生成,Xml数据格式写入
在上一篇博客,Android-XML格式描述,介绍来XML在Android中的格式: 生成xml文件格式数据,Android提供了Xml.newSerializer();,可以理解为Xml序列化: 序 ...
- Unity核心对象模型
总结的Unity引擎部分的核心对象模型类图,供大家学习时参考,根基类为Object,下一层包括核心基类GameObject,及其他作为资源的Mesh,Material,Shader,Texture,S ...
- 用C#开发的双色球走势图(原创)值得园友拥有(二)接上一篇
昨晚由于时间的原因只写了一部分内容,今天将这一部分内容补充完毕,多谢各位园友的支持. 这是用C#开发的双色球走势图(原创)值得园友拥有 新的园友可以看昨晚写的内容,以免脱节.首先回复园友的评论,有说好 ...
- .NET高级代码审计(第一课)XmlSerializer反序列化漏洞
0X00 前言 在.NET 框架中的 XmlSerializer 类是一种很棒的工具,它是将高度结构化的 XML 数据映射为 .NET 对象.XmlSerializer类在程序中通过单个 API 调用 ...
- FFmpeg命令详解
命令格式 功能 FFmpeg命令是在ffmpeg.exe可执行文件环境下执行,ffmpeg.exe用于音视频的转码,加水印,去水印,视频剪切,提取音频,提取视频,码率控制等等功能. 最简单的命令 ff ...
- golang 编译为dll 的方法
之前一直再找如何将geojson 转为 svg 格式的数据,看到github上大多都是js来转的,只有一篇是golang来做的,想来把它封成dll 给c#.c++ 调用,网上查了很多方法,并没有写的很 ...
- 毕业回馈-89C51之数码管的使用
7段码的数码管由7个LED等共同组成,根据公共端的不同有共阴和共阳之分.现在很多数码管在7段码的基础上加了一个.即dp,其内部结构如下图所示: 公共端为LED灯的阴极,所以为共阴极接法: 公共端为阳极 ...
- Lucene.net 全文检索数据库
#define Search using Lucene.Net.Analysis; using Lucene.Net.Analysis.Tokenattributes; using Lucene.Ne ...
- 在sqlite中,如何删除字段? how to drop a column in sqlite
在sqlite中可以使用ALTER TABLE语法对表结构进行修改,从官方的文档说明中,语法如下图: 从图中可以看出,ALTER TABLE仅仅支持表名重命名,添加字段,却没有删除字段的方法.那么该如 ...
- ModelForm错误验证自定义钩子和全局钩子
当需要对model_class中字段作进一步验证,作进一步的约束时,需要使用到钩子,即claan_xxx和clean方法.其返回的errors有点不是那么好处理.看示例. 1.Model_clas ...