Невозможно объединить 2 Superpower TextParser с или с Span

У меня есть 2 Superpower TextParser - каждая цель для анализа определенного ввода - различается префиксом и параметрами. Я пытаюсь создать комбинированный синтаксический анализатор, который выдает результат, когда любой из TextParser может анализировать ввод. Результатом является список с определенными строками, описывающими ввод.

например, некоторая пара ввода и вывода следующим образом

"interrupt(20)" -> List { "interrupt", "20" }
"insert(20,12)" -> List {"insert", "20", "12" }
"delete(18)" -> Error

Для примеров пар ввода и вывода я написал следующее на C# с добавленной ссылкой на сверхмощность.

// Works fine for "insert(12,24)"
string failingTest = "interrupt(12)";

TextParser<List<string>> identifier001 =
    from prefix in Span.EqualTo("insert")
    from open in Character.EqualTo('(')
    from num0 in Character.Numeric.Many()
    from comma1 in Character.EqualTo(',')
    from num1 in Character.Numeric.Many()
    from close in Character.EqualTo(')')
    select new List<string> { prefix.ToStringValue(), string.Join("", num0), string.Join("", num1) };

TextParser<List<string>> identifier002 =
    from prefix in Span.EqualTo("interrupt")
    from open in Character.EqualTo('(')
    from num0 in Character.Numeric.Many()
    from close in Character.EqualTo(')')
    select new List<string> { prefix.ToStringValue(), string.Join("", num0) };

TextParser<List<string>> combined =
    from span in identifier001.Or(identifier002)
    select span;

var res = combined.Parse(failingTest);
foreach (var item in res)
{
    Console.WriteLine(item);
}

Мой combined идентификатор не может проанализировать ввод interrupt(12) и дает следующую ошибку

Синтаксическая ошибка (строка 1, столбец 3): неожиданно t, ожидается s.

Есть ли какой-нибудь правильный способ выполнить комбинацию идентификаторов "ИЛИ"?

1 ответ

Решение

Ты должен позвонить Try() после вашего первого парсера, затем соедините его с Or() функция, например:

TextParser<List<string>> combined =
    from span in identifier001.Try().Or(identifier002)
    select span;

Что происходит, так это то, что ваш первый парсер identifier001 уже поглотил "in" часть строки, которая оставляет identifier002 чтобы попытаться разобрать строку "terrupt(20)"который терпит неудачу. Призыв кTry() указывает синтаксическому анализатору вернуться к исходной точке предыдущего синтаксического анализатора, что вы и хотите.

Документация по Try() это:

Создайте синтаксический анализатор, который пробует один синтаксический анализатор и выполняет возврат в случае неудачи, чтобы никакие входные данные не использовались при последующих проверках результата.

Другие вопросы по тегам