Skip to content

Commit

Permalink
Merge pull request #2580 from Kodiologist/dehierarch
Browse files Browse the repository at this point in the history
Make user-facing reader objects available as direct children of `hy`
  • Loading branch information
Kodiologist authored May 3, 2024
2 parents 96ba4df + f539436 commit 5784c1f
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 11 deletions.
6 changes: 3 additions & 3 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1307,13 +1307,13 @@ Readers
Hy's reader (i.e., parser) classes are most interesting to the user in the
context of :ref:`reader macros <reader-macros>`.

.. autoclass:: hy.reader.hy_reader.HyReader
.. autoclass:: hy.HyReader
:members: parse, parse_one_form, parse_forms_until, read_default, fill_pos

.. autoclass:: hy.reader.reader.Reader
.. autoclass:: hy.Reader
:members:

.. autoexception:: hy.reader.exceptions.PrematureEndOfInput
.. autoexception:: hy.PrematureEndOfInput

.. _pyop:

Expand Down
4 changes: 2 additions & 2 deletions docs/macros.rst
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ Ultimately it's wisest to use only four kinds of names in macro expansions: gens
Reader macros
-------------

Reader macros allow you to hook directly into Hy's parser to customize how text is parsed into models. They're defined with :hy:func:`defreader <hy.core.macros.defreader>`, or, like regular macros, brought in from other modules with :hy:func:`require`. Rather than receiving function arguments, a reader macro has access to a :py:class:`HyReader <hy.reader.hy_reader.HyReader>` object named ``&reader``, which provides all the text-parsing logic that Hy uses to parse itself (see :py:class:`HyReader <hy.reader.hy_reader.HyReader>` and its base class :py:class:`Reader <hy.reader.reader.Reader>` for the available methods). A reader macro is called with the hash sign ``#``, and like a regular macro, it should return a model or something convertible to a model.
Reader macros allow you to hook directly into Hy's parser to customize how text is parsed into models. They're defined with :hy:func:`defreader <hy.core.macros.defreader>`, or, like regular macros, brought in from other modules with :hy:func:`require`. Rather than receiving function arguments, a reader macro has access to a :py:class:`hy.HyReader` object named ``&reader``, which provides all the text-parsing logic that Hy uses to parse itself (see :py:class:`hy.HyReader` and its base class :py:class:`hy.Reader` for the available methods). A reader macro is called with the hash sign ``#``, and like a regular macro, it should return a model or something convertible to a model.

The simplest kind of reader macro doesn't read anything::

Expand All @@ -170,7 +170,7 @@ The simplest kind of reader macro doesn't read anything::

#hi #hi #hi

A less trivial, and more common, usage of reader macros is to call :func:`HyReader.parse-one-form <hy.reader.hy_reader.HyReader.parse_one_form>` to get a single form from the following source text. Such a reader macro is like a unary regular macro that's called with ``#`` instead of parentheses. ::
A less trivial, and more common, usage of reader macros is to call :func:`hy.HyReader.parse_one_form` to get a single form from the following source text. Such a reader macro is like a unary regular macro that's called with ``#`` instead of parentheses. ::

(defreader do-twice
(setv x (.parse-one-form &reader))
Expand Down
3 changes: 3 additions & 0 deletions hy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ def __getattr__(self, s):
disassemble="hy.core.util",
as_model="hy.models",
REPL="hy.repl",
Reader="hy.reader.reader",
HyReader="hy.reader.hy_reader",
PrematureEndOfInput="hy.reader.exceptions"
)


Expand Down
8 changes: 5 additions & 3 deletions hy/reader/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
def read_many(stream, filename="<string>", reader=None, skip_shebang=False):
"""Parse all the Hy source code in ``stream``, which should be a textual file-like
object or a string. ``filename``, if provided, is used in error messages. If no
``reader`` is provided, a new :class:`hy.reader.hy_reader.HyReader` object is created.
If ``skip_shebang`` is true and a :ref:`shebang line <shebang>` is present, it's
``reader`` is provided, a new :class:`hy.HyReader` object is created. If
``skip_shebang`` is true and a :ref:`shebang line <shebang>` is present, it's
detected and discarded first.
Return a value of type :class:`hy.models.Lazy`. If you want to evaluate this, be
Expand All @@ -25,7 +25,9 @@ def read_many(stream, filename="<string>", reader=None, skip_shebang=False):
.. warning::
Thanks to reader macros, reading can execute arbitrary code. Don't read untrusted
input."""
input.
"""

if isinstance(stream, str):
stream = StringIO(stream)
Expand Down
2 changes: 1 addition & 1 deletion hy/reader/hy_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def err(msg):

class HyReader(Reader):
"""A modular reader for Hy source. It inherits from
:py:class:`hy.reader.reader.Reader`.
:py:class:`hy.Reader`.
When ``use_current_readers`` is true, initialize this reader
with all reader macros from the calling module."""
Expand Down
4 changes: 2 additions & 2 deletions hy/reader/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __new__(cls, name, bases, namespace):
class Reader(metaclass=ReaderMeta):
"""An abstract base class for reading input character-by-character.
See :py:class:`HyReader <hy.reader.hy_reader.HyReader>` for an example
See :py:class:`hy.HyReader` for an example
of creating a reader class.
Attributes:
Expand Down Expand Up @@ -176,7 +176,7 @@ def peek_and_getc(self, target):
def chars(self, eof_ok=False):
"""Consume and yield characters of the stream. If ``eof_ok``
is false (the default) and the end of the stream is reached,
raise :exc:`hy.reader.exceptions.PrematureEndOfInput`."""
raise :exc:`hy.PrematureEndOfInput`."""

while True:
c = self.getc()
Expand Down

0 comments on commit 5784c1f

Please sign in to comment.