本家「@IT」にはない内容をエンジニアライフで技術紹介するコラム。広く議論する場になることを目指します。

第032回_条件付字句解析器8_PISectionLexer_PITokenizer他

»
今回はPI_WORDの字句解析器PISectionLexerを実装します。
これまでの内容を理解していれば問題ないと思いますので、解説はほとんどしません。

PISectionLexerの実装

構文のおさらい
 PI_WORD ::= (Char* - (Char* '?>' Char*)
 Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
つまり、
 PI_WORD ::= Char かつ "?>" を含まない文字列
です。

実装

public class PISectionLexer extends MapSwitchLexer
{
    private static final PISectionLexer m_instance = new PISectionLexer();
    
    private PISectionLexer()
    {
        //  記号   Unicode      処理
        //  -----------------------------------------------------
        //  char   0001-003E    PITokenizerへ
        //  ?      003F         PITokenizer2へ
        //  char   0040-D7FF    PITokenizerへ
        //  char   E000-FFFD    PITokenizerへ
        //  その他              UnkonownTokenを作成する
        //  EOF                 EofTokenを作成する
        Init_MovePos  pi1
                    = new Init_MovePos(new PITokenizer());
        MovePos       pi2
                    = new MovePos(new PITokenizer2());
        Init_MovePos  unknownTokenizer
                    = new Init_MovePos(new UnknownTokenizer());
        EofTokenizer  eof
                    = new EofTokenizer();
        
        m_map.put('\u0001', '\u003E', pi1);
        m_map.put('\u003F',           pi2);
        m_map.put('\u0040', '\uD7FF', pi1);
        m_map.put('\uE000', '\uFFFD', pi1);
        m_map.setOutOfRange(unknownTokenizer);
        m_map.setEofFunctor(eof);
    }

    public static PISectionLexer getInstance()
    {
        return m_instance;
    }
}

PITokenizerの実装


public class PITokenizer extends MultipleMapsSwitchTokenizer
{
    private class PIWordTokenMaker implements Functor
    {
        public PIWordTokenMaker()
        {
        }
        
        @Override
        public Token tokenize(StringBuilder str, int pos)
        {
            return new PIWordToken();
        }
    }
    
    protected final PIWordTokenMaker m_piWordMaker;
    
    public PITokenizer()
    {
        super();
        
        m_piWordMaker = new PIWordTokenMaker();
        
        makeMap_A();
        makeMap_B();
    }

    private void makeMap_A()
    {
        //A (1文字前は確定)
        //
        //  記号   Unicode      処理
        //  -----------------------------------------------------
        //  char 0001-003E    今の文字を確定する
        //  ?    003F         未確定でB
        //  char 0040-D7FF    今の文字を確定する
        //  char E000-FFFD    今の文字を確定する
        //  それ以外          PI_WORDを作成する
        //  EOF               PI_WORDを作成する
        //
        //  処理1:今の文字を確定する
        //  処理2:未確定でB
        //  処理3:PI_WORDを作成する

        LexicalMap map = new LexicalMap();
        
        Update_MovePos  proc1 = new Update_MovePos(this);
        MovePos_MoveMap proc2 = new MovePos_MoveMap(1);
        //              proc3 = m_piWordMaker

        map.put('\u0001', '\u003F', proc1);
        map.put('?', proc2);
        map.put('\u0040', '\uD7FF', proc1);
        map.put('\uE000', '\uFFFD', proc1);
        map.setOutOfRange(m_piWordMaker);
        map.setEofFunctor(m_piWordMaker);
        m_mapList.add(map);
    }

    private void makeMap_B()
    {
        //B (1文字前?で未確定)
        //
        //  記号   Unicode      処理
        //  -----------------------------------------------------
        //  char  0001-003D    1文字前、今の文字を確定してA
        //  >     003E         PI_WORdを作成する
        //  char  003F-D7FF    1文字前、今の文字を確定してA
        //  char  E000-FFFD    1文字前、今の文字を確定してA
        //  それ以外           1文字前を確定してPI_WORDを作成する
        //  EOF                1文字前を確定してPI_WORDを作成する
        //
        //  処理1:今の1文字前、今の文字を確定してA字を確定する
        //  処理2:PI_WORDを作成する
        // 処理3:1文字前を確定してPI_WORDを作成する

        LexicalMap map = new LexicalMap();

        UpdateRange_MovePos_MoveMap
                proc1 = new UpdateRange_MovePos_MoveMap(0,1,0);
        //      proc2 = m_piWordMaker
        UpdateRange_MovePos
                proc3 = new UpdateRange_MovePos(m_piWordMaker, 1,1);

        map.put('\u0001', '\u003D', proc1);
        map.put('>', m_piWordMaker);
        map.put('\u003F', '\uD7FF', proc1);
        map.put('\uE000', '\uFFFD', proc1);
        map.setOutOfRange(proc3);
        map.setEofFunctor(proc3);
        m_mapList.add(map);
    }
}

PITokenizer2の実装


public class PITokenizer2 extends PITokenizer
{
    private class EmptyPIWordTokenMaker implements Functor
    {
        public EmptyPIWordTokenMaker()
        {
        }
        
        @Override
        public Token tokenize(StringBuilder str, int pos)
        {
            m_tokenBuilder.initStart();
            return new PIWordToken();
        }
    }
    
    private final EmptyPIWordTokenMaker m_emptyPiWordMaker;
    
    public PITokenizer2()
    {
        super();
        
        m_emptyPiWordMaker = new EmptyPIWordTokenMaker();
        
        m_index = 2;

        makeMap_C();
    }

    private void makeMap_C()
    {
        //C (tokenBuilder.initStartしていない、1文字前?で未確定)
        //
        //  記号   Unicode      処理
        //  -----------------------------------------------------
        //  char 0001-003D    初期化、1文字前、今の文字を確定してA
        //  >    003E         初期化、空のPI_WORdを作成する
        //  char 003F-D7FF    初期化、1文字前、今の文字を確定してA
        //  char E000-FFFD    初期化、1文字前、今の文字を確定してA
        //  それ以外          初期化、1文字前の文字を確定して
        //                      PI_WORDを作成する
        //  EOF               初期化、1文字前の文字を確定して
        //                      PI_WORDを作成する
        //
        //  処理1:初期化、1文字前、今の文字を確定してA
        //  処理2:初期化、空のPI_WORdを作成する
        //  処理3:初期化、1文字前の文字を確定してPI_WORDを作成する

        LexicalMap map = new LexicalMap();
        
        InitUpdateRange_MovePos_MoveMap
             proc1 = new InitUpdateRange_MovePos_MoveMap(0,1,0);
        //   proc2 = m_emptyPiWordMaker
        InitUpdateRange_MovePos
             proc3 = new InitUpdateRange_MovePos(m_piWordMaker,1,1);

        map.put('\u0001', '\u003D', proc1);
        map.put('>', m_emptyPiWordMaker);
        map.put('\u003F', '\uD7FF', proc1);
        map.put('\uE000', '\uFFFD', proc1);
        map.setOutOfRange(proc3);
        map.setEofFunctor(proc3);
        m_mapList.add(map);
    }
}
Comment(0)

コメント

コメントを投稿する