Как вернуться к строке кода и восстановить стек вызовов? - PullRequest
0 голосов
/ 17 марта 2012

Я задал вопрос ранее , но я не думаю, что достаточно четко определился с тем типом ответов, на которые я надеялся, поэтому позвольте мне привести более конкретный пример:

class Program
{
    private static bool State;

    static void Main(string[] args)
    {
        State = false;
        Console.WriteLine(And());
        Console.ReadLine();
    }

    static bool And()
    {
        return Or() && C();
    }

    static bool Or()
    {
        return A() || AB();
    }

    static bool C()
    {
        return State;
    }

    static bool A()
    {
        return true;
    }

    static bool AB()
    {
        State = true;
        return true;
    }
}

Поток этой программы выглядит так:

  1. И () вызывается
  2. И () вызывает Или ()
  3. Или () вызывает A ()
  4. A () возвращает true
  5. Поток возвращается к Or (), который возвращает true (ленивая оценка)
  6. Поток возвращается к А (), А () вызывает C ()
  7. C () возвращает false
  8. Поток возвращается к And (), который возвращает false

Теперь, если Or () не выполняет отложенную оценку (я изменяю || на |), программа вернет true. Тем не менее, я не хочу, чтобы AB () выполнялась, пока не произойдет сбой результата всего анализа (And () вернет false).

Итак, что я хотел бы сделать, это где-нибудь в функции Or (), сохранить текущее состояние в стеке (статическая переменная), чтобы, если And () вернул false, я мог вытолкнуть элемент из стека и попробуйте альтернативу.

Как бы я это сделал в C #?

Ответы [ 2 ]

2 голосов
/ 17 марта 2012

Проблема не имеет ничего общего с ||оператор.Проблема в том, что вы забыли отказаться от неудачного разбора.Если Parse возвращает false, вам нужно восстановить i и любые другие переменные состояния до их первоначального значения, чтобы следующий анализатор мог попробовать.C # не является языком поиска целей.Если вы хотите вернуться назад, вам придется сделать это самостоятельно.(Или переключитесь на язык с возвратом, как Prolog.)

1 голос
/ 17 марта 2012

Мне кажется, что это довольно тривиально - просто переставьте вызовы:

static void Main(string[] args)
{
    State = false;
    Console.WriteLine(Or());
    Console.ReadLine();
}

static bool Or()
{
    return A() && C() || AB() && C();
}

Или я что-то упустил? Может быть, у C() есть побочные эффекты, которые не следует вызывать дважды?

РЕДАКТИРОВАТЬ: Теперь я понимаю, что вы пытаетесь сделать. Сделай себе одолжение. Слушайте предложения, которые вы получили, получите копию GPPG или (возможно, намного проще) ANTLR , с ANTLRWorks . Это так, поэтому намного проще и менее подвержен ошибкам, чем попытка свернуть парсер вручную, и вы все равно получите C # в конце.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...