⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse::recdescent.3

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 3
📖 第 1 页 / 共 5 页
字号:
\&    parser = new Parse::RecDescent (q{\&        expression: and_expr \*(Aq&&\*(Aq expression | and_expr\&        and_expr:   not_expr \*(Aq&&\*(Aq and_expr   | not_expr\&        not_expr:   \*(Aq!\*(Aq brack_expr           | brack_expr\&        brack_expr: \*(Aq(\*(Aq expression \*(Aq)\*(Aq       | identifier\&        identifier: /[a\-z]+/i\&                        { new terminal_node($item[1]) }\&        });.Ve.PPeach \f(CW\*(C`identifier\*(C'\fR match produces a \f(CW\*(C`terminal_node\*(C'\fR object, \fInot\fR an\&\f(CW\*(C`identifier_node\*(C'\fR object..PPA level 1 warning is issued each time an \*(L"autoaction\*(R" is added tosome production..Sh "Autotrees".IX Subsection "Autotrees"A commonly needed autoaction is one that builds a parse-tree. It is moderatelytricky to set up such an action (which must treat terminals differently fromnon-terminals), so Parse::RecDescent simplifies the process by providing the\&\f(CW\*(C`<autotree>\*(C'\fR directive..PPIf this directive appears at the start of grammar, it causesParse::RecDescent to insert autoactions at the end of any rule exceptthose which already end in an action. The action inserted depends on whetherthe production is an intermediate rule (two or more items), or a terminalof the grammar (i.e. a single pattern or string item)..PPSo, for example, the following grammar:.PP.Vb 1\&        <autotree>\&\&        file    : command(s)\&        command : get | set | vet\&        get     : \*(Aqget\*(Aq ident \*(Aq;\*(Aq\&        set     : \*(Aqset\*(Aq ident \*(Aqto\*(Aq value \*(Aq;\*(Aq\&        vet     : \*(Aqcheck\*(Aq ident \*(Aqis\*(Aq value \*(Aq;\*(Aq\&        ident   : /\ew+/\&        value   : /\ed+/.Ve.PPis equivalent to:.PP.Vb 7\&        file    : command(s)                    { bless \e%item, $item[0] }\&        command : get                           { bless \e%item, $item[0] }\&                | set                           { bless \e%item, $item[0] }\&                | vet                           { bless \e%item, $item[0] }\&        get     : \*(Aqget\*(Aq ident \*(Aq;\*(Aq               { bless \e%item, $item[0] }\&        set     : \*(Aqset\*(Aq ident \*(Aqto\*(Aq value \*(Aq;\*(Aq    { bless \e%item, $item[0] }\&        vet     : \*(Aqcheck\*(Aq ident \*(Aqis\*(Aq value \*(Aq;\*(Aq  { bless \e%item, $item[0] }\&\&        ident   : /\ew+/          { bless {_\|_VALUE_\|_=>$item[1]}, $item[0] }\&        value   : /\ed+/          { bless {_\|_VALUE_\|_=>$item[1]}, $item[0] }.Ve.PPNote that each node in the tree is blessed into a class of the same nameas the rule itself. This makes it easy to build object-orientedprocessors for the parse-trees that the grammar produces. Note too thatthe last two rules produce special objects with the single attribute\&'_\|_VALUE_\|_'. This is because they consist solely of a single terminal..PPThis autoaction-ed grammar would then produce a parse tree in a datastructure like this:.PP.Vb 10\&        {\&          file => {\&                    command => {\&                                 [ get => {\&                                            identifier => { _\|_VALUE_\|_ => \*(Aqa\*(Aq },\&                                          },\&                                   set => {\&                                            identifier => { _\|_VALUE_\|_ => \*(Aqb\*(Aq },\&                                            value      => { _\|_VALUE_\|_ => \*(Aq7\*(Aq },\&                                          },\&                                   vet => {\&                                            identifier => { _\|_VALUE_\|_ => \*(Aqb\*(Aq },\&                                            value      => { _\|_VALUE_\|_ => \*(Aq7\*(Aq },\&                                          },\&                                  ],\&                               },\&                  }\&        }.Ve.PP(except, of course, that each nested hash would also be blessed intothe appropriate class)..Sh "Autostubbing".IX Subsection "Autostubbing"Normally, if a subrule appears in some production, but no rule of thatname is ever defined in the grammar, the production which refers to thenon-existent subrule fails immediately. This typically occurs as aresult of misspellings, and is a sufficiently common occurance that awarning is generated for such situations..PPHowever, when prototyping a grammar it is sometimes useful to beable to use subrules before a proper specification of them is really possible.  For example, a grammar might include a section like:.PP.Vb 1\&        function_call: identifier \*(Aq(\*(Aq arg(s?) \*(Aq)\*(Aq\&\&        identifier: /[a\-z]\ew*/i.Ve.PPwhere the possible format of an argument is sufficiently complex thatit is not worth specifying in full until the general function callsyntax has been debugged. In this situation it is convenient to leavethe real rule \f(CW\*(C`arg\*(C'\fR undefined and just slip in a placeholder (or\&\*(L"stub\*(R"):.PP.Vb 1\&        arg: \*(Aqarg\*(Aq.Ve.PPso that the function call syntax can be tested with dummy input such as:.PP.Vb 4\&        f0()\&        f1(arg)\&        f2(arg arg)\&        f3(arg arg arg).Ve.PPet cetera..PPEarly in prototyping, many such \*(L"stubs\*(R" may be required, so \&\f(CW\*(C`Parse::RecDescent\*(C'\fR provides a means of automating their definition.If the variable \f(CW$::RD_AUTOSTUB\fR is defined when a parser is built,a subrule reference to any non-existent rule (say, \f(CW\*(C`sr\*(C'\fR),causes a \*(L"stub\*(R" rule of the form:.PP.Vb 1\&        sr: \*(Aqsr\*(Aq.Ve.PPto be automatically defined in the generated parser.A level 1 warning is issued for each such \*(L"autostubbed\*(R" rule..PPHence, with \f(CW$::AUTOSTUB\fR defined, it is possible to only partiallyspecify a grammar, and then \*(L"fake\*(R" matches of the unspecified(sub)rules by just typing in their name..Sh "Look-ahead".IX Subsection "Look-ahead"If a subrule, token, or action is prefixed by \*(L"...\*(R", then it istreated as a \*(L"look-ahead\*(R" request. That means that the current production can(as usual) only succeed if the specified item is matched, but that the matching\&\fIdoes not consume any of the text being parsed\fR. This is very similar to the\&\f(CW\*(C`/(?=...)/\*(C'\fR look-ahead construct in Perl patterns. Thus, the rule:.PP.Vb 1\&        inner_word: word ...word.Ve.PPwill match whatever the subrule \*(L"word\*(R" matches, provided that match is followedby some more text which subrule \*(L"word\*(R" would also match (although thissecond substring is not actually consumed by \*(L"inner_word\*(R").PPLikewise, a \*(L"...!\*(R" prefix, causes the following item to succeed (withoutconsuming any text) if and only if it would normally fail. Hence, arule such as:.PP.Vb 1\&        identifier: ...!keyword ...!\*(Aq_\*(Aq /[A\-Za\-z_]\ew*/.Ve.PPmatches a string of characters which satisfies the pattern\&\f(CW\*(C`/[A\-Za\-z_]\ew*/\*(C'\fR, but only if the same sequence of characters wouldnot match either subrule \*(L"keyword\*(R" or the literal token '_'..PPSequences of look-ahead prefixes accumulate, multiplying their positive and/ornegative senses. Hence:.PP.Vb 1\&        inner_word: word ...!......!word.Ve.PPis exactly equivalent the the original example above (a warning is issued incases like these, since they often indicate something left out, ormisunderstood)..PPNote that actions can also be treated as look-aheads. In such cases,the state of the parser text (in the local variable \f(CW$text\fR)\&\fIafter\fR the look-ahead action is guaranteed to be identical to itsstate \fIbefore\fR the action, regardless of how it's changed \fIwithin\fRthe action (unless you actually undefine \f(CW$text\fR, in which case youget the disaster you deserve :\-)..Sh "Directives".IX Subsection "Directives"Directives are special pre-defined actions which may be used to alterthe behaviour of the parser. There are currently eighteen directives:\&\f(CW\*(C`<commit>\*(C'\fR,\&\f(CW\*(C`<uncommit>\*(C'\fR,\&\f(CW\*(C`<reject>\*(C'\fR,\&\f(CW\*(C`<score>\*(C'\fR,\&\f(CW\*(C`<autoscore>\*(C'\fR,\&\f(CW\*(C`<skip>\*(C'\fR,\&\f(CW\*(C`<resync>\*(C'\fR,\&\f(CW\*(C`<error>\*(C'\fR,\&\f(CW\*(C`<rulevar>\*(C'\fR,\&\f(CW\*(C`<matchrule>\*(C'\fR,\&\f(CW\*(C`<leftop>\*(C'\fR,\&\f(CW\*(C`<rightop>\*(C'\fR,\&\f(CW\*(C`<defer>\*(C'\fR,\&\f(CW\*(C`<nocheck>\*(C'\fR,\&\f(CW\*(C`<perl_quotelike>\*(C'\fR,\&\f(CW\*(C`<perl_codeblock>\*(C'\fR,\&\f(CW\*(C`<perl_variable>\*(C'\fR,and \f(CW\*(C`<token>\*(C'\fR..IP "Committing and uncommitting" 4.IX Item "Committing and uncommitting"The \f(CW\*(C`<commit>\*(C'\fR and \f(CW\*(C`<uncommit>\*(C'\fR directives permit the recursivedescent of the parse tree to be pruned (or \*(L"cut\*(R") for efficiency.Within a rule, a \f(CW\*(C`<commit>\*(C'\fR directive instructs the rule to ignore subsequentproductions if the current production fails. For example:.Sp.Vb 3\&        command: \*(Aqfind\*(Aq <commit> filename\&               | \*(Aqopen\*(Aq <commit> filename\&               | \*(Aqmove\*(Aq filename filename.Ve.SpClearly, if the leading token 'find' is matched in the first production but thatproduction fails for some other reason, then the remainingproductions cannot possibly match. The presence of the\&\f(CW\*(C`<commit>\*(C'\fR causes the \*(L"command\*(R" rule to fail immediately ifan invalid \*(L"find\*(R" command is found, and likewise if an invalid \*(L"open\*(R"command is encountered..SpIt is also possible to revoke a previous commitment. For example:.Sp.Vb 5\&        if_statement: \*(Aqif\*(Aq <commit> condition\&                                \*(Aqthen\*(Aq block <uncommit>\&                                \*(Aqelse\*(Aq block\&                    | \*(Aqif\*(Aq <commit> condition\&                                \*(Aqthen\*(Aq block.Ve.SpIn this case, a failure to find an \*(L"else\*(R" block in the firstproduction shouldn't preclude trying the second production, but afailure to find a \*(L"condition\*(R" certainly should..SpAs a special case, any production in which the \fIfirst\fR item is an\&\f(CW\*(C`<uncommit>\*(C'\fR immediately revokes a preceding \f(CW\*(C`<commit>\*(C'\fR(even though the production would not otherwise have been tried). Forexample, in the rule:.Sp.Vb 5\&        request: \*(Aqexplain\*(Aq expression\&               | \*(Aqexplain\*(Aq <commit> keyword\&               | \*(Aqsave\*(Aq\&               | \*(Aqquit\*(Aq\&               | <uncommit> term \*(Aq?\*(Aq.Ve.Spif the text being matched was \*(L"explain?\*(R", and the first twoproductions failed, then the \f(CW\*(C`<commit>\*(C'\fR in production two would causeproductions three and four to be skipped, but the leading\&\f(CW\*(C`<uncommit>\*(C'\fR in the production five would allow that production toattempt a match..SpNote in the preceding example, that the \f(CW\*(C`<commit>\*(C'\fR was only placedin production two. If production one had been:.Sp.Vb 1\&        request: \*(Aqexplain\*(Aq <commit> expression.Ve.Spthen production two would be (inappropriately) skipped if a leading\&\*(L"explain...\*(R" was encountered..SpBoth \f(CW\*(C`<commit>\*(C'\fR and \f(CW\*(C`<uncommit>\*(C'\fR directives always succeed, and their valueis always 1..IP "Rejecting a production" 4.IX Item "Rejecting a production"The \f(CW\*(C`<reject>\*(C'\fR directive immediately causes the current productionto fail (it is exactly equivalent to, but more obvious than, theaction \f(CW\*(C`{undef}\*(C'\fR). A \f(CW\*(C`<reject>\*(C'\fR is useful when it is desirable to getthe side effects of the actions in one production, without prejudicing a matchby some other production later in the rule. For example, to inserttracing code into the parse:.Sp.Vb 1\&        complex_rule: { print "In complex rule...\en"; } <reject>\&                    \&        complex_rule: simple_rule \*(Aq+\*(Aq \*(Aqi\*(Aq \*(Aq*\*(Aq simple_rule\&                    | \*(Aqi\*(Aq \*(Aq*\*(Aq simple_rule\&                    | simple_rule.Ve.SpIt is also possible to specify a conditional rejection, using theform \f(CW\*(C`<reject:\f(CIcondition\f(CW>\*(C'\fR, which only rejects if thespecified condition is true. This form of rejection is exactlyequivalent to the action \f(CW\*(C`{(\f(CIcondition\f(CW)?undef:1}>\*(C'\fR.For example:.Sp.Vb 4\&        command: save_command\&               | restore_command\&               | <reject: defined $::tolerant> { exit }\&               | <error: Unknown command. Ignored.>.Ve.SpA \f(CW\*(C`<reject>\*(C'\fR directive never succeeds (and hence has noassociated value). A conditional rejection may succeed (if itscondition is not satisfied), in which case its value is 1..SpAs an extra optimization, \f(CW\*(C`Parse::RecDescent\*(C'\fR ignores any productionwhich \fIbegins\fR with an unconditional \f(CW\*(C`<reject>\*(C'\fR directive,since any such production can never successfully match or have anyuseful side-effects. A level 1 warning is issued in all such cases..SpNote that productions beginning with conditional\&\f(CW\*(C`<reject:...>\*(C'\fR directives are \fInever\fR \*(L"optimized away\*(R" inthis manner, even if they are always guaranteed to fail (for example:\&\f(CW\*(C`<reject:1>\*(C'\fR).SpDue to the way grammars are parsed, there is a minor restriction on thecondition of a conditional \f(CW\*(C`<reject:...>\*(C'\fR: it cannotcontain any raw '<' or '>' characters. For example:.Sp.Vb 1\&        line: cmd <reject: $thiscolumn > max> data.Ve

⌨️ 快捷键说明

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