bool CanParse(Precedence context, int li, out Precedence prec) { var opTok = LT(li); if (opTok.Type() == TokenType.Id) { var opTok2 = LT(li + 1); if (opTok2.Type() == TokenType.NormalOp && opTok.EndIndex == opTok2.StartIndex) { prec = _prec.Find(OperatorShape.Infix, opTok2.Value); } else { // Oops, LesPrecedenceMap doesn't yet support non-single-quote ops // (bacause it's shared with LESv2 which doesn't have them) // TODO: improve performance by avoiding this concat prec = _prec.Find(OperatorShape.Infix, (Symbol)("'" + opTok.Value.ToString())); } } else { prec = _prec.Find(OperatorShape.Infix, opTok.Value); } bool result = context.CanParse(prec); if (!context.CanMixWith(prec)) { Error(li, "Operator \"{0}\" cannot be mixed with the infix operator to its left. Add parentheses to clarify the code's meaning.", LT(li).Value); } return(result); }
// Checks if an operator with precedence 'prec' can appear in this context. bool CanAppearHere(Precedence prec, out bool extraParens, bool prefix = false) { extraParens = false; if (prec.CanAppearIn(_context, prefix) && (prefix || _o.MixImmiscibleOperators || prec.CanMixWith(_context))) return true; if (_n.IsParenthesizedExpr()) return true; if (_o.AllowChangeParentheses || !EP.Primary.CanAppearIn(_context)) { Trace.WriteLineIf(!_o.AllowChangeParentheses, "Forced to write node in parens"); return extraParens = true; } return false; }
// Checks if an operator with precedence 'prec' can appear in this context. bool CanAppearIn(Precedence prec, Precedence context, out bool extraParens, bool prefix = false) { extraParens = false; if (prec.CanAppearIn(context, prefix) && (prefix || MixImmiscibleOperators || prec.CanMixWith(context))) { return(true); } if (_n.IsParenthesizedExpr()) { return(true); } if (AllowChangeParenthesis || !EP.Primary.CanAppearIn(context)) { Trace.WriteLineIf(!AllowChangeParenthesis, "Forced to write node in parens"); return(extraParens = true); } return(false); }