def __init__( self, *args, allow_gaps=True, optional=False, ephemeral_name=None, ): """Deal with kwargs common to all grammars. Args: *args: Any number of elements which because the subjects of this grammar. allow_gaps (:obj:`bool`, optional): Does this instance of the grammar allow gaps between the elements it matches? This may be exhibited slightly differently in each grammar. See that grammar for details. Defaults `True`. optional (:obj:`bool`, optional): In the context of a sequence, is this grammar *optional*, i.e. can it be skipped if no match is found. Outside of a Sequence, this option does nothing. Defaults `False`. ephemeral_name (:obj:`str`, optional): If specified this allows the grammar to match anything, and create an EphemeralSegment with the given name in its place. The content of this grammar is passed to the segment, and will become the parse grammar for it. If used widely this is an excellent way of breaking up the parse process and also signposting the name of a given chunk of code that might be parsed separately. """ # We provide a common interface for any grammar that allows positional elements. # If *any* for the elements are a string and not a grammar, then this is a shortcut # to the Ref.keyword grammar by default. if self.allow_keyword_string_refs: self._elements = [] for elem in args: self._elements.append(self._resolve_ref(elem)) else: self._elements = list(args) # Now we deal with the standard kwargs self.allow_gaps = allow_gaps self.optional = optional self.ephemeral_segment = None # Set up the ephemeral_segment if name is specified. if ephemeral_name: # Make the EphemeralSegment class. This is effectively syntactic sugar # to allow us to avoid specifying a EphemeralSegment directly in a dialect. # Copy self (*before* making the EphemeralSegment, but with everything else in place) parse_grammar = copy.copy(self) # Add the EphemeralSegment to self. self.ephemeral_segment = EphemeralSegment.make( match_grammar=None, # Pass in the copy without the EphemeralSegment parse_grammar=parse_grammar, name=ephemeral_name, )
def test__parser__core_ephemeral_segment(raw_seg_list): """Test the Mystical KeywordSegment.""" # First make a keyword BarKeyword = StringParser("bar", KeywordSegment) ephemeral_segment = EphemeralSegment( segments=raw_seg_list[:1], pos_marker=None, parse_grammar=BarKeyword, name="foobar", ) with RootParseContext(dialect=None) as ctx: # Parse it and make sure we don't get an EphemeralSegment back res = ephemeral_segment.parse(ctx) assert isinstance(res, tuple) elem = res[0] assert not isinstance(elem, EphemeralSegment) assert isinstance(elem, KeywordSegment)
def test__parser__core_ephemeral_segment(raw_seg_list): """Test the Mystical KeywordSegment.""" # First make a keyword BarKeyword = StringParser("bar", KeywordSegment) ephemeral_segment = EphemeralSegment.make(match_grammar=BarKeyword, parse_grammar=BarKeyword, name="foobar") with RootParseContext(dialect=None) as ctx: # Test on a slice containing only the first element m = ephemeral_segment.match(raw_seg_list[:1], parse_context=ctx) assert m # Make sure that it matches as an instance of EphemeralSegment elem = m.matched_segments[0] assert isinstance(elem, ephemeral_segment) # Parse it and make sure we don't get an EphemeralSegment back res = elem.parse(ctx) assert isinstance(res, tuple) elem = res[0] assert not isinstance(elem, ephemeral_segment) assert isinstance(elem, KeywordSegment)