2013-03-04 48 views
2

我正在用C#編寫一個非常簡單的腳本解釋器。此語言中沒有If/Else語句或用戶可編程子例程;唯一的控制流程是goto關鍵字。C#:在foreach中跳過行嗎?

如果我用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) 
     { 

     } 
    } 
} 
+3

轉換'foreach'成'for'環路和環路指數設定爲GoTo' – oleksii 2013-03-04 18:27:56

+1

的'價值或者你也可以使用一些醜陋continue語句。除非goto允許回去。 – 2013-03-04 18:31:05

回答

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) 
      { 

      } 
     } 
+1

啊''i ++'應該需要特別小心,因爲你有'try-catch'。但是你可以自己做調試和測試:)。你會得到想法 – bas 2013-03-04 18:37:35

+0

是!我會處理它:) – 2013-03-04 19:55:45

6

您將無法使用此foreach。您需要一個while循環並按索引跳轉。

看起來這可能只是您想要做的冰山一角。如果是這樣,你會很快超過正則表達式。閱讀編譯器設計,特別是如何分離詞法,句法和語義階段,以及如何重用現有工具,以便在每一步都能爲您提供幫助。

在閱讀了一些內容之後,我很可能會很快理解爲什麼你現在的方法可能不夠用,而且一個成熟的編譯器可能會矯枉過正。在這種情況下,.Net內置了一些很好的功能來幫助定義所謂的「Domain Specific Languages」,這可能正是您所需要的。

+0

謝謝!是的,這是我打算在將來用更復雜的語言追求的東西。 – 2013-03-04 19:57:08

2

使用for循環。變量i可以跟蹤您的當前行,並且可以在循環內更改它,模擬轉到。

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) 
    { 

    } 
} 
+2

我認爲有一段時間更適合於此,因爲for循環類型意味着特定數量的迭代。有一段時間只能在需要時增加 – Cemafor 2013-03-04 18:38:16

+2

是的,bas的答案讀得更好,並且沒有討厭-1 – Tom 2013-03-04 18:40:33