本文介绍了是否有可能抛出一个异常,如果输入的是无效的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我有一个简单ANLTR语法和相应的访问者。一切都很正常,除非输入无效。如果输入无效,错误得到吞噬我的计算器出来用错误的输出。 我试过实现一个错误监听,比骑恢复词法分析器的方法,和..嗯...今天半打其他的事情。可有人告诉我如何简单地抛出一个错误,而不是吞咽坏令牌? (我用引号,因为他们的不的令牌在所有的人物都在我的语法定义。) 有效输入: 和由此产生分析树。 BasicMath.g4 语法BasicMath; / * *语法规则 * / compileUnit:表达+ EOF; 表达式:表达乘法表达#Multiplication |表达DIVIDE表达#Division |表达式添加表情#Addition |表达SUBTRACT表达#Subtraction | NUMBER #NUMBER ; / * *词法规则 * / 编号:INT; //留有余地延长哪种数学,我们可以做的。 INT:('0'..'9')+; 乘:'*'; 除法:'/'; 减:' - '; 地址:'+'; WS:[\t\r\\\] - >通道(隐藏); 计算器: 公共静态类计算器 {公共静态INT评估(字符串表达式) {变种词法分析器=新BasicMathLexer(新AntlrInputStream (表达)); 变种令牌=新CommonTokenStream(词法分析器); 变种分析器=新BasicMathParser(标记); VAR树= parser.compileUnit(); 无功先生=新IntegerMathVisitor(); 返回visitor.Visit(树); } } 解决方案 @CoronA是正确的。在词法分析器。发生的错误。所以,虽然我仍然认为,建立一个ErrorStrategy会的更好的,这是实际工作对我和我扔未定义输入异常的目标。 首先,我创建了一个派生类从 BaseErrorListener 继承 和的工具 IAntlrErrorListener< T> 。第二部分是我的问题,一直以来它似乎。因为我从访问者 FooBarBaseVistor<继承; INT> ,我的错误监听器还需要是类型与我的词法分析器进行注册的。 类ThrowExceptionErrorListener:BaseErrorListener,IAntlrErrorListener< INT> { // BaseErrorListener实施;不叫在我的测试,但离开它,以防万一 公共覆盖无效的SyntaxError(IRecognizer识别器,的IToken offendingSymbol,诠释行,诠释charPositionInLine,弦乐味精,RecognitionException E) {抛出新的ArgumentException(无效的表达:{0},味精,E); } // IAntlrErrorListener< INT>实施;这其中居然被调用。 公共无效的SyntaxError(IRecognizer识别,诠释offendingSymbol,诠释行,诠释charPositionInLine,弦乐味精,RecognitionException E) {抛出新的ArgumentException(无效的表达:{0} 味精,E); } } 和改变了我的计算器类,我的自定义错误监听器连接到的词法分析的。请注意,您不必删除 ConsoleListener 像我一样的错误实际上被抛出。由于我没有真正使用它,我想最好还是继续前进,这样做。 公共静态类计算器 {公共静态INT评估(字符串表达式) {变种词法分析器=新BasicMathLexer(新AntlrInputStream(表达)); lexer.RemoveErrorListeners(); //删除默认的控制台监听 lexer.AddErrorListener(新ThrowExceptionErrorListener()); 变种令牌=新CommonTokenStream(词法分析器); 变种分析器=新BasicMathParser(标记); VAR树= parser.compileUnit(); 无功先生=新IntegerMathVisitor(); 返回visitor.Visit(树); } } 就是这样。参数异常被抛出这个测试通过了。 [TestMethod的] [的ExpectedException(typeof运算(ArgumentException的)) ] 公共无效BadInput() { VAR EXPR =1 + 5 + 2(3); int值= Calculator.Evaluate(表达式); } 最后一个音符。如果你抛出一个 RecognitionException 在这里,它只会再次得到吞没。 ParseCancelationException 建议,因为它不会从 RecognitionException 派生,但我选择了的ArgumentException ,因为我觉得那才是最有意义的给客户端的C#代码。 I have a simple ANLTR grammar and accompanying Visitor. Everything works great, unless the input is invalid. If the input is invalid, the errors get swallowed and my calculator comes out with the wrong output.I've tried implementing an error listener, over riding the Recover method of the lexer, and.. well... half a dozen other things today. Can someone show me how to simply throw an error instead of swallowing bad "tokens"? (I use quotes because they're not tokens at all. The characters are undefined in my grammar.)Valid Input:Invalid Input:I want to throw an ArgumentException if the parser/lexer comes across parenthesis (or any other undefined character). Currently, the invalid characters seem to just disappear into the ether and the parser just plods along like nothing is wrong.If I run it in the console with the grun command, I get the following output, so it recognizes the invalid tokens on some level.and this resulting parse tree.BasicMath.g4grammar BasicMath;/* * Parser Rules */compileUnit : expression+ EOF;expression : expression MULTIPLY expression #Multiplication | expression DIVIDE expression #Division | expression ADD expression #Addition | expression SUBTRACT expression #Subtraction | NUMBER #Number ;/* * Lexer Rules */NUMBER : INT; //Leave room to extend what kind of math we can do.INT : ('0'..'9')+;MULTIPLY : '*';DIVIDE : '/';SUBTRACT : '-';ADD : '+';WS : [ \t\r\n] -> channel(HIDDEN);Calculator:public static class Calculator{ public static int Evaluate(string expression) { var lexer = new BasicMathLexer(new AntlrInputStream(expression)); var tokens = new CommonTokenStream(lexer); var parser = new BasicMathParser(tokens); var tree = parser.compileUnit(); var visitor = new IntegerMathVisitor(); return visitor.Visit(tree); }} 解决方案 @CoronA was right. The error happens in the lexer.. So, while I still think that creating an ErrorStrategy would be better, this is what actually worked for me and my goal of throwing an exception for undefined input.First, I created a derived class that inherits from BaseErrorListener and implements IAntlrErrorListener<T>. The second part was my problem all along it seems. Because my visitor inherited from FooBarBaseVistor<int>, my error listener also needed to be of type to register it with my lexer. class ThrowExceptionErrorListener : BaseErrorListener, IAntlrErrorListener<int>{ //BaseErrorListener implementation; not called in my test, but left it just in case public override void SyntaxError(IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e) { throw new ArgumentException("Invalid Expression: {0}", msg, e); } //IAntlrErrorListener<int> implementation; this one actually gets called. public void SyntaxError(IRecognizer recognizer, int offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e) { throw new ArgumentException("Invalid Expression: {0}", msg, e); }}And changed my Calculator class to attach my custom error listener to the lexer. Note that you don't have to remove the ConsoleListener like I did for the error to actually be thrown. Since I'm not really using it, I figured it best to go ahead and do so.public static class Calculator{ public static int Evaluate(string expression) { var lexer = new BasicMathLexer(new AntlrInputStream(expression)); lexer.RemoveErrorListeners(); //removes the default console listener lexer.AddErrorListener(new ThrowExceptionErrorListener()); var tokens = new CommonTokenStream(lexer); var parser = new BasicMathParser(tokens); var tree = parser.compileUnit(); var visitor = new IntegerMathVisitor(); return visitor.Visit(tree); }}And that's it. An argument exception is thrown and this test now passes. [TestMethod] [ExpectedException(typeof(ArgumentException))] public void BadInput() { var expr = "1 + 5 + 2(3)"; int value = Calculator.Evaluate(expr); }One last note. If you throw a RecognitionException here, it will just get swallowed up again. ParseCancelationException is recommended, because it does not derive from RecognitionException, but I choose an ArgumentException because I felt that made the most sense to the client C# code. 这篇关于是否有可能抛出一个异常,如果输入的是无效的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-14 16:46