private void RegisterSurroundingParenthesesDuringInitialization() { ParenthesizedExpression parentheses = GetSurroundingParentheses(); ParenthesizedExpression registeredParentheses; bool alreadyRegistered; if (parentheses != null && (!(alreadyRegistered = expressionThatMayNeedParenthesesToParentheses.TryGetValue(parentheses.Expression, out registeredParentheses)) || parentheses == registeredParentheses)) { if (!alreadyRegistered) { expressionThatMayNeedParenthesesToParentheses.Add(parentheses.Expression, parentheses); } expressionsThatCanCauseOthersBeingParenthesized.Add(GetExpressionOfSurroundingOperator()); } else { // we don't have surrounding parentheses at all, or we have more than one parentheses which causes ambiguity throw new UnparserInitializationException(string.Format("Cannot automatically determine parentheses")); } }
private BnfTermKind CalculateBnfTermKindForNonTerminal(NonTerminal current) { BnfTermKind?currentKind = null; var childOperators = new List <BnfTerm>(); foreach (BnfTermList children in Unparser.GetChildBnfTermListsLeftToRight(current)) { int operatorCount = 0; int leftParenthesisCount = 0; int rightParenthesisCount = 0; int otherCount = 0; /* * NOTE: we should not read bnfTermToBnfTermKind in this method (because of recursive definitions in grammar), * that's why we store BnfTermKind as well * */ BnfTerm prevChild = null; BnfTermKind? prevChildKind = null; ParenthesizedExpression parentheses = null; BnfTerm childExpression = null; if (children.Count == 0) { continue; } BnfTerm childOperator = null; foreach (BnfTerm child in children) { BnfTermKind childKind = CalculateBnfTermKind(child); Debug.Assert(childKind != BnfTermKind.Undetermined); #region Handle childKind switch (childKind) { case BnfTermKind.Operator: operatorCount++; childOperator = child; childExpression = null; parentheses = null; break; case BnfTermKind.LeftParenthesis: leftParenthesisCount++; parentheses = new ParenthesizedExpression() { LeftParenthesis = child }; childExpression = null; break; case BnfTermKind.RightParenthesis: rightParenthesisCount++; if (prevChildKind == BnfTermKind.Other && childExpression == prevChild) { Debug.Assert(parentheses != null && parentheses.LeftParenthesis != null && parentheses.Expression != null); parentheses.RightParenthesis = child; ParenthesizedExpression registeredParentheses; if (_expressionToParentheses.TryGetValue(childExpression, out registeredParentheses)) { if (parentheses != registeredParentheses) { _expressionToParentheses[childExpression] = null; // ambiguous parentheses -> set to null, and check later (we might not need the parentheses at all) } } else { _expressionToParentheses.Add(childExpression, parentheses); } } childExpression = null; parentheses = null; break; case BnfTermKind.Other: otherCount++; if (prevChildKind == BnfTermKind.LeftParenthesis) { Debug.Assert(parentheses != null && parentheses.LeftParenthesis != null); childExpression = child; parentheses.Expression = childExpression; } else { childExpression = null; parentheses = null; } break; } #endregion if (childKind != BnfTermKind.GrammarHint) { prevChild = child; prevChildKind = childKind; } } #region Determine childListLooksLike BnfTermKind?childListLooksLike; if (operatorCount == 1 && leftParenthesisCount == 0 && rightParenthesisCount == 0 && otherCount == 0) { childListLooksLike = BnfTermKind.Operator; } else if (leftParenthesisCount == 1 && operatorCount == 0 && rightParenthesisCount == 0 && otherCount == 0) { childListLooksLike = BnfTermKind.LeftParenthesis; } else if (rightParenthesisCount == 1 && operatorCount == 0 && leftParenthesisCount == 0 && otherCount == 0) { childListLooksLike = BnfTermKind.RightParenthesis; } else { childListLooksLike = BnfTermKind.Other; } #endregion if (childListLooksLike == BnfTermKind.Operator) { childOperators.Add(childOperator); } #region Determine currentKind if ((currentKind == null || currentKind == BnfTermKind.Operator) && childListLooksLike == BnfTermKind.Operator) { currentKind = BnfTermKind.Operator; } else if ((currentKind == null || currentKind == BnfTermKind.LeftParenthesis) && childListLooksLike == BnfTermKind.LeftParenthesis) { currentKind = BnfTermKind.LeftParenthesis; } else if ((currentKind == null || currentKind == BnfTermKind.RightParenthesis) && childListLooksLike == BnfTermKind.RightParenthesis) { currentKind = BnfTermKind.RightParenthesis; } else { currentKind = BnfTermKind.Other; } #endregion } if (currentKind == BnfTermKind.Operator) { HandleOperators(current, childOperators); } return(currentKind ?? BnfTermKind.Other); }