• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評(píng)論-2670  文章-0  trackbacks-0
                雖然說(shuō)分析語(yǔ)法樹依賴于遞歸,但是你真的去寫遞歸那是一件很煩的事情,個(gè)人覺(jué)得煩事煩在你每次都要去RegexExpression.h里面聲明所有的虛函數(shù)之后復(fù)制過(guò)來(lái)一一運(yùn)行。有沒(méi)有辦法僅編輯.cpp文件就能做到呢?也就是說(shuō),在如何不修改Expression一系列類的接口的情況下給Expression添加算法?一般來(lái)說(shuō)對(duì)付樹形結(jié)構(gòu)都是使用Visitor模式的。

                首先對(duì)于上一篇文章定義的樹來(lái)看,我們需要設(shè)計(jì)一個(gè)通用的Visitor接口:
             1         class IRegexExpressionAlgorithm : public Interface
             2         {
             3         public:
             4             virtual void                Visit(CharSetExpression* expression)=0;
             5             virtual void                Visit(LoopExpression* expression)=0;
             6             virtual void                Visit(SequenceExpression* expression)=0;
             7             virtual void                Visit(AlternateExpression* expression)=0;
             8             virtual void                Visit(BeginExpression* expression)=0;
             9             virtual void                Visit(EndExpression* expression)=0;
            10             virtual void                Visit(CaptureExpression* expression)=0;
            11             virtual void                Visit(MatchExpression* expression)=0;
            12             virtual void                Visit(PositiveExpression* expression)=0;
            13             virtual void                Visit(NegativeExpression* expression)=0;
            14             virtual void                Visit(UsingExpression* expression)=0;
            15         };

                接口定義好了之后,就給所有的表達(dá)式樹添加一個(gè)Apply(虛)函數(shù)來(lái)訪問(wèn)相應(yīng)的Visit函數(shù):
             1         void CharSetExpression::Apply(IRegexExpressionAlgorithm& algorithm)
             2         {
             3             algorithm.Visit(this);
             4         }
             5 
             6         void LoopExpression::Apply(IRegexExpressionAlgorithm& algorithm)
             7         {
             8             algorithm.Visit(this);
             9         }
            10 
            11         void SequenceExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            12         {
            13             algorithm.Visit(this);
            14         }
            15 
            16         void AlternateExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            17         {
            18             algorithm.Visit(this);
            19         }
            20 
            21         void BeginExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            22         {
            23             algorithm.Visit(this);
            24         }
            25 
            26         void EndExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            27         {
            28             algorithm.Visit(this);
            29         }
            30 
            31         void CaptureExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            32         {
            33             algorithm.Visit(this);
            34         }
            35 
            36         void MatchExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            37         {
            38             algorithm.Visit(this);
            39         }
            40 
            41         void PositiveExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            42         {
            43             algorithm.Visit(this);
            44         }
            45 
            46         void NegativeExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            47         {
            48             algorithm.Visit(this);
            49         }
            50 
            51         void UsingExpression::Apply(IRegexExpressionAlgorithm& algorithm)
            52         {
            53             algorithm.Visit(this);
            54         }

                于是我們可以去實(shí)現(xiàn)一個(gè)IRegexExpressionAlgorithm了。但是事情還沒(méi)完。如果每一個(gè)算法都要去實(shí)現(xiàn)一個(gè)IRegexExpressionAlgorithm的話,我們會(huì)發(fā)現(xiàn)因?yàn)樗惴ㄋ枰膮?shù)不同,為了使用Visit這種無(wú)參數(shù)的函數(shù),我們都需要為每一個(gè)具體的Apply實(shí)現(xiàn)一次參數(shù)的緩存工作。但是因?yàn)閰?shù)是未知的,而且模板函數(shù)又不能是虛函數(shù)(所以不能把Expression::Apply寫成模板函數(shù)),所以IRegexExpressionAlgorithm的Visit系列函數(shù)是沒(méi)有參數(shù)的。因此一個(gè)輔助類就應(yīng)運(yùn)而生了。

                這個(gè)輔助類用來(lái)給你很直接地寫具有一個(gè)參數(shù)的算法。你只要?jiǎng)?chuàng)建它,然后寫完所有的(算法類里面的)Apply函數(shù)就行了。那么你怎么在一個(gè)表達(dá)式上面調(diào)用你自己的算法呢?假設(shè)參數(shù)是p,我們希望只需要簡(jiǎn)單地執(zhí)行Invoke(expression, p)就可以調(diào)用到自己了。所以這里實(shí)現(xiàn)了一個(gè)RegexExpressionAlgorithm<ReturnType, ParameterType>。當(dāng)然對(duì)于ReturnType==void的時(shí)候,我們還需要再特化一個(gè),不過(guò)這個(gè)就不說(shuō)了:
             1         template<typename ReturnType, typename ParameterType=void*>
             2         class RegexExpressionAlgorithm : public Object, public IRegexExpressionAlgorithm
             3         {
             4         private:
             5             ReturnType                    returnValue;
             6             void*                        parameterValue;
             7         public:
             8 
             9             ReturnType Invoke(Expression* expression, ParameterType parameter)
            10             {
            11                 parameterValue=(void*)&parameter;
            12                 expression->Apply(*this);
            13                 return returnValue;
            14             }
            15 
            16             ReturnType Invoke(Expression::Ref expression, ParameterType parameter)
            17             {
            18                 parameterValue=(void*)&parameter;
            19                 expression->Apply(*this);
            20                 return returnValue;
            21             }
            22 
            23             virtual ReturnType            Apply(CharSetExpression* expression, ParameterType parameter)=0;
            24             virtual ReturnType            Apply(LoopExpression* expression, ParameterType parameter)=0;
            25             virtual ReturnType            Apply(SequenceExpression* expression, ParameterType parameter)=0;
            26             virtual ReturnType            Apply(AlternateExpression* expression, ParameterType parameter)=0;
            27             virtual ReturnType            Apply(BeginExpression* expression, ParameterType parameter)=0;
            28             virtual ReturnType            Apply(EndExpression* expression, ParameterType parameter)=0;
            29             virtual ReturnType            Apply(CaptureExpression* expression, ParameterType parameter)=0;
            30             virtual ReturnType            Apply(MatchExpression* expression, ParameterType parameter)=0;
            31             virtual ReturnType            Apply(PositiveExpression* expression, ParameterType parameter)=0;
            32             virtual ReturnType            Apply(NegativeExpression* expression, ParameterType parameter)=0;
            33             virtual ReturnType            Apply(UsingExpression* expression, ParameterType parameter)=0;
            34         public:
            35             void Visit(CharSetExpression* expression)
            36             {
            37                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            38             }
            39 
            40             void Visit(LoopExpression* expression)
            41             {
            42                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            43             }
            44 
            45             void Visit(SequenceExpression* expression)
            46             {
            47                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            48             }
            49 
            50             void Visit(AlternateExpression* expression)
            51             {
            52                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            53             }
            54 
            55             void Visit(BeginExpression* expression)
            56             {
            57                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            58             }
            59 
            60             void Visit(EndExpression* expression)
            61             {
            62                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            63             }
            64 
            65             void Visit(CaptureExpression* expression)
            66             {
            67                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            68             }
            69 
            70             void Visit(MatchExpression* expression)
            71             {
            72                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            73             }
            74 
            75             void Visit(PositiveExpression* expression)
            76             {
            77                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            78             }
            79 
            80             void Visit(NegativeExpression* expression)
            81             {
            82                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            83             }
            84 
            85             void Visit(UsingExpression* expression)
            86             {
            87                 returnValue=Apply(expression, *((ParameterType*)parameterValue));
            88             }
            89         };

                好了,讓我們使用它來(lái)實(shí)現(xiàn)之前提到過(guò)的IsEqual功能吧。首先實(shí)現(xiàn)一個(gè)IsEqualAlgorithm:
              1         class IsEqualAlgorithm : public RegexExpressionAlgorithm<bool, Expression*>
              2         {
              3         public:
              4             bool Apply(CharSetExpression* expression, Expression* target)
              5             {
              6                 CharSetExpression* expected=dynamic_cast<CharSetExpression*>(target);
              7                 if(expected)
              8                 {
              9                     if(expression->reverse!=expected->reverse)return false;
             10                     if(expression->ranges.Count()!=expected->ranges.Count())return false;
             11                     for(int i=0;i<expression->ranges.Count();i++)
             12                     {
             13                         if(expression->ranges[i]!=expected->ranges[i])return false;
             14                     }
             15                     return true;
             16                 }
             17                 return false;
             18             }
             19 
             20             bool Apply(LoopExpression* expression, Expression* target)
             21             {
             22                 LoopExpression* expected=dynamic_cast<LoopExpression*>(target);
             23                 if(expected)
             24                 {
             25                     if(expression->min!=expected->min)return false;
             26                     if(expression->max!=expected->max)return false;
             27                     if(!Invoke(expression->expression, expected->expression.Obj()))return false;
             28                     return true;
             29                 }
             30                 return false;
             31             }
             32 
             33             bool Apply(SequenceExpression* expression, Expression* target)
             34             {
             35                 SequenceExpression* expected=dynamic_cast<SequenceExpression*>(target);
             36                 if(expected)
             37                 {
             38                     if(!Invoke(expression->left, expected->left.Obj()))return false;
             39                     if(!Invoke(expression->right, expected->right.Obj()))return false;
             40                     return true;
             41                 }
             42                 return false;
             43             }
             44 
             45             bool Apply(AlternateExpression* expression, Expression* target)
             46             {
             47                 AlternateExpression* expected=dynamic_cast<AlternateExpression*>(target);
             48                 if(expected)
             49                 {
             50                     if(!Invoke(expression->left, expected->left.Obj()))return false;
             51                     if(!Invoke(expression->right, expected->right.Obj()))return false;
             52                     return true;
             53                 }
             54                 return false;
             55             }
             56 
             57             bool Apply(BeginExpression* expression, Expression* target)
             58             {
             59                 BeginExpression* expected=dynamic_cast<BeginExpression*>(target);
             60                 if(expected)
             61                 {
             62                     return true;
             63                 }
             64                 return false;
             65             }
             66 
             67             bool Apply(EndExpression* expression, Expression* target)
             68             {
             69                 EndExpression* expected=dynamic_cast<EndExpression*>(target);
             70                 if(expected)
             71                 {
             72                     return true;
             73                 }
             74                 return false;
             75             }
             76 
             77             bool Apply(CaptureExpression* expression, Expression* target)
             78             {
             79                 CaptureExpression* expected=dynamic_cast<CaptureExpression*>(target);
             80                 if(expected)
             81                 {
             82                     if(expression->name!=expected->name)return false;
             83                     if(!Invoke(expression->expression, expected->expression.Obj()))return false;
             84                     return true;
             85                 }
             86                 return false;
             87             }
             88 
             89             bool Apply(MatchExpression* expression, Expression* target)
             90             {
             91                 MatchExpression* expected=dynamic_cast<MatchExpression*>(target);
             92                 if(expected)
             93                 {
             94                     if(expression->name!=expected->name)return false;
             95                     if(expression->index!=expected->index)return false;
             96                     return true;
             97                 }
             98                 return false;
             99             }
            100 
            101             bool Apply(PositiveExpression* expression, Expression* target)
            102             {
            103                 PositiveExpression* expected=dynamic_cast<PositiveExpression*>(target);
            104                 if(expected)
            105                 {
            106                     if(!Invoke(expression->expression, expected->expression.Obj()))return false;
            107                     return true;
            108                 }
            109                 return false;
            110             }
            111 
            112             bool Apply(NegativeExpression* expression, Expression* target)
            113             {
            114                 NegativeExpression* expected=dynamic_cast<NegativeExpression*>(target);
            115                 if(expected)
            116                 {
            117                     if(!Invoke(expression->expression, expected->expression.Obj()))return false;
            118                     return true;
            119                 }
            120                 return false;
            121             }
            122 
            123             bool Apply(UsingExpression* expression, Expression* target)
            124             {
            125                 UsingExpression* expected=dynamic_cast<UsingExpression*>(target);
            126                 if(expected)
            127                 {
            128                     if(expression->name!=expected->name)return false;
            129                     return true;
            130                 }
            131                 return false;
            132             }
            133         };

                譬如看AlternateExpression的IsEqual方法。AlternateExpression跟Expression是否相等只需要通過(guò)比較兩個(gè)子表達(dá)式是否相等即可,于是代碼就變成了:
             1             bool Apply(AlternateExpression* expression, Expression* target)
             2             {
             3                 AlternateExpression* expected=dynamic_cast<AlternateExpression*>(target);
             4                 if(expected)
             5                 {
             6                     if(!Invoke(expression->left, expected->left.Obj()))return false;
             7                     if(!Invoke(expression->right, expected->right.Obj()))return false;
             8                     return true;
             9                 }
            10                 return false;
            11             }

                如果將AlternateExpression* expression變?yōu)锳lternateExpression* const this,將Invoke(a, b)換成a->IsEqual(b),就跟直接寫IsEqual虛函數(shù)沒(méi)兩樣了。于是自己調(diào)用自己還是很方便的。但是我們最終還是想做成a->IsEqual(b)的,于是還要在Expression基類中寫一點(diǎn):
            1         bool Expression::IsEqual(vl::regex_internal::Expression *expression)
            2         {
            3             IsEqualAlgorithm algorithm;
            4             return algorithm.Invoke(this, expression);
            5         }

                于是IsEqual的實(shí)現(xiàn)就結(jié)束了。雖然Visitor直接使用會(huì)很麻煩,但是我們可以通過(guò)稍微的改造一下讓其更好用。當(dāng)然這里跟Visitor其實(shí)還不是完全一致,細(xì)節(jié)問(wèn)題就不詳細(xì)討論了。至少文章的目標(biāo)“不通過(guò)修改Expression的接口而添加新功能”的目標(biāo)已經(jīng)實(shí)現(xiàn)了。就結(jié)果來(lái)講,添加一個(gè)新的功能還是很方便的。
            posted on 2009-10-17 17:34 陳梓瀚(vczh) 閱讀(2016) 評(píng)論(0)  編輯 收藏 引用 所屬分類: VL++3.0開發(fā)紀(jì)事
            欧美亚洲日本久久精品| 乱亲女H秽乱长久久久| 久久精品国产色蜜蜜麻豆| 久久无码人妻一区二区三区 | 久久婷婷国产综合精品| 久久亚洲av无码精品浪潮| 97久久精品人妻人人搡人人玩| 久久亚洲AV无码西西人体| 91精品国产综合久久精品| 2020久久精品亚洲热综合一本| 久久香蕉国产线看观看99| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 色综合久久精品中文字幕首页| 欧美日韩精品久久久久| 久久午夜综合久久| 99久久国产综合精品网成人影院| 无码人妻少妇久久中文字幕蜜桃| 久久性生大片免费观看性| 蜜桃麻豆www久久| 久久w5ww成w人免费| 久久精品人妻中文系列| 欧美日韩成人精品久久久免费看| 精品亚洲综合久久中文字幕| 新狼窝色AV性久久久久久| 亚洲?V乱码久久精品蜜桃| 国产成人久久久精品二区三区| 久久91综合国产91久久精品| 久久精品国产亚洲AV电影| 麻豆AV一区二区三区久久 | 久久精品国产亚洲一区二区三区| 国产69精品久久久久777| 久久国产精品无码一区二区三区 | 久久精品国产亚洲av麻豆色欲| 久久久久久久久久久精品尤物 | 午夜精品久久久久久中宇| 一本一本久久aa综合精品| 伊人色综合九久久天天蜜桃| 亚洲国产高清精品线久久| 婷婷国产天堂久久综合五月| 亚洲国产精品成人久久蜜臀| 亚洲欧美日韩久久精品|