2

C# で非常に単純なスクリプト インタープリターを作成しています。If/Elseこの言語には、ステートメントやユーザーがプログラム可能なサブルーチンはありません。唯一の制御フローはgotoキーワードです。

ループを使用してスクリプトを 1 行ずつ解析している場合、ブロックforeach内のパラメーターで指定された行番号にプログラムを「ジャンプ」させるにはどうすればよいですか?GoTo()

static void Main(string[] args)
{
    string testLines = "SomeCommand(34,32)\n" +
    "SomeCommand(1)\n" +
    "GoTo(5)\n" +
    "This(\"Will\",\"Be\",\"Skipped\")\n" +
    "Destination(\"OfTheGoToKeyWord\")";
    Regex r = new Regex("^(?<cmd>\\w+)[(](?<params>\\S+)[)]", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
    string[] lines = testLines.Split('\n');
    foreach (string line in lines)
    {
        try
        {
            string[] matches = r.Split(line);
            if (matches[1].Equals("GoTo"))
            {
                GoToLineSpecifiedByMatchesElement2();
            }
        }
        catch (Exception)
        {

        }
    }
}
4

3 に答える 3

6

これには foreach を使用できません。ループが必要になり、whileインデックスでジャンプします。

これは、あなたがやりたいことの氷山の一角に過ぎないようです。もしそうなら、あなたはすぐに正規表現を超えてしまいます. コンパイラの設計、特に字句、構文、意味の各段階を分離する方法、および各ステップで役立つ既存のツールを再利用する方法について読んでください。

また、いくつかのことを読んだ後、現在のアプローチが十分ではない理由をすぐに理解できるように思えますが、本格的なコンパイラーはやり過ぎかもしれません。その場合、.Net には「ドメイン固有言語」と呼ばれるものを定義するのに役立つ便利な機能が組み込まれています。

于 2013-03-04T18:26:25.243 に答える
3

while代わりにループを使用してください:

    private static void Main(string[] args)
    {
        string testLines = "SomeCommand(34,32)\n" +
                           "SomeCommand(1)\n" +
                           "GoTo(5)\n" +
                           "This(\"Will\",\"Be\",\"Skipped\")\n" +
                           "Destination(\"OfTheGoToKeyWord\")";
        Regex r = new Regex(
            "^(?<cmd>\\w+)[(](?<params>\\S+)[)]", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

        List<string> lines = testLines.Split('\n').ToList();
        int i = 0;

        while (i < lines.Count)
        {
            try
            {
                var input = lines[i];
                var matches = r.Split(input);
                if (matches[1].Equals("GoTo"))
                {
                    i = testLines.IndexOf(input);
                }
                else
                {
                    i++;
                }
            }
            catch (Exception)
            {

            }
        }
于 2013-03-04T18:35:56.223 に答える
2

for ループを使用します。変数iは現在の行を追跡でき、goto をシミュレートしてループ内で変数を変更できます。

 for (int i = 0; i < lines.Length; i++)
{
    try
    {
        string[] matches = r.Split(lines[i]);
        if (matches[1].Equals("GoTo"))
        {
            i = matches[2] - 1; // -1 because for loop will do i++
        }
    }
    catch (Exception)
    {

    }
}
于 2013-03-04T18:29:40.080 に答える