function _canonicalizeRule (ruleObject, context) {
    const newRule = {}
    if (ruleObject.s) {
      const lr = ruleObject.s.split('->')
      if (lr.length === 2) {
        newRule.l = lr[0]
        newRule.r = lr[1]
      } else {
        throw SyntaxError('Could not parse rule: ' + ruleObject.s)
      }
    } else {
      newRule.l = ruleObject.l
      newRule.r = ruleObject.r
    }
    newRule.l = removeParens(parse(newRule.l))
    newRule.r = removeParens(parse(newRule.r))
    for (const prop of ['imposeContext', 'repeat', 'assuming']) {
      if (prop in ruleObject) {
        newRule[prop] = ruleObject[prop]
      }
    }
    if (ruleObject.evaluate) {
      newRule.evaluate = parse(ruleObject.evaluate)
    }

    if (isAssociative(newRule.l, context)) {
      const nonCommutative = !isCommutative(newRule.l, context)
      let leftExpandsym
      // Gen. the LHS placeholder used in this NC-context specific expansion rules
      if (nonCommutative) leftExpandsym = _getExpandPlaceholderSymbol()

      const makeNode = createMakeNodeFunction(newRule.l)
      const expandsym = _getExpandPlaceholderSymbol()
      newRule.expanded = {}
      newRule.expanded.l = makeNode([newRule.l, expandsym])
      // Push the expandsym into the deepest possible branch.
      // This helps to match the newRule against nodes returned from getSplits() later on.
      flatten(newRule.expanded.l, context)
      unflattenr(newRule.expanded.l, context)
      newRule.expanded.r = makeNode([newRule.r, expandsym])

      // In and for a non-commutative context, attempting with yet additional expansion rules makes
      // way for more matches cases of multi-arg expressions; such that associative rules (such as
      // 'n*n -> n^2') can be applied to exprs. such as 'a * b * b' and 'a * b * b * a'.
      if (nonCommutative) {
        // 'Non-commutative' 1: LHS (placeholder) only
        newRule.expandedNC1 = {}
        newRule.expandedNC1.l = makeNode([leftExpandsym, newRule.l])
        newRule.expandedNC1.r = makeNode([leftExpandsym, newRule.r])
        // 'Non-commutative' 2: farmost LHS and RHS placeholders
        newRule.expandedNC2 = {}
        newRule.expandedNC2.l = makeNode([leftExpandsym, newRule.expanded.l])
        newRule.expandedNC2.r = makeNode([leftExpandsym, newRule.expanded.r])
      }
    }

    return newRule
  }
Takes any rule object as allowed by the specification in simplify
and puts it in a standard form used by applyRule