第026回_条件付字句解析器2_CDataLexer_CDataTokenizer
»
今回は、CDATA_WORDの字句解析器を検討します。
CDataを字句解析するCDataLexerの検討
CDataの構文を確認した上で検討に入ります。
■CDataの構文
■CDataの構文
[20] CData ::= (Char* − (Char* ']]>' Char*))
つまり、
CDATA_WORD ::= "]]>" を含まないCharの文字列
また、Char*とあるので0文字の場合もありえます。
■1文字目における処理分岐つまり、
CDATA_WORD ::= "]]>" を含まないCharの文字列
また、Char*とあるので0文字の場合もありえます。
CDataの範囲で1文字取得した場合、どのように処理するかを検討します。
まず、CDataは "]]>"を含まない Charの文字列ですから、1文字目にCharと"]"を取得した場合とその他の場合で分岐します。
まず、CDataは "]]>"を含まない Charの文字列ですから、1文字目にCharと"]"を取得した場合とその他の場合で分岐します。
記号 | UniCode | 処理 |
―――――――――――――――――――――――――――――――――――――― | ||
Char | #x0001-#x005C | 初期化して、CDataTokenizerへ移動する |
] | #x005D | 今の文字"]"を確定せず、次の文字に移動して、CDataTokenizer2へ移動する |
Char | #x005E-#xD7FF | 初期化して、CDataTokenizerへ移動する |
Char | #xE000-#xFFFD | 初期化して、CDataTokenizerへ移動する |
その他 | 空のCDataTokenを作成する | |
EOF | 空のCDataTokenを作成する |
CDataLexerの実装
ここまでの検討から実装は次のようになります。
public class CDataLexer extends MapSwitchLexer
{
private class CDataTokenMaker implements Functor
{
public CDataTokenMaker()
{
}
@Override
public Token tokenize(StringBuilder str, int pos)
{
m_tokenBuilder.initStart();
return new CDataToken();
}
}
private static final CDataLexer m_instance = new CDataLexer();
private CDataLexer()
{
//記号 UniCode 処理
//-----------------------------------------------------------------------------------------
//Char #x0001-#x005C 初期化して、CDataTokenizerへ移動する
//"]" #x005D 今の文字"]"を確定せず、
// 次の文字に移動して
// CDataTokenizer2へ移動する
//Char #x005E-#xD7FF 初期化して、CDataTokenizerへ移動する
// #xE000-#xFFFD 初期化して、CDataTokenizerへ移動する
//その他 ------ 空のCDataTokenを作成する
//EOF 空のCDataTokenを作成する
Init_MovePos
cDataTokenizer = new Init_MovePos(new CDataTokenizer());
MovePos
cDataTokenizer2 = new MovePos(new CDataTokenizer2());
CDataTokenMaker ctm = new CDataTokenMaker();
//0005Cはスラッシュ
m_map.put('\u0001', '\u005C\u005C', cDataTokenizer);
m_map.put('\u005D', cDataTokenizer2);
m_map.put('\u005E', '\uD7FF', cDataTokenizer);
m_map.put('\uE000', '\uFFFD', cDataTokenizer);
m_map.setOutOfRange(ctm);
m_map.setEofFunctor(ctm);
}
public static CDataLexer getInstance()
{
return m_instance;
}
}
CDataTokenizerの検討
CDataTokenizerで1文字目がCharの場合に2文字目以降に対して実施するトークナイザがCDataTokenizerです。
■表Aの処理(1つ前が確定している)
■表Aの処理(1つ前が確定している)
CDataTokenizerがスタート地点として使う表Aについて検討します。
■表Bの処理(一つ前が ]で未確定)記号 | UniCode | 処理 |
―――――――――――――――――――――――――――――――――――――― | ||
Char | #x0001-#x005C | 今の文字を確定する(次の文字も表Aで処理する) |
] | #x005D | 確定せずに次の文字のために表Bへ移動する |
Char | #x005E-#xD7FF | 今の文字を確定する(次の文字も表Aで処理する) |
Char | #xE000-#xFFFD | 今の文字を確定する(次の文字も表Aで処理する) |
その他 | CDataTokenを作成する | |
EOF | CDataTokenを作成する |
表Aで出てきた表Bについても検討すると、
となります。
■表Cの処理(2つ前が ]で未確定,1つ前が ]で未確定)記号 | UniCode | 処理 |
―――――――――――――――――――――――――――――――――――――― | ||
Char | #x0001-#x005C | 1つ前と今の文字を確定する。表Aへ移動する |
] | #x005D | 確定せずに次の文字のために表Cへ移動する |
Char | #x005E-#xD7FF | 1つ前と今の文字を確定する。表Aへ移動する |
Char | #xE000-#xFFFD | 1つ前と今の文字を確定する。表Aへ移動する |
その他 | 1つ前を確定する。CDataTokenを作成する | |
EOF | 1つ前を確定する。CDataTokenを作成する |
表Bで出てきた表Cについても検討すると、
となります。
記号 | UniCode | 処理 |
―――――――――――――――――――――――――――――――――――――― | ||
Char | #x0001-#x003D | 2つ前、1つ前、今の文字を確定する。表Aへ移動する |
> | #x003E | CDataTokenを作成する |
Char | #x003F-#xD05C | 2つ前、1つ前、今の文字を確定する。表Aへ移動する |
] | #xD05D | 2つ前を確定する。表Cへ移動する |
Char | #x005E-#xD7FF | 2つ前、1つ前、今の文字を確定する。表Aへ移動する |
Char | #xE000-#xFFFD | 2つ前、1つ前、今の文字を確定する。表Aへ移動する |
その他 | 2つ前、1つ前を確定する。CDataTokenを作成する | |
EOF | 2つ前、1つ前を確定する。CDataTokenを作成する |
CDataTokenizerの実装
先ほどの検討を元にCDataTokenizerを実装します。
public class CDataTokenizer extends MultipleMapsSwitchTokenizer
{
private class CDataTokenMaker implements Functor
{
public CDataTokenMaker()
{
}
@Override
public Token tokenize(StringBuilder str, int pos)
{
return new CDataToken();
}
}
protected final CDataTokenMaker m_ctm;
public CDataTokenizer()
{
m_ctm = new CDataTokenMaker();
makeMap_A();
makeMap_B();
makeMap_C();
}
private void makeMap_A()
{
LexicalMap map = new LexicalMap();
//表Aの処理(1つ前が確定している)
//次の文字 UniCode 処理
//-----------------------------------------------------------------------------------------
//Char #x0001-#x005C 今の文字を確定する
// (次の文字も表Aで処理する)
//"]" #x005D 確定せずに次の文字のために
// 表Bへ移動する
//Char #x005E-#xD7FF 今の文字を確定する
// (次の文字も表Aで処理する)
// #xE000-#xFFFD 今の文字を確定する
// (次の文字も表Aで処理する)
//その他 ------ CDataTokenを作成する
//EOF CDataTokenを作成する
Update_MovePos proc1 = new Update_MovePos(this);
MovePos_MoveMap proc2 = new MovePos_MoveMap(1);
map.put('\u0001', '\u005C\u005C', proc1);
map.put('\u005D', proc2);
map.put('\u005E', '\uD7FF', proc1);
map.put('\uE000', '\uFFFD', proc1);
map.setOutOfRange(m_ctm);
//EOFの場合
map.setEofFunctor(m_ctm);
m_mapList.add(map);
}
private void makeMap_B()
{
LexicalMap map = new LexicalMap();
//表Bの処理(一つ前が ]で未確定)
//次の文字 UniCode 処理
//-----------------------------------------------------------------------------------------
//Char #x0001-#x005C 1つ前と今の文字を確定する。
// 表Aへ移動する
//"]" #x005D 確定せずに次の文字のために
// 表Cへ移動する
//Char #x005E-#xD7FF 1つ前と今の文字を確定する。
// 表Aへ移動する
// #xE000-#xFFFD 1つ前と今の文字を確定する。
// 表Aへ移動する
//その他 ------ 1つ前を確定する。CDataTokenを作成する
//EOF 1つ前を確定する。CDataTokenを作成する
UpdateRange_MovePos_MoveMap
proc1 = new UpdateRange_MovePos_MoveMap(0,1,0);
MovePos_MoveMap proc2 = new MovePos_MoveMap(2);
UpdateRange_MovePos proc3 = new UpdateRange_MovePos(m_ctm,1,1);
map.put('\u0001', '\u005C\u005C', proc1);
map.put('\u005D', proc2);
map.put('\u005E', '\uD7FF', proc1);
map.put('\uE000', '\uFFFD', proc1);
map.setOutOfRange(proc3);
map.setEofFunctor(proc3);
m_mapList.add(map);
}
private void makeMap_C()
{
LexicalMap map = new LexicalMap();
//表Cの処理(2つ前が ]で未確定,1つ前が ]で未確定)
//次の文字 UniCode 処理
//-----------------------------------------------------------------------------------------
//Char #x0001-#x003D 2つ前、1つ前、今の文字を確定する。
// 表Aへ移動する
//">" #x003E CDataTokenを作成する
//Char #x003F-#x005C 2つ前、1つ前、今の文字を確定する。
// 表Aへ移動する
//"]" #x005D 2つ前を確定する。表Cへ移動する
//Char #x005E-#xD7FF 2つ前、1つ前、今の文字を確定する。
// 表Aへ移動する
// #xE000-#xFFFD 2つ前、1つ前、今の文字を確定する。
// 表Aへ移動する
//その他 ------ 2つ前、1つ前を確定する。
// CDataTokenを作成する
//EOF 2つ前、1つ前を確定する。
// CDataTokenを作成する
UpdateRange_MovePos_MoveMap
proc1 = new UpdateRange_MovePos_MoveMap(0,2,0);
// proc2 = m_ctm
UpdateRange_MovePos_MoveMap
proc3 = new UpdateRange_MovePos_MoveMap(2,2,2);
UpdateRange_MovePos proc4 = new UpdateRange_MovePos(m_ctm,2,1);
map.put('\u0001', '\u003D', proc1);
map.put('\u003E', m_ctm);
map.put('\u003F', '\u005C\u005C', proc1);
map.put('\u005D', proc3);
map.put('\u005E', '\uD7FF', proc1);
map.put('\uE000', '\uFFFD', proc1);
map.setOutOfRange(proc4);
map.setEofFunctor(proc4);
m_mapList.add(map);
}
}
CDataTokenizer2の検討
CDataLexerで1文字目が"]"の場合に、未初期化で2文字目以降に対して実施するトークナイザがCDataTokenizer2です。
■表Dの処理(初期化していない、1つ前が]で確定していない)
■表Eの処理(初期化していない、2つ前が]で確定していない、1つ前が]で確定していない)
■継承関係
CDataTokenizer2は表A(表Aの内部では表Bにも移動する)、表Cに移動する可能性があるためCDataTokenizerを継承します。
■表Dの処理(初期化していない、1つ前が]で確定していない)
記号 | UniCode | 処理 |
―――――――――――――――――――――――――――――――――――――― | ||
Char | #x0001-#x005C | 初期化する。1つ前と今の文字を確定させて表Aへ移動する | ] | #xD05D | 確定せずに表Eへ移動する |
Char | #x005E-#xD7FF | 初期化する。1つ前と今の文字を確定させて表Aへ移動する |
Char | #xE000-#xFFFD | 初期化する。1つ前と今の文字を確定させて表Aへ移動する |
その他 | 初期化する。1つ前を確定する。CDataTokenを作成する | |
EOF | 初期化する。1つ前を確定する。CDataTokenを作成する |
記号 | UniCode | 処理 |
―――――――――――――――――――――――――――――――――――――― | ||
Char | #x0001-#x003D | 初期化する。2つ前、1つ前、今の文字を確定する。表Aへ移動する |
> | #x003E | CDataTokenを作成する |
Char | #x003F-#xD05C | 初期化する。2つ前、1つ前、今の文字を確定する。表Aへ移動する |
] | #xD05D | 初期化する。2つ前を確定する。表Cへ移動する |
Char | #x005E-#xD7FF | 初期化する。2つ前、1つ前、今の文字を確定する。表Aへ移動する |
Char | #xE000-#xFFFD | 初期化する。2つ前、1つ前、今の文字を確定する。表Aへ移動する |
その他 | 初期化する。2つ前、1つ前を確定する。CDataTokenを作成する | |
EOF | 初期化する。2つ前、1つ前を確定する。CDataTokenを作成する |
CDataTokenizer2は表A(表Aの内部では表Bにも移動する)、表Cに移動する可能性があるためCDataTokenizerを継承します。
CDataTokenizer2の実装
先の検討から実装は次のようになります。
public class CDataTokenizer2 extends CDataTokenizer
{
private class EmptyCDataTokenMaker implements Functor
{
public EmptyCDataTokenMaker()
{
}
@Override
public Token tokenize(StringBuilder str, int pos)
{
m_tokenBuilder.initStart();
return new CDataToken();
}
}
private final EmptyCDataTokenMaker m_ectm;
public CDataTokenizer2()
{
super();
m_startIndex= 3;//(Dのmapから始める)
m_currentIndex = 3;
m_ectm = new EmptyCDataTokenMaker();
makeMap_D();
makeMap_E();
}
private void makeMap_D()
{
LexicalMap map = new LexicalMap();
//表Dの処理(初期化していない、1つ前が]で確定していない)
//次の文字 UniCode 処理
//-----------------------------------------------------------------------------------------
//Char #x0001-#x005C 1初期化する。1つ前と今の文字を確定させて
// 表Aへ移動する
//"]" #x005D 確定せずに表Eへ移動する
//Char #x005E-#xD7FF 初期化する。1つ前と今の文字を確定させて
// 表Aへ移動する
// #xE000-#xFFFD 初期化する。1つ前と今の文字を確定させて
// 表Aへ移動する
//その他 ------ 初期化する。1つ前を確定する。
// CDataTokenを作成する
//EOF 初期化する。1つ前を確定する。
// CDataTokenを作成する
InitUpdateRange_MovePos_MoveMap
proc1 = new InitUpdateRange_MovePos_MoveMap(0,1,0);
MovePos_MoveMap
proc2 = new MovePos_MoveMap(4);
InitUpdateRange_MovePos
proc3 = new InitUpdateRange_MovePos(m_ctm,1,1);
map.put('\u0001', '\u005C\u005C', proc1);
map.put('\u005D', proc2 );
map.put('\u005E', '\uD7FF', proc1);
map.put('\uE000', '\uFFFD', proc1);
map.setOutOfRange(proc3);
map.setEofFunctor(proc3);
m_mapList.add(map);
}
private void makeMap_E()
{
LexicalMap map = new LexicalMap();
//表Eの処理(初期化していない、2つ前が]で確定していない、1つ前が]で確定していない)
//次の文字 UniCode 処理
//-----------------------------------------------------------------------------------------
//Char #x0001-#x003D 初期化する。2つ前、1つ前、
// 今の文字を確定する。
// 表Aへ移動する
//">" #x003E CDataTokenを作成する
//Char #x003F-#x005C 初期化する。2つ前、1つ前、
// 今の文字を確定する。
// 表Aへ移動する
//"]" #x005D 初期化する。2つ前を確定する。
// 表Cへ移動する
//Char #x005E-#xD7FF 初期化する。2つ前、1つ前、
// 今の文字を確定する。
// 表Aへ移動する
// #xE000-#xFFFD 初期化する。2つ前、1つ前、
// 今の文字を確定する。
// 表Aへ移動する
//その他 ------ 初期化する。2つ前、1つ前を確定する。
// CDataTokenを作成する
//EOF 初期化する。2つ前、1つ前を確定する。
// CDataTokenを作成する
InitUpdateRange_MovePos_MoveMap
proc1 = new InitUpdateRange_MovePos_MoveMap(0,2,0);
// proc2 = m_ectm
InitUpdateRange_MovePos_MoveMap
proc3 = new InitUpdateRange_MovePos_MoveMap(2,2,2);
InitUpdateRange_MovePos
proc4 = new InitUpdateRange_MovePos(m_ctm,2,1);
map.put('\u0001', '\u003D', proc1);
map.put('\u003E', m_ectm);
map.put('\u003F', '\u005C\u005C', proc1);
map.put('\u005D', proc3);
map.put('\u005E', '\uD7FF', proc1);
map.put('\uE000', '\uFFFD', proc1);
map.setOutOfRange(proc4);
map.setEofFunctor(proc4);
m_mapList.add(map);
}
}
コメント
コメントを投稿する
SpecialPR