diff options
author | ptmcg <ptmcg@austin.rr.com> | 2023-05-04 03:11:59 -0500 |
---|---|---|
committer | ptmcg <ptmcg@austin.rr.com> | 2023-05-04 03:11:59 -0500 |
commit | fa12321610037188f9043323ad580b922726831d (patch) | |
tree | 036e8dc354c59269fc08583b3e30543999f6a35b | |
parent | 6f3d0af494c4d52e979414f8f0f3b4d068b44d8e (diff) | |
download | pyparsing-git-fa12321610037188f9043323ad580b922726831d.tar.gz |
Updated several examples to latest method names
-rw-r--r-- | examples/0README.html | 9 | ||||
-rw-r--r-- | examples/builtin_parse_action_demo.py | 10 | ||||
-rw-r--r-- | examples/chemicalFormulas.py | 121 | ||||
-rw-r--r-- | examples/chemical_formulas.py | 119 | ||||
-rw-r--r-- | examples/cpp_enum_parser.py | 24 | ||||
-rw-r--r-- | examples/datetime_parse_actions.py (renamed from examples/datetimeParseActions.py) | 168 | ||||
-rw-r--r-- | examples/excelExpr.py | 112 | ||||
-rw-r--r-- | examples/excel_expr.py | 93 | ||||
-rw-r--r-- | examples/greetingInKorean.py | 6 | ||||
-rw-r--r-- | examples/hola_mundo.py (renamed from examples/holaMundo.py) | 133 | ||||
-rw-r--r-- | examples/parsePythonValue.py | 69 | ||||
-rw-r--r-- | examples/parse_python_value.py | 80 | ||||
-rw-r--r-- | examples/parse_results_sum_example.py (renamed from examples/parseResultsSumExample.py) | 58 | ||||
-rw-r--r-- | examples/range_check.py (renamed from examples/rangeCheck.py) | 128 | ||||
-rw-r--r-- | tests/test_examples.py | 2 |
15 files changed, 557 insertions, 575 deletions
diff --git a/examples/0README.html b/examples/0README.html index aec7b8c..ba5bab0 100644 --- a/examples/0README.html +++ b/examples/0README.html @@ -21,12 +21,12 @@ Unicode example to parse "Hello, World!" in Greek. </li> <p> -<li><a href="holaMundo.py">holaMundo.py</a> <i>~ submission by Marco Alfonso</i><br> +<li><a href="hola_mundo.py">hola_mundo.py</a> <i>~ submission by Marco Alfonso</i><br> "Hello, World!" example translated to Spanish, from Marco Alfonso's blog. </li> <p> -<li><a href="chemicalFormulas.py">chemicalFormulas.py</a><br> +<li><a href="chemical_formulas.py">chemical_formulas.py</a><br> Simple example to demonstrate the use of ParseResults returned from parseString(). Parses a chemical formula (such as "H2O" or "C6H5OH"), and walks the returned list of tokens to calculate the molecular weight. </li> @@ -245,26 +245,22 @@ A parser for the data representation format, Stackish. <p> <li><a href="builtin_parse_action_demo.py">builtin_parse_action_demo.py</a><br> -<b>New in version 1.5.7</b><br> Demonstration of using builtins (min, max, sum, len, etc.) as parse actions. </li> <p> <li><a href="antlr_grammar.py">antlr_grammar.py</a><i>~ submission by Luca DellOlio</i><br> -<b>New in version 1.5.7</b><br> Pyparsing example parsing ANTLR .a files and generating a working pyparsing parser. </li> <p> <li><a href="shapes.py">shapes.py</a><br> -<b>New in version 1.5.7</b><br> Parse actions example simple shape definition syntax, and returning the matched tokens as domain objects instead of just strings. </li> <p> <li><a href="datetimeParseActions.py">datetimeParseActions.py</a><br> -<b>New in version 1.5.7</b><br> Parse actions example showing a parse action returning a datetime object instead of string tokens, and doing validation of the tokens, raising a ParseException if the given YYYY/MM/DD string does not represent a valid date. @@ -272,7 +268,6 @@ given YYYY/MM/DD string does not represent a valid date. <p> <li><a href="position.py">position.py</a><br> -<b>New in version 1.5.7</b><br> Demonstration of a couple of different ways to capture the location a particular expression was found within the overall input string. </li> diff --git a/examples/builtin_parse_action_demo.py b/examples/builtin_parse_action_demo.py index 36b3a98..fed6e2a 100644 --- a/examples/builtin_parse_action_demo.py +++ b/examples/builtin_parse_action_demo.py @@ -5,14 +5,13 @@ # Simple example of using builtin functions as parse actions.
#
-from pyparsing import *
-
-integer = Word(nums).setParseAction(lambda t: int(t[0]))
+import pyparsing as pp
+ppc = pp.common
# make an expression that will match a list of ints (which
# will be converted to actual ints by the parse action attached
# to integer)
-nums = OneOrMore(integer)
+nums = ppc.integer[...]
test = "2 54 34 2 211 66 43 2 0"
@@ -20,10 +19,9 @@ print(test) # try each of these builtins as parse actions
for fn in (sum, max, min, len, sorted, reversed, list, tuple, set, any, all):
- fn_name = fn.__name__
if fn is reversed:
# reversed returns an iterator, we really want to show the list of items
fn = lambda x: list(reversed(x))
# show how each builtin works as a free-standing parse action
- print(fn_name, nums.setParseAction(fn).parseString(test))
+ print(fn.__name__, nums.set_parse_action(fn).parse_string(test))
diff --git a/examples/chemicalFormulas.py b/examples/chemicalFormulas.py deleted file mode 100644 index 87a5b6a..0000000 --- a/examples/chemicalFormulas.py +++ /dev/null @@ -1,121 +0,0 @@ -#
-# chemicalFormulas.py
-#
-# Copyright (c) 2003,2019 Paul McGuire
-#
-
-import pyparsing as pp
-
-atomicWeight = {
- "O": 15.9994,
- "H": 1.00794,
- "Na": 22.9897,
- "Cl": 35.4527,
- "C": 12.0107,
-}
-
-digits = "0123456789"
-
-# Version 1
-element = pp.Word(pp.alphas.upper(), pp.alphas.lower(), max=2).set_name("element")
-# for stricter matching, use this Regex instead
-# element = Regex("A[cglmrstu]|B[aehikr]?|C[adeflmorsu]?|D[bsy]|"
-# "E[rsu]|F[emr]?|G[ade]|H[efgos]?|I[nr]?|Kr?|L[airu]|"
-# "M[dgnot]|N[abdeiop]?|Os?|P[abdmortu]?|R[abefghnu]|"
-# "S[bcegimnr]?|T[abcehilm]|U(u[bhopqst])?|V|W|Xe|Yb?|Z[nr]")
-elementRef = pp.Group(element + pp.Opt(pp.Word(digits), default="1"))
-formula = elementRef[...]
-
-
-def sum_atomic_weights(element_list):
- return sum(atomicWeight[elem] * int(qty) for elem, qty in element_list)
-
-
-formula.runTests(
- """\
- H2O
- C6H5OH
- NaCl
- """,
- fullDump=False,
- postParse=lambda _, tokens: "Molecular weight: {}".format(
- sum_atomic_weights(tokens)
- ),
-)
-print()
-
-# Version 2 - access parsed items by results name
-elementRef = pp.Group(
- element("symbol") + pp.Opt(pp.Word(digits), default="1")("qty")
-)
-formula = elementRef[...]
-
-
-def sum_atomic_weights_by_results_name(element_list):
- return sum(atomicWeight[elem.symbol] * int(elem.qty) for elem in element_list)
-
-
-formula.runTests(
- """\
- H2O
- C6H5OH
- NaCl
- """,
- fullDump=False,
- postParse=lambda _, tokens: "Molecular weight: {}".format(
- sum_atomic_weights_by_results_name(tokens)
- ),
-)
-print()
-
-# Version 3 - convert integers during parsing process
-integer = pp.Word(digits).add_parse_action(lambda t: int(t[0])).set_name("integer")
-elementRef = pp.Group(element("symbol") + pp.Opt(integer, default=1)("qty"))
-formula = elementRef[...].set_name("chemical_formula")
-
-
-def sum_atomic_weights_by_results_name_with_converted_ints(element_list):
- return sum(atomicWeight[elem.symbol] * int(elem.qty) for elem in element_list)
-
-
-formula.runTests(
- """\
- H2O
- C6H5OH
- NaCl
- """,
- fullDump=False,
- postParse=lambda _, tokens: "Molecular weight: {}".format(
- sum_atomic_weights_by_results_name_with_converted_ints(tokens)
- ),
-)
-print()
-
-# Version 4 - parse and convert integers as subscript digits
-subscript_digits = "₀₁₂₃₄₅₆₇₈₉"
-subscript_int_map = {e[1]: e[0] for e in enumerate(subscript_digits)}
-
-
-def cvt_subscript_int(s):
- ret = 0
- for c in s[0]:
- ret = ret * 10 + subscript_int_map[c]
- return ret
-
-
-subscript_int = pp.Word(subscript_digits).add_parse_action(cvt_subscript_int).set_name("subscript")
-
-elementRef = pp.Group(element("symbol") + pp.Opt(subscript_int, default=1)("qty"))
-formula = elementRef[1, ...].set_name("chemical_formula")
-formula.runTests(
- """\
- H₂O
- C₆H₅OH
- NaCl
- """,
- fullDump=False,
- postParse=lambda _, tokens: "Molecular weight: {}".format(
- sum_atomic_weights_by_results_name_with_converted_ints(tokens)
- ),
-)
-print()
diff --git a/examples/chemical_formulas.py b/examples/chemical_formulas.py new file mode 100644 index 0000000..16d4bb4 --- /dev/null +++ b/examples/chemical_formulas.py @@ -0,0 +1,119 @@ +# +# chemicalFormulas.py +# +# Copyright (c) 2003,2019 Paul McGuire +# + +import pyparsing as pp + +atomic_weight = { + "O": 15.9994, + "H": 1.00794, + "Na": 22.9897, + "Cl": 35.4527, + "C": 12.0107, +} + +digits = "0123456789" + +# Version 1 +element = pp.Word(pp.alphas.upper(), pp.alphas.lower(), max=2).set_name("element") +# for stricter matching, use this Regex instead +# element = Regex("A[cglmrstu]|B[aehikr]?|C[adeflmorsu]?|D[bsy]|" +# "E[rsu]|F[emr]?|G[ade]|H[efgos]?|I[nr]?|Kr?|L[airu]|" +# "M[dgnot]|N[abdeiop]?|Os?|P[abdmortu]?|R[abefghnu]|" +# "S[bcegimnr]?|T[abcehilm]|U(u[bhopqst])?|V|W|Xe|Yb?|Z[nr]") +element_ref = pp.Group(element + pp.Opt(pp.Word(digits), default="1")) +formula = element_ref[...] + + +def sum_atomic_weights(element_list): + return sum(atomic_weight[elem] * int(qty) for elem, qty in element_list) + + +formula.run_tests( + """\ + H2O + C6H5OH + NaCl + """, + full_dump=False, + post_parse=lambda _, tokens: f"Molecular weight: {sum_atomic_weights(tokens)}", +) +print() + + +# Version 2 - access parsed items by results name +element_ref = pp.Group( + element("symbol") + pp.Opt(pp.Word(digits), default="1")("qty") +) +formula = element_ref[...] + + +def sum_atomic_weights_by_results_name(element_list): + return sum(atomic_weight[elem.symbol] * int(elem.qty) for elem in element_list) + + +formula.run_tests( + """\ + H2O + C6H5OH + NaCl + """, + full_dump=False, + post_parse=lambda _, tokens: + f"Molecular weight: {sum_atomic_weights_by_results_name(tokens)}", +) +print() + +# Version 3 - convert integers during parsing process +integer = pp.Word(digits).set_name("integer") +integer.add_parse_action(lambda t: int(t[0])) +element_ref = pp.Group(element("symbol") + pp.Opt(integer, default=1)("qty")) +formula = element_ref[...].set_name("chemical_formula") + + +def sum_atomic_weights_by_results_name_with_converted_ints(element_list): + return sum(atomic_weight[elem.symbol] * int(elem.qty) for elem in element_list) + + +formula.run_tests( + """\ + H2O + C6H5OH + NaCl + """, + full_dump=False, + post_parse=lambda _, tokens: + f"Molecular weight: {sum_atomic_weights_by_results_name_with_converted_ints(tokens)}", +) +print() + +# Version 4 - parse and convert integers as subscript digits +subscript_digits = "₀₁₂₃₄₅₆₇₈₉" +subscript_int_map = {e[1]: e[0] for e in enumerate(subscript_digits)} + + +def cvt_subscript_int(s): + ret = 0 + for c in s[0]: + ret = ret * 10 + subscript_int_map[c] + return ret + + +subscript_int = pp.Word(subscript_digits).set_name("subscript") +subscript_int.add_parse_action(cvt_subscript_int) + +element_ref = pp.Group(element("symbol") + pp.Opt(subscript_int, default=1)("qty")) +formula = element_ref[1, ...].set_name("chemical_formula") +formula.run_tests( + """\ + H₂O + C₆H₅OH + NaCl + """, + full_dump=False, + post_parse=lambda _, tokens: + f"Molecular weight: {sum_atomic_weights_by_results_name_with_converted_ints(tokens)}", +) +print() diff --git a/examples/cpp_enum_parser.py b/examples/cpp_enum_parser.py index 26dde7c..77eb3a7 100644 --- a/examples/cpp_enum_parser.py +++ b/examples/cpp_enum_parser.py @@ -9,7 +9,7 @@ #
#
-from pyparsing import *
+import pyparsing as pp
# sample string with enums and other stuff
sample = """
@@ -35,19 +35,19 @@ sample = """ """
# syntax we don't want to see in the final parse tree
-LBRACE, RBRACE, EQ, COMMA = map(Suppress, "{}=,")
-_enum = Suppress("enum")
-identifier = Word(alphas, alphanums + "_")
-integer = Word(nums)
-enumValue = Group(identifier("name") + Optional(EQ + integer("value")))
-enumList = Group(enumValue + ZeroOrMore(COMMA + enumValue))
+LBRACE, RBRACE, EQ, COMMA = pp.Suppress.using_each("{}=,")
+_enum = pp.Suppress("enum")
+identifier = pp.Word(pp.alphas + "_", pp.alphanums + "_")
+integer = pp.Word(pp.nums)
+enumValue = pp.Group(identifier("name") + pp.Optional(EQ + integer("value")))
+enumList = pp.Group(enumValue + (COMMA + enumValue)[...])
enum = _enum + identifier("enum") + LBRACE + enumList("names") + RBRACE
# find instances of enums ignoring other syntax
-for item, start, stop in enum.scanString(sample):
- id = 0
+for item, start, stop in enum.scan_string(sample):
+ idx = 0
for entry in item.names:
if entry.value != "":
- id = int(entry.value)
- print("%s_%s = %d" % (item.enum.upper(), entry.name.upper(), id))
- id += 1
+ idx = int(entry.value)
+ print("%s_%s = %d" % (item.enum.upper(), entry.name.upper(), idx))
+ idx += 1
diff --git a/examples/datetimeParseActions.py b/examples/datetime_parse_actions.py index f7c4fc9..ff38656 100644 --- a/examples/datetimeParseActions.py +++ b/examples/datetime_parse_actions.py @@ -1,84 +1,84 @@ -# parseActions.py
-#
-# A sample program a parser to match a date string of the form "YYYY/MM/DD",
-# and return it as a datetime, or raise an exception if not a valid date.
-#
-# Copyright 2012, Paul T. McGuire
-#
-from datetime import datetime
-import pyparsing as pp
-from pyparsing import pyparsing_common as ppc
-
-# define an integer string, and a parse action to convert it
-# to an integer at parse time
-integer = pp.Word(pp.nums).setName("integer")
-
-
-def convertToInt(tokens):
- # no need to test for validity - we can't get here
- # unless tokens[0] contains all numeric digits
- return int(tokens[0])
-
-
-integer.setParseAction(convertToInt)
-# or can be written as one line as
-# integer = Word(nums).setParseAction(lambda t: int(t[0]))
-
-# define a pattern for a year/month/day date
-date_expr = integer("year") + "/" + integer("month") + "/" + integer("day")
-date_expr.ignore(pp.pythonStyleComment)
-
-
-def convertToDatetime(s, loc, tokens):
- try:
- # note that the year, month, and day fields were already
- # converted to ints from strings by the parse action defined
- # on the integer expression above
- return datetime(tokens.year, tokens.month, tokens.day).date()
- except Exception as ve:
- errmsg = "'%s/%s/%s' is not a valid date, %s" % (
- tokens.year,
- tokens.month,
- tokens.day,
- ve,
- )
- raise pp.ParseException(s, loc, errmsg)
-
-
-date_expr.setParseAction(convertToDatetime)
-
-
-date_expr.runTests(
- """\
- 2000/1/1
-
- # invalid month
- 2000/13/1
-
- # 1900 was not a leap year
- 1900/2/29
-
- # but 2000 was
- 2000/2/29
- """
-)
-
-
-# if dates conform to ISO8601, use definitions in pyparsing_common
-date_expr = ppc.iso8601_date.setParseAction(ppc.convertToDate())
-date_expr.ignore(pp.pythonStyleComment)
-
-date_expr.runTests(
- """\
- 2000-01-01
-
- # invalid month
- 2000-13-01
-
- # 1900 was not a leap year
- 1900-02-29
-
- # but 2000 was
- 2000-02-29
- """
-)
+# parseActions.py +# +# A sample program a parser to match a date string of the form "YYYY/MM/DD", +# and return it as a datetime, or raise an exception if not a valid date. +# +# Copyright 2012, Paul T. McGuire +# +from datetime import datetime +import pyparsing as pp +from pyparsing import pyparsing_common as ppc + +# define an integer string, and a parse action to convert it +# to an integer at parse time +integer = pp.Word(pp.nums).set_name("integer") + + +def convert_to_int(tokens): + # no need to test for validity - we can't get here + # unless tokens[0] contains all numeric digits + return int(tokens[0]) + + +integer.set_parse_action(convert_to_int) +# or can be written as one line as +# integer = Word(nums).set_parse_action(lambda t: int(t[0])) + +# define a pattern for a year/month/day date +date_expr = integer("year") + "/" + integer("month") + "/" + integer("day") +date_expr.ignore(pp.python_style_comment) + + +def convert_to_datetime(s, loc, tokens): + try: + # note that the year, month, and day fields were already + # converted to ints from strings by the parse action defined + # on the integer expression above + return datetime(tokens.year, tokens.month, tokens.day).date() + except Exception as ve: + errmsg = "'%s/%s/%s' is not a valid date, %s" % ( + tokens.year, + tokens.month, + tokens.day, + ve, + ) + raise pp.ParseException(s, loc, errmsg) + + +date_expr.set_parse_action(convert_to_datetime) + + +date_expr.run_tests( + """\ + 2000/1/1 + + # invalid month + 2000/13/1 + + # 1900 was not a leap year + 1900/2/29 + + # but 2000 was + 2000/2/29 + """ +) + + +# if dates conform to ISO8601, use definitions in pyparsing_common +date_expr = ppc.iso8601_date.set_parse_action(ppc.convert_to_date()) +date_expr.ignore(pp.python_style_comment) + +date_expr.run_tests( + """\ + 2000-01-01 + + # invalid month + 2000-13-01 + + # 1900 was not a leap year + 1900-02-29 + + # but 2000 was + 2000-02-29 + """ +) diff --git a/examples/excelExpr.py b/examples/excelExpr.py deleted file mode 100644 index 87af4fb..0000000 --- a/examples/excelExpr.py +++ /dev/null @@ -1,112 +0,0 @@ -# excelExpr.py
-#
-# Copyright 2010, Paul McGuire
-#
-# A partial implementation of a parser of Excel formula expressions.
-#
-from pyparsing import (
- CaselessKeyword,
- Suppress,
- Word,
- alphas,
- alphanums,
- nums,
- Opt,
- Group,
- one_of,
- Forward,
- infix_notation,
- OpAssoc,
- dblQuotedString,
- DelimitedList,
- Combine,
- Literal,
- QuotedString,
- ParserElement,
- pyparsing_common as ppc,
-)
-
-ParserElement.enablePackrat()
-
-EQ, LPAR, RPAR, COLON, COMMA = Suppress.using_each("=():,")
-EXCL, DOLLAR = Literal.using_each("!$")
-sheetRef = Word(alphas, alphanums) | QuotedString("'", escQuote="''")
-colRef = Opt(DOLLAR) + Word(alphas, max=2)
-rowRef = Opt(DOLLAR) + Word(nums)
-cellRef = Combine(
- Group(Opt(sheetRef + EXCL)("sheet") + colRef("col") + rowRef("row"))
-)
-
-cellRange = (
- Group(cellRef("start") + COLON + cellRef("end"))("range")
- | cellRef
- | Word(alphas, alphanums)
-)
-
-expr = Forward()
-
-COMPARISON_OP = one_of("< = > >= <= != <>")
-condExpr = expr + COMPARISON_OP + expr
-
-ifFunc = (
- CaselessKeyword("if")
- - LPAR
- + Group(condExpr)("condition")
- + COMMA
- + Group(expr)("if_true")
- + COMMA
- + Group(expr)("if_false")
- + RPAR
-)
-
-
-def stat_function(name):
- return Group(CaselessKeyword(name) + Group(LPAR + DelimitedList(expr) + RPAR))
-
-
-sumFunc = stat_function("sum")
-minFunc = stat_function("min")
-maxFunc = stat_function("max")
-aveFunc = stat_function("ave")
-funcCall = ifFunc | sumFunc | minFunc | maxFunc | aveFunc
-
-multOp = one_of("* /")
-addOp = one_of("+ -")
-numericLiteral = ppc.number
-operand = numericLiteral | funcCall | cellRange | cellRef
-arithExpr = infix_notation(
- operand,
- [
- (multOp, 2, OpAssoc.LEFT),
- (addOp, 2, OpAssoc.LEFT),
- ],
-)
-
-textOperand = dblQuotedString | cellRef
-textExpr = infix_notation(
- textOperand,
- [
- ("&", 2, OpAssoc.LEFT),
- ],
-)
-
-expr <<= arithExpr | textExpr
-
-
-def main():
- success, report = (EQ + expr).run_tests(
- """\
- =3*A7+5
- =3*Sheet1!$A$7+5
- =3*'Sheet 1'!$A$7+5
- =3*'O''Reilly''s sheet'!$A$7+5
- =if(Sum(A1:A25)>42,Min(B1:B25),if(Sum(C1:C25)>3.14, (Min(C1:C25)+3)*18,Max(B1:B25)))
- =sum(a1:a25,10,min(b1,c2,d3))
- =if("T"&a2="TTime", "Ready", "Not ready")
- """
- )
- assert success
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file diff --git a/examples/excel_expr.py b/examples/excel_expr.py new file mode 100644 index 0000000..db19f3c --- /dev/null +++ b/examples/excel_expr.py @@ -0,0 +1,93 @@ +# excelExpr.py +# +# Copyright 2010, Paul McGuire +# +# A partial implementation of a parser of Excel formula expressions. +# +import pyparsing as pp +ppc = pp.common + +pp.ParserElement.enablePackrat() + +EQ, LPAR, RPAR, COLON, COMMA = pp.Suppress.using_each("=():,") +EXCL, DOLLAR = pp.Literal.using_each("!$") +sheetRef = pp.Word(pp.alphas, pp.alphanums) | pp.QuotedString("'", escQuote="''") +colRef = pp.Opt(DOLLAR) + pp.Word(pp.alphas, max=2) +rowRef = pp.Opt(DOLLAR) + pp.Word(pp.nums) +cellRef = pp.Combine( + pp.Group(pp.Opt(sheetRef + EXCL)("sheet") + colRef("col") + rowRef("row")) +) + +cellRange = ( + pp.Group(cellRef("start") + COLON + cellRef("end"))("range") + | cellRef + | pp.Word(pp.alphas, pp.alphanums) +) + +expr = pp.Forward() + +COMPARISON_OP = pp.one_of("< = > >= <= != <>") +condExpr = expr + COMPARISON_OP + expr + +ifFunc = ( + pp.CaselessKeyword("if") + - LPAR + + pp.Group(condExpr)("condition") + + COMMA + + pp.Group(expr)("if_true") + + COMMA + + pp.Group(expr)("if_false") + + RPAR +) + + +def stat_function(name): + return pp.Group(pp.CaselessKeyword(name) + pp.Group(LPAR + pp.DelimitedList(expr) + RPAR)) + + +sumFunc = stat_function("sum") +minFunc = stat_function("min") +maxFunc = stat_function("max") +aveFunc = stat_function("ave") +funcCall = ifFunc | sumFunc | minFunc | maxFunc | aveFunc + +multOp = pp.one_of("* /") +addOp = pp.one_of("+ -") +numericLiteral = ppc.number +operand = numericLiteral | funcCall | cellRange | cellRef +arithExpr = pp.infix_notation( + operand, + [ + (multOp, 2, pp.OpAssoc.LEFT), + (addOp, 2, pp.OpAssoc.LEFT), + ], +) + +textOperand = pp.dblQuotedString | cellRef +textExpr = pp.infix_notation( + textOperand, + [ + ("&", 2, pp.OpAssoc.LEFT), + ], +) + +expr <<= arithExpr | textExpr + + +def main(): + success, report = (EQ + expr).run_tests( + """\ + =3*A7+5 + =3*Sheet1!$A$7+5 + =3*'Sheet 1'!$A$7+5 + =3*'O''Reilly''s sheet'!$A$7+5 + =if(Sum(A1:A25)>42,Min(B1:B25),if(Sum(C1:C25)>3.14, (Min(C1:C25)+3)*18,Max(B1:B25))) + =sum(a1:a25,10,min(b1,c2,d3)) + =if("T"&a2="TTime", "Ready", "Not ready") + """ + ) + assert success + + +if __name__ == '__main__': + main()
\ No newline at end of file diff --git a/examples/greetingInKorean.py b/examples/greetingInKorean.py index 63afebd..d2c0b63 100644 --- a/examples/greetingInKorean.py +++ b/examples/greetingInKorean.py @@ -7,11 +7,11 @@ #
from pyparsing import Word, pyparsing_unicode as ppu
-koreanChars = ppu.Korean.alphas
-koreanWord = Word(koreanChars, min=2)
+korean_chars = ppu.한국어.alphas
+korean_word = Word(korean_chars, min=2)
# define grammar
-greet = koreanWord + "," + koreanWord + "!"
+greet = korean_word + "," + korean_word + "!"
# input string
hello = "안녕, 여러분!" # "Hello, World!" in Korean
diff --git a/examples/holaMundo.py b/examples/hola_mundo.py index bb66ca2..f6ba601 100644 --- a/examples/holaMundo.py +++ b/examples/hola_mundo.py @@ -1,67 +1,66 @@ -# escrito por Marco Alfonso, 2004 Noviembre
-
-# importamos los símbolos requeridos desde el módulo
-from pyparsing import (
- Word,
- alphas,
- oneOf,
- nums,
- Group,
- OneOrMore,
- pyparsing_unicode as ppu,
-)
-
-# usamos las letras en latin1, que incluye las como 'ñ', 'á', 'é', etc.
-alphas = ppu.Latin1.alphas
-
-# Aqui decimos que la gramatica "saludo" DEBE contener
-# una palabra compuesta de caracteres alfanumericos
-# (Word(alphas)) mas una ',' mas otra palabra alfanumerica,
-# mas '!' y esos seian nuestros tokens
-saludo = Word(alphas) + "," + Word(alphas) + oneOf("! . ?")
-tokens = saludo.parseString("Hola, Mundo !")
-
-# Ahora parseamos una cadena, "Hola, Mundo!",
-# el metodo parseString, nos devuelve una lista con los tokens
-# encontrados, en caso de no haber errores...
-for i, token in enumerate(tokens):
- print("Token %d -> %s" % (i, token))
-
-# imprimimos cada uno de los tokens Y listooo!!, he aquí a salida
-# Token 0 -> Hola
-# Token 1 -> ,
-# Token 2-> Mundo
-# Token 3 -> !
-
-# ahora cambia el parseador, aceptando saludos con mas que una sola palabra antes que ','
-saludo = Group(OneOrMore(Word(alphas))) + "," + Word(alphas) + oneOf("! . ?")
-tokens = saludo.parseString("Hasta mañana, Mundo !")
-
-for i, token in enumerate(tokens):
- print("Token %d -> %s" % (i, token))
-
-# Ahora parseamos algunas cadenas, usando el metodo runTests
-saludo.runTests(
- """\
- Hola, Mundo!
- Hasta mañana, Mundo !
-""",
- fullDump=False,
-)
-
-# Por supuesto, se pueden "reutilizar" gramáticas, por ejemplo:
-numimag = Word(nums) + "i"
-numreal = Word(nums)
-numcomplex = numreal + "+" + numimag
-print(numcomplex.parseString("3+5i"))
-
-# Funcion para cambiar a complejo numero durante parsear:
-def hace_python_complejo(t):
- valid_python = "".join(t).replace("i", "j")
- return complex(valid_python)
-
-
-numcomplex.setParseAction(hace_python_complejo)
-print(numcomplex.parseString("3+5i"))
-
-# Excelente!!, bueno, los dejo, me voy a seguir tirando código...
+# escrito por Marco Alfonso, 2004 Noviembre + +# importamos los símbolos requeridos desde el módulo +from pyparsing import ( + Word, + one_of, + nums, + Group, + OneOrMore, + pyparsing_unicode as ppu, +) + +# usamos las letras en latin1, que incluye las como 'ñ', 'á', 'é', etc. +alphas = ppu.Latin1.alphas + +# Aqui decimos que la gramatica "saludo" DEBE contener +# una palabra compuesta de caracteres alfanumericos +# (Word(alphas)) mas una ',' mas otra palabra alfanumerica, +# mas '!' y esos seian nuestros tokens +saludo = Word(alphas) + "," + Word(alphas) + one_of("! . ?") +tokens = saludo.parse_string("Hola, Mundo !") + +# Ahora parseamos una cadena, "Hola, Mundo!", +# el metodo parseString, nos devuelve una lista con los tokens +# encontrados, en caso de no haber errores... +for i, token in enumerate(tokens): + print("Token %d -> %s" % (i, token)) + +# imprimimos cada uno de los tokens Y listooo!!, he aquí a salida +# Token 0 -> Hola +# Token 1 -> , +# Token 2-> Mundo +# Token 3 -> ! + +# ahora cambia el parseador, aceptando saludos con mas que una sola palabra antes que ',' +saludo = Group(OneOrMore(Word(alphas))) + "," + Word(alphas) + one_of("! . ?") +tokens = saludo.parse_string("Hasta mañana, Mundo !") + +for i, token in enumerate(tokens): + print("Token %d -> %s" % (i, token)) + +# Ahora parseamos algunas cadenas, usando el metodo runTests +saludo.run_tests( + """\ + Hola, Mundo! + Hasta mañana, Mundo ! +""", + fullDump=False, +) + +# Por supuesto, se pueden "reutilizar" gramáticas, por ejemplo: +numimag = Word(nums) + "i" +numreal = Word(nums) +numcomplex = numreal + "+" + numimag +print(numcomplex.parse_string("3+5i")) + +# Funcion para cambiar a complejo numero durante parsear: +def hace_python_complejo(t): + valid_python = "".join(t).replace("i", "j") + return complex(valid_python) + + +numcomplex.set_parse_action(hace_python_complejo) +print(numcomplex.parse_string("3+5i")) + +# Excelente!!, bueno, los dejo, me voy a seguir tirando código... diff --git a/examples/parsePythonValue.py b/examples/parsePythonValue.py deleted file mode 100644 index fd039ef..0000000 --- a/examples/parsePythonValue.py +++ /dev/null @@ -1,69 +0,0 @@ -# parsePythonValue.py -# -# Copyright, 2006, by Paul McGuire -# -import pyparsing as pp - - -cvtBool = lambda t: t[0] == "True" -cvtInt = lambda toks: int(toks[0]) -cvtReal = lambda toks: float(toks[0]) -cvtTuple = lambda toks: tuple(toks.as_list()) -cvtDict = lambda toks: dict(toks.as_list()) -cvtList = lambda toks: [toks.as_list()] - -# define punctuation as suppressed literals -lparen, rparen, lbrack, rbrack, lbrace, rbrace, colon, comma = pp.Suppress.using_each("()[]{}:,") - -integer = pp.Regex(r"[+-]?\d+").set_name("integer").add_parse_action(cvtInt) -real = pp.Regex(r"[+-]?\d+\.\d*([Ee][+-]?\d+)?").set_name("real").add_parse_action(cvtReal) -tupleStr = pp.Forward().set_name("tuple_expr") -listStr = pp.Forward().set_name("list_expr") -dictStr = pp.Forward().set_name("dict_expr") - -unistr = pp.unicodeString().add_parse_action(lambda t: t[0][2:-1]) -quoted_str = pp.quotedString().add_parse_action(lambda t: t[0][1:-1]) -boolLiteral = pp.oneOf("True False", as_keyword=True).add_parse_action(cvtBool) -noneLiteral = pp.Keyword("None").add_parse_action(pp.replace_with(None)) - -listItem = ( - real - | integer - | quoted_str - | unistr - | boolLiteral - | noneLiteral - | pp.Group(listStr) - | tupleStr - | dictStr -).set_name("list_item") - -tupleStr <<= ( - lparen + pp.Opt(pp.DelimitedList(listItem, allow_trailing_delim=True)) + rparen -) -tupleStr.add_parse_action(cvtTuple) - -listStr <<= ( - lbrack + pp.Opt(pp.DelimitedList(listItem, allow_trailing_delim=True)) + rbrack -) -listStr.add_parse_action(cvtList, lambda t: t[0]) - -dictEntry = pp.Group(listItem + colon + listItem).set_name("dict_entry") -dictStr <<= ( - lbrace + pp.Opt(pp.DelimitedList(dictEntry, allow_trailing_delim=True)) + rbrace -) -dictStr.add_parse_action(cvtDict) - -if __name__ == "__main__": - - tests = """['a', 100, ('A', [101,102]), 3.14, [ +2.718, 'xyzzy', -1.414] ] - [{0: [2], 1: []}, {0: [], 1: [], 2: []}, {0: [1, 2]}] - { 'A':1, 'B':2, 'C': {'a': 1.2, 'b': 3.4} } - 3.14159 - 42 - 6.02E23 - 6.02e+023 - 1.0e-7 - 'a quoted string'""" - - listItem.runTests(tests) diff --git a/examples/parse_python_value.py b/examples/parse_python_value.py new file mode 100644 index 0000000..cb4288f --- /dev/null +++ b/examples/parse_python_value.py @@ -0,0 +1,80 @@ +# parsePythonValue.py +# +# Copyright, 2006, by Paul McGuire +# +import pyparsing as pp + + +cvtBool = lambda t: t[0] == "True" +cvtInt = lambda toks: int(toks[0]) +cvtReal = lambda toks: float(toks[0]) +cvtTuple = lambda toks: tuple(toks.as_list()) +cvtSet = lambda toks: set(toks.as_list()) +cvtDict = lambda toks: dict(toks.as_list()) +cvtList = lambda toks: [toks.as_list()] + +# define punctuation as suppressed literals +lparen, rparen, lbrack, rbrack, lbrace, rbrace, colon, comma = pp.Suppress.using_each("()[]{}:,") + +integer = pp.Regex(r"[+-]?\d+").set_name("integer").add_parse_action(cvtInt) +real = pp.Regex(r"[+-]?\d+\.\d*([Ee][+-]?\d+)?").set_name("real").add_parse_action(cvtReal) +tuple_str = pp.Forward().set_name("tuple_expr") +list_str = pp.Forward().set_name("list_expr") +set_str = pp.Forward().set_name("set_expr") +dict_str = pp.Forward().set_name("dict_expr") + +unistr = pp.unicodeString().add_parse_action(lambda t: t[0][2:-1]) +quoted_str = pp.quotedString().add_parse_action(lambda t: t[0][1:-1]) +bool_literal = pp.oneOf("True False", as_keyword=True).add_parse_action(cvtBool) +none_literal = pp.Keyword("None").add_parse_action(pp.replace_with(None)) + +list_item = ( + real + | integer + | quoted_str + | unistr + | bool_literal + | none_literal + | pp.Group(list_str) + | tuple_str + | set_str + | dict_str +).set_name("list_item") + +tuple_str <<= ( + lparen + pp.Opt(pp.DelimitedList(list_item, allow_trailing_delim=True)) + rparen +) +tuple_str.add_parse_action(cvtTuple) + +set_str <<= ( + lbrace + pp.DelimitedList(list_item, allow_trailing_delim=True) + rbrace +) +set_str.add_parse_action(cvtSet) + +list_str <<= ( + lbrack + pp.Opt(pp.DelimitedList(list_item, allow_trailing_delim=True)) + rbrack +) +list_str.add_parse_action(cvtList, lambda t: t[0]) + +dict_entry = pp.Group(list_item + colon + list_item).set_name("dict_entry") +dict_str <<= ( + lbrace + pp.Opt(pp.DelimitedList(dict_entry, allow_trailing_delim=True)) + rbrace +) +dict_str.add_parse_action(cvtDict) + +if __name__ == "__main__": + + tests = """['a', 100, ('A', [101,102]), 3.14, [ +2.718, 'xyzzy', -1.414] ] + [{0: [2], 1: []}, {0: [], 1: [], 2: []}, {0: [1, 2]}] + { 'A':1, 'B':2, 'C': {'a': 1.2, 'b': 3.4} } + { 1, 2, 11, "blah" } + { 'A':1, 'B':2, 'C': {'a', 1.2, 'b', 3.4} } + 3.14159 + 42 + 6.02E23 + 6.02e+023 + 1.0e-7 + 'a quoted string'""" + + list_item.run_tests(tests) + list_item.create_diagram("parse_python_value.html") diff --git a/examples/parseResultsSumExample.py b/examples/parse_results_sum_example.py index 2341b7c..2b778cf 100644 --- a/examples/parseResultsSumExample.py +++ b/examples/parse_results_sum_example.py @@ -1,29 +1,29 @@ -#
-# parseResultsSumExample.py
-#
-# Sample script showing the value in merging ParseResults retrieved by searchString,
-# using Python's builtin sum() method
-#
-samplestr1 = "garbage;DOB 10-10-2010;more garbage\nID PARI12345678;more garbage"
-samplestr2 = "garbage;ID PARI12345678;more garbage\nDOB 10-10-2010;more garbage"
-samplestr3 = "garbage;DOB 10-10-2010"
-samplestr4 = "garbage;ID PARI12345678;more garbage- I am cool"
-
-from pyparsing import *
-
-dob_ref = "DOB" + Regex(r"\d{2}-\d{2}-\d{4}")("dob")
-id_ref = "ID" + Word(alphanums, exact=12)("id")
-info_ref = "-" + restOfLine("info")
-
-person_data = dob_ref | id_ref | info_ref
-
-for test in (
- samplestr1,
- samplestr2,
- samplestr3,
- samplestr4,
-):
- person = sum(person_data.searchString(test))
- print(person.id)
- print(person.dump())
- print()
+# +# parseResultsSumExample.py +# +# Sample script showing the value in merging ParseResults retrieved by searchString, +# using Python's builtin sum() method +# +samplestr1 = "garbage;DOB 10-10-2010;more garbage\nID PARI12345678;more garbage" +samplestr2 = "garbage;ID PARI12345678;more garbage\nDOB 10-10-2010;more garbage" +samplestr3 = "garbage;DOB 10-10-2010" +samplestr4 = "garbage;ID PARI12345678;more garbage- I am cool" + +from pyparsing import Regex, Word, alphanums, rest_of_line + +dob_ref = "DOB" + Regex(r"\d{2}-\d{2}-\d{4}")("dob") +id_ref = "ID" + Word(alphanums, exact=12)("id") +info_ref = "-" + rest_of_line("info") + +person_data = dob_ref | id_ref | info_ref + +for test in ( + samplestr1, + samplestr2, + samplestr3, + samplestr4, +): + person = sum(person_data.search_string(test)) + print(person.id) + print(person.dump()) + print() diff --git a/examples/rangeCheck.py b/examples/range_check.py index be54833..3182243 100644 --- a/examples/rangeCheck.py +++ b/examples/range_check.py @@ -1,64 +1,64 @@ -# rangeCheck.py
-#
-# A sample program showing how parse actions can convert parsed
-# strings into a data type or object, and to validate the parsed value.
-#
-# Updated to use new addCondition method and expr() copy.
-#
-# Copyright 2011,2015 Paul T. McGuire
-#
-
-from pyparsing import Word, nums, Suppress, Opt
-from datetime import datetime
-
-
-def ranged_value(expr, minval=None, maxval=None):
- # have to specify at least one range boundary
- if minval is None and maxval is None:
- raise ValueError("minval or maxval must be specified")
-
- # set range testing function and error message depending on
- # whether either or both min and max values are given
- inRangeCondition = {
- (True, False): lambda s, l, t: t[0] <= maxval,
- (False, True): lambda s, l, t: minval <= t[0],
- (False, False): lambda s, l, t: minval <= t[0] <= maxval,
- }[minval is None, maxval is None]
- outOfRangeMessage = {
- (True, False): "value is greater than %s" % maxval,
- (False, True): "value is less than %s" % minval,
- (False, False): "value is not in the range ({} to {})".format(minval, maxval),
- }[minval is None, maxval is None]
-
- return expr().add_condition(inRangeCondition, message=outOfRangeMessage)
-
-
-# define the expressions for a date of the form YYYY/MM/DD or YYYY/MM (assumes YYYY/MM/01)
-integer = Word(nums).set_name("integer")
-integer.setParseAction(lambda t: int(t[0]))
-
-month = ranged_value(integer, 1, 12)
-day = ranged_value(integer, 1, 31)
-year = ranged_value(integer, 2000, None)
-
-SLASH = Suppress("/")
-dateExpr = year("year") + SLASH + month("month") + Opt(SLASH + day("day"))
-dateExpr.set_name("date")
-
-# convert date fields to datetime (also validates dates as truly valid dates)
-dateExpr.set_parse_action(lambda t: datetime(t.year, t.month, t.day or 1).date())
-
-# add range checking on dates
-mindate = datetime(2002, 1, 1).date()
-maxdate = datetime.now().date()
-dateExpr = ranged_value(dateExpr, mindate, maxdate)
-
-
-dateExpr.run_tests(
- """
- 2011/5/8
- 2001/1/1
- 2004/2/29
- 2004/2
- 1999/12/31"""
-)
+# rangeCheck.py +# +# A sample program showing how parse actions can convert parsed +# strings into a data type or object, and to validate the parsed value. +# +# Updated to use new addCondition method and expr() copy. +# +# Copyright 2011,2015 Paul T. McGuire +# + +import pyparsing as pp +from datetime import datetime + + +def ranged_value(expr, minval=None, maxval=None): + # have to specify at least one range boundary + if minval is None and maxval is None: + raise ValueError("minval or maxval must be specified") + + # set range testing function and error message depending on + # whether either or both min and max values are given + in_range_condition = { + (False, True): lambda s, l, t: t[0] <= maxval, + (True, False): lambda s, l, t: minval <= t[0], + (True, True): lambda s, l, t: minval <= t[0] <= maxval, + }[minval is not None, maxval is not None] + out_of_range_message = { + (False, True): f"value is greater than {maxval}", + (True, False): f"value is less than {minval}", + (True, True): f"value is not in the range ({minval} to {maxval})", + }[minval is not None, maxval is not None] + + return expr().add_condition(in_range_condition, message=out_of_range_message) + + +# define the expressions for a date of the form YYYY/MM/DD or YYYY/MM (assumes YYYY/MM/01) +integer = pp.Word(pp.nums).set_name("integer") +integer.set_parse_action(lambda t: int(t[0])) + +month = ranged_value(integer, 1, 12) +day = ranged_value(integer, 1, 31) +year = ranged_value(integer, 2000, None) + +SLASH = pp.Suppress("/") +dateExpr = year("year") + SLASH + month("month") + pp.Opt(SLASH + day("day")) +dateExpr.set_name("date") + +# convert date fields to datetime (also validates dates as truly valid dates) +dateExpr.set_parse_action(lambda t: datetime(t.year, t.month, t.day or 1).date()) + +# add range checking on dates +mindate = datetime(2002, 1, 1).date() +maxdate = datetime.now().date() +dateExpr = ranged_value(dateExpr, mindate, maxdate) + + +dateExpr.run_tests( + """ + 2011/5/8 + 2001/1/1 + 2004/2/29 + 2004/2 + 1999/12/31""" +) diff --git a/tests/test_examples.py b/tests/test_examples.py index 9414b09..8e63beb 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -41,7 +41,7 @@ class TestExamples(unittest.TestCase): self._run("rosettacode") def test_excelExpr(self): - self._run("excelExpr") + self._run("excel_expr") def test_lucene_grammar(self): self._run("lucene_grammar") |