1

テキストフォーマットを解析しようとしています。SO と同じように、インライン コードをバッククォート ( `) でマークしたいと考えています。ルールは、インライン コード要素内でバッククォートを使用する場合は、インライン コードの周りに二重のバッククォートを使用する必要があるというものです。

このような:

`` インライン コードをバッククォートでマーク ( ` ) ``

私のパーサーは、何らかの理由で二重のバッククォートを完全にスキップしているようです。インライン コード解析を行う関数のコードは次のとおりです。

    private string ParseInlineCode(string input)
    {
        for (int i = 0; i < input.Length; i++)
        {
            if (input[i] == '`' && input[i - 1] != '\\')
            {
                if (input[i + 1] == '`')
                {
                    string str = ReadToCharacter('`', i + 2, input);
                    while (input[i + str.Length + 2] != '`')
                    {
                        str += ReadToCharacter('`', i + str.Length + 3, input);
                    }
                    string tbr = "``" + str + "``";
                    str = str.Replace("&", "&amp;");
                    str = str.Replace("<", "&lt;");
                    str = str.Replace(">", "&gt;");
                    input = input.Replace(tbr, "<code>" + str + "</code>");
                    i += str.Length + 13;
                }
                else
                {
                    string str = ReadToCharacter('`', i + 1, input);
                    input = input.Replace("`" + str + "`", "<code>" + str + "</code>");
                    i += str.Length + 13;
                }
            }
        }
        return input;
    }

何かを単一のバッククォートで囲むと、<code>タグで正しくラップされます。

4

2 に答える 2

4

whileループ内

while (input[i + str.Length + 2] != '`')
{
    str += ReadToCharacter('`', i + str.Length + 3, input);
}

i + str.Length + 2代わりに、間違ったインデックスを見てi + str.Length + 3、ボディにバッククォートを追加する必要があります。それはおそらく

while (input[i + str.Length + 3] != '`')
{
    str += '`' + ReadToCharacter('`', i + str.Length + 3, input);
}

しかし、あなたのコードにはさらにいくつかのバグがあります。次の行はIndexOutOfRangeException、入力の最初の文字がバッククォートの場合に発生します。

 if (input[i] == '`' && input[i - 1] != '\\')

次の行はIndexOutOfRangeException、入力に奇数の分離されたバックティックが含まれており、入力の最後の文字がバックティックである場合に発生します。

if (input[i + 1] == '`')

おそらく、コードをより小さなメソッドに refector する必要があり、1 つのメソッド内で多くのケースを処理しないようにする必要があります。これはバグが発生しやすい傾向にあります。コードの単体テストをジェットで書いていない場合は、そうすることを強くお勧めします。また、パーサーはすべての種類の無効な入力のために準備する必要があるため、テストが実際には簡単ではないため、PEXを検討することもできます。これは、すべての分岐点を分析し、すべての分岐点を分析してコードのテスト ケースを自動的に生成するツールです。可能なコード パス。

私はすぐに PEX を起動し、コードに対して実行しましたIndexOutOfRangeException。そしてもちろん、PEX はNullReferenceExceptions、入力が null 参照であるかどうかを明らかにしました。以下は、PEX が例外の原因であると判断した入力です。

case1 = "`"

case2 = "\0`"

case3 = "\0``"

case4 = "\0`\0````````````\u0001``````````````\0\0\0\0\0\0\0\0\0\0\0````"

case5 = "\0`\0````````````\u0001``````````````\0\0\0\0\0\0\0\0\0\0\0```\0````````````\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`"

case6 = "\0`\0````````````\u0001``````````````\0\0\0\0\0\0\0\0\0\0\0```\0````````````\0\0\0\0\0\0\0\0\0\0``<\0\0`````````````````````````````````````````````````````````````````````````````````````\0\0\0\0\0\0\0\0\0\0``<\0\0```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````\0\0\0\0\0\0\0\0\0`\0```````````````"

あなたのコードの私の「修正」により、例外を引き起こす入力が変更されました(そして、新しいバグも導入された可能性があります)。PEX は、変更されたコードで次のことをキャッチしました。

case7 = "\0```"

case8 = "\0`\0````````````\u0001``````````````\0\0\0\0\0\0\0\0\0\0\0```\0`\0"

case9 = "\0`\0````````````\u0001``````````````\0\0\0\0\0\0\0\0\0\0\0```\0````````````\0\0\0\0\0\0\0\0\0\0``<\0\0`````````````````````````````````````````````````````````````````````````````````````\0\0\0\0\0\0\0\0\0\0``\0`\0`\0``"

元のコードでは 3 つの入力すべてで例外が発生しませんでしたが、変更されたコードではケース 4 と 6 で例外が発生しなくなりました。

于 2010-05-25T20:29:57.730 に答える
1

これは、LinqPad でテストされた小さなスニペットです。

void Main()
{
    string test = "here is some code `public void Method( )` but ``this is not code``";
    Regex r = new Regex( @"(`[^`]+`)" );

    MatchCollection matches = r.Matches( test );

    foreach( Match match in matches )
    {
        Console.Out.WriteLine( match.Value );
        if( test[match.Index - 1] == '`' )
            Console.Out.WriteLine( "NOT CODE" );
            else
        Console.Out.WriteLine( "CODE" );
    }
}

出力:

`public void Method( )`
CODE
`this is not code`
NOT CODE
于 2010-05-25T19:50:41.413 に答える