软件构造6:语法驱动编程

一、引入:
对于编程环节,一个经常会出现的任务就是将给定的文本内容进行读取并将读取的字符串转化为应用中所需要的各类数据。显然仅仅通过编译器而不是人为设定某些规则的话我们无法做到将读取的字符串根据我们想要的划分结果进行分割。而如果对于每一次读入的字符均给定划分方式固然可行,但是这样做会造成两个负面结果:一是代码的可读性与整洁性大大下降,毕竟对于每个文本的处理并不是那么容易;二是如果文本的容量很大(比如10000行),这个时候对于每种情况给出划分显然不合适。对于输入的文本存在一定的格式规律的情况,我们通常使用一些特定的语法来规定一些表达式,将读取的字符串全部看作是生成式,将读取与划分转变为读取与识别匹配特定格式。要做到这一点,我认为主要需要的有两件事。首先应该由读入的文本中总结出规律,并将之抽象地表达为表达式的形式。然后还应该对于传入的文本的规范性进行要求,以保证匹配的效率和性能。

二、基本过程:
对于利用语法的构造编程,首先应该明确以下几个概念:
终止符:终止符应该为不能再继续变化为其他字符的符号,如果将语法表达式的演化推导过程转化为一棵语法分析树,那么树的所有叶子节点都必须是终结符,在定义语法时应该明确终止符的集合,显然操作符应该算作终止符。
非终止符:这类字符可以依据设计的派生式产生匹配到不同形式的或终结符或非终结符所构成的新串,相对应的就是语法分析树中的非叶节点,根节点一定是非终止符。
操作:这里所说的操作不是为字符串间加上加减乘除号使之能够运算。最基本的操作分为三种,连接,重复,选择。以串x、y、z为例,
x ::= yz(x匹配y和z连接后的串);
x ::= y*(x匹配任意次y的重复所构成的串);
x ::= y|z(x匹配y或匹配z)。
除此之外,经常用到的符号有?、+、[ ]、[^…] :
x ::= y?表示x ::= y|e(e为什么都没有);
x ::= y+表示x ::= yy*;
x ::= [a-z]表示x为一个小写字母,即x可以匹配中括号中填的所有字符;
x ::=[^a] 与之相对的则表示在这些元素所在的全集中刨除这些元素后的字符可以被x匹配。

三、应用现状与结合实例谈感想:
对于简化之后可以表达为一个产生式而不包含任何非终止节点的语法,我们称作正则语法,常见的如url。非正则语法当然也很常见,比如html语言的语法就不属于正则语法。而对于左侧只含有一个非终结符,所定义的语法范畴完全独立于可能出现的情况,也就是无需考虑上下文情况,我们将这种文法称作上下文无关文法,程序设计语言的语法多是上下文无关的。对于正则语法所构造的正则表达式,在Java中也多有运用。一些常见的用法如下:**.**可以匹配任意字符,\d可以匹配任何数字,\s匹配任意长度的空白,\w匹配字母(大小写)、数字、下划线,还有许多。
在实验四中有需要读取写入文件中的日志的操作,由于格式相近,故考虑按照正则表达式读入,在匹配时最初我对于每条日志最后部分的message使用了(.?)发现并不能匹配。后来改用了(.)发现可以匹配了。经过搜索,发现前者是采用了一种惰性匹配策略而后者采用了贪婪匹配策略。也就是说,对于前者,按照从前到后的顺序,先读入一个字符,判断匹配与否,只要匹配就结束,做到读取的字符数最少。后者则是首先读入全部字符,查看是否匹配,若不匹配,去掉最末的一个字符,依次匹配。可以看出即使是看似简单到只有有限的一些字符的正则表达式,其逻辑性也是及其严密的,同时不乏算法的知识,可学性很强。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值