Skip to content

Commit b60d250

Browse files
eemeligibson042aphillips
authored
Update the rest of the spec to match the ABNF after adding .keywords (#548)
* Update the rest of the spec to match the ABNF after #529 * Apply suggestions from code review Co-authored-by: Richard Gibson <richard.gibson@gmail.com> * Remove reserved-statement from matcher * Update spec/syntax.md --------- Co-authored-by: Richard Gibson <richard.gibson@gmail.com> Co-authored-by: Addison Phillips <addison@unicode.org>
1 parent f359856 commit b60d250

File tree

8 files changed

+469
-363
lines changed

8 files changed

+469
-363
lines changed

README.md

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,32 @@ Messages can interpolate arguments formatted using _formatting functions_:
2525

2626
Messages can define variants which correspond to the grammatical (or other) requirements of the language:
2727

28-
{{
29-
match {$count :number}
30-
when 1 {{You have one notification.}}
31-
when * {{You have {$count} notifications.}}
32-
}}
28+
.match {$count :number}
29+
1 {{You have one notification.}}
30+
* {{You have {$count} notifications.}}
3331

3432
The message syntax is also capable of expressing more complex translation, for example:
3533

36-
{{
37-
local $hostName = {$host :person firstName=long}
38-
local $guestName = {$guest :person firstName=long}
39-
local $guestsOther = {$guestCount :number offset=1}
34+
.local $hostName = {$host :person firstName=long}
35+
.local $guestName = {$guest :person firstName=long}
36+
.local $guestsOther = {$guestCount :number offset=1}
4037

41-
match {$host :gender} {$guestOther :number}
38+
.match {$host :gender} {$guestOther :number}
4239

43-
when female 0 {{{$hostName} does not give a party.}}
44-
when female 1 {{{$hostName} invites {$guestName} to her party.}}
45-
when female 2 {{{$hostName} invites {$guestName} and one other person to her party.}}
46-
when female * {{{$hostName} invites {$guestName} and {$guestsOther} other people to her party.}}
40+
female 0 {{{$hostName} does not give a party.}}
41+
female 1 {{{$hostName} invites {$guestName} to her party.}}
42+
female 2 {{{$hostName} invites {$guestName} and one other person to her party.}}
43+
female * {{{$hostName} invites {$guestName} and {$guestsOther} other people to her party.}}
4744

48-
when male 0 {{{$hostName} does not give a party.}}
49-
when male 1 {{{$hostName} invites {$guestName} to his party.}}
50-
when male 2 {{{$hostName} invites {$guestName} and one other person to his party.}}
51-
when male * {{{$hostName} invites {$guestName} and {$guestsOther} other people to his party.}}
45+
male 0 {{{$hostName} does not give a party.}}
46+
male 1 {{{$hostName} invites {$guestName} to his party.}}
47+
male 2 {{{$hostName} invites {$guestName} and one other person to his party.}}
48+
male * {{{$hostName} invites {$guestName} and {$guestsOther} other people to his party.}}
5249

53-
when * 0 {{{$hostName} does not give a party.}}
54-
when * 1 {{{$hostName} invites {$guestName} to their party.}}
55-
when * 2 {{{$hostName} invites {$guestName} and one other person to their party.}}
56-
when * * {{{$hostName} invites {$guestName} and {$guestsOther} other people to their party.}}
57-
}}
50+
* 0 {{{$hostName} does not give a party.}}
51+
* 1 {{{$hostName} invites {$guestName} to their party.}}
52+
* 2 {{{$hostName} invites {$guestName} and one other person to their party.}}
53+
* * {{{$hostName} invites {$guestName} and {$guestsOther} other people to their party.}}
5854

5955
See more examples and the formal definition of the grammar in [spec/syntax.md](./spec/syntax.md).
6056

spec/data-model/README.md

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Two equivalent definitions of the data model are also provided:
2525
A `SelectMessage` corresponds to a syntax message that includes _selectors_.
2626
A message without _selectors_ and with a single _pattern_ is represented by a `PatternMessage`.
2727

28+
In the syntax,
29+
a `PatternMessage` may be represented either as a _simple message_ or as a _complex message_,
30+
depending on whether it has declarations and if its `pattern` is allowed in a _simple message_.
31+
2832
```ts
2933
type Message = PatternMessage | SelectMessage;
3034

@@ -43,15 +47,47 @@ interface SelectMessage {
4347
```
4448

4549
Each message _declaration_ is represented by a `Declaration`,
46-
which connects the `name` of the _variable_
50+
which connects the `name` of a _variable_
4751
with its _expression_ `value`.
4852
The `name` does not include the initial `$` of the _variable_.
4953

54+
The `name` of an `InputDeclaration` MUST be the same
55+
as the `name` in the `VariableRef` of its `VariableExpression` `value`.
56+
57+
An `UnsupportedStatement` represents a statement not supported by the implementation.
58+
Its `keyword` is a non-empty string name (i.e. not including the initial `.`).
59+
If not empty, the `body` is the "raw" value (i.e. escape sequences are not processed)
60+
starting after the keyword and up to the first _expression_,
61+
not including leading or trailing whitespace.
62+
The non-empty `expressions` correspond to the trailing _expressions_ of the _reserved statement_.
63+
64+
> **Note**
65+
> Be aware that future versions of this specification
66+
> might assign meaning to _reserved statement_ values.
67+
> This would result in new interfaces being added to
68+
> this data model.
69+
5070
```ts
51-
interface Declaration {
71+
type Declaration = InputDeclaration | LocalDeclaration | UnsupportedStatement;
72+
73+
interface InputDeclaration {
74+
type: "input";
75+
name: string;
76+
value: VariableExpression;
77+
}
78+
79+
interface LocalDeclaration {
80+
type: "local";
5281
name: string;
5382
value: Expression;
5483
}
84+
85+
interface UnsupportedStatement {
86+
type: "unsupported-statement";
87+
keyword: string;
88+
body?: string;
89+
expressions: Expression[];
90+
}
5591
```
5692

5793
In a `SelectMessage`,
@@ -74,28 +110,35 @@ interface CatchallKey {
74110
## Patterns
75111

76112
Each `Pattern` represents a linear sequence, without selectors.
77-
Each element of the sequence MUST have either a `Text` or an `Expression` shape.
78-
`Text` represents literal _text_,
113+
Each element of the `body` array MUST either be a non-empty string or an `Expression` object.
114+
String values represent literal _text_,
79115
while `Expression` wraps each of the potential _expression_ shapes.
80-
The `value` of `Text` is the "cooked" value (i.e. escape sequences are processed).
116+
The `body` strings are the "cooked" _text_ values, i.e. escape sequences are processed.
81117

82-
Implementations MUST NOT rely on the set of `Expression` `body` values being exhaustive,
118+
Implementations MUST NOT rely on the set of `Expression` interfaces being exhaustive,
83119
as future versions of this specification MAY define additional expressions.
84-
A `body` with an unrecognized value SHOULD be treated as an `Unsupported` value.
120+
An `Expression` `func` with an unrecognized value SHOULD be treated as an `UnsupportedExpression` value.
85121

86122
```ts
87123
interface Pattern {
88-
body: Array<Text | Expression>;
124+
body: Array<string | Expression>;
89125
}
90126

91-
interface Text {
92-
type: "text";
93-
value: string;
127+
type Expression = LiteralExpression | VariableExpression | FunctionExpression;
128+
129+
interface LiteralExpression {
130+
arg: Literal;
131+
func?: FunctionRef | UnsupportedExpression;
132+
}
133+
134+
interface VariableExpression {
135+
arg: VariableRef;
136+
func?: FunctionRef | UnsupportedExpression;
94137
}
95138

96-
interface Expression {
97-
type: "expression";
98-
body: Literal | VariableRef | FunctionRef | Unsupported;
139+
interface FunctionExpression {
140+
arg?: never;
141+
func: FunctionRef | UnsupportedExpression;
99142
}
100143
```
101144

@@ -148,31 +191,31 @@ interface Option {
148191
}
149192
```
150193

151-
An `Unsupported` represents an _expression_ with a
152-
_reserved_ _annotation_ or a _private-use_ _annotation_ not supported
194+
An `UnsupportedExpression` represents an _expression_ with a
195+
_reserved annotation_ or a _private-use annotation_ not supported
153196
by the implementation.
154197
The `sigil` corresponds to the starting sigil of the _annotation_.
155198
The `source` is the "raw" value (i.e. escape sequences are not processed)
156199
and does not include the starting `sigil`.
157200

158201
> **Note**
159202
> Be aware that future versions of this specification
160-
> might assign meaning to _reserved_ `sigil` values.
203+
> might assign meaning to _reserved annotation_ `sigil` values.
161204
> This would result in new interfaces being added to
162205
> this data model.
163206
164207
If the _expression_ includes a _literal_ or _variable_ before the _annotation_,
165208
it is included as the `operand`.
166209

167-
When parsing the syntax of a _message_ that includes a _private-use_ _annotation_
210+
When parsing the syntax of a _message_ that includes a _private-use annotation_
168211
supported by the implementation,
169212
the implementation SHOULD represent it in the data model
170213
using an interface appropriate for the semantics and meaning
171214
that the implementation attaches to that _annotation_.
172215

173216
```ts
174-
interface Unsupported {
175-
type: "unsupported";
217+
interface UnsupportedExpression {
218+
type: "unsupported-expression";
176219
sigil: "!" | "@" | "#" | "%" | "^" | "&" | "*" | "<" | ">" | "/" | "?" | "~";
177220
source: string;
178221
operand?: Literal | VariableRef;

spec/data-model/message.dtd

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,46 @@
1-
<!ELEMENT message (declaration*,(pattern|(selectors,variant+)))>
1+
<!ELEMENT message (
2+
(declaration | unsupportedStatement)*,
3+
(pattern | (selectors,variant+))
4+
)>
25

6+
<!-- In a <declaration type="input">, the <expression> MUST contain a <variable> -->
37
<!ELEMENT declaration (expression)>
4-
<!ATTLIST declaration name NMTOKEN #REQUIRED>
8+
<!ATTLIST declaration
9+
type (input | local) #REQUIRED
10+
name NMTOKEN #REQUIRED
11+
>
12+
13+
<!ELEMENT unsupportedStatement (expression)+>
14+
<!ATTLIST unsupportedStatement
15+
keyword CDATA #REQUIRED
16+
body CDATA #IMPLIED
17+
>
518

619
<!ELEMENT selectors (expression)+>
720
<!ELEMENT variant (key+,pattern)>
821
<!ELEMENT key (#PCDATA)>
922
<!ATTLIST key default (true | false) "false">
1023

1124
<!ELEMENT pattern (#PCDATA | expression)*>
12-
<!ELEMENT expression (literal | variable | function | unsupported)>
25+
26+
<!ELEMENT expression (
27+
((literal | variable), (function | unsupportedExpression)?) |
28+
function | unsupportedExpression
29+
)>
1330

1431
<!ELEMENT literal (#PCDATA)>
1532
<!ATTLIST literal quoted (true | false) #REQUIRED>
1633

1734
<!ELEMENT variable (EMPTY)>
1835
<!ATTLIST variable name NMTOKEN #REQUIRED>
1936

20-
<!ELEMENT function (operand?,option*)>
37+
<!ELEMENT function (option)*>
2138
<!ATTLIST function
2239
kind (open | close | value) #REQUIRED
2340
name NMTOKEN #REQUIRED
2441
>
25-
<!ELEMENT operand (literal | variable)>
2642
<!ELEMENT option (literal | variable)>
2743
<!ATTLIST option name NMTOKEN #REQUIRED>
2844

29-
<!ELEMENT unsupported (operand?,source)>
30-
<!ATTLIST unsupported sigil CDATA #REQUIRED>
31-
<!ELEMENT source (#PCDATA)>
45+
<!ELEMENT unsupportedExpression (#PCDATA)>
46+
<!ATTLIST unsupportedExpression sigil CDATA #REQUIRED>

0 commit comments

Comments
 (0)