OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Contains a parser for ICU format plural/gender/select format for localized | 6 * Contains a parser for ICU format plural/gender/select format for localized |
7 * messages. See extract_to_arb.dart and make_hardcoded_translation.dart. | 7 * messages. See extract_to_arb.dart and make_hardcoded_translation.dart. |
8 */ | 8 */ |
9 library icu_parser; | 9 library icu_parser; |
10 | 10 |
11 import 'package:intl/src/intl_message.dart'; | 11 import 'package:intl/src/intl_message.dart'; |
12 import 'package:petitparser/petitparser.dart'; | 12 import 'package:petitparser/petitparser.dart'; |
13 | 13 |
14 /** | 14 /** |
15 * This defines a grammar for ICU MessageFormat syntax. Usage is | 15 * This defines a grammar for ICU MessageFormat syntax. Usage is |
16 * new ICUParser.message.parse(<string>).value; | 16 * new IcuParser.message.parse(<string>).value; |
17 * The "parse" method will return a Success or Failure object which responds | 17 * The "parse" method will return a Success or Failure object which responds |
18 * to "value". | 18 * to "value". |
19 */ | 19 */ |
20 class ICUParser { | 20 class IcuParser { |
21 get openCurly => char("{"); | 21 get openCurly => char("{"); |
22 | 22 |
23 get closeCurly => char("}"); | 23 get closeCurly => char("}"); |
24 get quotedCurly => (string("'{'") | string("'}'")).map((x) => x[1]); | 24 get quotedCurly => (string("'{'") | string("'}'")).map((x) => x[1]); |
25 | 25 |
26 get icuEscapedText => quotedCurly | twoSingleQuotes; | 26 get icuEscapedText => quotedCurly | twoSingleQuotes; |
27 get curly => (openCurly | closeCurly); | 27 get curly => (openCurly | closeCurly); |
28 get notAllowedInIcuText => curly | char("<"); | 28 get notAllowedInIcuText => curly | char("<"); |
29 get icuText => notAllowedInIcuText.neg(); | 29 get icuText => notAllowedInIcuText.neg(); |
30 get notAllowedInNormalText => char("{"); | 30 get notAllowedInNormalText => char("{"); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 62 |
63 get selectLiteral => string("select"); | 63 get selectLiteral => string("select"); |
64 get genderClause => (genderKeyword & openCurly & interiorText & closeCurly) | 64 get genderClause => (genderKeyword & openCurly & interiorText & closeCurly) |
65 .trim().map((result) => [result[0], result[2]]); | 65 .trim().map((result) => [result[0], result[2]]); |
66 get gender => | 66 get gender => |
67 preface & selectLiteral & comma & genderClause.plus() & closeCurly; | 67 preface & selectLiteral & comma & genderClause.plus() & closeCurly; |
68 get intlGender => | 68 get intlGender => |
69 gender.map((values) => new Gender.from(values.first, values[3], null)); | 69 gender.map((values) => new Gender.from(values.first, values[3], null)); |
70 get selectClause => (id & openCurly & interiorText & closeCurly).map( | 70 get selectClause => (id & openCurly & interiorText & closeCurly).map( |
71 (x) => [x.first, x[2]]); | 71 (x) => [x.first, x[2]]); |
72 get generalSelect => preface & selectLiteral & comma & | 72 get generalSelect => preface & selectLiteral & comma & |
73 selectClause.plus() & closeCurly; | 73 selectClause.plus() & closeCurly; |
74 get intlSelect => generalSelect.map( | 74 get intlSelect => generalSelect.map( |
75 (values) => new Select.from(values.first, values[3], null)); | 75 (values) => new Select.from(values.first, values[3], null)); |
76 | 76 |
77 get pluralOrGenderOrSelect => intlPlural | intlGender | intlSelect; | 77 get pluralOrGenderOrSelect => intlPlural | intlGender | intlSelect; |
78 | 78 |
79 get contents => pluralOrGenderOrSelect | parameter | messageText; | 79 get contents => pluralOrGenderOrSelect | parameter | messageText; |
80 get simpleText => (nonIcuMessageText | parameter | openCurly).plus(); | 80 get simpleText => (nonIcuMessageText | parameter | openCurly).plus(); |
81 get empty => epsilon().map((_) => ''); | 81 get empty => epsilon().map((_) => ''); |
82 | 82 |
83 get parameter => (openCurly & id & closeCurly).map( | 83 get parameter => (openCurly & id & closeCurly).map( |
84 (param) => new VariableSubstitution.named(param[1], null)); | 84 (param) => new VariableSubstitution.named(param[1], null)); |
85 | 85 |
86 /** | 86 /** |
87 * The primary entry point for parsing. Accepts a string and produces | 87 * The primary entry point for parsing. Accepts a string and produces |
88 * a parsed representation of it as a Message. | 88 * a parsed representation of it as a Message. |
89 */ | 89 */ |
90 get message => (pluralOrGenderOrSelect | empty).map((chunk) => | 90 get message => (pluralOrGenderOrSelect | empty).map((chunk) => |
91 Message.from(chunk, null)); | 91 Message.from(chunk, null)); |
92 | 92 |
93 /** | 93 /** |
94 * Represents an ordinary message, i.e. not a plural/gender/select, although | 94 * Represents an ordinary message, i.e. not a plural/gender/select, although |
95 * it may have parameters. | 95 * it may have parameters. |
96 */ | 96 */ |
97 get nonIcuMessage => (simpleText | empty).map((chunk) => | 97 get nonIcuMessage => (simpleText | empty).map((chunk) => |
98 Message.from(chunk, null)); | 98 Message.from(chunk, null)); |
99 | 99 |
100 get stuff => (pluralOrGenderOrSelect | empty).map( | 100 get stuff => (pluralOrGenderOrSelect | empty).map( |
101 (chunk) => Message.from(chunk, null)); | 101 (chunk) => Message.from(chunk, null)); |
102 | |
103 | 102 |
104 ICUParser() { | 103 IcuParser() { |
105 // There is a cycle here, so we need the explicit set to avoid | 104 // There is a cycle here, so we need the explicit set to avoid |
106 // infinite recursion. | 105 // infinite recursion. |
107 interiorText.set(contents.plus() | empty); | 106 interiorText.set(contents.plus() | empty); |
108 } | 107 } |
109 } | 108 } |
OLD | NEW |