📜 ⬆️ ⬇️

Regular expressions and math parser

Once upon a time I needed a parser for mathematical expressions in C #. Of course, downloading the finished implementation is not a problem. But only I did not have the Internet in those years. As a result, absolutely without hesitation and without the theoretical foundations of parsers, finite automata, and other things, it was written through regular expressions. Minutes past 10. It is worth noting that only arithmetic actions and brackets were needed. Support for trigonometric functions and other things not required.

First, select regular expressions for numbers and actions:
private const string RegexBr = "\\(([1234567890\\.\\+\\-\\*\\/^%]*)\\)"; //  private const string RegexNum = "[-]?\\d+\\.?\\d*"; //  private const string RegexMulOp = "[\\*\\/^%]"; //   private const string RegexAddOp = "[\\+\\-]"; //   

Now the method that separates the resulting string into elements and recursively calculates them:
 public static double Parse(string str) { //   var matchSk = Regex.Match(str, RegexBr); if (matchSk.Groups.Count > 1) { string inner = matchSk.Groups[0].Value.Substring(1, matchSk.Groups[0].Value.Trim().Length - 2); string left = str.Substring(0, matchSk.Index); string right = str.Substring(matchSk.Index + matchSk.Length); return Parse(left + Parse(inner).ToString(CultureInfo.InvariantCulture) + right); } //   var matchMulOp = Regex.Match(str, string.Format("({0})\\s?({1})\\s?({2})\\s?", RegexNum, RegexMulOp, RegexNum)); var matchAddOp = Regex.Match(str, string.Format("({0})\\s?({1})\\s?({2})\\s?", RegexNum, RegexAddOp, RegexNum)); var match = matchMulOp.Groups.Count > 1 ? matchMulOp : matchAddOp.Groups.Count > 1 ? matchAddOp : null; if (match != null) { string left = str.Substring(0, match.Index); string right = str.Substring(match.Index + match.Length); return Parse(left + ParseAct(match).ToString(CultureInfo.InvariantCulture) + right); } //   try { return double.Parse(str, CultureInfo.InvariantCulture); } catch (FormatException) { throw new FormatException(string.Format("   '{0}'", str)); } } 

And the last write method that directly calculates the value of the action:
 private static double ParseAct(Match match) { double a = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); double b = double.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture); switch (match.Groups[2].Value) { case "+": return a + b; case "-": return a - b; case "*": return a * b; case "/": return a / b; case "^": return Math.Pow(a, b); case "%": return a % b; default: throw new FormatException($"   '{match.Value}'"); } } 

I had this “abnormal programming”. I don’t see any point in the full text of the source text - it is unlikely that anyone will need it. But in any case, to make a class of three pieces is a matter of a couple of seconds.

Thanks for attention.

')

Source: https://habr.com/ru/post/271285/


All Articles