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

第034回_Visitorの機能拡張2

»
前回の続きでEbnfVisitorに解析用の子クラスを作成していきます。
前回は、基本のパーサ用クラスの処理:BaseSyntaxParserVisitorを作成しました。
今回は、基本トークン用クラスの処理:BaseTokenSyntaxParserVisitorXMLトークン用クラスの処理:XmlTokenSyntaxParserVisitor
を作成します。基本トークンとXMLトークンを分けたのは、他のパーサに転用するときにメンテナンスを楽にするためです。

BaseTokenSyntaxParserVisitorの検討と実装

検討
XMLの基本ノードとトークンは、字句解析器の実装から
ノード:トークン
――――――――――――――――――――――
EbnfCommentNode:CommentToken
EbnfSymbolNode:SymbolToken
EbnfWhiteSpaceNode:WhiteSpaceToken
EbnfLimitedWordNode:WordToken
EbnfLimitedLiteralNode:LiteralToken
とします。

Visitorの実装

public abstract class BaseTokenSyntaxParserVisitor
                      extends BaseSyntaxParserVisitor
{
    public BaseTokenSyntaxParserVisitor()
    {
        super();
    }

    @Override
    public void visit(EbnfCommentNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }

    @Override
    public void visit(EbnfSymbolNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }

    @Override
    public void visit(EbnfWhiteSpaceNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }

    @Override
    public void visit(EbnfLimitedWordNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }
    
    
    @Override
    public void visit(EbnfLimitedLiteralNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }
}
Tokenの実装
文字列パターンがない場合:CommentToken、WhiteSpaceToken

public class CommentToken extends NonDocumentToken
{
    ・・・・
    
    //追加
    @Override
    public boolean match(EbnfCommentNode n)
    {
        TokenManager.getInstance().consumeToken();
        return true;
    }
}

文字列パターンがある場合:SymbolToken、WordToken、LiteralToken

public class LiteralToken extends NonDocumentToken
{
    ・・・・
    
    @Override
    public boolean match(EbnfLimitedLiteralNode n)
    {
        boolean retval = n.equals(m_str);

        if (retval)
        {
            TokenManager.getInstance().consumeToken();
        }
        else
        {
            //何もしない
        }
        
        return retval;
    }
}

XmlTokenSyntaxParserVisitorの検討と実装

検討
基本以外で構文に出てくるトークンは、字句解析器の実装から
ノード:トークン
――――――――――――――――――――――
EbnfPIWordNode:PIWordToken
EbnfPITargetNode:WordToken
EbnfSystemLiteralNode:LiteralToken
EbnfCharDataNode:CharDataToken
EbnfCDataNode:CDataToken
EbnfIgnoreNode:IgnoreWordToken
となるので、上記のノードを実装するXmlTokenSyntaxParserVisitorクラスを用意します。字句解析器の変更が必要なものはTokenManagerのnotifyメソッドで変更します。

実装

public abstract class XmlTokenSyntaxParserVisitor extends BaseTokenSyntaxParserVisitor
{
    public XmlTokenSyntaxParserVisitor()
    {
        super();
    }
    
    @Override
    public void visit(EbnfPIWordNode n)
    {
        m_tokenManager.notifyPIWordStart();
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        m_tokenManager.notifyPIWordEnd();
    }

    @Override
    public void visit(EbnfPITargetNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }

    @Override
    public void visit(EbnfSystemLiteralNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
    }

    @Override
    public void visit(EbnfCharDataNode n)
    {
        m_tokenManager.notifyCharDataStart();
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        m_tokenManager.notifyCharDataEnd();
    }

    @Override
    public void visit(EbnfCDataNode n)
    {
        m_tokenManager.notifyCDataStart();
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        m_tokenManager.notifyCDataEnd();
    }
    
    @Override
    public void visit(EbnfIgnoreNode n)
    {
        m_tokenManager.notifyIgnoreWordStart();
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        m_tokenManager.notifyIgnoreWordEnd();
    }
}
PIWordToken、CharDataToken、CDataToken、IgnoreWordTokenの実装は文字列パターンのない処理として実装します。(割愛)
Comment(0)

コメント

コメントを投稿する