public Expression Pop(ExpressionT type) { var expression = Peek(type); expressions.RemoveAt(expressions.Count - 1); types.RemoveAt(types.Count - 1); return(expression); }
public Expression Peek(ExpressionT toType) { var fromType = types[types.Count - 1]; var expression = expressions[expressions.Count - 1]; if (toType == fromType) { return(expression); } switch (toType) { case ExpressionT.Bool: return(IfThenElse(AsBool(expression), True, False)); case ExpressionT.Int: return(IfThenElse(expression, One, Zero)); } throw new InvalidProgramException("Unable to convert ExpressionType.{0} to ExpressionType.{1}".F(Enum <ExpressionT> .GetValues()[(int)fromType], Enum <ExpressionT> .GetValues()[(int)toType])); }
public Expression Build(Token[] postfix, ExpressionT resultType) { foreach (var t in postfix) { switch (t.Type) { case TokenType.And: { var y = ast.Pop(ExpressionT.Bool); var x = ast.Pop(ExpressionT.Bool); ast.Push(Expressions.Expression.And(x, y)); continue; } case TokenType.Or: { var y = ast.Pop(ExpressionT.Bool); var x = ast.Pop(ExpressionT.Bool); ast.Push(Expressions.Expression.Or(x, y)); continue; } case TokenType.Add: { var y = ast.Pop(ExpressionT.Bool); var x = ast.Pop(ExpressionT.Bool); ast.Push(Expressions.Expression.Add(x, y)); continue; } case TokenType.GreaterThan: { var y = ast.Pop(ExpressionT.Int); var x = ast.Pop(ExpressionT.Int); ast.Push(Expressions.Expression.GreaterThan(x, y)); continue; } case TokenType.GreaterThanOrEqual: { var y = ast.Pop(ExpressionT.Int); var x = ast.Pop(ExpressionT.Int); ast.Push(Expressions.Expression.GreaterThanOrEqual(x, y)); continue; } case TokenType.LessThan: { var y = ast.Pop(ExpressionT.Int); var x = ast.Pop(ExpressionT.Int); ast.Push(Expressions.Expression.LessThan(x, y)); continue; } case TokenType.LessThanOrEqual: { var y = ast.Pop(ExpressionT.Int); var x = ast.Pop(ExpressionT.Int); ast.Push(Expressions.Expression.LessThanOrEqual(x, y)); continue; } case TokenType.False: { ast.Push(False); continue; } case TokenType.True: { ast.Push(True); continue; } case TokenType.Number: { ast.Push(Expressions.Expression.Constant(((NumberToken)t).Value)); continue; } case TokenType.Variable: { var symbol = Expressions.Expression.Constant(((VariableToken)t).Symbol); Func <string, IReadOnlyDictionary <string, int>, int> parseSymbol = ParseSymbol; ast.Push(Expressions.Expression.Call(parseSymbol.Method, symbol, SymbolsParam)); continue; } case TokenType.Not: { ast.Push(Expressions.Expression.Not(ast.Pop(ExpressionT.Bool))); continue; } case TokenType.NotEquals: { var y = ast.Pop(ExpressionT.Int); var x = ast.Pop(ExpressionT.Int); ast.Push(Expressions.Expression.NotEqual(x, y)); continue; } case TokenType.Equals: { var y = ast.Pop(ExpressionT.Int); var x = ast.Pop(ExpressionT.Int); ast.Push(Expressions.Expression.Equal(x, y)); continue; } default: throw new InvalidProgramException("ConditionExpression.Compile() is missing an expression builder for TokenType.{0}".F(Enum <TokenType> .GetValues()[(int)t.Type])); } } return(ast.Pop(resultType)); }
Expression Build(ExpressionT resultType) { var tokens = new List <Token>(); var currentOpeners = new Stack <Token>(); Token lastToken = null; for (var i = 0; ;) { var token = Token.GetNext(Expression, ref i, lastToken != null ? lastToken.Type : TokenType.Invalid); if (token == null) { //Sanity check parsed tree if (lastToken == null) { throw new InvalidDataException("Empty expression"); } //Expressions can't end with a binary or unary prefix operation //表达式不能以二进制或一元前缀操作结束 if (lastToken.RightOperand) { throw new InvalidDataException("Missing value or sub-expression at end for '{0}' operator".F(lastToken.Symbol)); } break; } if (token.Closes != Grouping.None) { if (currentOpeners.Count == 0) { throw new InvalidDataException("Unmatched closing parenthesis at index {0}".F(token.Index)); } currentOpeners.Pop(); } if (token.Opens != Grouping.None) { currentOpeners.Push(token); } if (lastToken == null) { //Expressions can't end with a binary or unary prefix operation if (token.LeftOperand) { throw new InvalidDataException("Missing value or sub-expression at beginning for '{0}' operator".F(token.Symbol)); } } else { if (lastToken.Opens != Grouping.None && token.Closes != Grouping.None) { throw new InvalidDataException("Empty parenthesis at index {0}".F(lastToken.Index)); } if (lastToken.RightOperand == token.LeftOperand) { if (lastToken.RightOperand) { throw new InvalidDataException("Missing value or sub-expression or there is an extra operator '{0}' at index {1} or '{2}' at index {3}".F( lastToken.Symbol, lastToken.Index, token.Symbol, token.Index )); } throw new InvalidDataException("Missing binary operation before '{0}' at index {1}".F(token.Symbol, token.Index)); } } if (token.Type == TokenType.Variable) { variables.Add(token.Symbol); } tokens.Add(token); lastToken = token; } if (currentOpeners.Count > 0) { throw new InvalidDataException("Unclosed opening parenthesis at index {0}".F(currentOpeners.Peek().Index)); } return(new Compiler().Build(ToPostfix(tokens).ToArray(), resultType)); }