/// <summary> /// Parses an anonymous function definition in the format "(a) => body" or "(a) { body }" /// </summary> public static ExpressionBase ParseAnonymous(PositionalTokenizer tokenizer) { var name = CreateAnonymousFunctionName(tokenizer.Line, tokenizer.Column); var function = new AnonymousUserFunctionDefinitionExpression(name); function.Location = new TextRange(tokenizer.Line, tokenizer.Column, 0, 0); return(function.Parse(tokenizer)); }
/// <summary> /// Parses an anonymous function definition in the format "a => body" where <paramref name="parameter"/> /// is "a" and <paramref name="tokenizer"/> is pointing at "body". /// </summary> public static ExpressionBase ParseAnonymous(PositionalTokenizer tokenizer, ExpressionBase parameter) { var variable = parameter as VariableExpression; if (variable == null) { return(new ParseErrorExpression("Cannot create anonymous function from " + parameter.Type)); } var name = CreateAnonymousFunctionName(parameter.Location.Start.Line, parameter.Location.Start.Column); var function = new AnonymousUserFunctionDefinitionExpression(name); function.Location = parameter.Location; function.Parameters.Add(new VariableDefinitionExpression(variable.Name, variable.Location.Start.Line, variable.Location.Start.Column)); return(function.ParseShorthandBody(tokenizer)); }
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 ParseClauseExtension(ExpressionBase clause, PositionalTokenizer tokenizer, OperationPriority priority) { do { var clauseEndLine = tokenizer.Line; var clauseEndColumn = tokenizer.Column; SkipWhitespace(tokenizer); var joinerLine = tokenizer.Line; var joinerColumn = tokenizer.Column; switch (tokenizer.NextChar) { case '+': if (priority == OperationPriority.AddSubtract && clause.Type == ExpressionType.StringConstant) { priority = OperationPriority.AppendString; } if (priority >= OperationPriority.AddSubtract) { return(clause); } tokenizer.Advance(); clause = ParseMathematic(tokenizer, clause, MathematicOperation.Add, joinerLine, joinerColumn); break; case '-': if (priority >= OperationPriority.AddSubtract) { return(clause); } tokenizer.Advance(); clause = ParseMathematic(tokenizer, clause, MathematicOperation.Subtract, joinerLine, joinerColumn); break; case '*': if (priority >= OperationPriority.MulDivMod) { return(clause); } tokenizer.Advance(); clause = ParseMathematic(tokenizer, clause, MathematicOperation.Multiply, joinerLine, joinerColumn); break; case '/': if (priority >= OperationPriority.MulDivMod) { return(clause); } tokenizer.Advance(); clause = ParseMathematic(tokenizer, clause, MathematicOperation.Divide, joinerLine, joinerColumn); break; case '%': if (priority >= OperationPriority.MulDivMod) { return(clause); } tokenizer.Advance(); clause = ParseMathematic(tokenizer, clause, MathematicOperation.Modulus, joinerLine, joinerColumn); break; case '=': if (tokenizer.MatchSubstring("==") == 2) { if (priority >= OperationPriority.Compare) { return(clause); } tokenizer.Advance(2); clause = ParseComparison(tokenizer, clause, ComparisonOperation.Equal, joinerLine, joinerColumn); } else { if (priority > OperationPriority.Assign) { return(clause); } tokenizer.Advance(); if (tokenizer.NextChar == '>') { tokenizer.Advance(); clause = AnonymousUserFunctionDefinitionExpression.ParseAnonymous(tokenizer, clause); } else { clause = ParseAssignment(tokenizer, clause, joinerLine, joinerColumn); } } break; case '!': if (priority >= OperationPriority.Compare) { return(clause); } tokenizer.Advance(); if (tokenizer.NextChar != '=') { ParseError(tokenizer, "= expected following !", joinerLine, joinerColumn); } else { tokenizer.Advance(); clause = ParseComparison(tokenizer, clause, ComparisonOperation.NotEqual, joinerLine, joinerColumn); } break; case '<': if (priority >= OperationPriority.Compare) { return(clause); } tokenizer.Advance(); if (tokenizer.NextChar == '=') { tokenizer.Advance(); clause = ParseComparison(tokenizer, clause, ComparisonOperation.LessThanOrEqual, joinerLine, joinerColumn); } else { clause = ParseComparison(tokenizer, clause, ComparisonOperation.LessThan, joinerLine, joinerColumn); } break; case '>': if (priority >= OperationPriority.Compare) { return(clause); } tokenizer.Advance(); if (tokenizer.NextChar == '=') { tokenizer.Advance(); clause = ParseComparison(tokenizer, clause, ComparisonOperation.GreaterThanOrEqual, joinerLine, joinerColumn); } else { clause = ParseComparison(tokenizer, clause, ComparisonOperation.GreaterThan, joinerLine, joinerColumn); } break; case '&': if (tokenizer.MatchSubstring("&&") == 2) { if (priority >= OperationPriority.And) { return(clause); } tokenizer.Advance(2); clause = ParseConditional(tokenizer, clause, ConditionalOperation.And, joinerLine, joinerColumn); } else { if (priority >= OperationPriority.BitwiseAnd) { return(clause); } tokenizer.Advance(); clause = ParseMathematic(tokenizer, clause, MathematicOperation.BitwiseAnd, joinerLine, joinerColumn); } break; case '|': if (priority >= OperationPriority.Or) { return(clause); } tokenizer.Advance(); if (tokenizer.NextChar != '|') { ParseError(tokenizer, "| expected following |", joinerLine, joinerColumn); } else { tokenizer.Advance(); clause = ParseConditional(tokenizer, clause, ConditionalOperation.Or, joinerLine, joinerColumn); } break; default: if (clause.Location.End.Column == 0) { clause.Location = new TextRange(clause.Location.Start, new TextLocation(clauseEndLine, clauseEndColumn)); } return(clause); } if (clause.Type == ExpressionType.ParseError) { return(clause); } } while (true); }