语法和解析树:

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

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

主语是名词,因此有 :

主语->名词

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

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

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

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

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

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

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

谓语动词-> 动词

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

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

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实现一个简易编译器-语法解析的更多相关文章

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

    本文对应代码下载地址为: http://download.csdn.net/detail/tyler_download/9435103 视频地址: http://v.youku.com/v_show/ ...

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

  3. 用java实现一个简易编译器

  4. Java实现 LeetCode 736 Lisp 语法解析(递归)

    736. Lisp 语法解析 给定一个类似 Lisp 语句的表达式 expression,求出其计算结果. 表达式语法如下所示: 表达式可以为整数,let 语法,add 语法,mult 语法,或赋值的 ...

  5. java 实现一个简易计算器

    import java.util.Scanner;public class Test { public static void main(String[] args) { count(); } pub ...

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

    16 个回答 默认排序​ RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...

  7. Boost学习之语法解析器--Spirit

    Boost.Spirit能使我们轻松地编写出一个简单脚本的语法解析器,它巧妙利用了元编程并重载了大量的C++操作符使得我们能够在C++里直接使用类似EBNF的语法构造出一个完整的语法解析器(同时也把C ...

  8. 用java实现编译器-算术表达式及其语法解析器的实现

    大家在参考本节时,请先阅读以下博文,进行预热: http://blog.csdn.net/tyler_download/article/details/50708807 本节代码下载地址: http: ...

  9. 使用 java 实现一个简单的 markdown 语法解析器

    1. 什么是 markdown Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的 ...

随机推荐

  1. 面向对象编程思想(前传)--你必须知道的javascript(转载)

    原文地址:http://www.cnblogs.com/zhaopei/p/6623460.html阅读目录   什么是鸭子类型 javascript的面向对象 封装 继承 多态 原型 this指向 ...

  2. EF添加Msysql实体异常:表“TableDetails”中列“IsPrimaryKey”的值为 DBNull。 ---> System.InvalidCastException: 指定的转换无效。

    尝试一下以下步骤: 1.关闭VS项目, 以管理员权限来打开: 1.执行语句 set global optimizer_switch='derived_merge=OFF'; set optimizer ...

  3. Alwayson--使用证书创建高可用性组

    --场景: --有服务器SQLNode11,SQLNODE21,SQLNODE31三台在同一故障转移群集SQLNode01中 --的数据库服务器,安装SQL SERVER 2012 并配置启动alwa ...

  4. 对php和java里面的static函数和static的一些理解

    static function: "static方法就是没有this的方法.在static方法里面不可以调用非静态方法,反过来是可以的.并且可以在没有创建任何对象的前提下,仅仅通过类名来调用 ...

  5. SQL 取两日期的记录

    SELECT TOP 1000 [ID]      ,[SourcePageID]      ,[PlatformType]      ,[CreateTime]  FROM [home_sendor ...

  6. asp.net——公共帮助类

    在项目开发中公共帮助类是必不可少的,这里记录一些自己摘录或自己编写的帮助类. 64位编码与解码: #region URL的64位编码 /// <summary> /// URL的64位编码 ...

  7. python——回文函数(reversed)

    回文数:正向排列与反向排列所得结果是相等的(即从左到右和从右到左的结果是相等的),例如:“123321”,“0000”等. reversed函数:反转一个序列对象,将其元素从后向前颠倒构建成一个新的迭 ...

  8. qt中多线程用法总结

    1.多线程的理解 在操作系统中线程和进程划分. 操作系统可以同时执行多个任务,每个任务就是进程:进程可以同时执行多个任务,每个任务就是线程. 线程之间相互独立,抢占式执行.对于单核CPU来说同一时刻只 ...

  9. win10 打开sql server配置管理器

    win10 安装 sql server之后无法在开始菜单找到“sql server 配置管理器(SQL server configuration manager 1)在开始菜单中,无法找到 配置管理器 ...

  10. C# winform 去掉button的边框颜色

    Winform的话,设置FlatStyle为Flat,并且设置FlatAppearance下的BorderSize为0,foreColor设置成web下的Transparent