第028回_条件付字句解析器4_AttValue系Lexer_JustCreateSymbolTokenizer他
»
コラムニストの中で「いいね!」の数が底辺の相転移炉です。こんにちは。
ソースコードを載せてるだけで分析が少ないので手抜き回に見えるかも・・・と思いつつ、第032回まで(8月28日分まで)この流れが続きます。
今がダメに見えても後で見返すときに見やすいはず...と筆者は思っていますが、ご意見・ご感想がある場合は参考にさせていただきますのでお気軽にコメントしていただけたらと思います。
それでは本文へ。
今回は、AttValueを字句解析する字句解析器を検討します。
ソースコードを載せてるだけで分析が少ないので手抜き回に見えるかも・・・と思いつつ、第032回まで(8月28日分まで)この流れが続きます。
今がダメに見えても後で見返すときに見やすいはず...と筆者は思っていますが、ご意見・ご感想がある場合は参考にさせていただきますのでお気軽にコメントしていただけたらと思います。
それでは本文へ。
今回は、AttValueを字句解析する字句解析器を検討します。
字句解析器が必要な部分の洗い出し
第007回の内容から、
を分類しましたので、DoubleQuoteLexer,QuoteLexer,AttValueDoubleQuoteSectionLexer,AttValueQuoteSectionLexerを実装します。
AttValue ::= AttValueDoubleQuote | AttValueQuote
AttValueDoubleQuote ::= DoubleQuoteStart AttValueDoubleQuoteSection
DoubleQuoteStart ::= '"'
AttValueDoubleQuoteSection ::= (NORMAL_TOKEN_A1 | Reference)* '"'
AttValueQuote ::= QuoteStart AttValueQuoteSection
Quote ::= "'"
AttValueQuoteSection ::= (NORMAL_TOKEN_A2 | Reference)* "'"
と構文を整理し、AttValueDoubleQuote ::= DoubleQuoteStart AttValueDoubleQuoteSection
DoubleQuoteStart ::= '"'
AttValueDoubleQuoteSection ::= (NORMAL_TOKEN_A1 | Reference)* '"'
AttValueQuote ::= QuoteStart AttValueQuoteSection
Quote ::= "'"
AttValueQuoteSection ::= (NORMAL_TOKEN_A2 | Reference)* "'"
No. | 条件 | トークン一覧 |
――――――――――――――――――――――――――――――――――――― | ||
05 | DoubleQuoteを構文解析している | SYMBOL ('"') |
06 | Quoteを構文解析している | SYMBOL ("'") |
07 | AttValueDoubleQouteSectionを構文解析している | NORMAL_TOKEN_A1, |
SYMBOL ('&'), | ||
SYMBOL ('&#') | ||
SYMBOL ('&#x') | ||
08 | AttValueQouteSectionを構文解析している | NORMAL_TOKEN_A2 |
SYMBOL ('&'), | ||
SYMBOL ('&#') | ||
SYMBOL ('&#x') |
DoubleQuoteLexerの実装
public class DoubleQuoteLexer extends MapSwitchLexer
{
private static final DoubleQuoteLexer
m_instance = new DoubleQuoteLexer();
private DoubleQuoteLexer()
{
//次の文字 処理
//-----------------------------------------------------------------------------------------
//'"' 初期化して、"だけのSymbolTokenを作成する
//その他 初期化して、残りの文字列をすべてを使って
// UnknownTokenを作成する
//EOF EofTokenを作成する
Init_MovePos
symbol = new Init_MovePos(new JustCreateSymbolTokenizer());
Init_MovePos
unknown = new Init_MovePos(new UnknownTokenizer());
EofTokenizer eof = new EofTokenizer();
m_map.put('"', symbol);
m_map.setOutOfRange(unknown);
m_map.setEofFunctor(eof);
}
public static DoubleQuoteLexer getInstance()
{
return m_instance;
}
}
DoubleQuoteLexerで必要なTokenizerの実装
DoubleQuoteLexerで出現した未解説のクラスについて紹介しておきます。中身は単純ですので細かい説明をしなくても良いと思います。
■JustCreateSymbolTokenizer
■UnknownTokenizer
■EofTokenizer
■JustCreateSymbolTokenizer
public class JustCreateSymbolTokenizer extends TermTokenizer
{
public JustCreateSymbolTokenizer(){}
@Override
public Token tokenize(StringBuilder str, int pos)
{
return new SymbolToken();
}
}
public class UnknownTokenizer extends TermTokenizer
{
public UnknownTokenizer(){}
@Override
public Token tokenize(StringBuilder str, int pos)
{
//バッファの残りすべてをトークンとする
m_tokenBuilder.update(str.substring(pos));
return new UnknownToken();
}
}
public class EofTokenizer extends TermTokenizer
{
public EofTokenizer(){}
@Override
public Token tokenize(StringBuilder str, int pos)
{
return new EofToken();
}
}
QuoteLexerの実装
public class QuoteLexer extends MapSwitchLexer
{
private static final QuoteLexer m_instance = new QuoteLexer();
private QuoteLexer()
{
//次の文字 処理
//-----------------------------------------------------------------------------------------
//"'" 初期化して、'だけのSymbolTokenを作成する
//その他 初期化して、残りの文字列をすべてを使って
// UnknownTokenを作成する
//EOF EofTokenを作成する
Init_MovePos
symbol = new Init_MovePos(new JustCreateSymbolTokenizer());
Init_MovePos
unknown = new Init_MovePos(new UnknownTokenizer());
EofTokenizer eof = new EofTokenizer();
m_map.put('\'', symbol);
m_map.setOutOfRange(unknown);
m_map.setEofFunctor(eof);
}
public static QuoteLexer getInstance()
{
return m_instance;
}
}
AttValueDoubleQuoteSectionLexerの実装
public class AttValueDoubleQuoteSectionLexer extends MapSwitchLexer
{
private static final AttValueDoubleQuoteSectionLexer
m_instance = new AttValueDoubleQuoteSectionLexer();
private AttValueDoubleQuoteSectionLexer()
{
super();
//記号 処理
//---------------------------------------------------------------
//'"' 初期化して、JustCreateSymbolTokenizerへ移動する
//'&' 初期化して、SymbolListTokenizer2(#x,#)へ移動する
//'<' 初期化して、UnknownTokenizerへ移動する
//その他 初期化して、NormalTokenA1Tokenizerへ移動する
//EOF EOFを作成する
Init_MovePos oneCharSymbol
= new Init_MovePos(new JustCreateSymbolTokenizer());
Init_MovePos normalTokenA1Tokenizer
= new Init_MovePos(new NormalTokenA1Tokenizer());
ArrayList<String> list = new ArrayList<String>();
list.add("#x");// 先に#xを評価しないと#でOKになってしまうので注意
list.add("#");
Init_MovePos ampersandTokenizer
= new Init_MovePos(new SymbolListTokenizer2(list));
Init_MovePos unknownTokenizer
= new Init_MovePos(new UnknownTokenizer());
EofTokenizer eof = new EofTokenizer();
m_map.put('"' , oneCharSymbol);
m_map.put('&' , ampersandTokenizer);
m_map.put('<' , unknownTokenizer);
m_map.setOutOfRange(normalTokenA1Tokenizer);
m_map.setEofFunctor(eof);
}
public static AttValueDoubleQuoteSectionLexer getInstance()
{
return m_instance;
}
}
SymbolListTokenizer系の実装
AttValueDoubleQuoteSectionLexerで出現した未解説のクラスSymbolListTokenizer2について紹介しておきます。
SymbolListTokenizer2は、指定した文字列リストのいずれかに合致する場合は1文字目に続いてそれらを含めてSymbolTokenを生成します。もしリストのいずれの文字列にも合致しなかった場合、最初の1文字だけのSymbolTokenを作成します。
ここには出てきませんが、SymbolListTokenizerはもしリストのいずれの文字列にも合致しなかった場合UnkwnownTokenを作成します。
SymbolListTokenizerとSymbolListTokenizer2はよく似ているので共通の親クラスAbstractSymbolListTokenizerを作成します。
■AbstractSymbolTokenizer
この処理はMapではなくif文の分岐で処理しています。
■SymbolListTokenizer
■SymbolListTokenizer2
SymbolListTokenizer2は、指定した文字列リストのいずれかに合致する場合は1文字目に続いてそれらを含めてSymbolTokenを生成します。もしリストのいずれの文字列にも合致しなかった場合、最初の1文字だけのSymbolTokenを作成します。
ここには出てきませんが、SymbolListTokenizerはもしリストのいずれの文字列にも合致しなかった場合UnkwnownTokenを作成します。
SymbolListTokenizerとSymbolListTokenizer2はよく似ているので共通の親クラスAbstractSymbolListTokenizerを作成します。
■AbstractSymbolTokenizer
この処理はMapではなくif文の分岐で処理しています。
public abstract class AbstractSymbolListTokenizer extends TermTokenizer
{
private final ArrayList<String> m_targetList;
public AbstractSymbolListTokenizer(ArrayList<String> targetList)
{
m_targetList = targetList;
}
@Override
public Token tokenize(StringBuilder str, int pos)
{
Token retval = null;
for(String target : m_targetList)
{
//Symbolの文字列の末尾位置+1を取得する
int endIndex = pos + target.length();
//対象バッファの残り文字数を取得する
int len = str.length();
//Symbolの文字長が残り文字数以下の場合
if (endIndex <= len)
{
//対象分の文字を取得する
//memo
// 取得するのはendIndex-1まで
String sub = str.substring(pos, endIndex);
//対象文字と一致する場合
if (sub.equals(target))
{
m_tokenBuilder.update(sub);
retval = new SymbolToken();
//ループを終了する
break;
}
//対象文字と一致しない場合
else
{
//何もしない
}
}
//Symbolの文字長が残り文字数より長い場合
else
{
//何もしない
}
}
//一致するものがなかった場合
if (retval == null)
{
retval = makeTokenIfUnmatch();
}
return retval;
}
protected abstract Token makeTokenIfUnmatch();
}
public class SymbolListTokenizer extends AbstractSymbolListTokenizer
{
public SymbolListTokenizer(ArrayList<String> target)
{
super(target);
}
protected Token makeTokenIfUnmatch()
{
return new UnknownToken();
}
}
public class SymbolListTokenizer2 extends AbstractSymbolListTokenizer
{
public SymbolListTokenizer2(ArrayList<String> target)
{
super(target);
}
protected Token makeTokenIfUnmatch()
{
return new SymbolToken();
}
}
NormalTokenA1Tokenizerの実装
実装はNormalTokenA1Tokenizerと後述するNormalTokenA2Tokenizerでほぼ同じなので、共通部分を抽象クラスNormalTokenATokenizerとして用意します。
■NormalTokenATokenizer
■NormalTokenA1Tokenizer
■NormalTokenATokenizer
public abstract class NormalTokenATokenizer extends MapSwitchTokenizer
{
private class NormalTokenMaker implements Functor
{
public NormalTokenMaker(){}
@Override
public Token tokenize(StringBuilder str, int pos)
{
return makeToken();
}
}
public NormalTokenATokenizer(char endChar)
{
super();
NormalTokenMaker ntm = new NormalTokenMaker();
Update_MovePos rm = new Update_MovePos();
//記号 処理
//----------------------------------------------
//endChar 今の文字を含めずに、NORMAL_TOKEN_Aを作成する
//'<' 今の文字を含めずに、NORMAL_TOKEN_Aを作成する
//'&' 今の文字を含めずに、NORMAL_TOKEN_Aを作成する
//その他 今の文字を確定して、次へ
//EOF NORMAL_TOKEN_Aを作成する
//
m_map.put(endChar , ntm);
m_map.put('<' , ntm);
m_map.put('&' , ntm);
m_map.setOutOfRange(rm);
m_map.setEofFunctor(ntm);
}
protected abstract Token makeToken();
}
public class NormalTokenA1Tokenizer extends NormalTokenATokenizer
{
public NormalTokenA1Tokenizer()
{
super('\"');
}
protected Token makeToken()
{
return new NormalTokenA1Token();
}
}
AttValueQuoteSectionLexerの実装
public class AttValueQuoteSectionLexer extends MapSwitchLexer
{
private static final AttValueQuoteSectionLexer
m_instance = new AttValueQuoteSectionLexer();
private AttValueQuoteSectionLexer()
{
super();
//記号 UniCode 処理
//-----------------------------------------------------------------------------------------
//"'" 初期化して、JustCreateSymbolTokenizerへ移動する
//'&' 初期化して、SymbolListTokenizer2(#x,#)へ移動する
//'<' 初期化して、UnknownTokenizerへ移動する
//' ' #xu0009 初期化して、WhiteSpaceTokenizerへ移動する
//'\r' 初期化して、WhiteSpaceTokenizerへ移動する
//'\n' 初期化して、WhiteSpaceTokenizerへ移動する
//' ' #xu0020 初期化して、WhiteSpaceTokenizerへ移動する
//その他 ------ 初期化して、NormalTokenA2Tokenizerへ移動する
//EOF EOFを作成する
Init_MovePos oneCharSymbol
= new Init_MovePos(new JustCreateSymbolTokenizer());
Init_MovePos normalTokenA2Tokenizer
= new Init_MovePos(new NormalTokenA2Tokenizer());
ArrayList<String> list = new ArrayList<String>();
list.add("#x");// 先に#xを評価させないと#でOKになってしまうので注意
list.add("#");
Init_MovePos ampersandTokenizer
= new Init_MovePos(new SymbolListTokenizer2(list));
Init_MovePos whiteSpaceTokenizer
= new Init_MovePos(new WhiteSpaceTokenizer());
Init_MovePos unknownTokenizer
= new Init_MovePos(new UnknownTokenizer());
EofTokenizer eof = new EofTokenizer();
m_map.put('\'' , oneCharSymbol);
m_map.put('&' , ampersandTokenizer);
m_map.put('<' , unknownTokenizer);
m_map.put('\u0009' , whiteSpaceTokenizer);
m_map.put('\r' , whiteSpaceTokenizer);
m_map.put('\n' , whiteSpaceTokenizer);
m_map.put('\u0020' , whiteSpaceTokenizer);
m_map.setOutOfRange(normalTokenA2Tokenizer);
m_map.setEofFunctor(eof);
}
public static AttValueQuoteSectionLexer getInstance()
{
return m_instance;
}
}
NormalTokenA2Tokenizerの実装
public class NormalTokenA2Tokenizer extends NormalTokenATokenizer
{
public NormalTokenA2Tokenizer()
{
super('\'');
}
protected Token makeToken()
{
return new NormalTokenA2Token();
}
}
コメント
コメントを投稿する
SpecialPR