Шаблон для формулы, которая содержит цифры, буквы, выражения и скобки - PullRequest
0 голосов
/ 28 июня 2019

Я пытаюсь написать регулярное выражение для формулы для следующих примеров.

  1. C=A+B => Output for match will be {A, +, B}
  2. D= C+50 => Output for match will be{C, +, 50}
  3. E = (A+B)*C -100 => Output for match will be{(, A, +, B, ), *, C, -, 100}

Я пытался с регулярным выражением

[A-Z(\d*)*+/-]

выход для этого {A, +, 5, 0}

Но это не дает правильного вывода для A+50

Ответы [ 2 ]

4 голосов
/ 28 июня 2019

Я предлагаю FSM (конечный автомат) вместо регулярных выражений . У нас есть 3 состояний здесь:

  1. Ни переменная, ни число 0
  2. в переменной 1
  3. Внутри номера 2

Код:

private static IEnumerable<string> Parse(string formula) {
  int state = 0;

  StringBuilder buffer = new StringBuilder();

  foreach (var c in formula) {
    if (state == 0) { // neither var nor number
      if (char.IsWhiteSpace(c))
        continue;

      if (char.IsDigit(c)) {
        buffer.Append(c);
        state = 2;
      }
      else if (char.IsLetter(c)) {
        buffer.Append(c);
        state = 1;
      } 
      else 
        yield return c.ToString();
    }
    else if (state == 1) { // within variable
      if (char.IsDigit(c) || char.IsLetter(c))
        buffer.Append(c);
      else {
        yield return buffer.ToString();
        buffer.Clear(); 

        state = 0;

        if (!char.IsWhiteSpace(c))
          yield return c.ToString();
      }
    }
    else if (state == 2) { // within number
      if (char.IsDigit(c))
        buffer.Append(c);
      else if (char.IsLetter(c)) {
        // 123abc we turn into 123 * abc
        yield return buffer.ToString();
        buffer.Clear();

        state = 1; 

        yield return "*";

        buffer.Append(c);
      }
      else {
        yield return buffer.ToString();
        buffer.Clear();

        state = 0;

        if (!char.IsWhiteSpace(c))
          yield return c.ToString();
      } 
    }
  } 

  if (buffer.Length > 0)
    yield return buffer.ToString();
}

Демо-версия:

  string[] tests = new string[] {
    "C=A+B",
    "D= C+50",
    "E = (A+B)*C -100",
  };

  string result = string.Join(Environment.NewLine, tests
    .Select(test => new {
      formula = test,
      parsed = Parse(test)
        .SkipWhile(term => term != "=") // we don't want "C = " or alike part
        .Skip(1)
    })
    .Select(test => $"{test.formula,-20} => {string.Join(", ", test.parsed)}"));

 Console.Write(result);

Результат:

C=A+B                => A, +, B
D= C+50              => C, +, 50
E = (A+B)*C -100     => (, A, +, B, ), *, C, -, 100
1 голос
/ 28 июня 2019

Используйте | (или) для отдельных элементов, таких как шаблон

\d+|\W|\w

, что переводится в любое число (и) ИЛИ любой не алфавитный символ ИЛИ любой алфавитный символ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...