| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 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. | |
| 8 */ | |
| 9 library icu_parser; | |
| 10 | |
| 11 import 'package:intl/src/intl_message.dart'; | |
| 12 import 'package:petitparser/petitparser.dart'; | |
| 13 | |
| 14 /** | |
| 15 * This defines a grammar for ICU MessageFormat syntax. Usage is | |
| 16 * new IcuParser.message.parse(<string>).value; | |
| 17 * The "parse" method will return a Success or Failure object which responds | |
| 18 * to "value". | |
| 19 */ | |
| 20 class IcuParser { | |
| 21 get openCurly => char("{"); | |
| 22 | |
| 23 get closeCurly => char("}"); | |
| 24 get quotedCurly => (string("'{'") | string("'}'")).map((x) => x[1]); | |
| 25 | |
| 26 get icuEscapedText => quotedCurly | twoSingleQuotes; | |
| 27 get curly => (openCurly | closeCurly); | |
| 28 get notAllowedInIcuText => curly | char("<"); | |
| 29 get icuText => notAllowedInIcuText.neg(); | |
| 30 get notAllowedInNormalText => char("{"); | |
| 31 get normalText => notAllowedInNormalText.neg(); | |
| 32 get messageText => (icuEscapedText | icuText).plus().map((x) => x.join()); | |
| 33 get nonIcuMessageText => normalText.plus().map((x) => x.join()); | |
| 34 get twoSingleQuotes => string("''").map((x) => "'"); | |
| 35 get number => digit().plus().flatten().trim().map(int.parse); | |
| 36 get id => (letter() & (word() | char("_")).star()).flatten().trim(); | |
| 37 get comma => char(",").trim(); | |
| 38 | |
| 39 /** | |
| 40 * Given a list of possible keywords, return a rule that accepts any of them. | |
| 41 * e.g., given ["male", "female", "other"], accept any of them. | |
| 42 */ | |
| 43 asKeywords(list) => list.map(string).reduce((a, b) => a | b).flatten().trim(); | |
| 44 | |
| 45 get pluralKeyword => asKeywords( | |
| 46 ["=0", "=1", "=2", "zero", "one", "two", "few", "many", "other"]); | |
| 47 get genderKeyword => asKeywords(["female", "male", "other"]); | |
| 48 | |
| 49 var interiorText = undefined(); | |
| 50 | |
| 51 get preface => (openCurly & id & comma).map((values) => values[1]); | |
| 52 | |
| 53 get pluralLiteral => string("plural"); | |
| 54 get pluralClause => (pluralKeyword & openCurly & interiorText & closeCurly) | |
| 55 .trim() | |
| 56 .map((result) => [result[0], result[2]]); | |
| 57 get plural => | |
| 58 preface & pluralLiteral & comma & pluralClause.plus() & closeCurly; | |
| 59 get intlPlural => | |
| 60 plural.map((values) => new Plural.from(values.first, values[3], null)); | |
| 61 | |
| 62 get selectLiteral => string("select"); | |
| 63 get genderClause => (genderKeyword & openCurly & interiorText & closeCurly) | |
| 64 .trim() | |
| 65 .map((result) => [result[0], result[2]]); | |
| 66 get gender => | |
| 67 preface & selectLiteral & comma & genderClause.plus() & closeCurly; | |
| 68 get intlGender => | |
| 69 gender.map((values) => new Gender.from(values.first, values[3], null)); | |
| 70 get selectClause => | |
| 71 (id & openCurly & interiorText & closeCurly).map((x) => [x.first, x[2]]); | |
| 72 get generalSelect => | |
| 73 preface & selectLiteral & comma & selectClause.plus() & closeCurly; | |
| 74 get intlSelect => generalSelect | |
| 75 .map((values) => new Select.from(values.first, values[3], null)); | |
| 76 | |
| 77 get pluralOrGenderOrSelect => intlPlural | intlGender | intlSelect; | |
| 78 | |
| 79 get contents => pluralOrGenderOrSelect | parameter | messageText; | |
| 80 get simpleText => (nonIcuMessageText | parameter | openCurly).plus(); | |
| 81 get empty => epsilon().map((_) => ''); | |
| 82 | |
| 83 get parameter => (openCurly & id & closeCurly) | |
| 84 .map((param) => new VariableSubstitution.named(param[1], null)); | |
| 85 | |
| 86 /** | |
| 87 * The primary entry point for parsing. Accepts a string and produces | |
| 88 * a parsed representation of it as a Message. | |
| 89 */ | |
| 90 get message => (pluralOrGenderOrSelect | empty) | |
| 91 .map((chunk) => Message.from(chunk, null)); | |
| 92 | |
| 93 /** | |
| 94 * Represents an ordinary message, i.e. not a plural/gender/select, although | |
| 95 * it may have parameters. | |
| 96 */ | |
| 97 get nonIcuMessage => | |
| 98 (simpleText | empty).map((chunk) => Message.from(chunk, null)); | |
| 99 | |
| 100 get stuff => (pluralOrGenderOrSelect | empty) | |
| 101 .map((chunk) => Message.from(chunk, null)); | |
| 102 | |
| 103 IcuParser() { | |
| 104 // There is a cycle here, so we need the explicit set to avoid | |
| 105 // infinite recursion. | |
| 106 interiorText.set(contents.plus() | empty); | |
| 107 } | |
| 108 } | |
| OLD | NEW |