private static IExpression TryMatchExpressionOnFile(ParseContext ctx, SkriptTypesManager skriptTypesManager, ParseContext clone, int currentPos, SkriptType skriptType) { IExpression result = null; //If we're dealing with a file, try matching event values too if (ctx is FileParseContext fileParseContext) { var currentNode = fileParseContext.File.Nodes[fileParseContext.CurrentLine]; if (currentNode?.RootParentSyntax?.Element is SkriptEvent rootEvent) { var typesAndExpressions = skriptTypesManager.GetEventExpressionsForEvent(rootEvent); var exprs = typesAndExpressions; if (exprs != null) { foreach (var(_, expressions) in exprs) { if (expressions != null) { foreach (var expression in expressions) { clone.CurrentPosition = currentPos; clone.StartRangeMeasure("Event-Value Expression"); clone.Matches.Clear(); clone.VisitExpression(skriptType, expression); for (var index = 0; index < expression.PatternNodes.Length; index++) { var pattern = expression.PatternNodes[index]; var resultValue = pattern.Parse(clone); if (resultValue.IsSuccess) { var range = clone.EndRangeMeasure("Event-Value Expression"); ctx.ReadUntilPosition(clone.CurrentPosition); result = new SkriptExpression(expression, range, ctx); } } clone.UndoRangeMeasure(); } } } } } } return(result); }
protected override WrappedObject TryParse(ParseContext ctx) { var clone = ctx.Clone(); ctx.Properties.WrappedObjectCount++; var typePattern = new TypePatternElement(); var possibleValues = new List <(int CurrentPosition, List <ParseMatch> expression, ParseResult result)>(); var startPos = clone.CurrentPosition; foreach (var type in WorkspaceManager.CurrentWorkspace.TypesManager.KnownTypesFromAddons) { //Only match once, multiple types are parsed elsewhere if (type.IsPlural) { continue; } clone.Matches.Clear(); clone.CurrentPosition = startPos; typePattern.Type = type.FinalTypeName; if (typePattern.ToString().Contains("%object")) { Debugger.Break(); } if (!RuntimeHelpers.TryEnsureSufficientExecutionStack()) { Debugger.Break(); } var result = typePattern.Parse(clone); if (result.IsSuccess) { var expression = new List <ParseMatch>(clone.Matches); if (expression.Count > 0) { possibleValues.Add((clone.CurrentPosition, expression, result)); } } } { //clone.ShouldJustCheckExpressionsThatMatchType = true; var expressions = WorkspaceManager.CurrentWorkspace.TypesManager.GetExpressionsThatCanFitType(KnownTypesManager .JavaLangObjectClass); if (expressions != null) { foreach (var expression in expressions) { foreach (var pattern in expression.PatternNodes) { if (pattern.ToString().Contains("ExprJavaCall")) { Debugger.Break(); } clone.Matches.Clear(); clone.CurrentPosition = startPos; clone.StartRangeMeasure(); var result = pattern.Parse(clone); if (!result.IsSuccess) { clone.UndoRangeMeasure(); continue; } var exprResult = clone.Matches; if (exprResult.Count > 0) { var cloneParseContext = clone.Clone(); result.Context = cloneParseContext; var expr = new SkriptExpression(expression, clone.EndRangeMeasure(), cloneParseContext); possibleValues.Add((clone.CurrentPosition, new List <ParseMatch>(new[] { new ExpressionParseMatch(expr, null) }), result)); } } } } } possibleValues.Sort((c1, c2) => - 1 * c1.CurrentPosition.CompareTo(c2.CurrentPosition)); if (possibleValues.Count <= 0) { return(null); } { var(lastPos, matches, _) = possibleValues[0]; ctx.ReadUntilPosition(lastPos); ctx.Properties.WrappedObjectCount--; return(new WrappedObject(matches)); } }
public ParseResult NarrowedParse(ParseContext ctx, bool tryNarrowContext = false) { var contextToUse = ctx; if (tryNarrowContext && NarrowContextIfPossible(ref contextToUse, out var parseResult)) { return(parseResult); } var skriptTypesManager = WorkspaceManager.CurrentWorkspace.TypesManager; //Split the types (if any) foreach (var typeRaw in Type.Split("/")) { var isObjectType = typeRaw.ToLower() == "object" || typeRaw.ToLower() == "objects"; var skriptType = skriptTypesManager.GetType(typeRaw); //Try to get a known type literal provider for that type var type = WorkspaceManager.Instance.KnownTypesManager.GetTypeByName(typeRaw); ISkriptType skriptTypeDescriptor = null; /*if (!RuntimeHelpers.TryEnsureSufficientExecutionStack()) * return ParseResult.Failure(ctx);*/ //Check if this type requires more than one variable var isMultipleValues = typeRaw.EndsWith("s"); if (isMultipleValues) { //It does so we first have to get the singular type representation for this type //Either get from the name we're given or just subtract the last letter ('s') from it type = WorkspaceManager.Instance.KnownTypesManager.GetTypeByName(typeRaw) ?? WorkspaceManager.Instance.KnownTypesManager.GetTypeByName( typeRaw.Substring(0, typeRaw.Length - 1) ); //If we have a type, replace the type descriptor for the generic multi type matcher if (type != null) // Hand over to GenericMultiValueType { skriptTypeDescriptor = new GenericMultiValueType(type, Constraint, CanMatchListConjunctions); } } else { //We got a single type so, use it. skriptTypeDescriptor = type?.CreateNewInstance(); } IExpression result = null; var oldPos = contextToUse.CurrentPosition; //In case it isn't for an object, always try matching type //if (!isObjectType && (!ctx.Properties.WrappedObjectCount) && !contextToUse.ShouldJustCheckExpressionsThatMatchType) if (isObjectType && ctx.Properties.WrappedObjectCount < 2 || !isObjectType && !contextToUse.ShouldJustCheckExpressionsThatMatchType) { result = skriptTypeDescriptor?.TryParseValue(contextToUse); } //This type has a flag to attempt to match conditionals. So, let's try do just that. if (result == null && Constraint.HasFlagFast(SyntaxValueAcceptanceConstraint.AllowConditionalExpressions)) { foreach (var condition in skriptTypesManager.KnownConditionsFromAddons) { var clone = contextToUse.Clone(false); for (var index = 0; index < condition.PatternNodes.Length; index++) { var conditionPatternNode = condition.PatternNodes[index]; clone.CurrentPosition = contextToUse.CurrentPosition; clone.StartRangeMeasure("Condition"); var conditionResult = conditionPatternNode.Parse(clone); if (conditionResult.IsSuccess) { //Read on real context until our current position on cloned ctx contextToUse.ReadUntilPosition(clone.CurrentPosition); result = new ConditionalExpression(condition, clone.Matches, index, clone.EndRangeMeasure(), contextToUse); } clone.UndoRangeMeasure(); } } } //This type doesn't have a flag to just match literals So, let's try first matching variables. if (result == null && !Constraint.HasFlagFast(SyntaxValueAcceptanceConstraint.LiteralsOnly)) { //Try parsing a variable var reference = new SkriptVariableReferenceType(); var ctxClone = contextToUse.Clone(); try { result = reference.TryParseValue(ctxClone); } catch (Exception) { // ignored } if (result != null) { contextToUse.ReadUntilPosition(ctxClone.CurrentPosition); } } //We have not matched a result. Let's try matching with parentheses if (result == null && !SkipParenthesis) { // Type descriptor wasn't able to parse the literal. Push back and try with parentheses. contextToUse.CurrentPosition = oldPos; //Try parsing with parentheses first var parenthesesType = new GenericParenthesesType(typeRaw); result = parenthesesType.TryParseValue(contextToUse); } //If we didn't match any literal for this type, try to match an expression for this type if (skriptType != null && result == null && !Constraint.HasFlagFast(SyntaxValueAcceptanceConstraint.LiteralsOnly)) { var clone = contextToUse.Clone(false); clone.ShouldJustCheckExpressionsThatMatchType = true; var currentPos = clone.CurrentPosition; result = TryMatchExpressionOnFile(contextToUse, skriptTypesManager, clone, currentPos, skriptType); //Temporarily disable if (false && isObjectType) { //Try matching a Skript expression // Time to check all expressions to make sure the user isn't just trying to mix types for whatever reason... var exprFitType = contextToUse.ShouldJustCheckExpressionsThatMatchType ? skriptTypesManager.GetExpressionsThatCanFitType(skriptType) : skriptTypesManager.KnownExpressionsFromAddons; if (exprFitType != null) { foreach (var expression in exprFitType) { clone.CurrentPosition = currentPos; if (clone.HasVisitedExpression(skriptType, expression)) { continue; } clone.StartRangeMeasure("Expression"); clone.Matches.Clear(); clone.VisitExpression(skriptType, expression); for (var index = 0; index < expression.PatternNodes.Length; index++) { var pattern = expression.PatternNodes[index]; var resultValue = pattern.Parse(clone); if (resultValue.IsSuccess && clone.CurrentPosition >= contextToUse.CurrentPosition) { var range = clone.EndRangeMeasure("Expression"); contextToUse.ReadUntilPosition(clone.CurrentPosition); result = new SkriptExpression(expression, range, contextToUse); } } clone.UndoRangeMeasure(); } } } } //If we have matched something, let's add it to the matches. if (result != null) { if (result.Type == null) { result.Type = skriptTypeDescriptor; } result.Context = contextToUse; var match = new ExpressionParseMatch(result, this); contextToUse.Matches.Add(match); } RestoreFromNarrowedContext(ctx, contextToUse); return(result != null?ParseResult.Success(ctx) : ParseResult.Failure(ctx)); } return(ParseResult.Failure(contextToUse)); }