| // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:messages/messages.dart'; | |
| import 'icu_message_parser.dart'; | |
| import 'message_parser.dart'; | |
| Map<String, int> numbers = {'zero': 0, 'one': 1, 'two': 2}; | |
| class PluralParser { | |
| MapEntry<T, Message>? getPluralCaseFrom<T>( | |
| T id, | |
| Node node, | |
| List<String> arguments, | |
| ) { | |
| final childMessage = node.children.firstWhere((e) => e.type == ST.message); | |
| final parsedMessage = MessageParser.parseNode(childMessage, arguments); | |
| if (parsedMessage != null) { | |
| return MapEntry(id, parsedMessage); | |
| } else { | |
| return null; | |
| } | |
| } | |
| Message? getNamed( | |
| List<Node> parts, | |
| String id, | |
| List<String> arguments, | |
| ) { | |
| final messages = parts | |
| .where((e) => | |
| e.children[0].type == ST.identifier && e.children[0].value == id) | |
| .map((e) => e.children.firstWhere((e) => e.type == ST.message)) | |
| .map((e) => MessageParser.parseNode(e, arguments)) | |
| .whereType<Message>(); | |
| if (messages.isNotEmpty) { | |
| return messages.first; | |
| } | |
| return null; | |
| } | |
| PluralMessage parse(Node node, List<String> arguments, | |
| [bool addId = false, String? name]) { | |
| final identifier = node.children | |
| .firstWhere((element) => element.type == ST.identifier) | |
| .value!; | |
| if (!arguments.contains(identifier)) arguments.add(identifier); | |
| final parts = node.children | |
| .firstWhere((element) => element.type == ST.pluralParts) | |
| .children; | |
| final numberCases = getNumberCases(parts, arguments); | |
| final wordCases = getWordCases(parts, arguments); | |
| return PluralMessage( | |
| numberCases: numberCases, | |
| wordCases: wordCases, | |
| few: getNamed(parts, 'few', arguments), | |
| many: getNamed(parts, 'many', arguments), | |
| other: getOther(parts, arguments)!, | |
| argIndex: arguments.indexOf(identifier), | |
| id: addId ? name : null, | |
| ); | |
| } | |
| Map<int, Message> getNumberCases(List<Node> parts, List<String> arguments) { | |
| final numberCases = parts | |
| .where((node) => | |
| node.children[0].type == ST.equalSign && | |
| node.children[1].type == ST.number) | |
| .map((node) => getPluralCaseFrom( | |
| int.parse(node.children[1].value ?? ''), | |
| node, | |
| arguments, | |
| )) | |
| .whereType<MapEntry<int, Message>>(); | |
| return Map.fromEntries(numberCases); | |
| } | |
| Map<int, Message> getWordCases(List<Node> parts, List<String> arguments) { | |
| final wordCases = parts | |
| .where((node) => node.children[0].type == ST.identifier) | |
| .where((node) => numbers.containsKey(node.children[0].value)) | |
| .map((node) => getPluralCaseFrom( | |
| numbers[node.children[0].value!]!, | |
| node, | |
| arguments, | |
| )) | |
| .whereType<MapEntry<int, Message>>(); | |
| return Map.fromEntries(wordCases); | |
| } | |
| Message? getOther(List<Node> parts, List<String> arguments) { | |
| final other = parts | |
| .where((e) => e.children[0].type == ST.other) | |
| .map((e) => e.children.firstWhere((e) => e.type == ST.message)) | |
| .map((e) => MessageParser.parseNode(e, arguments)) | |
| .whereType<Message>(); | |
| return other.isNotEmpty ? other.first : null; | |
| } | |
| } |