致电所有ANTLR专家!
我在IIS网站上托管了一个.NET程序集,它使用ANTLR进行自然语言查询处理,搜索引擎样式。例如,如果用户键入:
奶酪和饼干而不是薯条
它构建以下语句:
AND(AND(“cheese”,“crackers”),NOT(“筹码”))
然后我们将该声明发送到我们的内容存储库并向用户提供一些内容。 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运行时中有一个单例以某种方式搞砸了,并且在我们重新加载程序集之前,所有进一步的处理都没用。但是,我没有这方面的证据。
如果您需要更多详细信息或说明,请不要犹豫,因为我的机智已经结束了。