@@ -510,21 +510,13 @@ VariableName Parser::parseVariableName(UErrorCode& errorCode) {
510510 VariableName result;
511511
512512 U_ASSERT (inBounds ());
513- // If the '$' is missing, we don't want a binding
514- // for this variable to be created.
515- bool valid = peek () == DOLLAR;
513+
516514 parseToken (DOLLAR, errorCode);
517515 if (!inBounds ()) {
518516 ERROR (errorCode);
519517 return result;
520518 }
521- UnicodeString varName = parseName (errorCode);
522- // Set the name to "" if the variable wasn't
523- // declared correctly
524- if (!valid) {
525- varName.remove ();
526- }
527- return VariableName (varName);
519+ return VariableName (parseName (errorCode));
528520}
529521
530522/*
@@ -861,27 +853,17 @@ void Parser::parseAttribute(AttributeAdder<T>& attrAdder, UErrorCode& errorCode)
861853 parseTokenWithWhitespace (EQUALS, errorCode);
862854
863855 UnicodeString rhsStr;
864- // Parse RHS, which is either a literal or variable
865- switch (peek ()) {
866- case DOLLAR: {
867- rand = Operand (parseVariableName (errorCode));
868- break ;
869- }
870- default : {
871- // Must be a literal
872- rand = Operand (parseLiteral (errorCode));
873- break ;
874- }
875- }
876- U_ASSERT (!rand.isNull ());
856+ // Parse RHS, which must be a literal
857+ // attribute = "@" identifier [o "=" o literal]
858+ rand = Operand (parseLiteral (errorCode));
877859 } else {
878860 // attribute -> "@" identifier [[s] "=" [s]]
879861 // Use null operand, which `rand` is already set to
880862 // "Backtrack" by restoring the whitespace (if there was any)
881863 index = savedIndex;
882864 }
883865
884- attrAdder.addAttribute (lhs, std::move (rand), errorCode);
866+ attrAdder.addAttribute (lhs, std::move (Operand ( rand) ), errorCode);
885867}
886868
887869/*
@@ -1720,6 +1702,22 @@ Pattern Parser::parseSimpleMessage(UErrorCode& status) {
17201702 return result.build (status);
17211703}
17221704
1705+ void Parser::parseVariant (UErrorCode& status) {
1706+ CHECK_ERROR (status);
1707+
1708+ // At least one key is required
1709+ SelectorKeys keyList (parseNonEmptyKeys (status));
1710+
1711+ // parseNonEmptyKeys() consumes any trailing whitespace,
1712+ // so the pattern can be consumed next.
1713+
1714+ // Restore precondition before calling parsePattern()
1715+ // (which must return a non-null value)
1716+ CHECK_BOUNDS (status);
1717+ Pattern rhs = parseQuotedPattern (status);
1718+
1719+ dataModel.addVariant (std::move (keyList), std::move (rhs), status);
1720+ }
17231721
17241722/*
17251723 Consume a `selectors` (matching the nonterminal in the grammar),
@@ -1739,22 +1737,25 @@ void Parser::parseSelectors(UErrorCode& status) {
17391737 // Parse selectors
17401738 // "Backtracking" is required here. It's not clear if whitespace is
17411739 // (`[s]` selector) or (`[s]` variant)
1742- while (isWhitespace (peek ()) || peek () == LEFT_CURLY_BRACE) {
1743- parseOptionalWhitespace (status);
1740+ while (isWhitespace (peek ()) || peek () == DOLLAR) {
1741+ int32_t whitespaceStart = index;
1742+ parseRequiredWhitespace (status);
17441743 // Restore precondition
17451744 CHECK_BOUNDS (status);
1746- if (peek () != LEFT_CURLY_BRACE ) {
1745+ if (peek () != DOLLAR ) {
17471746 // This is not necessarily an error, but rather,
17481747 // means the whitespace we parsed was the optional
17491748 // whitespace preceding the first variant, not the
1750- // optional whitespace preceding a subsequent expression.
1749+ // required whitespace preceding a subsequent variable.
1750+ // In that case, "push back" the whitespace.
1751+ normalizedInput.truncate (normalizedInput.length () - 1 );
1752+ index = whitespaceStart;
17511753 break ;
17521754 }
1753- Expression expression;
1754- expression = parseExpression (status);
1755+ VariableName var = parseVariableName (status);
17551756 empty = false ;
17561757
1757- dataModel.addSelector (std::move (expression ), status);
1758+ dataModel.addSelector (std::move (var ), status);
17581759 CHECK_ERROR (status);
17591760 }
17601761
@@ -1770,27 +1771,29 @@ void Parser::parseSelectors(UErrorCode& status) {
17701771 } \
17711772
17721773 // Parse variants
1774+ // matcher = match-statement s variant *(o variant)
1775+
1776+ // Parse first variant
1777+ parseRequiredWhitespace (status);
1778+ if (!inBounds ()) {
1779+ ERROR (status);
1780+ return ;
1781+ }
1782+ parseVariant (status);
1783+ if (!inBounds ()) {
1784+ // Not an error; there might be only one variant
1785+ return ;
1786+ }
1787+
17731788 while (isWhitespace (peek ()) || isKeyStart (peek ())) {
1774- // Trailing whitespace is allowed
17751789 parseOptionalWhitespace (status);
1790+ // Restore the precondition.
1791+ // Trailing whitespace is allowed.
17761792 if (!inBounds ()) {
17771793 return ;
17781794 }
17791795
1780- // At least one key is required
1781- SelectorKeys keyList (parseNonEmptyKeys (status));
1782-
1783- CHECK_ERROR (status);
1784-
1785- // parseNonEmptyKeys() consumes any trailing whitespace,
1786- // so the pattern can be consumed next.
1787-
1788- // Restore precondition before calling parsePattern()
1789- // (which must return a non-null value)
1790- CHECK_BOUNDS (status);
1791- Pattern rhs = parseQuotedPattern (status);
1792-
1793- dataModel.addVariant (std::move (keyList), std::move (rhs), status);
1796+ parseVariant (status);
17941797
17951798 // Restore the precondition, *without* erroring out if we've
17961799 // reached the end of input. That's because it's valid for the
0 commit comments