我正在尝试制作解析器和解释器或编译器。 现在,当我尝试执行测试代码时,它显示的全部为空白。 我没有解析它或是干扰什么? 有人可以看看,告诉我什么不工作?
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";
}
}
}
}
}
答案 0 :(得分:1)
它没有按预期工作,因为即使string是引用类型,它实际上是按值传递的。这意味着每次传入字符串时,都会传入一个空白字符串,并且没有对它进行任何操作。看这篇文章:
您可以通过将其声明为“out”变量来修复它。
static void compile(string line, out string code)
或者更好的是,更改编译以返回字符串。
static string compile(string line, string code)
然后像这样调用它:
code = compile("code bits",code);
答案 1 :(得分:1)
正如Lasse V. Karlsen建议的那样,您可以通过引用传递code
(使用ref
),但最好的解决方案是使用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");
}
}
}
}
答案 2 :(得分:0)
static void compile(string line, string code)
您将代码作为字符串传递,但不要求它返回任何数据,但您对该函数的使用清楚地表明您正试图在每次调用时更改它。将呼叫更改为参考。
static void compile(string line, ref string code)
并使用引用来调用它,例如compile("function Main {", ref code);
答案 3 :(得分:0)
这里的问题是string
是不可变的,并且您没有通过引用传递参数。
您正在向该方法发送一个字符串变量,但该方法无法更改该变量的内容,它只能更改它有权访问的参数,其功能与局部变量非常相似。
因此,无论compile
方法对code
参数的作用是什么,都不会更改main方法中code
变量的内容。
要解决此问题,请通过添加ref
关键字将参数更改为按参考传递参数:
static void compile(string line, ref string code)
要打电话:
compile("function Main {", ref code);
观察:
PUSH x
和PUSH Hello
不区分变量或文字(在这种情况下为字符串),您可能想要解决此问题,通常是通过添加引号,即。 PUSH "Hello"