Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 词法分析;“这里”;文件_Perl_Parsing_Jcl - Fatal编程技术网

Perl 词法分析;“这里”;文件

Perl 词法分析;“这里”;文件,perl,parsing,jcl,Perl,Parsing,Jcl,对于那些在词法分析和句法分析方面的专家。。。我试图用perl编写一系列程序,这些程序将解析出IBM大型机z/OS JCL,用于各种目的,但在方法上遇到了障碍。我主要遵循Mark Jason Dominus在“高阶Perl”中提出的词法分析/解析思想,但有些事情我不太清楚如何做 JCL有所谓的内联数据,这与“here”文档非常相似。我不太清楚如何把这些东西变为代币 内联数据的布局如下所示: //DDNAME DD * this is the inline data this is some m

对于那些在词法分析和句法分析方面的专家。。。我试图用perl编写一系列程序,这些程序将解析出IBM大型机z/OS JCL,用于各种目的,但在方法上遇到了障碍。我主要遵循Mark Jason Dominus在“高阶Perl”中提出的词法分析/解析思想,但有些事情我不太清楚如何做

JCL有所谓的内联数据,这与“here”文档非常相似。我不太清楚如何把这些东西变为代币

内联数据的布局如下所示:

//DDNAME   DD *
this is the inline data
this is some more inline data
/*
...
通常,“DD”后面的“*”表示以下行是内联数据本身,以“/*”或下一个有效JCL记录(在前两列中以“/”开头)终止

更高级的是,内联数据可以显示为:

//DDNAME   DD *,DLM=ZZ
//THIS LOOKS LIKE JCL BUT IT'S ACTUALLY DATA
//MORE DATA MASQUERADING AS JCL
ZZ
...
有时,内联数据本身就是JCL(可能被泵送到程序或内部读取器,等等)

但问题是。在JCL中,记录为80字节,长度固定。超过第72列(cols 73-80)的所有内容都是“注释”。同样,在有效JCL后面的空白后面的所有内容同样也是注释。因为我希望在我的程序中操纵JCL并把它吐出来,所以我想捕获注释以便保存它们

下面是一个内联数据的内联注释示例:

//DDNAME   DD *,DLM=ZZ THIS IS A COMMENT                                COL73DAT
data
...
ZZ
...more JCL
我最初认为我可以让我最顶级的lexer拉入一行JCL,立即为cols 1-72创建一个非令牌,然后为coln 73 comment创建一个令牌(['COL73COMMENT',$1]),如果有。然后,这将向下游传递一个cols 1-72文本字符串,后跟col73标记,并传递给下一个迭代器/标记器

但我如何从那里下游获取内联数据呢?我最初认为,最顶级的标记器可以查找“DD\*(,DLM=(\S*))”(或类似内容),然后继续从馈送迭代器中提取记录,直到它碰到分隔符或有效的JCL启动器(“/”)

但你可能会看到这里的问题。。。我不能有两个最顶级的标记器。。。查找COL73注释的标记器必须位于顶部,或者获取内联数据的标记器必须位于顶部

我想perl解析器也面临同样的挑战,因为


在这个答案中,我将集中讨论heredocs,因为课程可以很容易地转移到JCL

任何支持heredocs的语言都不是上下文无关的,因此无法使用递归下降等常用技术进行解析。我们需要一种方法来引导lexer沿着更扭曲的路径,但这样做,我们可以保持上下文无关语言的外观。我们所需要的只是另一堆


对于解析器,我们将介绍heredocs
,以防有人想知道我是如何决定解决这个问题的,下面是我所做的

我的主要词法分析例程接受一个迭代器,该迭代器输出整行文本(它可以从文件、字符串或任何我想要的内容中获取文本)。例程使用它来创建另一个迭代器,该迭代器检查第72列之后的行中的“注释”,然后将其作为“mainline”标记返回,后跟“col72”标记。然后使用该迭代器创建另一个迭代器,该迭代器将col72标记传递给unchanged,但将主线标记和词法转换为原子标记(如字符串、数字、逗号、换行符等)

但关键是。。。词法分析例程仍然具有原始迭代器。。。因此,当它接收到一个表示存在“here”文档的标记时,它将继续处理标记,直到它碰到一个换行标记(表示实际文本行的末尾),然后使用原始迭代器提取here文档数据。由于迭代器向原子令牌迭代器提供信息,因此从原子令牌迭代器中抽取可以防止这些行被原子化

为了举例说明,请考虑像软管这样的迭代器。第一个软管是主迭代器。我将col72迭代器软管连接到它,并将原子标记器软管连接到它。当字符流进入第一个软管时,雾化的令牌从第三个软管的末端出来。但我可以在第一根软管上安装一个双向喷嘴,使其输出从备用喷嘴出来,防止数据进入第二根软管(以及第三根软管)。当我完成通过备用喷嘴转移数据时,我可以将其关闭,然后数据开始再次通过第二和第三根软管


Easy peasey.

传统的词法分析器/解析器方法只有在您的语言与上下文无关时才有效。您只需要在正确的抽象级别编写解析代码。使用JCL时需要注意的是,
/*
不必为
DD*
定义流内数据的结尾,但对于不带
DLM
关键字的
DD data
则需要。此外,JES2 JECL使用
/*
作为其命令,JES3使用
/*
(是的,与注释相同)。。。在这一点上,我只想了解一些基础知识,以便稍后添加更多的“标记”和元素。JCL确实是一种hodge podge语言。您也可以跳过DD行,SYSIN DD行将为您生成非常有趣的。。。我必须用细齿梳子仔细检查一下你的例子,但这看起来非常可行。谢谢。@mswanberg哦,如果需要,我可以添加解释。正则表达式清楚了吗?在这样一个人为的例子中,实际的控制流当然是相当无聊的。我认为这是非常不言自明的。。。我只需要对它有一个很好的理解,这样我就可以将它概念化到我的设计中。总之,如果像字符串文字这样的东西不是问题的一部分,那么这类事情就会容易得多。这些往往会在很大程度上阻碍正则表达式的使用。
my $this=$obj->ingest(<<DELIM)->reformat();
inline here document data
more data
DELIM
use strict; use warnings; use 5.010;

my $s = <<'INPUT-END'; pos($s) = 0;
<<A <<B
body 1
A
body 2
B
<<C
body 3
C
INPUT-END

my @strs;
push @strs, parse_line() while pos($s) < length($s);
for my $i (0 .. $#strs) {
  say "STRING $i:";
  say $strs[$i];
}

sub parse_line {
  my @strings;
  my @heredocs;

  $s =~ /\G\s+/gc;

  # get the markers
  while ($s =~ /\G<<(\w+)/gc) {
    push @strings, '';
    push @heredocs, [ \$strings[-1], $1 ];
    $s =~ /\G[^\S\n]+/gc;  # spaces that are no newlines
  }

  # lex the EOL
  $s =~ /\G\n/gc or die "Newline expected";

  # process the deferred heredocs:
  while (my $heredoc = shift @heredocs) {
    my ($placeholder, $marker) = @$heredoc;
    $s =~ /\G(.*\n)$marker\n/sgc or die "Heredoc <<$marker expected";
    $$placeholder = $1;
  }

  return @strings;
}
STRING 0:
body 1

STRING 1:
body 2

STRING 2:
body 3