0

パーサーとインタープリターまたはコンパイラーを作成しようとしています。現在、テスト コードを実行しようとすると、空白が表示されます。私はそれを解析していませんか、それとも何かが干渉していますか? 誰かが見て、何がうまくいかないのか教えてもらえますか?

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace Mikebite
{
     class Program
     {
        static void Main(string[] args)
        {
            try
            {
                string code = "";
                compile("function Main {", code);
                compile("x = Hello world!!", code);
                compile("print x", code);
                compile("input x", code);
                compile("} ;", code);

                Console.WriteLine(code);
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
            }
        }
        static void compile(string line, string code)
        {
            string[] tokens = line.Split(' ');

            for (int i = 0; i < tokens.Length; i++)
            {
                if (tokens[i].Contains("function"))
                {
                    code += ":" + tokens[i+1];
                    i++;
                }
                else if (tokens[i].Contains("="))
                {
                    code += "PUSH " + tokens[i-1] + "\n";
                    code += "PUSH " + tokens[i+1] + "\n";
                    code += "SET\n";
                    i++;
                }
                else if (tokens[i].Contains("exec"))
                {
                    code += "GOTO " + tokens[i+1] + "\n";
                    i++;
                }
                else if (tokens[i].Contains("}"))
                {
                    code += "RTN\n";
                }
                else if (tokens[i].Contains("input"))
                {
                    code += "PUSH " + tokens[i+1] + "\nPUSH NULL\nINPUT\n";
                }
                else if (tokens[i].Contains("print"))
                {
                    code += "PUSH " + tokens[i+1] + "\nPUSH NULL\nPRINT\n";
                }
            }
        }
    }
 }
4

4 に答える 4

1

Lasse V. Karlsen が示唆したように、code( を使用して) 参照渡しすることもできますが、変更可能でrefあるため、 a を使用するのが最善の解決策でStringBuilderあり、これにより無駄なstringインスタンス化を何十回も節約できます。

class Program
{
    static void Main(string[] args)
    {
        try
        {
            StringBuilder code = new StringBuilder();
            Compile("function Main {", code);
            Compile("x = Hello world!!", code);
            Compile("print x", code);
            Compile("input x", code);
            Compile("} ;", code);

            Console.WriteLine(code);
            Console.ReadLine();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
        }
    }
    static void Compile(string line, StringBuilder code)
    {
        string[] tokens = line.Split(' ');

        for (int i = 0; i < tokens.Length; i++)
        {
            if (tokens[i].Contains("function"))
            {
                code.Append(":")
                    .Append(tokens[i+1]);
                i++;
            }
            else if (tokens[i].Contains("="))
            {

                code.Append("PUSH ")
                    .Append(tokens[i-1])
                    .Append("\n")
                    .Append("PUSH ")
                    .Append(tokens[i+1])
                    .Append("\n")
                    .Append("SET\n");
                i++;
            }
            else if (tokens[i].Contains("exec"))
            {
                code.Append("GOTO ")
                    .Append(tokens[i+1])
                    .Append("\n");
                i++;
            }
            else if (tokens[i].Contains("}"))
            {
                code.Append("RTN\n");
            }
            else if (tokens[i].Contains("input"))
            {
                code.Append("PUSH ")
                    .Append(tokens[i+1])
                    .Append("\nPUSH NULL\nINPUT\n");
            }
            else if (tokens[i].Contains("print"))
            {
                code.Append("PUSH ")
                    .Append(tokens[i+1])
                    .Append("\nPUSH NULL\nPRINT\n");
            }
        }
    }
}
于 2013-06-26T14:41:29.803 に答える
1

文字列は参照型ですが、実際には値で渡されるため、期待どおりに動作しません。つまり、文字列を渡すたびに空の文字列が渡され、何も行われません。この投稿を参照してください。

C#文字列参照型?

「out」変数として宣言することで修正できます。

static void compile(string line, out string code)

またはさらに良いことに、文字列を返すようにコンパイルを変更します。

static string compile(string line, string code)

そして、次のように呼び出します。

code = compile("code bits",code);
于 2013-06-26T14:38:59.213 に答える
0

static void compile(string line, string code)

コードを文字列として渡していますが、データを返すように要求していませんが、関数の使用法は、呼び出しごとにコードを変更しようとしていることを明確に示しています。呼び出しを参照に変更します。

static void compile(string line, ref string code)

そしてrefでそれを呼び出します、例えばcompile("function Main {", ref code);

于 2013-06-26T14:37:53.743 に答える
0

ここでの問題は、それstringが不変であり、参照によってパラメーターを渡していないことです。

文字列変数をメソッドに送信していますが、メソッドは変数の内容を変更できません。アクセスできるパラメーターのみを変更できます。これは、ローカル変数のように機能します。

したがって、compileメソッドがパラメーターに対して何を行っても、メイン メソッドcodeの変数の内容は変更されません。code

これを修正するには、次のキーワード を追加して、パラメーターを参照渡しパラメーターに変更します。ref

static void compile(string line, ref string code)

それを呼び出すには:

compile("function Main {", ref code);

所見:

  • 出力の ":Main" プログラム ラベルの後の改行を忘れた
  • PUSH x変数とPUSH Helloリテラル (この場合は文字列) を区別しません。おそらく、通常は引用符を追加して、これを修正する必要があります。PUSH "Hello"
于 2013-06-26T14:38:58.047 に答える