/// <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) { // FunctionDefinition.ReplaceVariables is called when evaluating a function for an assignment. // For user functions (see UserFunctionDefinition.ReplaceVariables) - it will just evaluate the // function call and return the result. Several internal functions have very special Evaluate // handling that should not be executed when defining variables. Those functions rely on this // behavior to just evaluate the parameters without calling Evaluate. There are some built-in // functions that should call Evaluate when ReplaceVariables is called. They will override // ReplaceVariables to do that. var parameters = new ExpressionBase[Parameters.Count]; int i = 0; foreach (var parameterName in Parameters) { // do a direct lookup here. calling GetParameter will discard the VariableReference // and we want to preserve those for now. var parameter = scope.GetVariable(parameterName.Name); if (parameter == null) { result = new ParseErrorExpression("No value provided for " + parameterName.Name + " parameter", parameterName); return(false); } parameters[i++] = parameter; } result = new FunctionCallExpression(Name.Name, parameters); CopyLocation(result); return(true); }
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 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 '(': 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': if (tokenizer.Match("0x")) { string hexNumber = ""; while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f')) { hexNumber += tokenizer.NextChar; tokenizer.Advance(); } int hexValue = 0; Int32.TryParse(hexNumber, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hexValue); return(new IntegerConstantExpression(hexValue)); } goto case '1'; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { var number = tokenizer.ReadNumber(); uint value; UInt32.TryParse(number.ToString(), out value); return(new IntegerConstantExpression((int)value)); } case '-': tokenizer.Advance(); if (tokenizer.NextChar >= '0' && tokenizer.NextChar <= '9') { if (tokenizer.Match("0x")) { string hexNumber = ""; while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f')) { hexNumber += tokenizer.NextChar; tokenizer.Advance(); } int hexValue = 0; Int32.TryParse(hexNumber, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hexValue); return(new IntegerConstantExpression(-hexValue)); } var number = tokenizer.ReadNumber(); int value; Int32.TryParse(number.ToString(), out value); return(new IntegerConstantExpression(-value)); } return(ParseError(tokenizer, "Minus without value")); 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(FunctionDefinitionExpression.Parse(tokenizer, line, column)); } if (identifier == "for") { return(ForExpression.Parse(tokenizer, line, column)); } if (identifier == "if") { return(IfExpression.Parse(tokenizer, line, column)); } if (tokenizer.NextChar == '(') { tokenizer.Advance(); var parameters = new List <ExpressionBase>(); ParseParameters(tokenizer, parameters); var functionCall = new FunctionCallExpression(new VariableExpression(identifier.ToString(), line, column), parameters); functionCall.EndLine = tokenizer.Line; functionCall.EndColumn = 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)); } }