我正在用C#编写一个非常简单的脚本解释器。这种语言中没有If/Else语句或用户可编程的子例程;唯一的控制流是goto关键字。
如果我使用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)
{
}
}
}发布于 2013-03-05 02:35:56
改用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-05 02:26:25
你不能使用foreach来做这件事。您将需要一个while循环并按索引跳转。
看起来这可能只是你想要做的事情的冰山一角。如果是这样的话,您很快就会超出正则表达式。阅读编译器设计,特别是如何分离词法、语法和语义阶段,以及如何重用可以在每个步骤中帮助您的现有工具。
在我看来,在阅读了一些东西之后,你很快就会明白为什么你现在的方法可能还不够,但是一个成熟的编译器可能会被过度使用。在这种情况下,.Net内置了一些很好的特性来帮助定义所谓的"Domain Specific Languages“,这可能正是您所需要的。
发布于 2013-03-05 02:29:40
使用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)
{
}
}https://stackoverflow.com/questions/15208350
复制相似问题