@@ -512,21 +512,13 @@ VariableName Parser::parseVariableName(UErrorCode& errorCode) {
512512 VariableName result;
513513
514514 U_ASSERT (inBounds ());
515- // If the '$' is missing, we don't want a binding
516- // for this variable to be created.
517- bool valid = peek () == DOLLAR;
515+
518516 parseToken (DOLLAR, errorCode);
519517 if (!inBounds ()) {
520518 ERROR (errorCode);
521519 return result;
522520 }
523- UnicodeString varName = parseName (errorCode);
524- // Set the name to "" if the variable wasn't
525- // declared correctly
526- if (!valid) {
527- varName.remove ();
528- }
529- return VariableName (varName);
521+ return VariableName (parseName (errorCode));
530522}
531523
532524/*
@@ -863,27 +855,17 @@ void Parser::parseAttribute(AttributeAdder<T>& attrAdder, UErrorCode& errorCode)
863855 parseTokenWithWhitespace (EQUALS, errorCode);
864856
865857 UnicodeString rhsStr;
866- // Parse RHS, which is either a literal or variable
867- switch (peek ()) {
868- case DOLLAR: {
869- rand = Operand (parseVariableName (errorCode));
870- break ;
871- }
872- default : {
873- // Must be a literal
874- rand = Operand (parseLiteral (errorCode));
875- break ;
876- }
877- }
878- U_ASSERT (!rand.isNull ());
858+ // Parse RHS, which must be a literal
859+ // attribute = "@" identifier [o "=" o literal]
860+ rand = Operand (parseLiteral (errorCode));
879861 } else {
880862 // attribute -> "@" identifier [[s] "=" [s]]
881863 // Use null operand, which `rand` is already set to
882864 // "Backtrack" by restoring the whitespace (if there was any)
883865 index = savedIndex;
884866 }
885867
886- attrAdder.addAttribute (lhs, std::move (rand), errorCode);
868+ attrAdder.addAttribute (lhs, std::move (Operand ( rand) ), errorCode);
887869}
888870
889871/*
@@ -1722,6 +1704,22 @@ Pattern Parser::parseSimpleMessage(UErrorCode& status) {
17221704 return result.build (status);
17231705}
17241706
1707+ void Parser::parseVariant (UErrorCode& status) {
1708+ CHECK_ERROR (status);
1709+
1710+ // At least one key is required
1711+ SelectorKeys keyList (parseNonEmptyKeys (status));
1712+
1713+ // parseNonEmptyKeys() consumes any trailing whitespace,
1714+ // so the pattern can be consumed next.
1715+
1716+ // Restore precondition before calling parsePattern()
1717+ // (which must return a non-null value)
1718+ CHECK_BOUNDS (status);
1719+ Pattern rhs = parseQuotedPattern (status);
1720+
1721+ dataModel.addVariant (std::move (keyList), std::move (rhs), status);
1722+ }
17251723
17261724/*
17271725 Consume a `selectors` (matching the nonterminal in the grammar),
@@ -1741,22 +1739,25 @@ void Parser::parseSelectors(UErrorCode& status) {
17411739 // Parse selectors
17421740 // "Backtracking" is required here. It's not clear if whitespace is
17431741 // (`[s]` selector) or (`[s]` variant)
1744- while (isWhitespace (peek ()) || peek () == LEFT_CURLY_BRACE) {
1745- parseOptionalWhitespace (status);
1742+ while (isWhitespace (peek ()) || peek () == DOLLAR) {
1743+ int32_t whitespaceStart = index;
1744+ parseRequiredWhitespace (status);
17461745 // Restore precondition
17471746 CHECK_BOUNDS (status);
1748- if (peek () != LEFT_CURLY_BRACE ) {
1747+ if (peek () != DOLLAR ) {
17491748 // This is not necessarily an error, but rather,
17501749 // means the whitespace we parsed was the optional
17511750 // whitespace preceding the first variant, not the
1752- // optional whitespace preceding a subsequent expression.
1751+ // required whitespace preceding a subsequent variable.
1752+ // In that case, "push back" the whitespace.
1753+ normalizedInput.truncate (normalizedInput.length () - 1 );
1754+ index = whitespaceStart;
17531755 break ;
17541756 }
1755- Expression expression;
1756- expression = parseExpression (status);
1757+ VariableName var = parseVariableName (status);
17571758 empty = false ;
17581759
1759- dataModel.addSelector (std::move (expression ), status);
1760+ dataModel.addSelector (std::move (var ), status);
17601761 CHECK_ERROR (status);
17611762 }
17621763
@@ -1772,27 +1773,29 @@ void Parser::parseSelectors(UErrorCode& status) {
17721773 } \
17731774
17741775 // Parse variants
1776+ // matcher = match-statement s variant *(o variant)
1777+
1778+ // Parse first variant
1779+ parseRequiredWhitespace (status);
1780+ if (!inBounds ()) {
1781+ ERROR (status);
1782+ return ;
1783+ }
1784+ parseVariant (status);
1785+ if (!inBounds ()) {
1786+ // Not an error; there might be only one variant
1787+ return ;
1788+ }
1789+
17751790 while (isWhitespace (peek ()) || isKeyStart (peek ())) {
1776- // Trailing whitespace is allowed
17771791 parseOptionalWhitespace (status);
1792+ // Restore the precondition.
1793+ // Trailing whitespace is allowed.
17781794 if (!inBounds ()) {
17791795 return ;
17801796 }
17811797
1782- // At least one key is required
1783- SelectorKeys keyList (parseNonEmptyKeys (status));
1784-
1785- CHECK_ERROR (status);
1786-
1787- // parseNonEmptyKeys() consumes any trailing whitespace,
1788- // so the pattern can be consumed next.
1789-
1790- // Restore precondition before calling parsePattern()
1791- // (which must return a non-null value)
1792- CHECK_BOUNDS (status);
1793- Pattern rhs = parseQuotedPattern (status);
1794-
1795- dataModel.addVariant (std::move (keyList), std::move (rhs), status);
1798+ parseVariant (status);
17961799
17971800 // Restore the precondition, *without* erroring out if we've
17981801 // reached the end of input. That's because it's valid for the
0 commit comments