recdescent.pod

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

POD
1,783
字号
An action is a block of Perl code which is to be executed (as theblock of a C<do> statement) when the parser reaches that point in aproduction. The action executes within a special namespace belonging tothe active parser, so care must be taken in correctly qualifying variablenames (see also L<Start-up Actions> below).The action is considered to succeed if the final value of the blockis defined (that is, if the implied C<do> statement evaluates to adefined value - I<even one which would be treated as "false">). Notethat the value associated with a successful action is also the finalvalue in the block.An action will I<fail> if its last evaluated value is C<undef>. This issurprisingly easy to accomplish by accident. For instance, here's aninfuriating case of an action that makes its production fail, but onlywhen debugging I<isn't> activated:	description: name rank serial_number			{ print "Got $item[2] $item[1] ($item[3])\n"				if $::debugging			}If C<$debugging> is false, no statement in the block is executed, sothe final value is C<undef>, and the entire production fails. The solution is:	description: name rank serial_number			{ print "Got $item[2] $item[1] ($item[3])\n"				if $::debugging;			  1;			}Within an action, a number of useful parse-time variables areavailable in the special parser namespace (there are other variablesalso accessible, but meddling with them will probably just break yourparser. As a general rule, if you avoid referring to unqualifiedvariables - especially those starting with an underscore - inside an action,things should be okay):=over 4=item C<@item> and C<%item>The array slice C<@item[1..$#item]> stores the value associated with each item(that is, each subrule, token, or action) in the current production. Theanalogy is to C<$1>, C<$2>, etc. in a I<yacc> grammar.Note that, for obvious reasons, C<@item> only contains thevalues of items I<before> the current point in the production.The first element (C<$item[0]>) stores the name of the current rulebeing matched.C<@item> is a standard Perl array, so it can also be indexed with negativenumbers, representing the number of items I<back> from the current position inthe parse:	stuff: /various/ bits 'and' pieces "then" data 'end'			{ print $item[-2] }  # PRINTS data					     # (EASIER THAN: $item[6])The C<%item> hash complements the <@item> array, providing namedaccess to the same item values:	stuff: /various/ bits 'and' pieces "then" data 'end'			{ print $item{data}  # PRINTS data					     # (EVEN EASIER THAN USING @item)The results of named subrules are stored in the hash under eachsubrule's name (including the repetition specifier, if any),whilst all other items are stored under a "namedpositional" key that indictates their ordinal position within their itemtype: __STRINGI<n>__, __PATTERNI<n>__, __DIRECTIVEI<n>__, __ACTIONI<n>__:        stuff: /various/ bits 'and' pieces "then" data 'end' { save }                        { print $item{__PATTERN1__}, # PRINTS 'various'                                $item{__STRING2__},  # PRINTS 'then'                                $item{__ACTION1__},  # PRINTS RETURN						     # VALUE OF save                        }If you want proper I<named> access to patterns or literals, you need to turn them into separate rules:         stuff: various bits 'and' pieces "then" data 'end'                        { print $item{various}  # PRINTS various                        }        various: /various/The special entry C<$item{__RULE__}> stores the name of the currentrule (i.e. the same value as C<$item[0]>.The advantage of using C<%item>, instead of C<@items> is that itremoves the need to track items positions that may change as a grammarevolves. For example, adding an interim C<E<lt>skipE<gt>> directiveof action can silently ruin a trailing action, by moving an C<@item>element "down" the array one place. In contrast, the named entry of C<%item> is unaffected by such an insertion.A limitation of the C<%item> hash is that it only records the I<last>value of a particular subrule. For example:        range: '(' number '..' number )'                        { $return = $item{number} }will return only the value corresponding to the I<second> match of theC<number> subrule. In other words, successive calls to a subruleoverwrite the corresponding entry in C<%item>. Once again, thesolution is to rename each subrule in its own rule:        range: '(' from_num '..' to_num )'                        { $return = $item{from_num} }        from_num: number        to_num:   number=item C<@arg> and C<%arg>The array C<@arg> and the hash C<%arg> store any arguments passed tothe rule from some other rule (see L<"Subrule argument lists>). Changesto the elements of either variable do not propagate back to the callingrule (data can be passed back from a subrule via the C<$return>variable - see next item).=item C<$return>If a value is assigned to C<$return> within an action, that value isreturned if the production containing the action eventually matchessuccessfully. Note that setting C<$return> I<doesn't> cause the currentproduction to succeed. It merely tells it what to return if it I<does> succeed.Hence C<$return> is analogous to C<$$> in a I<yacc> grammar.If C<$return> is not assigned within a production, the value of thelast component of the production (namely: C<$item[$#item]>) isreturned if the production succeeds.=item C<$commit>The current state of commitment to the current production (see L<"Directives">below).=item C<$skip>The current terminal prefix (see L<"Directives"> below).=item C<$text>The remaining (unparsed) text. Changes to C<$text> I<do notpropagate> out of unsuccessful productions, but I<do> survivesuccessful productions. Hence it is possible to dynamically alter thetext being parsed - for example, to provide a C<#include>-like facility:        hash_include: '#include' filename                                { $text = ::loadfile($item[2]) . $text }        filename: '<' /[a-z0-9._-]+/i '>'  { $return = $item[2] }                | '"' /[a-z0-9._-]+/i '"'  { $return = $item[2] }=item C<$thisline> and C<$prevline>C<$thisline> stores the current line number within the current parse(starting from 1). C<$prevline> stores the line number for the last character which was already successfully parsed (this will be different fromC<$thisline> at the end of each line).For efficiency, C<$thisline> and C<$prevline> are actually tiedhashes, and only recompute the required line number when the variable'svalue is used.Assignment to C<$thisline> adjusts the line number calculator, so thatit believes that the current line number is the value being assigned. Notethat this adjustment will be reflected in all subsequent line numberscalculations.Modifying the value of the variable C<$text> (as in the previousC<hash_include> example, for instance) will confuse the linecounting mechanism. To prevent this, you should callC<Parse::RecDescent::LineCounter::resync($thisline)> I<immediately>after any assignment to the variable C<$text> (or, at least, before thenext attempt to use C<$thisline>).Note that if a production fails after assigning to orresync'ing C<$thisline>, the parser's line counter mechanism willusually be corrupted.Also see the entry for C<@itempos>.The line number can be set to values other than 1, by calling the startrule with a second argument. For example:        $parser = new Parse::RecDescent ($grammar);        $parser->input($text, 10);      # START LINE NUMBERS AT 10=item C<$thiscolumn> and C<$prevcolumn>C<$thiscolumn> stores the current column number within the current linebeing parsed (starting from 1). C<$prevcolumn> stores the column numberof the last character which was actually successfully parsed. Usually C<$prevcolumn == $thiscolumn-1>, but not at the end of lines.For efficiency, C<$thiscolumn> and C<$prevcolumn> areactually tied hashes, and only recompute the required column numberwhen the variable's value is used.Assignment to C<$thiscolumn> or C<$prevcolumn> is a fatal error.Modifying the value of the variable C<$text> (as in the previousC<hash_include> example, for instance) may confuse the columncounting mechanism. Note that C<$thiscolumn> reports the column number I<before> anywhitespace that might be skipped before reading a token. Henceif you wish to know where a token started (and ended) use something like this:        rule: token1 token2 startcol token3 endcol token4                        { print "token3: columns $item[3] to $item[5]"; }        startcol: '' { $thiscolumn }    # NEED THE '' TO STEP PAST TOKEN SEP        endcol:      { $prevcolumn }Also see the entry for C<@itempos>.=item C<$thisoffset> and C<$prevoffset>C<$thisoffset> stores the offset of the current parsing positionwithin the complete textbeing parsed (starting from 0). C<$prevoffset> stores the offsetof the last character which was actually successfully parsed. In allcases C<$prevoffset == $thisoffset-1>.For efficiency, C<$thisoffset> and C<$prevoffset> areactually tied hashes, and only recompute the required offsetwhen the variable's value is used.Assignment to C<$thisoffset> or <$prevoffset> is a fatal error.Modifying the value of the variable C<$text> will I<not> affect theoffset counting mechanism. Also see the entry for C<@itempos>.=item C<@itempos>The array C<@itempos> stores a hash reference corresponding toeach element of C<@item>. The elements of the hash provide thefollowing:        $itempos[$n]{offset}{from}      # VALUE OF $thisoffset BEFORE $item[$n]        $itempos[$n]{offset}{to}        # VALUE OF $prevoffset AFTER $item[$n]        $itempos[$n]{line}{from}        # VALUE OF $thisline BEFORE $item[$n]        $itempos[$n]{line}{to}          # VALUE OF $prevline AFTER $item[$n]        $itempos[$n]{column}{from}      # VALUE OF $thiscolumn BEFORE $item[$n]        $itempos[$n]{column}{to}        # VALUE OF $prevcolumn AFTER $item[$n]Note that the various C<$itempos[$n]...{from}> values record theappropriate value I<after> any token prefix has been skipped.Hence, instead of the somewhat tedious and error-prone:        rule: startcol token1 endcol              startcol token2 endcol              startcol token3 endcol                        { print "token1: columns $item[1]                                              to $item[3]                                 token2: columns $item[4]                                              to $item[6]                                 token3: columns $item[7]                                              to $item[9]" }        startcol: '' { $thiscolumn }    # NEED THE '' TO STEP PAST TOKEN SEP        endcol:      { $prevcolumn }it is possible to write:        rule: token1 token2 token3                        { print "token1: columns $itempos[1]{column}{from}                                              to $itempos[1]{column}{to}                                 token2: columns $itempos[2]{column}{from}                                              to $itempos[2]{column}{to}                                 token3: columns $itempos[3]{column}{from}                                              to $itempos[3]{column}{to}" }Note however that (in the current implementation) the use of C<@itempos>anywhere in a grammar implies that item positioning information is collected I<everywhere> during the parse. Depending on the grammarand the size of the text to be parsed, this may be prohibitivelyexpensive and the explicit use of C<$thisline>, C<$thiscolumn>, etc. maybe a better choice.=item C<$thisparser>A reference to the S<C<Parse::RecDescent>> object through whichparsing was initiated. The value of C<$thisparser> propagates down the subrules of a parsebut not back up. Hence, you can invoke subrules from another parserfor the scope of the current rule as follows:        rule: subrule1 subrule2            | { $thisparser = $::otherparser } <reject>            | subrule3 subrule4            | subrule5The result is that the production calls "subrule1" and "subrule2" ofthe current parser, and the remaining productions call the named subrulesfrom C<$::otherparser>. Note, however that "Bad Things" will happen ifC<::otherparser> isn't a blessed reference and/or doesn't have methodswith the same names as the required subrules!=item C<$thisrule>A reference to the S<C<Parse::RecDescent::Rule>> object corresponding to the rule currently being matched.=item C<$thisprod>A reference to the S<C<Parse::RecDescent::Production>> objectcorresponding to the production currently being matched.=item C<$score> and C<$score_return>$score stores the best production score to date, as specified byan earlier C<E<lt>score:...E<gt>> directive. $score_return storesthe corresponding return value for the successful production.See L<Scored productions>.=backB<Warning:> the parser relies on the information in the various C<this...>objects in some non-obvious ways. Tinkering with the other members ofthese objects will probably cause Bad Things to happen, unless youI<really> know what you're doing. The only exception to this advice isthat the use of C<$this...-E<gt>{local}> is always safe.=head2 Start-up ActionsAny actions which appear I<before> the first rule definition in agrammar are treated as "start-up" actions. Each such action isstripped of its outermost brackets and then evaluated (in the parser'sspecial namespace) just before the rules of the grammar are firstcompiled.The main use of start-up actions is to declare local variables within theparser's special namespace:

⌨️ 快捷键说明

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