对于那些是lexing和解析专家的人......我试图在perl中编写一系列程序来解析IBM大型机z/OS JCL用于各种目的,但是我在方法论上遇到了障碍.我主要遵循Mark Jason Dominus在"高阶Perl"中提出的lexing/parsing意识形态,但有些事情我不知道该怎么做.
JCL具有所谓的内联数据,这与"此处"文档非常相似.我不太确定如何把它们变成令牌.
内联数据的布局如下:
//DDNAME DD *
this is the inline data
this is some more inline data
/*
...
Run Code Online (Sandbox Code Playgroud)
通常,"DD"之后的"*"表示后续行是内联数据本身,由"/*"或下一个有效JCL记录(前两列中以"//"开头)终止.
更高级,内联数据可能如下所示:
//DDNAME DD *,DLM=ZZ
//THIS LOOKS LIKE JCL BUT IT'S ACTUALLY DATA
//MORE DATA MASQUERADING AS JCL
ZZ
...
Run Code Online (Sandbox Code Playgroud)
有时,内联数据本身就是JCL(可能被抽到一个程序或内部读者,无论如何).
但这就是问题所在.在JCL中,记录是80个字节,长度固定.第72栏(第73-80栏)的所有内容都是"评论".同样,跟随有效JCL的空白之后的所有内容同样是评论.由于我希望在我的程序中操作JCL并将其吐出来,我想捕获注释以便我可以保留它们.
所以,这是内联数据中的内联注释的示例:
//DDNAME DD *,DLM=ZZ THIS IS A COMMENT COL73DAT
data
...
ZZ
...more JCL
Run Code Online (Sandbox Code Playgroud)
我原本以为我可以让我最顶级的词法分析器拉入JCL系列并立即为cols 1-72创建一个非令牌,然后为第73列注释创建一个令牌(['COL73COMMENT',$ 1]),如果任何.然后,这将向下游传递给下一个迭代器/标记生成器,其中包含cols 1-72文本的字符串,后跟col73标记.
但是,从那里下游,我将如何获取内联数据?我原本认为最顶级的标记器可能会寻找"DD\*(,DLM =(\ S*))"(等),然后继续从进给迭代器中提取记录,直到它达到分隔符为止或有效的JCL启动器("//").
但是你可能会在这里看到问题...我不能拥有2个最顶级的标记符...要么寻找COL73注释的标记生成器必须是顶部,要么获取内联数据的标记生成器必须位于顶部.
我认为perl解析器有同样的挑战,因为看到了
<<DELIM
不一定是该行的结尾,其次是此处的文档数据.毕竟,你可以看到perl像:
my $this=$obj->ingest(<<DELIM)->reformat();
inline here document data
more data
DELIM
Run Code Online (Sandbox Code Playgroud)
令牌化器/解析器如何知道标记化") - …
我喜欢哈希切片并经常使用它们:
my %h;
@h{@keys}=@vals;
Run Code Online (Sandbox Code Playgroud)
工作出色!但有两件事总是让我烦恼.
首先,是否可以将上面的两行组合成一行代码?声明哈希并立即填充它会很好.
其次,是否可以对现有的匿名哈希进行切片...类似于:
my $slice=$anonh->{@fields}
Run Code Online (Sandbox Code Playgroud) 假设以下代码:
package Thing;
sub new {
my $this=shift;
bless {@_},$this;
}
sub name {
my $this=shift;
if (@_) {
$this->{_name}=shift;
}
return $this->{_name};
}
Run Code Online (Sandbox Code Playgroud)
现在假设我们已经实例化了一个对象:
my $o=Thing->new();
$o->name('Harold');
Run Code Online (Sandbox Code Playgroud)
够好了.我们还可以使用以下任一方法更快地实例化相同的事情:
my $o=Thing->new(_name=>'Harold'); # poor form
my $o=Thing->new()->name('Harold');
Run Code Online (Sandbox Code Playgroud)
可以肯定的是,我允许在构造函数中传递属性,以允许"友好"类更完整地创建对象.它还可以允许克隆类型运算符使用以下代码:
my $o=Thing->new(%$otherthing); # will clone attrs if not deeper than 1 level
Run Code Online (Sandbox Code Playgroud)
这一切都很好.我理解需要隐藏方法背后的属性以允许验证等.
$o->name; # returns 'Harold'
$o->name('Fred'); # sets name to 'Fred' and returns 'Fred'
Run Code Online (Sandbox Code Playgroud)
但是这不允许基于自身轻松操纵属性,例如:
$o->{_name}=~s/old/ry/; # name is now 'Harry', but this "exposes" the attribute
Run Code Online (Sandbox Code Playgroud)
一种替代方法是执行以下操作:
# Cumbersome, not syntactically …Run Code Online (Sandbox Code Playgroud) 有没有办法在qw中保留一些空白?例如:
my @a=qw(1234 John Smith 123 Main St.);
Run Code Online (Sandbox Code Playgroud)
将生成一个包含6个元素的数组.有没有办法,哦,我不知道......逃离白色空间保留一些吗?就像是:
my @a=qw(1234 John\ Smith 123\ Main\ St.);
Run Code Online (Sandbox Code Playgroud)
返回3个元素:'1234','John Smith','123 Main St.'?
(仅供参考,我已尝试过以上内容,也有不同的报价组合,但都无济于事)
好的,所以创建对数组的引用很容易......
my @a;
my $b=\@a;
#can now reference the same list of scalars from either @$b or @a
Run Code Online (Sandbox Code Playgroud)
但是我怎么能这样做呢?例如:
my $a=[1..4];
my @b;
#some magic happens here and now @b is an alias for @$a
@b=(6..10);
print "@$a\n"; #should print "6 7 8 9 10"
Run Code Online (Sandbox Code Playgroud)
我认为这会通过typeglobs发生,但那些只是躲避我.想法?
对哈希和数组做同样的事情也会很好.
编辑:这似乎工作,但它有点kludgy因为它只是将anon数组元素复制到"别名",然后重新指向数组:
my @b=@$a;
$a=\@b;
Run Code Online (Sandbox Code Playgroud)
有更好的想法吗?
穿过这个小金块......我想我已经弄清楚了,但看看是否有人可以放下更多的光.
我在PERL5LIB环境变量中有一个用于记录的模块.它在e:/Scripts/Log/Logger.pm.以下是摘录:
package Log::Logger;
...
package Log::NullLogger;
use base 'Log::Logger';
...
package Log::FileLogger;
use base 'Log::Logger';
...
package Log::DateFileLogger;
use base 'Log::FileLogger';
...
package LogTester;
use Data::Dump 'dump';
test() unless caller();
sub test {
warn dump \%INC;
...
}
Run Code Online (Sandbox Code Playgroud)
我想对这个模块进行一些更改,所以我将其复制到e:/Test/Log/Log/Logger.pm并开始进行更改和测试...我添加了一个新类并更改了Log::Logger包中的继承例程...
package BasicFormatter;
...
Run Code Online (Sandbox Code Playgroud)
但我的测试很奇怪.一些新代码正在使用,有些则没有.转储%INC有:
"Log/Logger.pm" => "e:/Scripts/Log/Logger.pm"
Run Code Online (Sandbox Code Playgroud)
...... 旧模块!从我可以告诉,use base 'Log::Logger'走了出去,并重新加载Log/Logger.pm从PERL5LIB,替换只有在它的包装(即package BasicFormatter由新模块来了,但其他所有的包都是从旧的模块).
我读到了use parent,当我替换我时use base,use parent …