王朝网络
分享
 
 
 

功能丰富的Perl:Perl6语法和正则表达式

王朝perl·作者佚名  2008-05-19
宽屏版  字体: |||超大  

Perl 6 终于即将面世。在本文中,Ted 将向您介绍 Perl 6 语言的语法和正则表达式,并将它们与当前可用的 Perl 5 Parse::RecDescent 模块进行对比。认识 Perl 正则表达式的新特性,并学会如何具体使用新奇而又功能强大的 Perl 脚本语言。

对所有 Perl 编程人员而言,Perl 6 项目是一个热门话题。Perl 一直是一门不断发展的语言,几乎从任何可以想像得到的角度都可以确定,Perl 6 确实是由 Perl 5 进化而来(不过,您也可以说它们的起源相同)。Perl 6 将运行于 Parrot 之上,Parrot 是一种通用虚拟机,不但可以加载和解释 Perl 6 字节码,还可以加载和解释其他许多语言。

不要让将来的问题困扰着您。如果您曾经用了几个月的时间来观察某个建筑物的建筑过程,您就会知道,选好地基后要进行挖掘,金属骨架似乎总是矗立着。工人们来来往往,工作一直在进行,但是表面看到的却总是陈旧的、丑陋的、生锈的金属。然后,若干天以后,突然间,建筑物就完成了。Perl 6 项目当前正是处于那个长期的中间阶段,表面看到的只是生锈的金属,而工人们正在深入地下进行幕后工作。如果您想洞悉项目的进展,那么可以去查看最新的 Parrot 发行版本以及 Perl 6 每周的更新(请参阅参考资料中的链接)。

本文将向您介绍 Perl 6 语言的语法和正则表达式,并将这些与当前可用的 Perl 5 Parse::RecDescent 模块进行对比。如果以前对 Perl 5 有所了解,熟悉 Parse::RecDescent,并且有词法分析(lexing)和句法分析(parsing)方面的经验,那么这些会对您掌握本文有很大帮助,此外,本文是为那些对 Perl 6 语法和正则表达式感兴趣的所有 Perl 编程人员撰写的。

Perl 6 正则表达式和语法概述

首先需要声明一件事:Perl 将通过使用 :p5 修饰符来支持 Perl 5 正则表达式。对于那些对 Perl 6 正则表达式不感兴趣或者不想转到这方面来的人而言,这是一个福音。此外,Perl 6 正则表达式可能(但不是必须)与 Perl 5 中对应的正则表达式有本质上的区别。

在需要时,Perl 6 正则表达式可以被复用。在匹配单一的词时,复用正则表达式是很荒谬的;但在解析配置文件时,几乎必须要复用正则表达式(这取决于配置文法的复杂度、发生修改的频率等)。

在 Perl 5 中,Regexp::Common 模块(请参阅参考资料)已经在尝试复用正则表达式,但是,因为 Perl 5 不允许复用正则表达式,所以不得不将它们封装在一个模块接口中。 Perl 6 完全支持这种复用。

尽管您可以编写类似 Perl 5 正则表达式的模糊而晦涩的 Perl 6 正则表达式,但在默认情况下,允许启用空格注解;所以,虽然在 Perl 5 中您可以用“hello there”本身来匹配“hello there”,但在 Perl 6 中,您必须将其改为 /hello <sp there/。这样就可以在正则表达中将条件清晰地分离开来。

更重要的是,在语法(grammars)内部使用正则表达式时,Perl 6 正则表达式必须不那么晦涩。编程人员会发现(我希望如此, Larry Wall 也是),对清单 2 的理解与维护要比对清单 1 的容易得多:

清单 1. 没有语法的正则表达式

# note this is just a language example, not an accurate name matcher

# Perl 6 <[A-Z] is equivalent to the Perl 5 [A-Z]

# Perl 6 :w modifier surrounds all tokens with "automagic" whitespace,

# which basically means it will match what most people would call

# "words"

$name = m:w/ <[A-Z]<[a-z]+ <[A-Z]<[a-z]+ /;

清单 2. 在语法中作为规则的正则表达式

# note this is just a language example, not an accurate name matcher

grammar English

{

rule name :w { <singlename <singlename };

rule singlename { <[A-Z]<[a-z]+ };

};

清单 2 不仅更容易读懂,而且维护起来也更容易。例如,Perl 6 本身已经定义了 <upper 和 <lower 规则,这使事情变得更为简单:

清单 3. 在语法中作为规则的经过改进的正则表达式

# note this is just a language example, not an accurate name matcher

grammar Names

{

rule name :w { <singlename <singlename };

rule singlename { <upper<lower+ };

};

瞧!使用 <upper 和 <lower 之后,我们就复用了代码。此外,我们现在还可以处理 Unicode 名称,而这之前,我们只能局限于处理从 A 到 Z 开头的名称。代码复用是一项出色的技术。

在进行更进一步的维护时,几乎总是需要对名称中的破折号或其他名称(比如 Don Quixote de la Mancha)进行修正(举例来说)。同样,在将对个别规则的更改隔离出来,或者在需要时创建一个新规则的时候,您会注意到这是多么简单。

语法(Grammars) 是相当简单的概念。它们是具有专用名称空间(namespace)和专用子例程的程序包;每一个子例程被称为一个规则。语法可以继承其他语法。这样就使得编程人员既可以复用其他人的代码,也可以编写能够复用的代码。从 Perl 模块的 CPAN 存档文件(archive)获得的成功中可以明显地看出这种复用的价值。Perl 6 语法在规则中使用正则表达式,然后可以将这些规则用于其他规则之中。

对比 Parse::RecDescent 与 Perl 6 的语法

熟悉 Parse::RecDescent 的人都知道,它是一个功能强大的工具。Parse::RecDescent 是一个 Perl 5 模块,只使用很少代码就可以生成非常强大的语法。这些语法与 Perl 6 的语法是否非常相似呢?是这样的,Parse::RecDescent 的作者 Damian Conway 深入参与了 Perl 6 的许多工作。因此,很多在 Parse::RecDescent 中证明好用的思想都被应用到 Perl 6 中也就不足为奇了。它们的一些语法有很多类似之处。

Parse::RecDescent(此后称之为 P::RD)使用 new() 模块文法来创建新的语法。每个 P::RD 语法成为 P::RD 类中的一个对象,语法中的每一个规则都可以作为用来执行动作的方法。P::RD 语法可以将动作(action)与每一个规则关联起来,将其作为解析过程中的一个完整部分。在 Perl 5 本身中,解析是一个事件,而使用了扩展语法的动作则是达成目标途径中的不幸牺牲品(roadkill),那些扩展的语法被证明是造成迷惑的罪魁祸首。这一区别使得 P::RD 比 Perl 5 正则表达式更为有效,原因在于当检测到匹配对象时,它会使某些事情发生。

Perl 6 语法吸取了 P::RD 的经验,它意识到了这些动作的实用性,现在,这些动作已经成为其首要的组成部分。每发现一个匹配对象,就会执行一个动作(代码块)。即使匹配对象的内容可能已经被修改也是如此!此外,这些动作的语法与 P::RD 中的语法同样简单。

清单 4. 包含动作的 Parse::RecDescent 语法

# small extract from my cfperl.pl program's global parser

my $parse_global = new Parse::RecDescent (q{

input:

blank | comment | class | section

comment: /^\s*/ '#' { 1; }

blank: /^\s*$/ { 1; }

section: /\w+/ ':'

{ $::current_section = $item[1];

$::current_classes = 'any'; 1;

}

class: compound_class '::'

{ $::current_classes = $item{compound_class}; 1; }

compound_class: /[-!.|\w]+/

});

$parse_global-input("TEXT GOES HERE");

上面的语法只有一个规则,即 input,它将匹配 blank、comment、class 或者 section 规则。这些规则中的每一个规则都有一个定义,它们可以是独立的或是基于另一个规则的,也可以同时具备这两种特性。

注意像普通的代码块那样封装在大括号 { } 内的动作。对于一个片断(section),动作将全局变量 $current_section 设置为正在进行匹配的片断,并重新设置 $current_classes 全局变量。对于类,动作将全局的 $current_classes 变量设置为匹配的条目。

这个语法在 Perl 6 中会是什么样的呢?

清单 5. 清单 4 语法的 Perl 6 译本

# this may be buggy - it's certainly untested

# every input is known to be one line, without newline characters

grammar Global

{

rule input { <blank | <comment | <class | <section }

rule blank { ^^ \s* $$ }

rule comment { ^^ \s* \# }

rule section

{ (\w+) \s* \:

{

$::current_section = $1;

$::current_classes = 'any';

}

}

rule class { (<compound_class) \s* \:\:

{

$::current_classes = $1;

}

}

rule compound_class { <[-!.|\w]+ }

}

Perl 5 的正则表达式

如果您对 Perl 5 正则表达式非常熟悉,那么可以跳过这一节。

所有 Perl 5 编程人员都熟悉 Perl 5 正则表达式。在进行匹配时,要用 m// 操作符来标识这些正则表达式(有时是可选的),而当匹配并替换时,则要用 s/// 操作符来标识它们。在特定的情况下,/ 字符可以由其他字符取代,并且有一些特定的操作符,它们与正则表达式有几分类似,不过这样的操作符不多(例如 tr///)。Perl 5 正则表达式要指明的或者是“寻找此内容”,或者是“寻找此内容,并

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有