| 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 |