sys27 / xFunc

xFunc provides a powerful parser and analyzer for mathematical expressions. It excels at calculating derivatives, simplifying expressions, and achieving high performance.
https://sys27.github.io/xFunc/
MIT License
57 stars 6 forks source link

Parse() can throw unexpected exceptions #766

Open mschessler opened 8 months ago

mschessler commented 8 months ago

Describe the bug Is parse() supposed to be able to deal with user input ? Currently it throws several unexpected exceptions on malformed input. I would expect xFunc.Maths.ParseException or xFunc.Maths.TokenizeException.

First Case var exp = processor.Parse("2e");

System.FormatException: The input string '2e' was not in a correct format. at System.Number.ThrowFormatException[TChar](ReadOnlySpan1 value) at System.Double.Parse(ReadOnlySpan1 s, IFormatProvider provider) at xFunc.Maths.Tokenization.Lexer.CreateDecToken() at xFunc.Maths.Tokenization.Lexer.CreateNumberToken() at xFunc.Maths.Tokenization.Lexer.MoveNext() at xFunc.Maths.Parser.TokenReader.Read() at xFunc.Maths.Parser.TokenReader.GetCurrentAndAdvance(TokenKind kind) at xFunc.Maths.Parser.ParseFor(TokenReader& tokenReader) at xFunc.Maths.Parser.ParseStatement(TokenReader& tokenReader) at xFunc.Maths.Parser.Parse(String expression) at xFunc.Maths.Processor.Parse(String function)

Second Case var exp = processor.Parse("0111111111111151111110000");

System.OverflowException: Arithmetic operation resulted in an overflow. at xFunc.Maths.Tokenization.ParseNumbers.GrabLongs(Int32 radix, ReadOnlySpan1 s, Int32& i) at xFunc.Maths.Tokenization.ParseNumbers.ToInt64(ReadOnlySpan1 value, Int32 fromBase) at xFunc.Maths.Tokenization.Lexer.CreateOctToken() at xFunc.Maths.Tokenization.Lexer.CreateNumberToken() at xFunc.Maths.Tokenization.Lexer.MoveNext() at xFunc.Maths.Parser.TokenReader.Read() at xFunc.Maths.Parser.TokenReader.GetCurrentAndAdvance(TokenKind kind) at xFunc.Maths.Parser.ParseFor(TokenReader& tokenReader) at xFunc.Maths.Parser.ParseStatement(TokenReader& tokenReader) at xFunc.Maths.Parser.Parse(String expression) at xFunc.Maths.Processor.Parse(String function)

Third Case string = "{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{"

Trying to parse it leads to a StackOverflow.

sys27 commented 8 months ago

Currently TokenizeExcetion/ParseException is thrown only when Lexer/Parse detects incorrect input. For example, the last case doesn't result in StackOverflow but instead throws ParseException because it detects invalid grammar.

First two cases are different, they are based on methods from the standard .NET library. They may throw FormatException or OverflowException. FormatException - it tries to parse 2e as "scientific notation", like 2e+10 but the last part is missing, so here is an exception. An additional point to think about: xFunc supports implicit multiplication, like 2x. So, in that case, 2e could be parsed as 2 * e, maybe we need to validate it. OverflowException - completely valid case. xFunc supports different numeral systems (dec, oct - number start from 0, hex - 0x prefix, bin - 0b prefix), and oct/hex/bin are only supported for integer numbers. So, your number is treated as octal and it is too big to be stored in long.

Unfortunately, these exceptions aren't handled by xFunc. I agree it is better to wrap them into a custom exception. #767