Logic.fromString constructor

Logic.fromString(
  1. String text
)

Logic from string with space around & and | but none after !.

e.g.

!a & b | c

Implementation

factory Logic.fromString(String text) {
  Logic? lExpr; // current logical expression
  String? schedOp; // scheduled operation
  for (String term in text.split(" ")) {
    // operation symbol
    if ("&|".contains(term)) {
      if (schedOp != null) {
        throw FormatException("double op forbidden: $term $schedOp");
      }
      if (lExpr == null) {
        throw FormatException(
            "$term cannot be in the beginning of expression");
      }
      schedOp = term;
      continue;
    }
    if (term.contains("&") || term.contains("|")) {
      throw FormatException("& and | must have space around them");
    }

    late final Logic logicTerm;
    if (term[0] == "!") {
      if (term.length == 1) {
        throw FormatException("do not include space after '!'");
      }
      logicTerm = Not.create(LogicAtom(term.substring(1)));
    } else {
      logicTerm = LogicAtom(term);
    }

    // already scheduled operation, e.g. '&'
    if (schedOp != null) {
      lExpr = switch (schedOp) {
        '&' => And.fromList([if (lExpr != null) lExpr, logicTerm]),
        '|' => Or.fromList([if (lExpr != null) lExpr, logicTerm]),
        String() =>
          throw UnimplementedError("Operator $schedOp is not supported"),
      };
      schedOp = null;
      continue;
    }

    // this should be atom
    if (lExpr != null) {
      throw FormatException("missing op between '$lExpr' and '$term'");
    }

    lExpr = logicTerm;
  }

  // let's check that we ended up in correct state
  if (schedOp != null) {
    throw FormatException("premature end-of-expression in '$text'");
  }
  if (lExpr == null) {
    throw FormatException("'$text' is empty");
  }

  // everything looks good now
  return lExpr;
}