Question

I am trying to make a Parser and Interpreter or Compiler. Right now when I try to execute the test code all it shows is blank. Am I not parsing it or is something interfering or what? Can someone take a look and tell me whats not working?

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";
                }
            }
        }
    }
 }
Était-ce utile?

La solution 3

static void compile(string line, string code)

You're passing code in as a string, but not requesting it to return with any data, yet your usage of the function clearly states that you're trying to alter it with each call. Change the call to a ref.

static void compile(string line, ref string code)

and call it with a ref, e.g. compile("function Main {", ref code);

Autres conseils

It is not working as expected because even though string is a reference type, it is actually passed by value. That means that each time you are passing in string, you are passing in a blank string, and nothing is being done to it. See this post:

C# string reference type?

You can fix it by declaring it an "out" variable.

static void compile(string line, out string code)

Or better yet, change compile to return the string.

static string compile(string line, string code)

and then invoke it like this:

code = compile("code bits",code);

As Lasse V. Karlsen suggested, you may pass code by reference (using ref), but the best solution would be to use a StringBuilder since it's mutable and this will save you tens of useless string instantiations:

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");
            }
        }
    }
}

The problem here is that string is immutable and that you're not passing the parameter by reference.

You're sending in a string variable to the method, but the method cannot change the contents of the variable, it can only change the parameter it has access to, which functions pretty much like a local variable.

Thus, whatever it is the compile method does to the code parameter does not change the contents of the code variable in the main method.

To fix this, change the parameter to a pass by reference parameter by adding the ref keyword:

static void compile(string line, ref string code)

To call it:

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

Observations:

  • You've forgotten a newline after the ":Main" program label in your output
  • PUSH x and PUSH Hello does not distinguish between a variable or a literal (string in this case), you probably want to fix this, typically by adding quotes, ie. PUSH "Hello"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top