From 389d8398dbd1c02310a0c636072311892f17e7e5 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Sun, 8 Sep 2024 17:28:11 +0300 Subject: [PATCH 1/6] Clarify error & fallback handling --- spec/errors.md | 6 ++-- spec/formatting.md | 75 ++++++++++++++++++++++++---------------------- spec/syntax.md | 27 ++++++++++------- 3 files changed, 58 insertions(+), 50 deletions(-) diff --git a/spec/errors.md b/spec/errors.md index a2ddd669d..b437be695 100644 --- a/spec/errors.md +++ b/spec/errors.md @@ -32,7 +32,7 @@ Some examples include throwing an exception, returning an error code, or providing a function or method for enumerating any errors. -For all _messages_ without _Syntax Errors_ or _Data Model Errors_, +For all _valid_ _messages_, an implementation MUST enable a user to get a formatted result. The formatted result might include _fallback values_ such as when a _placeholder_'s _expression_ produced an error @@ -52,7 +52,7 @@ and a _Resolution Error_ or a _Message Function Error_ MUST be emitted. ## Syntax Errors -**_Syntax Errors_** occur when the syntax representation of a message is not well-formed. +**_Syntax Errors_** occur when the syntax representation of a message is not _well-formed_. > Example invalid messages resulting in a _Syntax Error_: > @@ -74,7 +74,7 @@ and a _Resolution Error_ or a _Message Function Error_ MUST be emitted. ## Data Model Errors -**_Data Model Errors_** occur when a message is invalid due to +**_Data Model Errors_** occur when a message is not _valid_ due to violating one of the semantic requirements on its structure. ### Variant Key Mismatch diff --git a/spec/formatting.md b/spec/formatting.md index 5e71d24a3..2913bcfe6 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -7,10 +7,20 @@ when formatting a message for display in a user interface, or for some later pro To start, we presume that a _message_ has either been parsed from its syntax or created from a data model description. -If this construction has encountered any _Syntax Errors_ or _Data Model Errors_, -an appropriate error MUST be emitted and a _fallback value_ MAY be used as the formatting result. +If the resulting _message_ is not _well-formed_, a _Syntax Error_ is emitted. +If the resulting _message_ is _well-formed_ but is not _valid_, a _Data Model Error_ is emitted. -Formatting of a _message_ is defined by the following operations: +The formatting of a _message_ is defined by the following operations, +starting with _Pattern Selection_: + +- **_Pattern Selection_** determines which of a message's _patterns_ is formatted. + For a message with no _selectors_, this is simple as there is only one _pattern_. + With _selectors_, this will depend on their resolution. + +- **_Formatting_** takes the resolved values of the selected _pattern_, + and produces the formatted result for the _message_. + Depending on the implementation, this result could be a single concatenated string, + an array of objects, an attributed string, or some other locally appropriate data type. - **_Expression and Markup Resolution_** determines the value of an _expression_ or _markup_, with reference to the current _formatting context_. @@ -24,6 +34,14 @@ Formatting of a _message_ is defined by the following operations: The resolution of _text_ is rather straightforward, and is detailed under _literal resolution_. +Formatter implementations are not required to expose +the _expression resolution_ and _pattern selection_ operations to their users, +or even use them in their internal processing, +as long as the final _formatting_ result is made available to users +and the observable behavior of the formatter matches that described here. + +_Attributes_ MUST NOT affect the processing or output of a _message_. + > [!IMPORTANT] > > **This specification does not require either eager or lazy _expression resolution_ of _message_ @@ -39,27 +57,6 @@ Formatting of a _message_ is defined by the following operations: > have already been evaluated in the order in which the relevant _declarations_ > and _selectors_ appear in the _message_. -- **_Pattern Selection_** determines which of a message's _patterns_ is formatted. - For a message with no _selectors_, this is simple as there is only one _pattern_. - With _selectors_, this will depend on their resolution. - - At the start of _pattern selection_, - if the _message_ contains any _reserved statements_, - emit an _Unsupported Statement_ error. - -- **_Formatting_** takes the resolved values of the selected _pattern_, - and produces the formatted result for the _message_. - Depending on the implementation, this result could be a single concatenated string, - an array of objects, an attributed string, or some other locally appropriate data type. - -Formatter implementations are not required to expose -the _expression resolution_ and _pattern selection_ operations to their users, -or even use them in their internal processing, -as long as the final _formatting_ result is made available to users -and the observable behavior of the formatter matches that described here. - -_Attributes_ MUST NOT affect the processing or output of a _message_. - ## Formatting Context A message's **_formatting context_** represents the data and procedures that are required @@ -82,8 +79,7 @@ At a minimum, it includes: - The _function registry_, providing the implementations of the functions referred to by message _functions_. -- Optionally, a fallback string to use for the message - if it contains any _Syntax Errors_ or _Data Model Errors_. +- Optionally, a fallback string to use for the message if it is not _valid_. Implementations MAY include additional fields in their _formatting context_. @@ -193,7 +189,7 @@ Otherwise, the _variable_ is an implicit reference to an input value, and its value is looked up from the _formatting context_ _input mapping_. The resolution of a _variable_ MAY fail if no value is identified for its _name_. -If this happens, an _Unresolved Variable_ error MUST be emitted. +If this happens, an _Unresolved Variable_ error is emitted. If a _variable_ would resolve to a _fallback value_, this MUST also be considered a failure. @@ -435,6 +431,18 @@ _Pattern selection_ is not supported for _fallback values_. ## Pattern Selection +At the start of _pattern selection_, +if the _message_ contains any _reserved statements_, +emit an _Unsupported Statement_ error. + +If the _message_ being formatted is not _well-formed_ and _valid_, +the result of pattern selection is a _pattern_ consisting of a single _fallback value_ +using the _message_'s fallback string defined in the _formatting context_ +or if this is not available or empty, the U+FFFD REPLACEMENT CHARACTER `�`. + +If the _message_ being formatted does not contain a _matcher_, +the result of pattern selection is its _pattern_ value. + When a _message_ contains a _matcher_ with one or more _selectors_, the implementation needs to determine which _variant_ will be used to provide the _pattern_ for the formatting operation. @@ -504,11 +512,6 @@ This selection method is defined in more detail below. An implementation MAY use any pattern selection method, as long as its observable behavior matches the results of the method defined here. -If the message being formatted has any _Syntax Errors_ or _Data Model Errors_, -the result of pattern selection MUST be a pattern resolving to a single _fallback value_ -using the message's fallback string defined in the _formatting context_ -or if this is not available or empty, the U+FFFD REPLACEMENT CHARACTER `�`. - ### Resolve Selectors First, resolve the values of each _selector_: @@ -741,8 +744,8 @@ each _text_ and _placeholder_ part of the selected _pattern_ is resolved and for Resolved values cannot always be formatted by a given implementation. When such an error occurs during _formatting_, -an implementation MUST emit an appropriate _Message Function Error_ and use a -_fallback value_ for the _placeholder_ with the error. +an appropriate _Message Function Error_ is emitted and +a _fallback value_ is used for the _placeholder_ with the error. Implementations MAY represent the result of _formatting_ using the most appropriate data type or structure. Some examples of these include: @@ -787,8 +790,8 @@ the _fallback value_ as a string, and a U+007D RIGHT CURLY BRACKET `}`. > For example, -> a message with a _Syntax Error_ and no fallback string -> defined in the _formatting context_ would format to a string as `{�}`. +> a _message_ that is not _well-formed_ would format to a string as `{�}`, +> if no fallback string is defined in the _formatting context_. ### Handling Bidirectional Text diff --git a/spec/syntax.md b/spec/syntax.md index 76fc74502..b85d4baa2 100644 --- a/spec/syntax.md +++ b/spec/syntax.md @@ -90,7 +90,7 @@ Attempting to parse a _message_ that is not _well-formed_ will result in a _Synt A _message_ is **_valid_** if it is _well-formed_ and **also** meets the additional content restrictions and semantic requirements about its structure defined below for -_declarations_, _matcher_, _options_, and _attributes_. +_declarations_, _matcher_, and _options_. Attempting to parse a _message_ that is not _valid_ will result in a _Data Model Error_. ## The Message @@ -368,14 +368,18 @@ and at least one _variant_. When the _matcher_ is processed, the result will be a single _pattern_ that serves as the template for the formatting process. -A _message_ can only be considered _valid_ if the following requirements are -satisfied: +A _message_ can only be considered _valid_ if the following requirements are satisfied; +otherwise, a corresponding _Data Model Error_ will be produced during processing: -- The number of _keys_ on each _variant_ MUST be equal to the number of _selectors_. -- At least one _variant_ MUST exist whose _keys_ are all equal to the "catch-all" key `*`. -- Each _selector_ MUST have an _annotation_, +- _Variant Key Mismatch_: + The number of _keys_ on each _variant_ MUST be equal to the number of _selectors_. +- _Missing Fallback Variant_: + At least one _variant_ MUST exist whose _keys_ are all equal to the "catch-all" key `*`. +- _Missing Selector Annotation_: + Each _selector_ MUST have an _annotation_, or contain a _variable_ that directly or indirectly references a _declaration_ with an _annotation_. -- Each _variant_ MUST use a list of _keys_ that is unique from that +- _Duplicate Variant_: + Each _variant_ MUST use a list of _keys_ that is unique from that of all other _variants_ in the _message_. _Literal_ _keys_ are compared by their contents, not their syntactical appearance. @@ -587,7 +591,8 @@ Multiple _options_ are permitted in an _annotation_. _Options_ are separated from the preceding _function_ _identifier_ and from each other by whitespace. Each _option_'s _identifier_ MUST be unique within the _annotation_: -an _annotation_ with duplicate _option_ _identifiers_ is not _valid_. +an _annotation_ with duplicate _option_ _identifiers_ is not _valid_ +and will produce a _Duplicate Option Name_ error during processing. The order of _options_ is not significant. @@ -750,10 +755,10 @@ by an U+003D EQUALS SIGN `=` along with optional whitespace. Multiple _attributes_ are permitted in an _expression_ or _markup_. Each _attribute_ is separated by whitespace. -Each _attribute_'s _identifier_ MUST be unique within the _expression_ or _markup_: -an _expression_ or _markup_ with duplicate _attribute_ _identifiers_ is not _valid_. -The order of _attributes_ is not significant. +Each _attribute_'s _identifier_ SHOULD be unique within the _expression_ or _markup_: +_attributes_ beyond the first with the same _identifier_ are ignored. +The order of _attributes_ is not otherwise significant. ```abnf attribute = "@" identifier [[s] "=" [s] literal] From 7ef350866d8176a5907d6a4cf6099b1ea17aab4d Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Sun, 8 Sep 2024 18:58:19 +0300 Subject: [PATCH 2/6] Apply suggestions from code review Co-authored-by: Addison Phillips --- spec/formatting.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 2913bcfe6..f0f5341c8 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -34,11 +34,11 @@ starting with _Pattern Selection_: The resolution of _text_ is rather straightforward, and is detailed under _literal resolution_. -Formatter implementations are not required to expose +Implementations are not required to expose the _expression resolution_ and _pattern selection_ operations to their users, or even use them in their internal processing, as long as the final _formatting_ result is made available to users -and the observable behavior of the formatter matches that described here. +and the observable behavior of the _formatting_ matches that described here. _Attributes_ MUST NOT affect the processing or output of a _message_. @@ -188,7 +188,7 @@ If a _declaration_ exists for the _variable_, its resolved value is used. Otherwise, the _variable_ is an implicit reference to an input value, and its value is looked up from the _formatting context_ _input mapping_. -The resolution of a _variable_ MAY fail if no value is identified for its _name_. +The resolution of a _variable_ fails if no value is identified for its _name_. If this happens, an _Unresolved Variable_ error is emitted. If a _variable_ would resolve to a _fallback value_, this MUST also be considered a failure. @@ -431,8 +431,7 @@ _Pattern selection_ is not supported for _fallback values_. ## Pattern Selection -At the start of _pattern selection_, -if the _message_ contains any _reserved statements_, +If the _message_ contains any _reserved statements_, emit an _Unsupported Statement_ error. If the _message_ being formatted is not _well-formed_ and _valid_, @@ -791,7 +790,8 @@ and a U+007D RIGHT CURLY BRACKET `}`. > For example, > a _message_ that is not _well-formed_ would format to a string as `{�}`, -> if no fallback string is defined in the _formatting context_. +> unless a fallback string is defined in the _formatting context_, +> in which case that string would be used instead. ### Handling Bidirectional Text From 25ba6a2430b0d4b169437630a8c839854371714a Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Sun, 8 Sep 2024 19:01:07 +0300 Subject: [PATCH 3/6] Select last rather than first attribute --- spec/syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/syntax.md b/spec/syntax.md index b85d4baa2..80b704bcb 100644 --- a/spec/syntax.md +++ b/spec/syntax.md @@ -757,7 +757,7 @@ Multiple _attributes_ are permitted in an _expression_ or _markup_. Each _attribute_ is separated by whitespace. Each _attribute_'s _identifier_ SHOULD be unique within the _expression_ or _markup_: -_attributes_ beyond the first with the same _identifier_ are ignored. +all but the last _attribute_ with the same _identifier_ are ignored. The order of _attributes_ is not otherwise significant. ```abnf From 4e249fab9bffb1f4974a9ff2b0584c5eaea56938 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Sun, 8 Sep 2024 19:27:07 +0300 Subject: [PATCH 4/6] Drop mention of "starting with Pattern Selection" --- spec/formatting.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index f0f5341c8..a49779bd5 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -10,8 +10,7 @@ or created from a data model description. If the resulting _message_ is not _well-formed_, a _Syntax Error_ is emitted. If the resulting _message_ is _well-formed_ but is not _valid_, a _Data Model Error_ is emitted. -The formatting of a _message_ is defined by the following operations, -starting with _Pattern Selection_: +The formatting of a _message_ is defined by the following operations: - **_Pattern Selection_** determines which of a message's _patterns_ is formatted. For a message with no _selectors_, this is simple as there is only one _pattern_. From 022c806d530b08557551fc9a3e755b541072527c Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Sun, 8 Sep 2024 21:07:10 +0300 Subject: [PATCH 5/6] Attributes can't change the formatted output --- spec/formatting.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/formatting.md b/spec/formatting.md index a49779bd5..e7fe6f7bc 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -39,7 +39,8 @@ or even use them in their internal processing, as long as the final _formatting_ result is made available to users and the observable behavior of the _formatting_ matches that described here. -_Attributes_ MUST NOT affect the processing or output of a _message_. +_Attributes_ MUST NOT have any effect on the formatted output of a _message_, +or be made available to function implementations. > [!IMPORTANT] > From 75da938e21e6e14ebefe76d6a666bffa52319408 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Mon, 9 Sep 2024 09:41:17 +0300 Subject: [PATCH 6/6] Use "nor" instead of "or" regarding attribute restrictions --- spec/formatting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/formatting.md b/spec/formatting.md index e7fe6f7bc..cbf6d4622 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -40,7 +40,7 @@ as long as the final _formatting_ result is made available to users and the observable behavior of the _formatting_ matches that described here. _Attributes_ MUST NOT have any effect on the formatted output of a _message_, -or be made available to function implementations. +nor be made available to function implementations. > [!IMPORTANT] >