Representer内での正規化


本質的でない違いしかない解答が同じリプレゼンテーションになるように、リプレゼンターは正規化を適用すべきです。一般に、正規化されたリプレゼンテーションを作る流れは次のとおりです。

  • 解答のコードを解析して抽象構文木(AST)にする
  • ASTに正規化を適用する
  • 正規化したASTを文字列に変換する
  • 正規化したASTの文字列をrepresentation.txtという名前のファイルに書き出す(インターフェースを参照)

ただし、リプレゼンテーションは必ずしもASTである必要はありません。普通の(正規化された)コードでもよく、トラックにとって最適なものを選べばよいのです。

まずは手始めに、よく使われる正規化の方法をいくつか紹介します。

注意1:以下の正規化の例は互いに積み重なるものではなく、それぞれが1つの特定の正規化を示しているだけです。実際のリプレゼンターでは、これらを続けて適用することになります。

注意2:このガイドのコードはC#で書かれていますが、ガイドの内容は特定のプログラミング言語に依存しません。

識別子を正規化する

リプレゼンテーションが名前にとらわれないようにするために、ユーザーが定義した名前(変数や関数など)をプレースホルダーに置き換えることができます。この場合は、mapping.jsonを生成する必要があります(インターフェースを参照)。

重要なのは、スコープに関係なく、同じ名前はすべて同じプレースホルダーに置き換えなければならないという点です。

ソースコード

public static class Fake
{
    public static int Test(int input)
    {
        var test = input + 2;
        return test;
    }
}

リプレゼンテーション

public static class PLACEHOLDER_1
{
    public static int PLACEHOLDER_2(int PLACEHOLDER_3)
    {
        var PLACEHOLDER_4 = PLACEHOLDER_3 + 2;
        return PLACEHOLDER_4;
    }
}

空白を正規化する

空白のばらつきは非常によくあるため、その正規化は一般的な手順です。改行コードも正規化しておくべきです。

ソースコード

using   System;

     public static    class Fake
{
    public     static   DateTime Add    (DateTime    birthDate)
    {
        return birthDate.Add( TimeSpan.FromSeconds   (   10  ) )   ;
    }
}

リプレゼンテーション

public static class Fake
{
    public static DateTime Add(DateTime birthDate)
    {
        return birthDate.Add(TimeSpan.FromSeconds(10));
    }
}

ブロックを正規化する

多くの言語では、ブロック(スコープ)の書き方にいくらかの自由があります。たとえば、Cに似た言語の多くでは、スコープは波括弧で囲んで宣言します。通常、波括弧を同じ行に置くか次の行に置くかは問題ではないので、これを正規化できます。

ソースコード

public static class Fake {
    public static int Test() {
        if (1 > 2) {
            return 0;
        }

        return 1;
    }
}

リプレゼンテーション

public static class Fake
{
    public static int Test()
    {
        if (1 > 2)
        {
            return 0;
        }

        return 1;
    }
}

重要でないコードを削除する

コードのすべてがリプレゼンターにとって重要というわけではなく、重要でない部分は削除できます。たとえば、ほとんどの言語ではコメントは重要ではないので、安全に削除できます。

ソースコード

/*
   These are some very nice
   comments spanning multiple lines
*/
public static class Fake
{
    // Nice method
    public static string Test()
    {
        return "Test"; // This is very nice
    }
}

リプレゼンテーション

public static class Fake
{
    public static string Test()
    {
        return "Test";
    }
}

重要でない部分の順序を正規化する

コードの順序が問題にならない場合もあります。同じコードが順序の違いによって別のリプレゼンテーションになるのを防ぐために、並べ替えるとよいことがあります。並べ替えの対象は通常、関数や宣言です。並べ替えの基準を見つけるのは難しく、実装も難しいかもしれません。基準の1つは、そのノードが持つASTの子ノードの数で、もう1つは最初の子ノードの型の名前です。

次の例では、何らかの関数の長さで並べ替えています。

ソースコード

public static class Fake
{
    public static string Test2()
    {
        int a = "Test2";
        return a;
    }

    public static string Test()
    {
        return "Test";
    }
}

リプレゼンテーション

public static class Fake
{
    public static string Test()
    {
        return "Test";
    }

    public static string Test2()
    {
        int a = "Test2";
        return a;
    }
}