private ParseErrorType HandleOperator(ParseContext context, out bool isUnary) { var currentOperator = new TokenOperator(firstInExpression: (_operands.Count == 0)); currentOperator.Parse(context, null); isUnary = currentOperator.IsUnary; if (currentOperator.OperatorType == OperatorType.Not) { //This comes from the fact that // x < -1 // y < -1 // 2 + !x + y // yields 2 (i.e. bang applies to the entire expression that follows isUnary = true; if (!IsInGroup && context.Tokens.IsLineBreakAfter(context.TextProvider, context.Tokens.Position - 1)) { // Make sure expression that follows is not empty return(ParseErrorType.RightOperandExpected); } var exp = new Expression(IsInGroup); if (!exp.Parse(context, null)) { return(ParseErrorType.RightOperandExpected); } _operators.Push(currentOperator); _operands.Push(exp); return(ParseErrorType.None); } return(HandleOperatorPrecedence(context, currentOperator)); }
private ParseErrorType HandleOperator(ParseContext context, IAstNode parent, out bool isUnary) { TokenOperator currentOperator = new TokenOperator(firstInExpression: (_operands.Count == 0)); currentOperator.Parse(context, null); isUnary = currentOperator.IsUnary; return(HandleOperatorPrecedence(context, currentOperator)); }
private ParseErrorType HandleOperator(ParseContext context, IAstNode parent, out bool isUnary) { ParseErrorType errorType = ParseErrorType.None; // If operands stack is empty the operator is unary. // If operator is preceded by another operator, // it is interpreted as unary. TokenOperator currentOperator = new TokenOperator(_operands.Count == 0); currentOperator.Parse(context, null); isUnary = currentOperator.IsUnary; IOperator lastOperator = _operators.Peek(); if (isUnary && lastOperator != null && lastOperator.IsUnary) { // !!!x is treated as !(!(!x))) // Step back and re-parse as expression context.Tokens.Position -= 1; var exp = new Expression(inGroup: false); if (exp.Parse(context, null)) { _operands.Push(exp); return(ParseErrorType.None); } } if (currentOperator.Precedence <= lastOperator.Precedence && !(currentOperator.OperatorType == lastOperator.OperatorType && currentOperator.Association == Association.Right)) { // New operator has lower or equal precedence. We need to make a tree from // the topmost operator and its operand(s). Example: a*b+c. + has lower priority // and a and b should be on the stack along with * on the operator stack. // Repeat until there are no more higher precendece operators on the stack. errorType = this.ProcessHigherPrecendenceOperators(context, currentOperator); } if (errorType == ParseErrorType.None) { _operators.Push(currentOperator); } return(errorType); }
void Digest(int start, int end) { // scan tokens while (start < end) { string s = text.Substring(start, end - start); if (s.StartsWith(")")) { throw new FormatException($"错误的右括号!"); } if (s.StartsWith("(")) { int bracket = 1; for (int i = 1; i < s.Length; i++) { if (s[i] == ')') { bracket--; if (bracket == 0) { tokens.Add(Expression.Parse(text, start + 1, start + i)); start += i + 1; break; } } else if (s[i] == '(') { bracket++; } } if (bracket > 0) { throw new FormatException($"括号未封闭!"); } continue; } // operators var ro = TokenOperator.Operators.Find(u => s.StartsWith(u.Simbol)); if (ro != null) { tokens.Add(TokenOperator.Parse(ro.Simbol)); start += ro.Simbol.Length; continue; } // names and values var m = Regex.Match(s, @"^[\d\p{L}-_]+"); if (m.Success) { tokens.Add(new TokenVal(m.Value)); start += m.Value.Length; continue; } // error throw new FormatException($"无法解析符号'{s[0]}'"); } // build tree List <Token> newTokens = new List <Token>(); List <Token> list = new List <Token>(); foreach (var item in tokens) { if (item is TokenLogical) { if (list.Count == 0) { throw new FormatException($"表达式不完整!"); } newTokens.Add(new Expression(text, list)); newTokens.Add(item); list.Clear(); } else { list.Add(item); } } if (newTokens.Count > 0) { if (list.Count == 0) { throw new FormatException($"表达式不完整!"); } newTokens.Add(new Expression(text, list)); tokens = newTokens; } }