2013-03-04 4 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

+1

Или же вы можете использовать некоторые уродливые продолжать заявления , Если goto не позволяет вернуться. –

ответ

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

+0

Yup! Я это обработаю :) –

6

Вы не сможете использовать foreach для этого. Вам понадобится цикл while и скачок по индексу.

Похоже, что это может быть только верхушка айсберга за то, что вы хотите сделать. Если это так, вы быстро перерастуте регулярные выражения. Прочитайте проект компилятора, в частности, как разделить лексические, синтаксические и семантические этапы и как повторно использовать существующие инструменты, которые могут помочь вам на каждом этапе.

Мне также кажется, что, прочитав несколько вещей, вы быстро поймете, почему ваш нынешний подход может быть недостаточным, но и полномасштабный компилятор может быть переполнен. В этом случае .Net имеет некоторые полезные функции, встроенные для определения того, что называется «Domain Specific Languages», которое может быть именно тем, что вам нужно.

+0

Спасибо! Да, это то, что я планирую продолжить с более сложными языками в будущем. –

2

Используйте петлю для петли. Переменная 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) 
    { 

    } 
} 
+2

Я думаю, что какое-то время лучше подходит для этого, потому что из-за типа цикла подразумевается определенное количество итераций. Некоторое время может быть сделано, чтобы увеличивать только при необходимости – Cemafor

+2

Да, ответ бара лучше читается и не имеет неприятности -1 – Tom

Смежные вопросы