2012年12月6日木曜日

一人Advent Calendar 5日目

5日目といいつつ6日の朝です。

4日目の記事も完成してないんですけどとりあえず5日目書きます。

1,2,3日とひたすらYAMLファイルを解析していたのですが実際はどうやって解析するかというのをJYamlのソースを少し見てみます。

Yamlの解析はデータの種類を把握しないといけないので流れしては

1 データ読み込み

2 データ構造理解

3 データを理解した構造に合わせて変換

でいいと思います

今回は
 
 Yaml.load(new File("test.yml"));
を呼び出したとして処理を追ってみます。

まずはYamlクラスのloadメソッドです
 
public static YamlConfig config = YamlConfig.getDefaultConfig();

public static Object load(File file) throws FileNotFoundException{
   return config.load(file);
}
loadメソッドは様々な引数に対応してましたが、今回はFileを引数に取るのだけを追っていきます。
YamlConfigのloadメソッドに処理を委譲しているようなのでそちらへ。

YamlConfig
 
public Object load(File file) throws FileNotFoundException{
  return load(new YamlDecoder(new FileInputStream(file), this));
}

public Object load(YamlDecoder dec){
  dec.setConfig(this);
  Object ret = null;
  try {
    ret = dec.readObject();
  } catch (EOFException e) {}
  return ret;
}

どうやらloadメソッドにYamlDecoder以外の引数を渡すとYamlConfigクラスの中でYamlDecoderに変換してYamlDecoderを使ってloadを行っているみたいです。
どうやら複数データをシリアライズしている時と1つのデータをシリアライズしている時で呼ぶ方は違っても結局内部では同じメソッド使ってるみたいです。
(落ち着いて考えたら当たり前だった・・・)

次はYamlDecoderクラスのreadObjectメソッドですね。(setConfigメソッドはYamlConfigを渡してYamlDecoderクラスから参照できるようにしているだけだったので省略)

YamlDecoderクラス
 
public Object readObject() throws EOFException{
  try {
    JYamlParserEvent event = new JYamlParserEvent(createLogger(), this);
    if (parser == null){
      parser = new YamlParser(in,event);
      firstDocument(parser, event);
    }else{
      parser.setEvent(event);
      if (!nextDocument(parser, event))
        throw new EOFException();
    }
    
    Object ret = event.getBean();
    
    if (ret == null)
      throw new YamlException("Document is empty.");
    return ret;
  
  } catch (EOFException e) {
    throw e;
  } catch (YamlException e){
    e.setLineNumber(parser.getLineNumber());
    hrow e;
  }
}
最初に呼ばれた時、YamkParserを初期化してfirstDocumentメソッドをそれ以外はnextDocumentメソッドを呼ぶ出しているみたいです。
解析としてはやっていることは同じはずなのでfirstDocument側だけ追います
 
void firstDocument(YamlParser p, YamlParserEvent event){
  try {
    while (p.comment(-1,false));
            
    if (!p.header())
      p.document_first();
    else
      p.value_na(-1);
    }catch (SyntaxException e){
      event.error(e,e.line);
    }catch (IOException e){
      throw new YamlException(e);
    }
}
ここから先はすべてメソッド追っていくと長くなるのでそれぞれのメソッドでなにをしていたかだけ書いていきます、まずはcommentでコメントかどうか判定します。またコメントの前にもtabが使われていたらエラーがでるようになってました。

headerメソッドは---から始まるかどうかを判定してました。


まだここまでしか見れてないですが、ここから先は実際にデータを読み込んで解析してデータを指定されている構造に直せば解析は終わりだと思います。
とりあえず今日はここまでで。

0 件のコメント:

コメントを投稿