recdescent.pod

来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· POD 代码 · 共 1,783 行 · 第 1/5 页

POD
1,783
字号
Note that setting C<$::RD_HINT> at any point automagicallysets C<$::RD_WARN> to 1.Defining C<$::RD_TRACE> causes the parser generator and the parser toreport their progress to STDERR in excruciating detail (although, without hintsunless $::RD_HINT is separately defined). This detailcan be moderated in only one respect: if C<$::RD_TRACE> has aninteger value (I<N>) greater than 1, only the I<N> characters ofthe "current parsing context" (that is, where in the input string weare at any point in the parse) is reported at any time.   > C<$::RD_TRACE> is mainly useful for debugging a grammar that isn'tbehaving as you expected it to. To this end, if C<$::RD_TRACE> isdefined when a parser is built, any actual parser code which isgenerated is also written to a file named "RD_TRACE" in the localdirectory.Note that the four variables belong to the "main" package, whichmakes them easier to refer to in the code controlling the parser, andalso makes it easy to turn them into command line flags ("-RD_ERRORS","-RD_WARN", "-RD_HINT", "-RD_TRACE") under B<perl -s>.=item Specifying local variablesIt is occasionally convenient to specify variables which are localto a single rule. This may be achieved by including aC<E<lt>rulevar:...E<gt>> directive anywhere in the rule. For example:        markup: <rulevar: $tag>        markup: tag {($tag=$item[1]) =~ s/^<|>$//g} body[$tag]The example C<E<lt>rulevar: $tagE<gt>> directive causes a "my" variable namedC<$tag> to be declared at the start of the subroutine implementing theC<markup> rule (that is, I<before> the first production, regardless ofwhere in the rule it is specified).Specifically, any directive of the form:C<E<lt>rulevar:I<text>E<gt>> causes a line of the form C<my I<text>;>to be added at the beginning of the rule subroutine, immediately afterthe definitions of the following local variables:        $thisparser     $commit        $thisrule       @item        $thisline       @arg        $text           %argThis means that the following C<E<lt>rulevarE<gt>> directives workas expected:        <rulevar: $count = 0 >        <rulevar: $firstarg = $arg[0] || '' >        <rulevar: $myItems = \@item >        <rulevar: @context = ( $thisline, $text, @arg ) >        <rulevar: ($name,$age) = $arg{"name","age"} >If a variable that is also visible to subrules is required, it needsto be C<local>'d, not C<my>'d. C<rulevar> defaults to C<my>, but if C<local>is explicitly specified:        <rulevar: local $count = 0 >then a C<local>-ized variable is declared instead, and will be availablewithin subrules.Note however that, because all such variables are "my" variables, theirvalues I<do not persist> between match attempts on a given rule. Topreserve values between match attempts, values can be stored within the"local" member of the C<$thisrule> object:        countedrule: { $thisrule->{"local"}{"count"}++ }                     <reject>                   | subrule1                   | subrule2                   | <reject: $thisrule->{"local"}{"count"} == 1>                     subrule3When matching a rule, each C<E<lt>rulevarE<gt>> directive is matched asif it were an unconditional C<E<lt>rejectE<gt>> directive (that is, itcauses any production in which it appears to immediately fail to match).For this reason (and to improve readability) it is usual to specify anyC<E<lt>rulevarE<gt>> directive in a separate production at the start ofthe rule (this has the added advantage that it enablesC<Parse::RecDescent> to optimize away such productions, just as it doesfor the C<E<lt>rejectE<gt>> directive).=item Dynamically matched rulesBecause regexes and double-quoted strings are interpolated, it is relativelyeasy to specify productions with "context sensitive" tokens. For example:        command:  keyword  body  "end $item[1]"which ensures that a command block is bounded by a"I<E<lt>keywordE<gt>>...end I<E<lt>same keywordE<gt>>" pair.Building productions in which subrules are context sensitive is also possible,via the C<E<lt>matchrule:...E<gt>> directive. This directive behavesidentically to a subrule item, except that the rule which is invoked to matchit is determined by the string specified after the colon. For example, we couldrewrite the C<command> rule like this:        command:  keyword  <matchrule:body>  "end $item[1]"Whatever appears after the colon in the directive is treated as an interpolatedstring (that is, as if it appeared in C<qq{...}> operator) and the value ofthat interpolated string is the name of the subrule to be matched.Of course, just putting a constant string like C<body> in aC<E<lt>matchrule:...E<gt>> directive is of little interest or benefit.The power of directive is seen when we use a string that interpolatesto something interesting. For example:        command:        keyword <matchrule:$item[1]_body> "end $item[1]"        keyword:        'while' | 'if' | 'function'        while_body:     condition block        if_body:        condition block ('else' block)(?)        function_body:  arglist blockNow the C<command> rule selects how to proceed on the basis of the keywordthat is found. It is as if C<command> were declared:        command:        'while'    while_body    "end while"                |        'if'       if_body       "end if"                |        'function' function_body "end function" When a C<E<lt>matchrule:...E<gt>> directive is used as a repeatedsubrule, the rule name expression is "late-bound". That is, the name ofthe rule to be called is re-evaluated I<each time> a match attempt ismade. Hence, the following grammar:        { $::species = 'dogs' }        pair:   'two' <matchrule:$::species>(s)        dogs:   /dogs/ { $::species = 'cats' }        cats:   /cats/will match the string "two dogs cats cats" completely, whereas it willonly match the string "two dogs dogs dogs" up to the eighth letter. Ifthe rule name were "early bound" (that is, evaluated only the firsttime the directive is encountered in a production), the reversebehaviour would be expected.Note that the C<matchrule> directive takes a string that is to be treatedas a rule name, I<not> as a rule invocation. That is,it's like a Perl symbolic reference, not an C<eval>. Just as you can say:        $subname = 'foo';	# and later...        &{$foo}(@args);but not:        $subname = 'foo(@args)';	# and later...        &{$foo};likewise you can say:	$rulename = 'foo';	# and in the grammar...	<matchrule:$rulename>[@args]but not:	$rulename = 'foo[@args]';	# and in the grammar...	<matchrule:$rulename>=item Deferred actionsThe C<E<lt>defer:...E<gt>> directive is used to specify an action to be performed when (and only if!) the current production ultimately succeeds.Whenever a C<E<lt>defer:...E<gt>> directive appears, the code it specifiesis converted to a closure (an anonymous subroutine reference) which isqueued within the active parser object. Note that,because the deferred code is converted to a closure, the values of any"local" variable (such as C<$text>, <@item>, etc.) are preserveduntil the deferred code is actually executed.If the parse ultimately succeedsI<and> the production in which the C<E<lt>defer:...E<gt>> directive wasevaluated formed part of the successful parse, then the deferred code isexecuted immediately before the parse returns. If however the productionwhich queued a deferred action fails, or one of the higher-level rules which called that production fails, then the deferred action isremoved from the queue, and hence is never executed.For example, given the grammar:        sentence: noun trans noun                | noun intrans        noun:     'the dog'                        { print "$item[1]\t(noun)\n" }            |     'the meat'                        { print "$item[1]\t(noun)\n" }        trans:    'ate'                        { print "$item[1]\t(transitive)\n" }        intrans:  'ate'                        { print "$item[1]\t(intransitive)\n" }               |  'barked'                        { print "$item[1]\t(intransitive)\n" }then parsing the sentence C<"the dog ate"> would produce the output:        the dog  (noun)        ate      (transitive)        the dog  (noun)        ate      (intransitive)This is because, even though the first production of C<sentence>ultimately fails, its initial subrules C<noun> and C<trans> do match,and hence they execute their associated actions.Then the second production of C<sentence> succeeds, causing theactions of the subrules C<noun> and C<intrans> to be executed as well.On the other hand, if the actions were replaced by C<E<lt>defer:...E<gt>>directives:        sentence: noun trans noun                | noun intrans        noun:     'the dog'                        <defer: print "$item[1]\t(noun)\n" >            |     'the meat'                        <defer: print "$item[1]\t(noun)\n" >        trans:    'ate'                        <defer: print "$item[1]\t(transitive)\n" >        intrans:  'ate'                        <defer: print "$item[1]\t(intransitive)\n" >               |  'barked'                        <defer: print "$item[1]\t(intransitive)\n" >the output would be:        the dog  (noun)        ate      (intransitive)since deferred actions are only executed if they were evaluated ina production which ultimately contributes to the successful parse.In this case, even though the first production of C<sentence> causedthe subrules C<noun> and C<trans> to match, that production ultimatelyfailed and so the deferred actions queued by those subrules were subsequentlydisgarded. The second production then succeeded, causing the entireparse to succeed, and so the deferred actions queued by the (second) match ofthe C<noun> subrule and the subsequent match of C<intrans> I<are> preserved and eventually executed.Deferred actions provide a means of improving the performance of a parser,by only executing those actions which are part of the final parse-treefor the input data. Alternatively, deferred actions can be viewed as a mechanism for building (and executing) acustomized subroutine corresponding to the given input data, much in thesame way that autoactions (see L<"Autoactions">) can be used to build acustomized data structure for specific input.Whether or not the action it specifies is ever executed,a C<E<lt>defer:...E<gt>> directive always succeeds, returning the number of deferred actions currently queued at that point.=item Parsing PerlParse::RecDescent provides limited support for parsing subsets of Perl,namely: quote-like operators, Perl variables, and complete code blocks.The C<E<lt>perl_quotelikeE<gt>> directive can be used to parse any Perlquote-like operator: C<'a string'>, C<m/a pattern/>, C<tr{ans}{lation}>,etc.  It does this by calling Text::Balanced::quotelike().If a quote-like operator is found, a reference to an array of eight elementsis returned. Those elements are identical to the last eight elements returnedby Text::Balanced::extract_quotelike() in an array context, namely:=over 4=item [0]the name of the quotelike operator -- 'q', 'qq', 'm', 's', 'tr' -- if theoperator was named; otherwise C<undef>,=item [1]the left delimiter of the first block of the operation,=item [2]the text of the first block of the operation(that is, the contents ofa quote, the regex of a match, or substitution or the target list of atranslation),=item [3]the right delimiter of the first block of the operation,=item [4]the left delimiter of the second block of the operation if there is one(that is, if it is a C<s>, C<tr>, or C<y>); otherwise C<undef>,=item [5]the text of the second block of the operation if there is one(that is, the replacement of a substitution or the translation listof a translation); otherwise C<undef>,=item [6]the right delimiter of the second block of the operation (if any);otherwise C<undef>,=item [7]the trailing modifiers on the operation (if any); otherwise C<undef>.=backIf a quote-like expression is not found, the directive fails with the usualC<undef> value.The C<E<lt>perl_variableE<gt>> directive can be used to parse any Perlvariable: $scalar, @array, %hash, $ref->{field}[$index], etc.It does this by calling Text::Balanced::extract_variab

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?