diff --git a/omegaconf/grammar/OmegaConfGrammarParser.g4 b/omegaconf/grammar/OmegaConfGrammarParser.g4 index eaa496d8f..58000e2b6 100644 --- a/omegaconf/grammar/OmegaConfGrammarParser.g4 +++ b/omegaconf/grammar/OmegaConfGrammarParser.g4 @@ -42,7 +42,7 @@ element: listContainer: BRACKET_OPEN sequence? BRACKET_CLOSE; // [], [1,2,3], [a,b,[1,2]] dictContainer: BRACE_OPEN (dictKeyValuePair (COMMA dictKeyValuePair)*)? BRACE_CLOSE; // {}, {a:10,b:20} dictKeyValuePair: dictKey COLON element; -sequence: element (COMMA element)*; +sequence: (element (COMMA element?)*) | (COMMA element?)+; // Interpolations. diff --git a/omegaconf/grammar_visitor.py b/omegaconf/grammar_visitor.py index debfa7f52..8f8b87863 100644 --- a/omegaconf/grammar_visitor.py +++ b/omegaconf/grammar_visitor.py @@ -1,4 +1,5 @@ import sys +import warnings from typing import ( TYPE_CHECKING, Any, @@ -246,20 +247,41 @@ def visitSequence( ) -> Generator[Any, None, None]: from ._utils import _get_value - assert ctx.getChildCount() >= 1 # element (COMMA element)* + # (element (COMMA element?)*) | (COMMA element?)+ + assert ctx.getChildCount() >= 1 + + def empty_str_warning() -> None: + txt = ctx.getText() + warnings.warn( + f"In the sequence `{txt}` some elements are missing: please replace " + f"them with empty strings (\"\" or '') since this will not be supported " + f"anymore in the future.", + category=UserWarning, + ) + + is_previous_comma = True # whether previous child was a comma (init to True) for i, child in enumerate(ctx.getChildren()): - if i % 2 == 0: - assert isinstance(child, OmegaConfGrammarParser.ElementContext) + if isinstance(child, OmegaConfGrammarParser.ElementContext): # Also preserve the original text representation of `child` so # as to allow backward compatibility with old resolvers (registered # with `legacy_register_resolver()`). Note that we cannot just cast # the value to string later as for instance `null` would become "None". yield _get_value(self.visitElement(child)), child.getText() + is_previous_comma = False else: assert ( isinstance(child, TerminalNode) and child.symbol.type == OmegaConfGrammarLexer.COMMA ) + if is_previous_comma: + empty_str_warning() + yield "", "" + else: + is_previous_comma = True + if is_previous_comma: + # Trailing comma. + empty_str_warning() + yield "", "" def visitSingleElement( self, ctx: OmegaConfGrammarParser.SingleElementContext