コード例 #1
0
ファイル: parser.py プロジェクト: jessemapel/pvl
    def _parse_set_seq(self, delimiters, tokens: abc.Generator) -> list:
        """The internal parsing of PVL Sets and Sequences are very
        similar, and this function provides that shared logic.

        *delimiters* are a two-tuple containing the start and end
        characters for the PVL Set or Sequence.
        """
        t = next(tokens)
        if t != delimiters[0]:
            tokens.send(t)
            raise ValueError(f'Expecting a begin delimiter "{delimiters[0]}" '
                             f'but found: "{t}"')
        set_seq = list()
        # Initial WSC and/or empty
        if self.parse_WSC_until(delimiters[1], tokens):
            return set_seq

        # First item:
        set_seq.append(self.parse_value(tokens))
        if self.parse_WSC_until(delimiters[1], tokens):
            return set_seq

        # Remaining items, if any
        for t in tokens:
            # print(f'in loop, t: {t}, set_seq: {set_seq}')
            if t == ',':
                self.parse_WSC_until(None, tokens)  # consume WSC after ','
                set_seq.append(self.parse_value(tokens))
                if self.parse_WSC_until(delimiters[1], tokens):
                    return set_seq
            else:
                tokens.send(t)
                tokens.throw(ValueError,
                             'While parsing, expected a comma (,)'
                             f'but found: "{t}"')
コード例 #2
0
    def parse_module(self, tokens: abc.Generator):
        """Parses the tokens for a PVL Module.

         <PVL-Module-Contents> ::=
          ( <Assignment-Statement> | <WSC>* | <Aggregation-Block> )*
          [<End-Statement>]

        """
        m = self.modcls()

        parsing = True
        while parsing:
            # print(f'top of while parsing: {m}')
            parsing = False
            for p in (
                self.parse_aggregation_block,
                self.parse_assignment_statement,
                self.parse_end_statement,
            ):
                try:
                    self.parse_WSC_until(None, tokens)
                    # t = next(tokens)
                    # print(f'next token: {t}, {t.pos}')
                    # tokens.send(t)
                    parsed = p(tokens)
                    # print(f'parsed: {parsed}')
                    if parsed is None:  # because parse_end_statement returned
                        return m
                    else:
                        m.append(*parsed)
                        parsing = True
                except LexerError:
                    raise
                except ValueError:
                    pass
            try:
                (m, keep_parsing) = self.parse_module_post_hook(m, tokens)
                if keep_parsing:
                    parsing = True
                else:
                    return m
            except Exception:
                pass

        # print(f'got to bottom: {m}')
        t = next(tokens)
        tokens.throw(
            ValueError,
            "Expecting an Aggregation Block, an Assignment "
            "Statement, or an End Statement, but found "
            f'"{t}" ',
        )
コード例 #3
0
    def parse_end_aggregation(
        self, begin_agg: str, block_name: str, tokens: abc.Generator
    ) -> None:
        """Parses the tokens for an End Aggregation Statement.

        <End-Aggregation-Statement-block> ::=
             <End-Aggegation-Statement> [<WSC>* '=' <WSC>*
             <Block-Name>] [<Statement-Delimiter>]

        Where <Block-Name> ::= <Parameter-Name>

        """
        end_agg = next(tokens)

        # Need to do a little song and dance to case-independently
        # match the keys:
        for k in self.grammar.aggregation_keywords.keys():
            if k.casefold() == begin_agg.casefold():
                truecase_begin = k
                break
        if (
            end_agg.casefold()
            != self.grammar.aggregation_keywords[truecase_begin].casefold()
        ):
            tokens.send(end_agg)
            raise ValueError(
                "Expecting an End-Aggegation-Statement that "
                "matched the Begin-Aggregation_Statement, "
                f'"{begin_agg}" but found: {end_agg}'
            )

        try:
            self.parse_around_equals(tokens)
        except (ParseError, ValueError):  # No equals statement, which is fine.
            self.parse_statement_delimiter(tokens)
            return None

        t = next(tokens)
        if t != block_name:
            tokens.send(t)
            tokens.throw(
                ValueError,
                f'Expecting a Block-Name after "{end_agg} =" '
                f'that matches "{block_name}", but found: '
                f'"{t}"',
            )

        self.parse_statement_delimiter(tokens)

        return None
コード例 #4
0
    def parse_value(self, tokens: abc.Generator):
        """Parses PVL Values.

         <Value> ::= (<Simple-Value> | <Set> | <Sequence>)
                     [<WSC>* <Units Expression>]

        Returns the decoded <Value> as an appropriate Python object.
        """
        value = None

        try:
            t = next(tokens)
            value = self.decoder.decode_simple_value(t)
        except ValueError:
            tokens.send(t)
            for p in (
                self.parse_set,
                self.parse_sequence,
                self.parse_value_post_hook,
            ):
                try:
                    value = p(tokens)
                    break
                except LexerError:
                    # A LexerError is a subclass of ValueError, but
                    # if we get a LexerError, that's a problem and
                    # we need to raise it, and not let it pass.
                    raise
                except ValueError:
                    # Getting a ValueError is a normal conseqence of
                    # one of the parsing strategies not working,
                    # this pass allows us to go to the next one.
                    pass
            else:
                tokens.throw(
                    ValueError,
                    "Was expecting a Simple Value, or the "
                    "beginning of a Set or Sequence, but "
                    f'found: "{t}"',
                )

        # print(f'in parse_value, value is: {value}')
        self.parse_WSC_until(None, tokens)
        try:
            return self.parse_units(value, tokens)
        except (ValueError, StopIteration):
            return value
コード例 #5
0
    def parse_units(self, value, tokens: abc.Generator) -> str:
        """Parses PVL Units Expression.

         <Units-Expression> ::= "<" [<white-space>] <Units-Value>
                                    [<white-space>] ">"

        and

         <Units-Value> ::= <units-character>
                             [ [ <units-character> | <white-space> ]*
                                 <units-character> ]

        Returns the *value* and the <Units-Value> as a ``Units()``
        object.
        """
        t = next(tokens)

        if not t.startswith(self.grammar.units_delimiters[0]):
            tokens.send(t)
            raise ValueError(
                "Was expecting the start units delimiter, "
                + '"{}" '.format(self.grammar.units_delimiters[0])
                + f'but found "{t}"'
            )

        if not t.endswith(self.grammar.units_delimiters[1]):
            tokens.send(t)
            raise ValueError(
                "Was expecting the end units delimiter, "
                + '"{}" '.format(self.grammar.units_delimiters[1])
                + f'at the end, but found "{t}"'
            )

        delim_strip = t.strip("".join(self.grammar.units_delimiters))

        units_value = delim_strip.strip("".join(self.grammar.whitespace))

        for d in self.grammar.units_delimiters:
            if d in units_value:
                tokens.throw(
                    ValueError,
                    "Was expecting a units character, but found a "
                    f'unit delimiter, "{d}" instead.',
                )

        return self.decoder.decode_quantity(value, units_value)
コード例 #6
0
    def parse_begin_aggregation_statement(
        self, tokens: abc.Generator
    ) -> tuple:
        """Parses the tokens for a Begin Aggregation Statement, and returns
        the name Block Name as a ``str``.

        <Begin-Aggregation-Statement-block> ::=
             <Begin-Aggegation-Statement> <WSC>* '=' <WSC>*
             <Block-Name> [<Statement-Delimiter>]

        Where <Block-Name> ::= <Parameter-Name>

        """
        try:
            begin = next(tokens)
            if not begin.is_begin_aggregation():
                tokens.send(begin)
                raise ValueError(
                    "Expecting a Begin-Aggegation-Statement, but "
                    f"found: {begin}"
                )
        except StopIteration:
            raise ValueError(
                "Ran out of tokens before starting to parse "
                "a Begin-Aggegation-Statement."
            )

        try:
            self.parse_around_equals(tokens)
        except ValueError:
            tokens.throw(
                ValueError, f'Expecting an equals sign after "{begin}" '
            )

        block_name = next(tokens)
        if not block_name.is_parameter_name():
            tokens.throw(
                ValueError,
                f'Expecting a Block-Name after "{begin} =" '
                f'but found: "{block_name}"',
            )

        self.parse_statement_delimiter(tokens)

        return begin, str(block_name)
コード例 #7
0
 def throw(self, *args, **kwargs):  # noqa: D102
     return Generator.throw(self, *args, **kwargs)
コード例 #8
0
 def throw(self, exception_type, value=None, trace_back=None):
     return Generator.throw(self, exception_type, value, trace_back)
コード例 #9
0
ファイル: berny.py プロジェクト: azag0/berny-python
 def throw(self, *args, **kwargs):
     return Generator.throw(self, *args, **kwargs)
コード例 #10
0
 def throw(self, *args, **kwargs):
     return Generator.throw(self, *args, **kwargs)