diff --git a/CHANGES b/CHANGES
index abb74f38..eca5e61b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,10 +7,92 @@ RELEASE PLANNING NOTES:
In the pyparsing release 3.3.0, use of many of the pre-PEP8 methods (such as
`ParserElement.parseString`) will start to raise `DeprecationWarnings`. I plan to
completely drop the pre-PEP8 methods in pyparsing 4.0, though we won't see that release
-until some time in 2025. So there is plenty of time to convert existing parsers to
+until some time in 2026. So there is plenty of time to convert existing parsers to
the new function names before the old functions are completely removed. (Big help from
Devin J. Pohly in structuring the code to enable this peaceful transition.)
+===========================================================================================
+ The version 3.3.0 release will begin emitting `DeprecationWarnings` for pyparsing methods
+ that have been renamed to PEP8-compliant names (introduced in pyparsing 3.0.0, in August,
+ 2021, with legacy names retained as aliases). In preparation, I have added in pyparsing
+ 3.2.2 a utility for finding and replacing the legacy method names with the new names.
+ This utility is located at `pyparsing/tools/cvt_pep8_names.py`. This script will scan all
+ Python files specified on the command line, and if the `-u` option is selected, will
+ replace all occurrences of the old method names with the new PEP8-compliant names,
+ updating the files in place.
+
+ Here is an example that converts all the files in the pyparsing `/examples` directory:
+
+ python -m pyparsing.tools.cvt_pyparsing_pep8_names -u examples/*.py
+
+ The new names are compatible with pyparsing versions 3.0.0 and later.
+===========================================================================================
+
+
+Required Python versions by pyparsing version
+---------------------------------------------
+
++--------------------------------------------------+-------------------+
+| pyparsing version | Required Python |
++==================================================+===================+
+| 3.2.0 - 3.2.2 | 3.9 or later |
+| 3.0.8 - 3.1.4 | 3.6.8 or later |
+| 3.0.0 - 3.0.7 (these versions are discouraged) | 3.6 or later |
+| 2.4.7 | 2.7 or later |
+| 1.5.7 | 2.6 - 2.7 |
++--------------------------------------------------+-------------------+
+
+
+Version 3.2.2 - March, 2025
+---------------------------
+- Released `cvt_pyparsing_pep8_names.py` conversion utility to upgrade pyparsing-based
+ programs and libraries that use legacy camelCase names to use the new PEP8-compliant
+ snake_case method names. The converter can also be imported into other scripts as
+
+ from pyparsing.tools.cvt_pyparsing_pep8_names import pep8_converter
+
+- Fixed bug in `nested_expr` where nested contents were stripped of whitespace when
+ the default whitespace characters were cleared (raised in this StackOverflow
+ question https://stackoverflow.com/questions/79327649 by Ben Alan). Also addressed
+ bug in resolving PEP8 compliant argument name and legacy argument name.
+
+- Fixed bug in `rest_of_line` and the underlying `Regex` class, in which matching a
+ pattern that could match an empty string (such as `".*"` or `"[A-Z]*"` would not raise
+ a `ParseException` at or beyond the end of the input string. This could cause an
+ infinite parsing loop when parsing `rest_of_line` at the end of the input string.
+ Reported by user Kylotan, thanks! (Issue #593)
+
+- Enhancements and extra input validation for `pyparsing.util.make_compressed_re` - see
+ usage in `examples/complex_chemical_formulas.py` and result in the generated railroad
+ diagram `examples/complex_chemical_formulas_diagram.html`. Properly escapes characters
+ like "." and "*" that have special meaning in regular expressions.
+
+- Fixed bug in `one_of()` to properly escape characters that are regular expression markers
+ (such as '*', '+', '?', etc.) before building the internal regex.
+
+- Better exception message for `MatchFirst` and `Or` expressions, showing all alternatives
+ rather than just the first one. Fixes Issue #592, reported by Focke, thanks!
+
+- Added return type annotation of "-> None" for all `__init__()` methods, to satisfy
+ `mypy --strict` type checking. PR submitted by FeRD, thank you!
+
+- Added optional argument `show_hidden` to `create_diagram` to show
+ elements that are used internally by pyparsing, but are not part of the actual
+ parser grammar. For instance, the `Tag` class can insert values into the parsed
+ results but it does not actually parse any input, so by default it is not included
+ in a railroad diagram. By calling `create_diagram` with `show_hidden` = `True`,
+ these internal elements will be included. (You can see this in the tag_metadata.py
+ script in the examples directory.)
+
+- Fixed bug in `number_words.py` example. Also added `ebnf_number_words.py` to demonstrate
+ using the `ebnf.py` EBNF parser generator to build a similar parser directly from
+ EBNF.
+
+- Fixed syntax warning raised in `bigquery_view_parser.py`, invalid escape sequence "\s".
+ Reported by sameer-google, nice catch! (Issue #598)
+
+- Added support for Python 3.14.
+
Version 3.2.1 - December, 2024
------------------------------
@@ -31,7 +113,7 @@ Version 3.2.1 - December, 2024
- Added generated diagrams for many of the examples.
-- Replaced old examples/0README.html file with examples/README.md file.
+- Replaced old `examples/0README.html` file with `examples/README.md` file.
Version 3.2.0 - October, 2024
diff --git a/README.rst b/README.rst
index 24d603c7..cfb9889f 100644
--- a/README.rst
+++ b/README.rst
@@ -26,7 +26,7 @@ Here is a program to parse ``"Hello, World!"`` (or any greeting of the form
from pyparsing import Word, alphas
greet = Word(alphas) + "," + Word(alphas) + "!"
hello = "Hello, World!"
- print(hello, "->", greet.parseString(hello))
+ print(hello, "->", greet.parse_string(hello))
The program outputs the following::
@@ -36,7 +36,7 @@ The Python representation of the grammar is quite readable, owing to the
self-explanatory class names, and the use of '+', '|' and '^' operator
definitions.
-The parsed results returned from ``parseString()`` is a collection of type
+The parsed results returned from ``parse_string()`` is a collection of type
``ParseResults``, which can be accessed as a
nested list, a dictionary, or an object with named attributes.
diff --git a/docs/HowToUsePyparsing.rst b/docs/HowToUsePyparsing.rst
index f23047f0..03d4d925 100644
--- a/docs/HowToUsePyparsing.rst
+++ b/docs/HowToUsePyparsing.rst
@@ -998,7 +998,7 @@ Exception classes and Troubleshooting
expr = pp.Word(pp.alphanums).set_name("word").set_debug()
print(ppt.with_line_numbers(data))
- expr[...].parseString(data)
+ expr[...].parse_string(data)
prints::
@@ -1155,7 +1155,7 @@ Helper methods
expr = infix_notation(int_expr,
[
- (one_of("+ -"), 2, opAssoc.LEFT),
+ (one_of("+ -"), 2, OpAssoc.LEFT),
],
lpar="<",
rpar=">"
@@ -1170,7 +1170,7 @@ Helper methods
expr = infix_notation(int_expr,
[
- (one_of("+ -"), 2, opAssoc.LEFT),
+ (one_of("+ -"), 2, OpAssoc.LEFT),
],
lpar=Literal("<"),
rpar=Literal(">")
@@ -1489,6 +1489,8 @@ This will result in the railroad diagram being written to ``street_address_diagr
- ``show_groups`` - bool flag whether groups should be highlighted with an unlabeled surrounding box
+- ``show_hidden`` - bool flag whether internal pyparsing elements that are normally omitted in diagrams should be shown (default=False)
+
- ``embed`` - bool flag whether generated HTML should omit
, , and tags to embed
the resulting HTML in an enclosing HTML source (such as PyScript HTML)
diff --git a/docs/whats_new_in_3_2.rst b/docs/whats_new_in_3_2.rst
index daf85ad4..c210d800 100644
--- a/docs/whats_new_in_3_2.rst
+++ b/docs/whats_new_in_3_2.rst
@@ -117,7 +117,7 @@ New / Enhanced Examples
Robert Nystrom's "Crafting Interpreters" (http://craftinginterpreters.com/).
- Added ``complex_chemical_formulas.py`` example, to add parsing capability for
- formulas such as "3(C₆H₅OH)₂".
+ formulas such as "Ba(BrO₃)₂·H₂O".
- Updated ``tag_emitter.py`` to use new ``Tag`` class, introduced in pyparsing
3.1.3.
diff --git a/examples/README.md b/examples/README.md
index 73f3fd0c..efb50325 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -3,6 +3,16 @@
This directory contains a number of examples of parsers created using pyparsing. They fall into a few general
categories (several examples include supporting railroad diagrams):
+
+* [Pyparsing tutorial and language feature demonstrations](#pyparsing-tutorial-and-language-feature-demonstrations)
+* [Language parsers](#language-parsers)
+* [Domain Specific Language parsers](#domain-specific-language-parsers)
+* [Search and query language parsers](#search-and-query-language-parsers)
+* [Data format parsers](#data-format-parsers)
+* [Logical and arithmetic infix notation parsers and examples](#logical-and-arithmetic-infix-notation-parsers-and-examples)
+* [Helpful utilities](#helpful-utilities)
+
+
## Pyparsing tutorial and language feature demonstrations
* Hello World!
* [greeting.py](./greeting.py)
@@ -18,7 +28,7 @@ categories (several examples include supporting railroad diagrams):
* Unicode text handling
* [tag_metadata.py](./tag_metadata.py) [(diagram)](./tag_metadata_diagram.html)
* chemical formulas
- * [chemical_formula.py](./chemical_formula.py)
+ * [chemical_formulas.py](./chemical_formulas.py)
* [complex_chemical_formulas.py](./complex_chemical_formulas.py)
* API checker
* [apicheck.py](./apicheck.py) [(diagram)](./apicheck_diagram.html)
@@ -59,12 +69,15 @@ categories (several examples include supporting railroad diagrams):
* rosetta code
* [rosettacode.py](./rosettacode.py) [(diagram)](./rosettacode_diagram.html)
## Domain Specific Language parsers
- * adventureEngine
+ * adventureEngine - interactive fiction parser and game runner
* [adventureEngine.py](./adventureEngine.py) [(diagram)](./adventure_game_parser_diagram.html)
- * pgn
+ * pgn - Chess notation parser
* [pgn.py](./pgn.py)
- * TAP
+ * TAP - Test results parser
* [TAP.py](./TAP.py) [(diagram)](./TAP_diagram.html)
+ * EBNF - Extended Backus-Naur Format parser (and compiler to a running pyparsing parser)
+ * [ebnf.py](./ebnf.py) [(diagram)](./ebnf_diagram.html)
+ * [ebnf_number_words.py](./ebnf_number_words.py) [(diagram)](./ebnf_number_parser_diagram.html)
## Search and query language parsers
* basic search
* [searchparser.py](./searchparser.py) [demo](./searchParserAppDemo.py)
diff --git a/examples/adventureEngine.py b/examples/adventureEngine.py
index c4d155b6..b258b7c7 100644
--- a/examples/adventureEngine.py
+++ b/examples/adventureEngine.py
@@ -454,7 +454,7 @@ def make_bnf(self):
quitVerb = pp.one_of("QUIT Q", caseless=True)
lookVerb = pp.one_of("LOOK L", caseless=True)
doorsVerb = pp.CaselessLiteral("DOORS")
- helpVerb = pp.one_of("H HELP ?", caseless=True)
+ helpVerb = pp.one_of("H HELP ?", caseless=True).set_name("HELP | H | ?")
itemRef = pp.OneOrMore(pp.Word(pp.alphas)).set_parse_action(self.validate_item_name).setName("item_ref")
nDir = pp.one_of("N NORTH", caseless=True).set_parse_action(pp.replace_with("N"))
@@ -512,7 +512,12 @@ def make_bnf(self):
)("command").set_name("command")
with contextlib.suppress(Exception):
- parser.create_diagram("adventure_game_parser_diagram.html", vertical=2, show_groups=True)
+ parser.create_diagram(
+ "adventure_game_parser_diagram.html",
+ vertical=3,
+ show_groups=True,
+ show_results_names=True
+ )
return parser
diff --git a/examples/adventure_game_parser_diagram.html b/examples/adventure_game_parser_diagram.html
index e5ff5ca0..2a556301 100644
--- a/examples/adventure_game_parser_diagram.html
+++ b/examples/adventure_game_parser_diagram.html
@@ -21,55 +21,71 @@