Исключение ANTLR - «Невозможно перевести символ Unicode \ uDCAF по индексу 111 в указанную кодовую страницу». - PullRequest
1 голос
/ 08 августа 2011

Вызов всех экспертов ANTLR!

У меня есть сборка .NET, размещенная на веб-сайте IIS, в которой используется ANTLR для обработки запросов на естественном языке в стиле поисковой системы. Например, если пользователь вводит:

сыр и крекеры, а не чипсы

Он строит следующее утверждение:

И (И («сыр», «крекеры»), НЕ («чипсы»))

Затем мы запускаем это утверждение в нашем хранилище контента и предоставляем некоторый контент пользователю. 99,9% времени все отлично работает. Тем не менее, время от времени что-то не работает с ANTLR и размещенным на IIS сайтом, который выполняет эту обработку, застревает в каком-то состоянии ошибки и выдает ошибки без остановки, пока мы не выполним перезапуск IISReset / AppPool. После перезагрузки ошибки немедленно прекращаются.

Я фиксирую трассировку стека этих ошибок, которые я включил (санировал, согласно политике компании) ниже:

System.Text.EncoderFallbackException: Unable to translate Unicode character \uDCAF at index 111 to specified code page.
 at System.Text.EncoderExceptionFallbackBuffer.Fallback(Char charUnknown, Int32 index)
 at System.Text.EncoderFallbackBuffer.InternalFallback(Char ch, Char*& chars)
 at System.Text.UTF8Encoding.GetBytes(Char* chars, Int32 charCount, Byte* bytes, Int32 byteCount, EncoderNLS baseEncoder)
 at System.Text.EncoderNLS.GetBytes(Char* chars, Int32 charCount, Byte* bytes, Int32 byteCount, Boolean flush)
 at System.Text.EncoderNLS.GetBytes(Char[] chars, Int32 charIndex, Int32 charCount, Byte[] bytes, Int32 byteIndex, Boolean flush)
 at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
 at System.IO.StreamWriter.Write(Char[] buffer, Int32 index, Int32 count)
 at System.IO.TextWriter.WriteLine(String value)
 at System.IO.TextWriter.SyncTextWriter.WriteLine(String value)
 at Antlr.Runtime.BaseRecognizer.EmitErrorMessage(String msg)
 at Service123.Parser.atomicExpression() in Parser.cs:line 927
 at Service123.Parser.notExpression() in Parser.cs:line 657
 at Service123.Parser.orExpression() in Parser.cs:line 516
 at Service123.Parser.andnotExpression() in Parser.cs:line 416
 at Service123.Parser.andExpression() in Parser.cs:line 234
 at Service123.Parser.startExpression() in Parser.cs:line 167
 at Service123.Processor.ProcessQuery(String queryString) in Processor.cs:line 34
 at Service123.Search.ProcessQueryString(String query) in Search.cs:line 1017

Ниже приведена (снова обработанная, согласно политике компании) копия моего файла грамматики:

grammar Parser;

options { language = CSharp2; output = AST; }

tokens { IMPLICIT_AND; }

@lexer::namespace { Service123.Parser }
@parser::namespace { Service123.Parser }

L_PARENTHESIS : '(';
R_PARENTHESIS : ')';

AND    : ('A'|'a')('N'|'n')('D'|'d');
OR     : ('O'|'o')('R'|'r');
ANDNOT : ('A'|'a')('N'|'n')('D'|'d')('N'|'n')('O'|'o')('T'|'t');
NOT    : ('N'|'n')('O'|'o')('T'|'t');

fragment LETTER        : ('a'..'z'|'A'..'Z');
fragment NUMBER        : ('0'..'9');
fragment SYMBOL_1      : ('+'|'-'|'_'|'|'|'~'|'&'|'`'|'='|'['|']'|'{'|'}');
fragment SYMBOL_2      : ('!'|'@'|'#'|'$'|'%'|'^'|'*'|','|'.'|'/'|':'|';'|'<'|'>'|'?'|'\''|'\\');
fragment SYMBOL_QUOTE  : ('"');
fragment SPACE         : (' '|'\n'|'\r'|'\t'|'\u000C');

WS     : (SPACE) { $channel=HIDDEN; };
PHRASE : (SYMBOL_QUOTE)(LETTER|NUMBER|SYMBOL_1|SYMBOL_2)+((SPACE)+(LETTER|NUMBER|SYMBOL_1|SYMBOL_2)+)+(SYMBOL_QUOTE);
WORD   : (LETTER|NUMBER|SYMBOL_1)+;

startExpression  : andExpression;
andExpression    : (         andnotExpression ->              andnotExpression    )
                   (AND? e = andnotExpression -> ^(IMPLICIT_AND $andExpression $e))*;
andnotExpression : orExpression (ANDNOT^ orExpression)*;
orExpression     : notExpression (OR^ notExpression)*;
notExpression    : (NOT^)? atomicExpression;
atomicExpression : PHRASE | WORD | L_PARENTHESIS! andExpression R_PARENTHESIS!;

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

Что касается ошибки, то рассматриваемая кодовая точка не всегда \ uDCAF, но согласована на протяжении всего цикла ошибок; это всегда одна и та же кодовая точка, пока мы не откажемся от службы, а затем, когда ошибка снова появляется после недели, когда все работает нормально, все по-другому.

Все кодовые точки, которые я смог записать, являются частью суррогатной пары и сами по себе не представляют действительные глифы.

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

Если вам нужны подробности или разъяснения, пожалуйста, не стесняйтесь спрашивать, потому что я в своем уме.

...