第059回_一般実体テーブル作成処理の実装3
»
前回の続きで、検討したVisitorを実装します。
GettingNameVisitorの実装
工夫の内容を元にNameノードから値を取得するGettingNameVisitorを実装します。実装は次のようにできます。
public class GettingNameVisitor extends SyntaxParserVisitor
{
private String m_name;
public GettingNameVisitor()
{
m_name = null;
}
public String getName()
{
return m_name;
}
@Override
public void visit(EbnfNameNode n)
{
Token token = m_tokenManager.nextToken();
m_result = token.match(n);
if(m_result)
{
//処理に成功したので巡回用データに登録する
m_name = token.getString();
}
else
{
//何もしない
}
}
}
EntityValueVisitorの実装
CharRefVisitorとGettingNameVisitorの実装を元に EntityValueVisitorの実装は次のようになります。public class EntityValueVisitor extends SyntaxParserVisitor
{
private static EntityReferenceHelper m_EntityRefHelper
= EntityReferenceHelper.getInstance();
//PE実体のシンボルテーブルヘルパー
private static PeReferenceHelper m_peRefHelper
= PeReferenceHelper.getInstance();
private String m_value;
public EntityValueVisitor()
{
m_value = "";
}
public String getValue()
{
return m_value;
}
@Override
public void visit(EbnfEvCharRefNode n)
{
CharRefVisitor v = new CharRefVisitor();
v.visit(n);
m_result = v.getResult();
if(m_result)
{
m_value += v.getValue();
}
else
{
//何もしない
}
}
@Override
public void visit(EbnfNormalTokenB1Node n)
{
Token token = m_tokenManager.nextToken();
m_result = token.match(n);
if(m_result)
{
//巡回用データに文字列を追加する
m_value +=token.getString();
}
else
{
//何もしない
}
}
@Override
public void visit(EbnfNormalTokenB2Node n)
{
Token token = m_tokenManager.nextToken();
m_result = token.match(n);
if(m_result)
{
//巡回用データに文字列を追加する
m_value +=token.getString();
}
else
{
//何もしない
}
}
@Override
public void visit(EbnfEvEntityRefNode n)
{
GettingNameVisitor v = new GettingNameVisitor();
v.visit(n);
m_result = v.getResult();
if(m_result)
{
String entityRefName = v.getName();
//巡回用データに文字列を追加する
m_value += m_EntityRefHelper.bypassInEntityValue(entityRefName);
}
else
{
//何もしない
}
}
@Override
public void visit(EbnfEvPEReferenceNode n)
{
GettingNameVisitor v = new GettingNameVisitor();
v.visit(n);
m_result = v.getResult();
if(m_result)
{
String peRefName = v.getName();
//置換文字列を取得する
String text =
m_peRefHelper.getReplacementTextInEntityValue(peRefName);
//巡回用データに文字列を追加する
m_value+=text;
}
else
{
//何もしない
}
}
}
EntityReferenceHelperの実装
EntityValueVisitorに出てきたEntityReferenceHelperは一般実体の参照の処理の違いを表現するクラスです。EntityValueで一般実体参照を認識したときの処理
2.一般実体の参照を認識したとき(修正なし)
2-1.参照名を参照チェックテーブルに登録する
2-2.バイパスする(何もしない)
を実装すると、次のようになります。
public class EntityReferenceHelper
{
private static EntityReferenceHelper m_instance
= new EntityReferenceHelper();
//実体の参照をチェックするテーブル
private static EntityReferenceCheckSet m_checkTable
= EntityReferenceCheckSet.getInstance();
private EntityReferenceHelper()
{
}
public static EntityReferenceHelper getInstance()
{
return m_instance;
}
public String bypassInEntityValue(String refName)
{
//チェックテーブルに参照値を追加する
m_checkTable.add(refName);
return "&"+refName+";";
}
}
EntityReferenceCheckSetの実装
EntityReferenceCheckSetは検討の中に出てきた一般実体の参照をチェックするテーブル(セット)です。登録部分のみを実装すると、次のようになります。public class EntityReferenceCheckSet
{
private static EntityReferenceCheckSet
m_instance = new EntityReferenceCheckSet();
//実体のシンボルテーブル
private static GeTable m_table = GeTable.getInstance();
//チェックセット
HashSet<String> m_set;
private EntityReferenceCheckSet()
{
m_set = new HashSet<String>();
}
public static EntityReferenceCheckSet getInstance()
{
return m_instance;
}
public void add(String refName)
{
m_set.add(refName);
}
}
PeReferenceHelperの実装
EntityValueVisitorで使っているPeReferenceHelperについて説明します。PeReferenceHelperはパラメータ実体参照の、出現位置による処理の違いを表現するクラスです。
EntityValueでパラメータ実体参照を認識したときの処理
3.パラメータ実体の参照を認識したとき(修正あり)
3-1.実体名をキーにパラメータ実体テーブルを検索する
3-2.実体名がテーブルに無い場合
3-2-1.スタンドアロン文書宣言がyesのとき
3-2-1-1.★仕様なし
3-2-2.スタンドアロン文書宣言がnoのとき
3-2-2-1.外部サブセットが無い場合
3-2-2-1-1.★仕様なし
3-2-2-2.外部サブセットが有る場合
3-2-2-2-1.妥当性制約違反エラー
3-3.実体名がテーブルに有る場合
3-3-1.再帰用のスタックに実体名を追加する
3-3-2.置換テキストRepTextを取得する
3-3-3.RepTextをReplacementTextで構文解析する
3-3-4.パラメータ実体のトークン列の代わりに構文解析したトークン列を返す
を実装すると、次のようになります。
public class PeReferenceHelper
{
//シングルトンパターン
private static PeReferenceHelper m_instance
= new PeReferenceHelper();
//パラメータ実体のシンボルテーブル
private static PeTable m_peTable = PeTable.getInstance();
//整形式制約をチェックするためのスタック
private static NoRecursionPeEntityNameStack m_entityNameStack
= NoRecursionPeEntityNameStack.getInstance();
//トークンマネージャ
private static TokenManager m_tokenManager
= TokenManager.getInstance();
//XMLDeclの内容
private static XmlDeclData m_xmldecl = XmlDeclData.getInstance();
//DOCTYPE宣言の内容
private static DoctypeData m_doctype = DoctypeData.getInstance();
//EBNFデータツリー replacementText
private static EbnfNodeAcceptor m_replacementText
= SyntaxTree.getInstance().getReplacementText();
private PeReferenceHelper()
{
}
public static PeReferenceHelper getInstance()
{
return m_instance;
}
public String getReplacementTextInEntityValue(String refName)
{
String retval = null;
//パラメータ参照テーブルから置換テキストを取得する
String replacementStr = m_peTable.getData(refName);
//実体名がテーブルに無い場合
if (replacementStr == null)
{
//スタンドアロン文書宣言を取得する
boolean standalone_yes = m_xmldecl.isStandalone();
//スタンドアロン文書宣言がyesのとき
if (standalone_yes)
{
//TODO:仕様を決める
}
//スタンドアロン文書宣言がnoのとき
else
{
boolean hasExtSubset = m_doctype.hasExtSubset();
//外部サブセットが無い場合
if (!hasExtSubset)
{
//TODO:仕様を決める
}
//外部サブセットが有る場合
else
{
//TODO 妥当性制約違反エラー
}
}
}
//実体名がテーブルに有る場合
else
{
//再帰用のスタックにpushする
m_entityNameStack.push(refName);
//コンテキストを切り替える
m_tokenManager.setNewString(refName, replacementStr);
{
MakingReplacementTextVisitor v
= new MakingReplacementTextVisitor();
//置換テキストの構文を構文解析する
m_replacementText.accept(v);
//置換テキストの構文解析済みの文字列を取得する
retval = v.getText();
}
//スタックにつんでいたものを除去する
m_tokenManager.finalize();
m_entityNameStack.pop();
}
return retval;
}
}
ここで、ReplacementTextの構文解析の前後に、第021回で説明したコンテキストの切り替えを実施しています。
DoctypedeclVisitor/DoctypeDataの修正
PeReferenceHelperで出てきた外部サブセットの有無情報の取得処理を第046回で実装したDoctypedeclVisitor/DoctypeDataに追加します。DoctypedeclVisitor
public class DoctypedeclVisitor extends SyntaxParserVisitor
{
・・・・
//追加
private ExternalID m_externalId;
・・・・
//修正
public DoctypedeclVisitor()
{
m_externalId = null;
}
・・・・
//追加
@Override
public void visit(EbnfDocExternalIDNode n)
{
ExternalIDVisitor v = new ExternalIDVisitor();
n.accept(v);
m_result = v.getResult();
if (m_result)
{
m_externalId = v.getExternalId();
m_doctypedata.setExtSubsetOn();
}
}
}
DoctypeData
public class DoctypeData
{
・・・・
//追加
private boolean m_hasExtSubset;
private DoctypeData()
{
・・・・
//追加
m_hasExtSubset = false;
}
public static DoctypeData getInstance()
{
return m_instance;
}
・・・・・
//追加
public void setExtSubsetOn()
{
m_hasExtSubset = true;
}
//追加
public boolean hasExtSubset()
{
return m_hasExtSubset;
}
}
ExternalIDの実装は、EntityValue内のExternalIDで工夫した部分です。Doctypedecl内でも処理用のEbnfDocExternalIDNodeを追加しています。
長くなりましたのでExternalIDの説明は次回にします。
コメント
コメントを投稿する
SpecialPR