J2EE之巔

           

          DSL的實現要點(2)

           

          實現外部DSL

          與上一篇中所提及內部DSL不同,使用者不是通過API調用來使用DSL,而是通過我們定義的特定語法的領域語言來使用DSL

          1 XML形式的DSL

          腳本文件

          <process name="Auto-Door">

                <state name="Open">

                      <transition event="time-out" next_state="Close"/>

                </state>

                <state name="Close">

                      <transition event="people-closer" next_state="Open"/>

                </state>         

          </process>

          實現

          publicclass XmlConfigParser {

                //followings are context variables

                private Machine currentMachine;

                private State currentState;

                class ElementHandler extends DefaultHandler{

                      private String getAttributeValue(String elemName,String attributeName,Attributes attris){

                            String attrValue=attris.getValue(attributeName);

                            if (attrValue==null){

                                  thrownew XmlConfigParseException("Element "+elemName+" shoudle have the attribute:"+attributeName);

                            }

                            return attrValue;

                      }

                      @Override

                      publicvoid endElement(String arg0, String arg1, String elemName)

                      throws SAXException {

                            if (elemName.equals("state")){

                                  currentMachine.getStates().add(currentState);

                            }

                      }

                      @Override

                      publicvoid startElement(String arg0, String arg1, String elemName,

                                  Attributes attris) throws SAXException{              

                            if (elemName.equals("process")){

                                  String processName=getAttributeValue(elemName,"name",attris);

                                  currentMachine=new Machine(processName);

                            }

                            if (elemName.equals("state")){

                                  String stateName=getAttributeValue(elemName,"name",attris);

                                  currentState=new State(stateName);

                            }

                            if (elemName.equals("transition")){

                                  String eventName=getAttributeValue(elemName,"event",attris);

                                  String nextState=getAttributeValue(elemName,"next_state",attris);

                                  Transition transition=new Transition();

                                  transition.setEvent(new Event(eventName));

                                  transition.setNextState(nextState);

                                  currentState.getTransitions().add(transition);

                            }

                      }

                }

                public Machine parser(String fileName){

                      SAXParserFactory spfactory =

                           SAXParserFactory.newInstance();                 

                                 

                      try{

                       SAXParser saxParser =

                                 spfactory.newSAXParser();

                       XMLReader reader=saxParser.getXMLReader();

                       reader.setContentHandler(new ElementHandler());

                       reader.parse(fileName);                 

                       returncurrentMachine;

                      }catch(Exception e){          

                       thrownew XmlConfigParseException("parsing is failed",e);

                      }    

                }

          }

          實現要點

          上述實現是通過SAX來進行XML解析的。

          1 將領域模型結構直接映射為XML元素的結構

          我們用這種方式來設計我們的DSL,這樣做的好處是DSL比較容易使用(更接近領域模型),同時解析程序也會相對簡單,比較容易生成相應的語義模型。

          2 使用上下文變量

          如上面程序中的:

          private Machine currentMachine;

          private State currentState;

          他們就是上下文變量,由于SAX是順序解析的,所以必須保持正確的工作上下文,如把生產Transition對象加入到正確的State中。

          2 自定義語言

          腳本文件

          Machine   (Auto-Door){

                         State(Open){

                                        Transition{

                                                       event : time-out ,

                                                       next-state : Close

                                        }             

                         }

                         State (Close){

                                        Transition{

                                                       event : people-closer ,

                                                       next-state : Open

                                        }

                         }

          }

          實現

          自己設計語法并實現解析器,通常需要我們具備一定的編譯原理知識并且借用一定的解析器生成工具來幫助我們生產解析器代碼。

          實現中本人使用了 Antlr

          Antlr的語法描述文件:

          grammar StateMachineG;

          @header {

          import org.ccsoft.statemachine.models.Machine;

          import org.ccsoft.statemachine.models.State;

          import org.ccsoft.statemachine.models.Transition;

          import org.ccsoft.statemachine.models.Event;

          }

          @members {

                         public void emitErrorMessage(String msg) {

                                        throw new RuntimeException(msg);

                                        //super.emitErrorMessage(msg);

                         }

          }

          machine returns [Machine value]               :              'Machine''('NAME')''{'{$value=new Machine($NAME.text);} (e=state{$value.getStates().add($e.value);})+'}';

          state returns [State value]             :              'State''('NAME')''{'{$value=new State($NAME.text);}(e=transition{$value.getTransitions().add($e.value);})+'}';

          transition returns [Transition value]

                         :              'Transition''{'{$value=new Transition();}e=event{$value.setEvent($e.value);}','f=nextState{$value.setNextState($f.value);}'}';

          event     returns [Event value] :     'event'':'e=NAME{$value=new Event($NAME.text);};

          nextState returns [String value]

                         :              'next-state'':'e=NAME{$value=$NAME.text;};

          NAME    :              ('a'..'z' |'A'..'Z'|'0'..'9')+   ;

          WS : (' ' |'"t' |'"n' |'"r' )+ {skip();} ;

          實現要點

          1 采用Antlr的內嵌Action

          對于DSL的通常應用即通過外部腳本生產相關部分語義模型對象,使用Antlr的內嵌Action比采用語法樹方式簡單得多。

          posted on 2009-08-25 16:24 超越巔峰 閱讀(1246) 評論(1)  編輯  收藏 所屬分類: DSL

          評論

          # re: DSL的實現要點(2) 2009-08-25 17:09 長生界

          帥哥你排個版啊  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          常用鏈接

          留言簿(12)

          隨筆分類(54)

          隨筆檔案(59)

          文章分類(2)

          文章檔案(1)

          相冊

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 石城县| 金沙县| 和林格尔县| 宜春市| 松滋市| 嵊泗县| 昌吉市| 顺昌县| 开原市| 宁远县| 区。| 光山县| 苍梧县| 澄城县| 潼关县| 怀柔区| 东乌| 德令哈市| 石林| 双柏县| 安仁县| 黄梅县| 浠水县| 南宫市| 台中县| 广平县| 德格县| 长宁区| 合作市| 东平县| 丰原市| 卢氏县| 伊宁县| 象山县| 乳山市| 津市市| 灵川县| 定结县| 伽师县| 平安县| 保山市|