private static void ReducePreOperator(Operator op, List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { if (units[i].OperatorType == op) { if (i == units.Count - 1) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Unable to parse PreOperator {op}: No following value"); } if (units[i + 1].AsValueGetter == null) { throw new ScriptParsingException( source: units[i + 1].FirstToken, message: $"Unable to parse PreOperator {op}: Following value is not value not retrievable: {units[i + 1].FirstToken}"); } //Cache Value and remove IValueGetter value = units[i + 1].AsValueGetter; units.RemoveAt(i + 1); OperatorToken operatorToken = units[i].FirstToken as OperatorToken; //Swap the ParsingUnit for the calculated value switch (op) { case Operator.CastInteger: case Operator.CastDouble: units[i] = new ParsedValuedUnit( value: CastOperation.CreateCastOperation( arg: value, operatorToken: operatorToken), firstToken: units[i].FirstToken); break; case Operator.Negate: units[i] = new ParsedValuedUnit( value: NegationOperation.CreateNegationOperation( arg: value, source: operatorToken), firstToken: units[i].FirstToken); break; case Operator.Not: units[i] = new ParsedValuedUnit( value: NotOperation.CreateNotOperation( arg: value, operatorToken: operatorToken), firstToken: units[i].FirstToken); break; default: throw new ArgumentException($"Unexpected Operator: {op}"); } } } }
private static void ReducePreFixes(List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { if (units[i].OperatorType == Operator.Increment || units[i].OperatorType == Operator.Decrement) { if (i == units.Count - 1 || units[i + 1].AsValue == null) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Operator {units[i].OperatorType} could not be resolved as a Post-Fix or a Pre-Fix. It can only be attached to a modifiable value: {units[i].FirstToken}"); } //Cache Value and remove IValue value = units[i + 1].AsValue; units.RemoveAt(i + 1); OperatorToken operatorToken = units[i].FirstToken as OperatorToken; //Swap the ParsingUnit for the calculated value units[i] = new ParsedValuedUnit( value: new UnaryValueOperation( arg: value, operatorToken: operatorToken, prefix: true), firstToken: units[i].FirstToken); } } }
private static void ReducePostFixes(List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { //It's a postfix operator if it follows a modifiable value if (units[i].OperatorType == Operator.Increment || units[i].OperatorType == Operator.Decrement) { if (i == 0 || units[i - 1].AsValue == null) { //Definitely not a postfix continue; } //Cache operatortoken and remove operator OperatorToken operatorToken = units[i].FirstToken as OperatorToken; units.RemoveAt(i); //Move to Variable position i--; //Swap the ParsingUnit for the calculated value units[i] = new ParsedValuedUnit( value: new UnaryValueOperation( arg: units[i].AsValue, operatorToken: operatorToken, prefix: false), firstToken: units[i].FirstToken); } } }
private static void ReduceMemberAccessAndIndexing(List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { if (units[i] is MemberAccessUnit memberAccessUnit) { if (i == 0) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression began with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } //Remove units.RemoveAt(i); i--; //Swap the ParsingUnit for the calculated value units[i] = new ParsedValuedUnit( value: MemberManagement.HandleMemberExpression( value: units[i].AsValueGetter, args: memberAccessUnit.args, identifier: memberAccessUnit.identifier, source: memberAccessUnit.FirstToken), firstToken: units[i].FirstToken); } else if (units[i] is IndexAccessUnit indexAccessUnit) { if (i == 0) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression began with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } //Remove units.RemoveAt(i); i--; //Swap the ParsingUnit for the calculated value units[i] = new ParsedValuedUnit( value: new IndexerOperation( valueArg: units[i].AsValueGetter, indexArg: indexAccessUnit.arg, source: units[i].FirstToken), firstToken: units[i].FirstToken); } } }
private static void ReduceAssignmentOperators(List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { if (units[i].OperatorType == Operator.Assignment || units[i].OperatorType == Operator.PlusEquals || units[i].OperatorType == Operator.MinusEquals || units[i].OperatorType == Operator.TimesEquals || units[i].OperatorType == Operator.DivideEquals || units[i].OperatorType == Operator.PowerEquals || units[i].OperatorType == Operator.ModuloEquals || units[i].OperatorType == Operator.AndEquals || units[i].OperatorType == Operator.OrEquals) { if (i == 0) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression began with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } if (i == units.Count - 1) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression ended with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } if (units[i - 1].AsValue == null) { throw new ScriptParsingException( source: units[i - 1].FirstToken, message: $"Expression before {units[i].OperatorType} operator must be modifiable: {units[i - 1].FirstToken}"); } if (units[i + 1].AsValueGetter == null) { throw new ScriptParsingException( source: units[i + 1].FirstToken, message: $"Expression after {units[i].OperatorType} operator must have a value: {units[i + 1].FirstToken}"); } OperatorToken operatorToken = units[i].FirstToken as OperatorToken; //Cache Value and remove Right value and operator IValueGetter value = units[i + 1].AsValueGetter; units.RemoveAt(i + 1); units.RemoveAt(i); //adjust our current position i--; //Swap the ParsingUnit for the calculated value switch (operatorToken.operatorType) { case Operator.Assignment: units[i] = new ParsedValuedUnit( value: new AssignmentOperation( assignee: units[i].AsValue, value: value, source: operatorToken), firstToken: units[i].FirstToken); break; case Operator.PlusEquals: units[i] = new ParsedValuedUnit( value: new PlusEqualsOperation( assignee: units[i].AsValue, value: value, source: operatorToken), firstToken: units[i].FirstToken); break; case Operator.MinusEquals: case Operator.TimesEquals: case Operator.DivideEquals: case Operator.PowerEquals: case Operator.ModuloEquals: //Handle Numerical Operators units[i] = new ParsedValuedUnit( value: new NumericalInPlaceOperation( assignee: units[i].AsValue, value: value, operatorType: operatorToken.operatorType, source: operatorToken), firstToken: units[i].FirstToken); break; case Operator.AndEquals: case Operator.OrEquals: units[i] = new ParsedValuedUnit( value: new BooleanInPlaceOperation( assignee: units[i].AsValue, value: value, operatorType: operatorToken.operatorType, source: operatorToken), firstToken: units[i].FirstToken); break; default: throw new ArgumentException($"Unexpected Operator: {operatorToken.operatorType}"); } } } }
private static void ReduceTernaryOperator(List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { if (units[i].OperatorType == Operator.Ternary) { if (i == 0) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression began with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } if (i >= units.Count - 2) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression with a {units[i].OperatorType} operator didn't contain enought arguments: {units[i].FirstToken}"); } if (units[i - 1].AsValueGetter == null) { throw new ScriptParsingException( source: units[i - 1].FirstToken, message: $"Unexpected token before {units[i].OperatorType} operator: {units[i - 1].FirstToken}"); } if (units[i + 1].AsValueGetter == null) { throw new ScriptParsingException( source: units[i + 1].FirstToken, message: $"Unexpected token after {units[i].OperatorType} operator: {units[i + 1].FirstToken}"); } if (units[i + 2].AsValueGetter == null) { throw new ScriptParsingException( source: units[i + 1].FirstToken, message: $"Unexpected token for second arguemnt of {units[i].OperatorType} operator: {units[i + 2].FirstToken}"); } OperatorToken operatorToken = units[i].FirstToken as OperatorToken; //Cache Value and remove Right value and operator IValueGetter arg1Value = units[i + 1].AsValueGetter; IValueGetter arg2Value = units[i + 2].AsValueGetter; units.RemoveAt(i + 2); units.RemoveAt(i + 1); units.RemoveAt(i); //adjust our current position i--; //Swap the ParsingUnit for the calculated value units[i] = new ParsedValuedUnit( value: new TernaryOperation( condition: units[i].AsValueGetter, arg1: arg1Value, arg2: arg2Value, operatorToken: operatorToken), firstToken: units[i].FirstToken); } } }
private static void ReduceBinaryOperator( Operator op, List <ParsingUnit> units) { for (int i = 0; i < units.Count; i++) { if (units[i].OperatorType == op) { if (i == 0) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression began with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } if (i == units.Count - 1) { throw new ScriptParsingException( source: units[i].FirstToken, message: $"Expression ended with a {units[i].OperatorType} operator: {units[i].FirstToken}"); } if (units[i - 1].AsValueGetter == null) { throw new ScriptParsingException( source: units[i - 1].FirstToken, message: $"Unexpected token before {units[i].OperatorType} operator: {units[i - 1].FirstToken}"); } if (units[i + 1].AsValueGetter == null) { throw new ScriptParsingException( source: units[i + 1].FirstToken, message: $"Unexpected token after {units[i].OperatorType} operator: {units[i + 1].FirstToken}"); } OperatorToken operatorToken = units[i].FirstToken as OperatorToken; //Cache Value and remove Right value and operator IValueGetter arg2Value = units[i + 1].AsValueGetter; units.RemoveAt(i + 1); units.RemoveAt(i); //adjust our current position i--; //Swap the ParsingUnit for the calculated value switch (op) { case Operator.Plus: if (units[i].AsValueGetter.GetValueType() == typeof(string) || arg2Value.GetValueType() == typeof(string)) { //Handle String Concatenation units[i] = new ParsedValuedUnit( value: ConcatenateOperator.CreateConcatenateOperator( arg1: units[i].AsValueGetter, arg2: arg2Value), firstToken: units[i].FirstToken); break; } //Handle like addition goto case Operator.Minus; case Operator.Minus: case Operator.Times: case Operator.Divide: case Operator.Power: case Operator.Modulo: //Handle Numerical Operators units[i] = new ParsedValuedUnit( value: BinaryNumericalOperation.CreateBinaryNumericalOperation( arg1: units[i].AsValueGetter, arg2: arg2Value, operatorToken: operatorToken), firstToken: units[i].FirstToken); break; case Operator.IsEqualTo: case Operator.IsNotEqualTo: units[i] = new ParsedValuedUnit( value: EqualityCompairsonOperation.CreateEqualityComparisonOperator( arg1: units[i].AsValueGetter, arg2: arg2Value, operatorToken: operatorToken), firstToken: units[i].FirstToken); break; case Operator.IsGreaterThan: case Operator.IsGreaterThanOrEqualTo: case Operator.IsLessThan: case Operator.IsLessThanOrEqualTo: units[i] = new ParsedValuedUnit( value: ComparisonOperation.CreateComparisonOperation( arg1: units[i].AsValueGetter, arg2: arg2Value, operatorToken: operatorToken), firstToken: units[i].FirstToken); break; case Operator.And: case Operator.Or: units[i] = new ParsedValuedUnit( value: BinaryBoolOperation.CreateBinaryBoolOperator( arg1: units[i].AsValueGetter, arg2: arg2Value, operatorToken: operatorToken), firstToken: units[i].FirstToken); break; default: throw new ArgumentException($"Unexpected Operator: {op}"); } } } }