/* ******************************************************************************* * Copyright (C) 2010-2014, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* * created on: 2010aug21 * created by: Markus W. Scherer */ package com.ibm.icu.text; import java.util.ArrayList; import java.util.Locale; import com.ibm.icu.impl.ICUConfig; import com.ibm.icu.impl.PatternProps; import com.ibm.icu.util.Freezable; import com.ibm.icu.util.ICUCloneNotSupportedException; //Note: Minimize ICU dependencies, only use a very small part of the ICU core. //In particular, do not depend on *Format classes. /** * Parses and represents ICU MessageFormat patterns. * Also handles patterns for ChoiceFormat, PluralFormat and SelectFormat. * Used in the implementations of those classes as well as in tools * for message validation, translation and format conversion. *

* The parser handles all syntax relevant for identifying message arguments. * This includes "complex" arguments whose style strings contain * nested MessageFormat pattern substrings. * For "simple" arguments (with no nested MessageFormat pattern substrings), * the argument style is not parsed any further. *

* The parser handles named and numbered message arguments and allows both in one message. *

* Once a pattern has been parsed successfully, iterate through the parsed data * with countParts(), getPart() and related methods. *

* The data logically represents a parse tree, but is stored and accessed * as a list of "parts" for fast and simple parsing and to minimize object allocations. * Arguments and nested messages are best handled via recursion. * For every _START "part", {@link #getLimitPartIndex(int)} efficiently returns * the index of the corresponding _LIMIT "part". *

* List of "parts": *

 * message = MSG_START (SKIP_SYNTAX | INSERT_CHAR | REPLACE_NUMBER | argument)* MSG_LIMIT
 * argument = noneArg | simpleArg | complexArg
 * complexArg = choiceArg | pluralArg | selectArg
 *
 * noneArg = ARG_START.NONE (ARG_NAME | ARG_NUMBER) ARG_LIMIT.NONE
 * simpleArg = ARG_START.SIMPLE (ARG_NAME | ARG_NUMBER) ARG_TYPE [ARG_STYLE] ARG_LIMIT.SIMPLE
 * choiceArg = ARG_START.CHOICE (ARG_NAME | ARG_NUMBER) choiceStyle ARG_LIMIT.CHOICE
 * pluralArg = ARG_START.PLURAL (ARG_NAME | ARG_NUMBER) pluralStyle ARG_LIMIT.PLURAL
 * selectArg = ARG_START.SELECT (ARG_NAME | ARG_NUMBER) selectStyle ARG_LIMIT.SELECT
 *
 * choiceStyle = ((ARG_INT | ARG_DOUBLE) ARG_SELECTOR message)+
 * pluralStyle = [ARG_INT | ARG_DOUBLE] (ARG_SELECTOR [ARG_INT | ARG_DOUBLE] message)+
 * selectStyle = (ARG_SELECTOR message)+
 * 
*