public static void Write(this Pattern pattern, TextWriter writer, Scope scope) { var len = pattern.Elements.Count; var transformFunc = scope.Bundle.TransformFunc; for (var i = 0; i < len; i++) { if (scope.Dirty) { return; } var elem = pattern.Elements[i]; if (elem is TextLiteral textLiteral) { if (transformFunc != null) { writer.Write(transformFunc(textLiteral.ToString())); } else { writer.Write(textLiteral.Value.Span); } } else if (elem is Placeable placeable) { var expr = placeable.Expression; if (scope.IncrPlaceable() > scope.Bundle.MaxPlaceable) { scope.Dirty = true; scope.AddError(ResolverFluentError.TooManyPlaceables()); return; } var needsIsolating = scope.Bundle.UseIsolating && len > 1; if (needsIsolating) { writer.Write('\u2068'); } scope.MaybeTrack(writer, pattern, expr); if (needsIsolating) { writer.Write('\u2069'); } } } }
public static bool TryWrite(this IExpression expression, TextWriter writer, Scope scope) { var errors = new List <FluentError>(); if (expression is IInlineExpression inlineExpression) { inlineExpression.Write(writer, scope); } else if (expression is SelectExpression selectExpression) { var selector = selectExpression.Selector.Resolve(scope); if (selector is FluentString or FluentNumber) { foreach (var variant in selectExpression.Variants) { IFluentType key; switch (variant.Type) { case VariantType.NumberLiteral: key = FluentNumber.TryNumber(variant.Key.Span); break; default: key = new FluentString(variant.Key.Span); break; } if (key.Matches(selector, scope)) { variant.Value.Write(writer, scope); return(scope.Errors.Count == 0); } } } for (var i = 0; i < selectExpression.Variants.Count; i++) { var variant = selectExpression.Variants[i]; if (variant.IsDefault) { variant.Value.Write(writer, scope); return(errors.Count == 0); } } errors.Add(ResolverFluentError.MissingDefault()); } return(scope.Errors.Count == 0); }
public bool WriteRefError(TextWriter writer, IInlineExpression exp) { AddError(ResolverFluentError.Reference(exp)); try { writer.Write('{'); exp.WriteError(writer); writer.Write('}'); return(true); } catch (Exception) { return(false); } }
public void Track(TextWriter writer, Pattern pattern, IInlineExpression exp) { if (_travelled.Contains(pattern)) { AddError(ResolverFluentError.Cyclic(pattern)); writer.Write('{'); exp.WriteError(writer); writer.Write('}'); } else { _travelled.Add(pattern); pattern.Write(writer, this); PopTraveled(); } }
private static void ProcessMsgRef(IInlineExpression self, TextWriter writer, Scope scope, MessageReference msgRef) { var id = msgRef.Id; var attribute = msgRef.Attribute; if (scope.Bundle.TryGetAstMessage(id.Name.ToString(), out var msg)) { if (attribute != null) { var found = msg.Attributes.Find(e => e.Id.Equals(attribute)); if (found != null) { scope.Track(writer, found.Value, self); } else { scope.WriteRefError(writer, self); return; } } else { if (msg.Value != null) { scope.Track(writer, msg.Value, self); } else { scope.AddError(ResolverFluentError.NoValue(id.Name)); writer.Write('{'); self.WriteError(writer); writer.Write('}'); } } } else { scope.WriteRefError(writer, self); } }
public static IFluentType Resolve(this IInlineExpression self, Scope scope) { if (self is TextLiteral textLiteral) { StringWriter stringWriter = new(); UnicodeUtil.WriteUnescapedUnicode(textLiteral.Value, stringWriter); return((FluentString)stringWriter.ToString()); } if (self is NumberLiteral numberLiteral) { return(FluentNumber.TryNumber(numberLiteral.Value.Span)); } if (self is VariableReference varRef) { var args = scope.LocalArgs ?? scope.Args; if (args != null && args.TryGetValue(varRef.Id.ToString(), out var arg)) { return(arg.Copy()); } if (scope.LocalArgs == null) { scope.AddError(ResolverFluentError.UnknownVariable(varRef)); } return(new FluentErrType()); } var writer = new StringWriter(); self.TryWrite(writer, scope); return((FluentString)writer.ToString()); }
public void AddError(ResolverFluentError resolverFluentError) { _errors.Add(resolverFluentError); }
private static void Write(this IInlineExpression self, TextWriter writer, Scope scope) { if (self is TextLiteral textLiteral) { UnicodeUtil.WriteUnescapedUnicode(textLiteral.Value, writer); return; } if (self is NumberLiteral numberLiteral) { var value = FluentNumber.TryNumber(numberLiteral.Value.Span); value.Write(writer, scope); return; } if (self is MessageReference msgRef) { ProcessMsgRef(self, writer, scope, msgRef); return; } if (self is TermReference termRef) { var res = scope.GetArguments(termRef.Arguments); scope.SetLocalArgs(res.Named); if (scope.Bundle.TryGetAstTerm(termRef.Id.ToString(), out var term)) { var attrName = termRef.Attribute; var attr = term .Attributes .Find(a => a.Id.Equals(attrName)); scope.Track(writer, attr != null ? attr.Value : term.Value, self); } else { scope.WriteRefError(writer, self); } scope.SetLocalArgs(null); return; } if (self is FunctionReference funcRef) { var(resolvedPosArgs, resolvedNamedArgs) = scope.GetArguments(funcRef.Arguments); if (scope.Bundle.TryGetFunction(funcRef.Id, out var func)) { var result = func.Function(resolvedPosArgs, resolvedNamedArgs); if (result.IsError()) { self.WriteError(writer); } else { writer.Write(result.AsString()); } } else { scope.WriteRefError(writer, self); } } if (self is VariableReference varRef) { var id = varRef.Id; var args = scope.LocalArgs ?? scope.Args; if (args != null && args.TryGetValue(id.ToString(), out var arg)) { arg.Write(writer, scope); } else { if (scope.LocalArgs == null) { scope.AddError(ResolverFluentError.Reference(self)); } writer.Write('{'); self.WriteError(writer); writer.Write('}'); } } if (self is Placeable placeable) { placeable.Expression.TryWrite(writer, scope); } }