Skip to content

Commit f0c9151

Browse files
ezio-melottiCAM-GerlachAA-Turner
authored
Add a Sphinx role to link to GitHub files (#961)
* Add a new role to link to cpython files. * Use the new :cpy-file: role in internals/parser.rst. * Make the output a literal. * Apply suggestions from code review Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM> * Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> * Remove tabs. Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
1 parent 6b98942 commit f0c9151

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

Diff for: _extensions/custom_roles.py

+17-5
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,35 @@
88

99

1010
def setup(app):
11+
# role to link to cpython files
12+
app.add_role(
13+
"cpy-file",
14+
autolink("https://github.com/python/cpython/blob/main/{}"),
15+
)
16+
# role to link to cpython labels
1117
app.add_role(
1218
"gh-label",
13-
autolink("https://github.com/python/cpython/labels/%s"),
19+
autolink("https://github.com/python/cpython/labels/{}"),
1420
)
1521
# Parallel safety:
1622
# https://www.sphinx-doc.org/en/master/extdev/index.html#extension-metadata
1723
return {"parallel_read_safe": True, "parallel_write_safe": True}
1824

1925

2026
def autolink(pattern):
21-
def role(name, rawtext, text, lineno, inliner, options={}, content=[]):
27+
def role(name, rawtext, text, lineno, inliner, _options=None, _content=None):
28+
"""Combine literal + reference (unless the text is prefixed by a !)."""
2229
if " " in text:
23-
url_text = urllib.parse.quote(f"{text}")
30+
url_text = urllib.parse.quote(text)
2431
else:
2532
url_text = text
26-
url = pattern % (url_text,)
27-
node = nodes.reference(rawtext, text, refuri=url, **options)
33+
url = pattern.format(url_text)
34+
# don't create a reference if the text starts with !
35+
if text.startswith('!'):
36+
node = nodes.literal(rawtext, text[1:])
37+
else:
38+
node = nodes.reference(rawtext, '', nodes.literal(rawtext, text),
39+
refuri=url, internal=False)
2840
return [node], []
2941

3042
return role

Diff for: internals/parser.rst

+22-22
Original file line numberDiff line numberDiff line change
@@ -518,17 +518,17 @@ Pegen
518518
=====
519519

520520
Pegen is the parser generator used in CPython to produce the final PEG parser used by the interpreter. It is the
521-
program that can be used to read the python grammar located in :file:`Grammar/Python.gram` and produce the final C
521+
program that can be used to read the python grammar located in :cpy-file:`Grammar/python.gram` and produce the final C
522522
parser. It contains the following pieces:
523523

524524
* A parser generator that can read a grammar file and produce a PEG parser written in Python or C that can parse
525-
said grammar. The generator is located at :file:`Tools/peg_generator/pegen`.
525+
said grammar. The generator is located at :cpy-file:`Tools/peg_generator/pegen`.
526526
* A PEG meta-grammar that automatically generates a Python parser that is used for the parser generator itself
527527
(this means that there are no manually-written parsers). The meta-grammar is
528-
located at :file:`Tools/peg_generator/pegen/metagrammar.gram`.
528+
located at :cpy-file:`Tools/peg_generator/pegen/metagrammar.gram`.
529529
* A generated parser (using the parser generator) that can directly produce C and Python AST objects.
530530

531-
The source code for Pegen lives at :file:`Tools/peg_generator/pegen` but normally all typical commands to interact
531+
The source code for Pegen lives at :cpy-file:`Tools/peg_generator/pegen` but normally all typical commands to interact
532532
with the parser generator are executed from the main makefile.
533533

534534
How to regenerate the parser
@@ -539,18 +539,18 @@ parser (the one used by the interpreter) just execute: ::
539539

540540
make regen-pegen
541541

542-
using the :file:`Makefile` in the main directory. If you are on Windows you can
542+
using the :cpy-file:`!Makefile` in the main directory. If you are on Windows you can
543543
use the Visual Studio project files to regenerate the parser or to execute: ::
544544

545545
./PCbuild/build.bat --regen
546546

547-
The generated parser file is located at :file:`Parser/parser.c`.
547+
The generated parser file is located at :cpy-file:`Parser/parser.c`.
548548

549549
How to regenerate the meta-parser
550550
---------------------------------
551551

552552
The meta-grammar (the grammar that describes the grammar for the grammar files
553-
themselves) is located at :file:`Tools/peg_generator/pegen/metagrammar.gram`.
553+
themselves) is located at :cpy-file:`Tools/peg_generator/pegen/metagrammar.gram`.
554554
Although it is very unlikely that you will ever need to modify it, if you make any modifications
555555
to this file (in order to implement new Pegen features) you will need to regenerate
556556
the meta-parser (the parser that parses the grammar files). To do so just execute: ::
@@ -570,7 +570,7 @@ Pegen has some special grammatical elements and rules:
570570

571571
* Strings with single quotes (') (e.g. ``'class'``) denote KEYWORDS.
572572
* Strings with double quotes (") (e.g. ``"match"``) denote SOFT KEYWORDS.
573-
* Upper case names (e.g. ``NAME``) denote tokens in the :file:`Grammar/Tokens` file.
573+
* Upper case names (e.g. ``NAME``) denote tokens in the :cpy-file:`Grammar/Tokens` file.
574574
* Rule names starting with ``invalid_`` are used for specialized syntax errors.
575575

576576
- These rules are NOT used in the first pass of the parser.
@@ -592,7 +592,7 @@ to handle things like indentation boundaries, some special keywords like ``ASYNC
592592
interactive mode and much more. Some of these reasons are also there for historical purposes, and some
593593
others are useful even today.
594594

595-
The list of tokens (all uppercase names in the grammar) that you can use can be found in the :file:`Grammar/Tokens`
595+
The list of tokens (all uppercase names in the grammar) that you can use can be found in the :cpy-file:`Grammar/Tokens`
596596
file. If you change this file to add new tokens, make sure to regenerate the files by executing: ::
597597

598598
make regen-token
@@ -601,7 +601,7 @@ If you are on Windows you can use the Visual Studio project files to regenerate
601601

602602
./PCbuild/build.bat --regen
603603

604-
How tokens are generated and the rules governing this is completely up to the tokenizer (:file:`Parser/tokenizer.c`)
604+
How tokens are generated and the rules governing this is completely up to the tokenizer (:cpy-file:`Parser/tokenizer.c`)
605605
and the parser just receives tokens from it.
606606

607607
Memoization
@@ -627,7 +627,7 @@ To know if a new rule needs memoization or not, benchmarking is required
627627
(comparing execution times and memory usage of some considerably big files with
628628
and without memoization). There is a very simple instrumentation API available
629629
in the generated C parse code that allows to measure how much each rule uses
630-
memoization (check the :file:`Parser/pegen.c` file for more information) but it
630+
memoization (check the :cpy-file:`Parser/pegen.c` file for more information) but it
631631
needs to be manually activated.
632632

633633
Automatic variables
@@ -777,7 +777,7 @@ two phases:
777777
(see the :ref:`how PEG parsers work section <how-peg-parsers-work>` for more information).
778778

779779
You can find a collection of macros to raise specialized syntax errors in the
780-
:file:`Parser/pegen.h` header file. These macros allow also to report ranges for
780+
:cpy-file:`Parser/pegen.h` header file. These macros allow also to report ranges for
781781
the custom errors that will be highlighted in the tracebacks that will be
782782
displayed when the error is reported.
783783

@@ -803,13 +803,13 @@ Generating AST objects
803803
----------------------
804804

805805
The output of the C parser used by CPython that is generated by the
806-
:file:`Grammar/Python.gram` grammar file is a Python AST object (using C
806+
:cpy-file:`Grammar/python.gram` grammar file is a Python AST object (using C
807807
structures). This means that the actions in the grammar file generate AST objects
808808
when they succeed. Constructing these objects can be quite cumbersome (see
809809
the :ref:`AST compiler section <compiler-ast-trees>` for more information
810810
on how these objects are constructed and how they are used by the compiler) so
811811
special helper functions are used. These functions are declared in the
812-
:file:`Parser/pegen.h` header file and defined in the :file:`Parser/action_helpers.c`
812+
:cpy-file:`Parser/pegen.h` header file and defined in the :cpy-file:`Parser/action_helpers.c`
813813
file. These functions allow you to join AST sequences, get specific elements
814814
from them or to do extra processing on the generated tree.
815815

@@ -823,8 +823,8 @@ from them or to do extra processing on the generated tree.
823823

824824
As a general rule, if an action spawns multiple lines or requires something more
825825
complicated than a single expression of C code, is normally better to create a
826-
custom helper in :file:`Parser/action_helpers.c` and expose it in the
827-
:file:`Parser/pegen.h` header file so it can be used from the grammar.
826+
custom helper in :cpy-file:`Parser/action_helpers.c` and expose it in the
827+
:cpy-file:`Parser/pegen.h` header file so it can be used from the grammar.
828828

829829
If the parsing succeeds, the parser **must** return a **valid** AST object.
830830

@@ -833,14 +833,14 @@ Testing
833833

834834
There are three files that contain tests for the grammar and the parser:
835835

836-
* ``Lib/test/test_grammar.py``.
837-
* ``Lib/test/test_syntax.py``.
838-
* ``Lib/test/test_exceptions.py``.
836+
* :cpy-file:`Lib/test/test_grammar.py`
837+
* :cpy-file:`Lib/test/test_syntax.py`
838+
* :cpy-file:`Lib/test/test_exceptions.py`
839839

840840
Check the contents of these files to know which is the best place to place new tests depending
841841
on the nature of the new feature you are adding.
842842

843-
Tests for the parser generator itself can be found in the :file:`Lib/test/test_peg_generator` directory.
843+
Tests for the parser generator itself can be found in the :cpy-file:`Lib/test/test_peg_generator` directory.
844844

845845

846846
Debugging generated parsers
@@ -854,7 +854,7 @@ new rules to the grammar you cannot correctly compile and execute Python anymore
854854
to debug when something goes wrong, especially when making experiments.
855855

856856
For this reason it is a good idea to experiment first by generating a Python parser. To do this, you can go to the
857-
:file:`Tools/peg_generator/` directory on the CPython repository and manually call the parser generator by executing:
857+
:cpy-file:`Tools/peg_generator/` directory on the CPython repository and manually call the parser generator by executing:
858858

859859
.. code-block:: shell
860860
@@ -874,7 +874,7 @@ Verbose mode
874874
------------
875875

876876
When Python is compiled in debug mode (by adding ``--with-pydebug`` when running the configure step in Linux or by
877-
adding ``-d`` when calling the :file:`PCbuild/build.bat` script in Windows), it is possible to activate a **very** verbose
877+
adding ``-d`` when calling the :cpy-file:`PCbuild/build.bat` script in Windows), it is possible to activate a **very** verbose
878878
mode in the generated parser. This is very useful to debug the generated parser and to understand how it works, but it
879879
can be a bit hard to understand at first.
880880

0 commit comments

Comments
 (0)