private static bool MergeModulus(ExpressionBase left, ExpressionBase right, out ExpressionBase result) { // if either side is a float, convert both to float if (left.Type == ExpressionType.FloatConstant || right.Type == ExpressionType.FloatConstant) { if (!ConvertToFloat(ref left, ref right, out result)) { return(false); } if (((FloatConstantExpression)right).Value == 0.0) { result = new ParseErrorExpression("Division by zero"); return(false); } result = new FloatConstantExpression(((FloatConstantExpression)left).Value % ((FloatConstantExpression)right).Value); return(true); } if (left.Type == ExpressionType.IntegerConstant && right.Type == ExpressionType.IntegerConstant) { if (((IntegerConstantExpression)right).Value == 0) { result = new ParseErrorExpression("Division by zero"); return(false); } result = new IntegerConstantExpression(((IntegerConstantExpression)left).Value % ((IntegerConstantExpression)right).Value); return(true); } result = new ParseErrorExpression("Cannot modulus expressions"); return(false); }
private static bool MergeAddition(ExpressionBase left, ExpressionBase right, out ExpressionBase result) { // if either side is a string, combine to a larger string if (left.Type == ExpressionType.StringConstant || right.Type == ExpressionType.StringConstant) { var builder = new StringBuilder(); left.AppendStringLiteral(builder); right.AppendStringLiteral(builder); result = new StringConstantExpression(builder.ToString()); return(true); } // if either side is a float, convert both to float if (left.Type == ExpressionType.FloatConstant || right.Type == ExpressionType.FloatConstant) { if (!ConvertToFloat(ref left, ref right, out result)) { return(false); } result = new FloatConstantExpression(((FloatConstantExpression)left).Value + ((FloatConstantExpression)right).Value); return(true); } if (left.Type == ExpressionType.IntegerConstant && right.Type == ExpressionType.IntegerConstant) { result = new IntegerConstantExpression(((IntegerConstantExpression)left).Value + ((IntegerConstantExpression)right).Value); return(true); } result = new ParseErrorExpression("Cannot add expressions"); return(false); }
private static bool MergeBitwiseAnd(ExpressionBase left, ExpressionBase right, out ExpressionBase result) { if (left.Type == ExpressionType.IntegerConstant && right.Type == ExpressionType.IntegerConstant) { result = new IntegerConstantExpression(((IntegerConstantExpression)left).Value & ((IntegerConstantExpression)right).Value); return(true); } result = new ParseErrorExpression("Cannot bitwise and expressions"); return(false); }
/// <summary> /// Replaces the variables in the expression with values from <paramref name="scope" />. /// </summary> /// <param name="scope">The scope object containing variable values.</param> /// <param name="result">[out] The new expression containing the replaced variables.</param> /// <returns> /// <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />. /// </returns> public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result) { ExpressionBase left; if (!Left.ReplaceVariables(scope, out left)) { result = left; return(false); } ExpressionBase right; if (!Right.ReplaceVariables(scope, out right)) { result = right; return(false); } var integerLeft = left as IntegerConstantExpression; var integerRight = right as IntegerConstantExpression; switch (Operation) { case MathematicOperation.Add: var stringLeft = left as StringConstantExpression; var stringRight = right as StringConstantExpression; if (stringLeft != null) { if (stringRight != null) { result = new StringConstantExpression(stringLeft.Value + stringRight.Value); return(true); } if (integerRight != null) { result = new StringConstantExpression(stringLeft.Value + integerRight.Value.ToString()); return(true); } } else if (stringRight != null) { if (integerLeft != null) { result = new StringConstantExpression(integerLeft.Value.ToString() + stringRight.Value); return(true); } } // prefer constants on right if (integerLeft != null && integerRight == null) { var temp = left; left = right; right = temp; integerRight = integerLeft; integerLeft = null; } if (integerRight != null) { if (integerRight.Value == 0) // anything plus 0 is itself { result = left; return(true); } if (integerLeft != null) { result = new IntegerConstantExpression(integerLeft.Value + integerRight.Value); return(true); } } break; case MathematicOperation.Subtract: if (integerRight != null) { if (integerRight.Value == 0) // anything minus 0 is itself { result = left; return(true); } if (integerLeft != null) { result = new IntegerConstantExpression(integerLeft.Value - integerRight.Value); return(true); } } break; case MathematicOperation.Multiply: // prefer constants on right if (integerLeft != null && integerRight == null) { var temp = left; left = right; right = temp; integerRight = integerLeft; integerLeft = null; } if (integerRight != null) { if (integerRight.Value == 0) // anything times 0 is 0 { result = right; return(true); } if (integerRight.Value == 1) // anything times 1 is itself { result = left; return(true); } if (integerLeft != null) { result = new IntegerConstantExpression(integerLeft.Value * integerRight.Value); return(true); } } break; case MathematicOperation.Divide: if (integerRight != null) { if (integerRight.Value == 0) // division by 0 is impossible { result = new ParseErrorExpression("division by zero", this); return(false); } if (integerRight.Value == 1) // anything divided by 1 is itself { result = left; return(true); } if (integerLeft != null) { result = new IntegerConstantExpression(integerLeft.Value / integerRight.Value); return(true); } } break; case MathematicOperation.Modulus: if (integerRight != null) { if (integerRight.Value == 0) // division by 0 is impossible { result = new ParseErrorExpression("division by zero", this); return(false); } if (integerRight.Value == 1) // anything modulus 1 is 0 { result = new IntegerConstantExpression(0); return(true); } if (integerLeft != null) { result = new IntegerConstantExpression(integerLeft.Value % integerRight.Value); return(true); } } break; } var mathematic = new MathematicExpression(left, Operation, right); mathematic.Line = Line; mathematic.Column = Column; result = mathematic; return(true); }
private static bool MergeIdentity(ExpressionBase left, MathematicOperation operation, ExpressionBase right, out ExpressionBase result) { bool isZero = false; bool isOne = false; var integerRight = right as IntegerConstantExpression; if (integerRight != null) { isZero = (integerRight.Value == 0); isOne = (integerRight.Value == 1); } else { var floatRight = right as FloatConstantExpression; if (floatRight != null) { isZero = floatRight.Value == 0.0f; isOne = floatRight.Value == 1.0f; } } if (isZero) { switch (operation) { case MathematicOperation.Add: case MathematicOperation.Subtract: // anything plus or minus 0 is itself result = left; return(true); case MathematicOperation.Multiply: case MathematicOperation.BitwiseAnd: // anything times 0 is 0 // anything bitwise and 0 is 0 result = right; return(true); case MathematicOperation.Divide: case MathematicOperation.Modulus: result = new ParseErrorExpression("Division by zero"); return(false); } } else if (isOne) { switch (operation) { case MathematicOperation.Multiply: case MathematicOperation.Divide: // anything multiplied or divided by 1 is itself result = left; return(true); case MathematicOperation.Modulus: // anything modulus 1 is 0 result = new IntegerConstantExpression(0); return(true); } } result = null; return(false); }
private static ExpressionBase ParseClauseCore(PositionalTokenizer tokenizer) { ExpressionBase clause; switch (tokenizer.NextChar) { case '!': tokenizer.Advance(); clause = ParseClause(tokenizer); if (clause.Type == ExpressionType.ParseError) { return(clause); } return(new ConditionalExpression(null, ConditionalOperation.Not, clause)); case '(': if (AnonymousUserFunctionDefinitionExpression.IsAnonymousParameterList(tokenizer)) { return(AnonymousUserFunctionDefinitionExpression.ParseAnonymous(tokenizer)); } tokenizer.Advance(); clause = ExpressionBase.Parse(tokenizer); if (clause.Type == ExpressionType.ParseError) { return(clause); } if (tokenizer.NextChar != ')') { if (tokenizer.NextChar == '\0') { return(ParseError(tokenizer, "No closing parenthesis found")); } return(ParseError(tokenizer, "Expected closing parenthesis, found: " + tokenizer.NextChar)); } clause.IsLogicalUnit = true; tokenizer.Advance(); return(clause); case '"': try { var stringValue = tokenizer.ReadQuotedString().ToString(); return(new StringConstantExpression(stringValue)); } catch (InvalidOperationException ex) { return(ParseError(tokenizer, ex.Message)); } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return(ParseNumber(tokenizer, true)); case '-': var tokenStart = tokenizer.Location; tokenizer.Advance(); if (tokenizer.NextChar >= '0' && tokenizer.NextChar <= '9') { var result = ParseNumber(tokenizer, false); var tokenEnd = result.Location.End; switch (result.Type) { case ExpressionType.IntegerConstant: result = new IntegerConstantExpression(-((IntegerConstantExpression)result).Value); break; case ExpressionType.FloatConstant: result = new FloatConstantExpression(-((FloatConstantExpression)result).Value); break; default: return(result); } result.Location = new TextRange(tokenStart, tokenEnd); return(result); } return(ParseError(tokenizer, "Minus without value", tokenStart.Line, tokenStart.Column)); case '{': tokenizer.Advance(); return(DictionaryExpression.Parse(tokenizer)); case '[': tokenizer.Advance(); return(ParseArray(tokenizer)); default: var line = tokenizer.Line; var column = tokenizer.Column; var identifier = tokenizer.ReadIdentifier(); if (identifier.IsEmpty) { var error = ParseError(tokenizer, "Unexpected character: " + tokenizer.NextChar); tokenizer.Advance(); return(error); } SkipWhitespace(tokenizer); if (identifier == "return") { clause = ExpressionBase.Parse(tokenizer); if (clause.Type == ExpressionType.ParseError) { return(clause); } return(new ReturnExpression(new KeywordExpression(identifier.ToString(), line, column), clause)); } if (identifier == "function") { return(UserFunctionDefinitionExpression.Parse(tokenizer, line, column)); } if (identifier == "for") { return(ForExpression.Parse(tokenizer, line, column)); } if (identifier == "if") { return(IfExpression.Parse(tokenizer, line, column)); } if (identifier == "true") { return(new BooleanConstantExpression(true, line, column)); } if (identifier == "false") { return(new BooleanConstantExpression(false, line, column)); } if (tokenizer.NextChar == '(') { tokenizer.Advance(); var parameters = new List <ExpressionBase>(); ParseParameters(tokenizer, parameters); var functionCall = new FunctionCallExpression(new FunctionNameExpression(identifier.ToString(), line, column), parameters); functionCall.Location = new TextRange(line, column, tokenizer.Line, tokenizer.Column - 1); return(functionCall); } if (tokenizer.NextChar == '[') { IndexedVariableExpression parent = null; do { tokenizer.Advance(); var index = ExpressionBase.Parse(tokenizer); if (index.Type == ExpressionType.ParseError) { return(index); } SkipWhitespace(tokenizer); if (tokenizer.NextChar != ']') { return(ParseError(tokenizer, "Expecting closing bracket after index")); } tokenizer.Advance(); SkipWhitespace(tokenizer); if (parent != null) { parent = new IndexedVariableExpression(parent, index); } else { parent = new IndexedVariableExpression(new VariableExpression(identifier.ToString(), line, column), index); } } while (tokenizer.NextChar == '['); return(parent); } return(new VariableExpression(identifier.ToString(), line, column)); } }
private static ExpressionBase ParseNumber(PositionalTokenizer tokenizer, bool isUnsigned) { int line = tokenizer.Line; int column = tokenizer.Column; int endLine = line; int endColumn = column; uint value; string number = ""; if (tokenizer.Match("0x")) { while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f')) { number += tokenizer.NextChar; endLine = tokenizer.Line; endColumn = tokenizer.Column; tokenizer.Advance(); } if (!UInt32.TryParse(number, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out value)) { return(new ParseErrorExpression("Number too large")); } } else { while (Char.IsDigit(tokenizer.NextChar)) { number += tokenizer.NextChar; endLine = tokenizer.Line; endColumn = tokenizer.Column; tokenizer.Advance(); } if (tokenizer.NextChar == '.') { number += tokenizer.NextChar; tokenizer.Advance(); while (Char.IsDigit(tokenizer.NextChar)) { number += tokenizer.NextChar; endLine = tokenizer.Line; endColumn = tokenizer.Column; tokenizer.Advance(); } float floatValue; if (!float.TryParse(number, System.Globalization.NumberStyles.AllowDecimalPoint, System.Globalization.CultureInfo.InvariantCulture, out floatValue)) { return(new ParseErrorExpression("Number too large")); } var floatExpression = new FloatConstantExpression(floatValue); floatExpression.Location = new TextRange(line, column, endLine, endColumn); return(floatExpression); } if (!UInt32.TryParse(number, out value)) { return(new ParseErrorExpression("Number too large")); } } if (value > Int32.MaxValue && !isUnsigned) { return(new ParseErrorExpression("Number too large")); } var integerExpression = new IntegerConstantExpression((int)value); integerExpression.Location = new TextRange(line, column, endLine, endColumn); return(integerExpression); }