Я работаю над проектом с использованием библиотеки синтаксического анализатора ANTLR для C #. Я построил грамматику для разбора текста, и она работает хорошо. Однако, когда синтаксический анализатор обнаруживает недопустимый или неожиданный токен, он выдает одно из многих исключений. Проблема в том, что в некоторых случаях (не во всех) мой блок try / catch не будет его перехватывать и вместо этого останавливает выполнение как необработанное исключение.
Для меня проблема в том, что я не могу повторить эту проблему нигде, кроме как в своем полном коде. Стек вызовов показывает, что исключение определенно происходит в моем блоке try / catch (Exception). Единственное, о чем я могу думать, - это то, что между моим кодом и кодом, генерирующим исключение, происходит несколько вызовов сборки ANTLR, и в этой библиотеке не включена отладка, поэтому я не могу пройти через нее. Интересно, не-отлаживаемые сборки запрещают всплытие исключений? Стек вызовов выглядит следующим образом; вызовы внешних сборок в Antlr.Runtime:
Expl.Itinerary.dll!TimeDefLexer.mTokens() Line 1213 C#
Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken() + 0xfc bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer() + 0x22c bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 1) + 0x68 bytes
Expl.Itinerary.dll!TimeDefParser.prog() Line 109 + 0x17 bytes C#
Expl.Itinerary.dll!Expl.Itinerary.TDLParser.Parse(string Text = "", Expl.Itinerary.IItinerary Itinerary = {Expl.Itinerary.MemoryItinerary}) Line 17 + 0xa bytes C#
Фрагмент кода из самого нижнего вызова в Parse () выглядит следующим образом:
try {
// Execution stopped at parser.prog()
TimeDefParser.prog_return prog_ret = parser.prog();
return prog_ret == null ? null : prog_ret.value;
}
catch (Exception ex) {
throw new ParserException(ex.Message, ex);
}
Для меня предложение catch (Exception) должно было охватить любое исключение. Есть ли причина, по которой это не так?
Обновление: Я проследил через внешнюю сборку с помощью Reflector и не обнаружил никаких свидетельств о потоке. Похоже, что сборка является всего лишь классом служебной программы для сгенерированного кода ANTLR. Исключение выдается из метода TimeDefLexer.mTokens (), а его тип - NoViableAltException, который происходит от RecognitionException -> Exception. Это исключение выдается, когда лексер не может понять следующий токен в потоке; другими словами, неверный ввод. Это исключение ДОЛЖНО происходить, однако оно должно было быть перехвачено моим блоком try / catch.
Кроме того, повторное выбрасывание ParserException действительно не имеет отношения к этой ситуации. Это уровень абстракции, который принимает любое исключение во время синтаксического анализа и преобразует его в мое собственное исключение ParserException. Проблема обработки исключений, с которой я столкнулся, никогда не достигает этой строки кода. Фактически, я прокомментировал часть «throw new ParserException» и все еще получил тот же результат.
Еще одна вещь, я изменил исходный рассматриваемый блок try / catch, чтобы вместо этого перехватывать NoViableAltException, устраняя любую путаницу наследования. Я все еще получил тот же результат.
Кто-то однажды предположил, что иногда VS чрезмерно активен при перехвате обработанных исключений в режиме отладки, но эта проблема также возникает в режиме выпуска.
Чувак, я все еще в тупике! Я не упоминал об этом раньше, но я использую VS 2008, и весь мой код 3.5. Внешняя сборка 2.0. Кроме того, некоторые из моего кода являются подклассами класса в сборке 2.0. Может ли несовпадение версий вызвать эту проблему?
Обновление 2: Мне удалось устранить конфликт версий .NET, портировав соответствующие части моего кода .NET 3.5 в проект .NET 2.0 и повторив тот же сценарий. Мне удалось реплицировать одно и то же необработанное исключение при постоянной работе в .NET 2.0.
Я узнал, что ANTLR недавно выпустил 3.1. Итак, я обновился с 3.0.1 и повторил попытку. Оказывается, сгенерированный код немного переработан, но в моих тестовых примерах происходит то же необработанное исключение.
Обновление 3:
Я повторил этот сценарий в упрощенном проекте VS 2008 . Не стесняйтесь загружать и проверять проект для себя. Я применил все замечательные предложения, но пока не смог преодолеть это препятствие.
Если вы можете найти обходной путь, пожалуйста, поделитесь своими выводами. Еще раз спасибо!
Спасибо, но VS 2008 автоматически разбивается на необработанные исключения. Кроме того, у меня нет диалога Debug-> Exceptions. Создаваемое исключение NoViableAltException предназначено для перехвата кода пользователя. Поскольку он не перехвачен должным образом, выполнение программы неожиданно останавливается как необработанное исключение.
Исключение выдается из Exception, и многопоточность с ANTLR не выполняется.