summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorptmcg <ptmcg@austin.rr.com>2019-07-05 18:38:14 -0500
committerptmcg <ptmcg@austin.rr.com>2019-07-05 18:38:14 -0500
commit84ecc211279595d4d52d51630622a8dfceaaa0a5 (patch)
treed27aebf0ca0c5702b08e8ad699fa4b43d80585b0
parentbafd437305c82f064940314574ef8071dc641429 (diff)
downloadpyparsing-git-84ecc211279595d4d52d51630622a8dfceaaa0a5.tar.gz
Update examples to reflect newer pyparsing and coding styles, and use '...' to illustrate repetition and skipping
-rw-r--r--examples/chemicalFormulas.py27
-rw-r--r--examples/sexpParser.py69
-rw-r--r--examples/wordsToNum.py88
3 files changed, 93 insertions, 91 deletions
diff --git a/examples/chemicalFormulas.py b/examples/chemicalFormulas.py
index c1df9f3..753901b 100644
--- a/examples/chemicalFormulas.py
+++ b/examples/chemicalFormulas.py
@@ -2,11 +2,10 @@
#
# chemicalFormulas.py
#
-# Copyright (c) 2003, Paul McGuire
+# Copyright (c) 2003,2019 Paul McGuire
#
-from pyparsing import Word, Optional, OneOrMore, Group, ParseException, Regex
-from pyparsing import alphas
+import pyparsing as pp
atomicWeight = {
"O" : 15.9994,
@@ -19,14 +18,14 @@ atomicWeight = {
digits = "0123456789"
# Version 1
-element = Word( alphas.upper(), alphas.lower(), max=2)
+element = pp.Word(pp.alphas.upper(), pp.alphas.lower(), max=2)
# 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 = Group( element + Optional( Word( digits ), default="1" ) )
-formula = OneOrMore( elementRef )
+elementRef = pp.Group(element + pp.Optional(pp.Word(digits), default="1"))
+formula = elementRef[...]
fn = lambda elemList : sum(atomicWeight[elem]*int(qty) for elem,qty in elemList)
formula.runTests("""\
@@ -38,8 +37,8 @@ formula.runTests("""\
print()
# Version 2 - access parsed items by results name
-elementRef = Group( element("symbol") + Optional( Word( digits ), default="1" )("qty") )
-formula = OneOrMore( elementRef )
+elementRef = pp.Group(element("symbol") + pp.Optional(pp.Word(digits), default="1")("qty"))
+formula = elementRef[...]
fn = lambda elemList : sum(atomicWeight[elem.symbol]*int(elem.qty) for elem in elemList)
formula.runTests("""\
@@ -51,9 +50,9 @@ formula.runTests("""\
print()
# Version 3 - convert integers during parsing process
-integer = Word( digits ).setParseAction(lambda t:int(t[0]))
-elementRef = Group( element("symbol") + Optional( integer, default=1 )("qty") )
-formula = OneOrMore( elementRef )
+integer = pp.Word(digits).setParseAction(lambda t:int(t[0]))
+elementRef = pp.Group(element("symbol") + pp.Optional(integer, default=1)("qty"))
+formula = elementRef[...]
fn = lambda elemList : sum(atomicWeight[elem.symbol]*elem.qty for elem in elemList)
formula.runTests("""\
@@ -72,10 +71,10 @@ def cvt_subscript_int(s):
for c in s[0]:
ret = ret*10 + subscript_int_map[c]
return ret
-subscript_int = Word(subscript_digits).addParseAction(cvt_subscript_int)
+subscript_int = pp.Word(subscript_digits).addParseAction(cvt_subscript_int)
-elementRef = Group( element("symbol") + Optional(subscript_int, default=1)("qty") )
-formula = OneOrMore( elementRef )
+elementRef = pp.Group(element("symbol") + pp.Optional(subscript_int, default=1)("qty"))
+formula = elementRef[...]
formula.runTests("""\
H₂O
C₆H₅OH
diff --git a/examples/sexpParser.py b/examples/sexpParser.py
index 123b401..fd8ffd3 100644
--- a/examples/sexpParser.py
+++ b/examples/sexpParser.py
@@ -18,12 +18,12 @@ BNF reference: http://theory.lcs.mit.edu/~rivest/sexp.txt
<sexp> :: <string> | <list>
<string> :: <display>? <simple-string> ;
<simple-string> :: <raw> | <token> | <base-64> | <hexadecimal> |
- <quoted-string> ;
+ <quoted-string> ;
<display> :: "[" <simple-string> "]" ;
<raw> :: <decimal> ":" <bytes> ;
<decimal> :: <decimal-digit>+ ;
- -- decimal numbers should have no unnecessary leading zeros
-<bytes> -- any string of bytes, of the indicated length
+ -- decimal numbers should have no unnecessary leading zeros
+<bytes> -- any string of bytes, of the indicated length
<token> :: <tokenchar>+ ;
<base-64> :: <decimal>? "|" ( <base-64-char> | <whitespace> )* "|" ;
<hexadecimal> :: "#" ( <hex-digit> | <white-space> )* "#" ;
@@ -43,51 +43,51 @@ BNF reference: http://theory.lcs.mit.edu/~rivest/sexp.txt
<null> :: "" ;
"""
-from pyparsing import *
+import pyparsing as pp
from base64 import b64decode
import pprint
-def verifyLen(s,l,t):
+
+def verify_length(s, l, t):
t = t[0]
if t.len is not None:
t1len = len(t[1])
if t1len != t.len:
- raise ParseFatalException(s,l,\
- "invalid data of length %d, expected %s" % (t1len, t.len))
+ raise pp.ParseFatalException(s, l, "invalid data of length {0}, expected {1}".format(t1len, t.len))
return t[1]
+
# define punctuation literals
-LPAR, RPAR, LBRK, RBRK, LBRC, RBRC, VBAR = map(Suppress, "()[]{}|")
-
-decimal = Regex(r'0|[1-9]\d*').setParseAction(lambda t: int(t[0]))
-hexadecimal = ("#" + OneOrMore(Word(hexnums)) + "#")\
- .setParseAction(lambda t: int("".join(t[1:-1]),16))
-bytes = Word(printables)
-raw = Group(decimal("len") + Suppress(":") + bytes).setParseAction(verifyLen)
-token = Word(alphanums + "-./_:*+=")
-base64_ = Group(Optional(decimal|hexadecimal,default=None)("len") + VBAR
- + OneOrMore(Word( alphanums +"+/=" )).setParseAction(lambda t: b64decode("".join(t)))
- + VBAR).setParseAction(verifyLen)
-
-qString = Group(Optional(decimal,default=None)("len") +
- dblQuotedString.setParseAction(removeQuotes)).setParseAction(verifyLen)
-simpleString = base64_ | raw | decimal | token | hexadecimal | qString
-
-# extended definitions
-decimal = Regex(r'-?0|[1-9]\d*').setParseAction(lambda t: int(t[0]))
-real = Regex(r"[+-]?\d+\.\d*([eE][+-]?\d+)?").setParseAction(lambda tokens: float(tokens[0]))
-token = Word(alphanums + "-./_:*+=!<>")
+LPAR, RPAR, LBRK, RBRK, LBRC, RBRC, VBAR, COLON = (pp.Suppress(c).setName(c) for c in "()[]{}|:")
+
+decimal = pp.Regex(r'-?0|[1-9]\d*').setParseAction(lambda t: int(t[0]))
+hexadecimal = ("#" + pp.Word(pp.hexnums)[...] + "#").setParseAction(lambda t: int("".join(t[1:-1]), 16))
+bytes = pp.Word(pp.printables)
+raw = pp.Group(decimal("len") + COLON + bytes).setParseAction(verify_length)
+base64_ = pp.Group(pp.Optional(decimal | hexadecimal, default=None)("len")
+ + VBAR
+ + pp.Word(pp.alphanums + "+/=")[...].setParseAction(lambda t: b64decode("".join(t)))
+ + VBAR
+ ).setParseAction(verify_length)
+
+real = pp.Regex(r"[+-]?\d+\.\d*([eE][+-]?\d+)?").setParseAction(lambda tokens: float(tokens[0]))
+token = pp.Word(pp.alphanums + "-./_:*+=!<>")
+qString = pp.Group(pp.Optional(decimal, default=None)("len")
+ + pp.dblQuotedString.setParseAction(pp.removeQuotes)
+ ).setParseAction(verify_length)
simpleString = real | base64_ | raw | decimal | token | hexadecimal | qString
display = LBRK + simpleString + RBRK
-string_ = Optional(display) + simpleString
+string_ = pp.Optional(display) + simpleString
+
+sexp = pp.Forward()
+sexpList = pp.Group(LPAR + sexp[0, ...] + RPAR)
+sexp <<= string_ | sexpList
+
-sexp = Forward()
-sexpList = Group(LPAR + ZeroOrMore(sexp) + RPAR)
-sexp << ( string_ | sexpList )
+# Test data
-######### Test data ###########
test00 = """(snicker "abc" (#03# |YWJj|))"""
test01 = """(certificate
(issuer
@@ -142,7 +142,7 @@ test07 = """(defun factorial (x)
test51 = """(2:XX "abc" (#03# |YWJj|))"""
test51error = """(3:XX "abc" (#03# |YWJj|))"""
-test52 = """
+test52 = """
(and
(or (> uid 1000)
(!= gid 20)
@@ -152,7 +152,6 @@ test52 = """
"""
# Run tests
-t = None
-alltests = [ globals()[t] for t in sorted(locals()) if t.startswith("test") ]
+alltests = [globals()[testname] for testname in sorted(locals()) if testname.startswith("test")]
sexp.runTests(alltests, fullDump=False)
diff --git a/examples/wordsToNum.py b/examples/wordsToNum.py
index cbd3d26..d9511da 100644
--- a/examples/wordsToNum.py
+++ b/examples/wordsToNum.py
@@ -3,13 +3,13 @@
#
# Sample parser grammar to read a number given in words, and return the numeric value.
#
-from pyparsing import *
+import pyparsing as pp
from operator import mul
from functools import reduce
-def makeLit(s,val):
- ret = CaselessLiteral(s).setName(s)
- return ret.setParseAction( replaceWith(val) )
+def makeLit(s, val):
+ ret = pp.CaselessLiteral(s)
+ return ret.setParseAction(pp.replaceWith(val))
unitDefinitions = [
("zero", 0),
@@ -38,7 +38,7 @@ unitDefinitions = [
("eighteen", 18),
("nineteen", 19),
]
-units = Or(makeLit(s,v) for s,v in unitDefinitions)
+units = pp.MatchFirst(makeLit(s,v) for s,v in sorted(unitDefinitions, key=lambda d: -len(d[0])))
tensDefinitions = [
("ten", 10),
@@ -52,7 +52,7 @@ tensDefinitions = [
("eighty", 80),
("ninety", 90),
]
-tens = Or(makeLit(s,v) for s,v in tensDefinitions)
+tens = pp.MatchFirst(makeLit(s,v) for s,v in tensDefinitions)
hundreds = makeLit("hundred", 100)
@@ -64,43 +64,47 @@ majorDefinitions = [
("quadrillion", int(1e15)),
("quintillion", int(1e18)),
]
-mag = Or(makeLit(s,v) for s,v in majorDefinitions)
+mag = pp.MatchFirst(makeLit(s,v) for s,v in majorDefinitions)
wordprod = lambda t: reduce(mul,t)
-wordsum = lambda t: sum(t)
-numPart = (((( units + Optional(hundreds) ).setParseAction(wordprod) +
- Optional(tens)).setParseAction(wordsum)
- ^ tens )
- + Optional(units) ).setParseAction(wordsum)
-numWords = OneOrMore( (numPart + Optional(mag)).setParseAction(wordprod)
- ).setParseAction(wordsum) + StringEnd()
-numWords.ignore(Literal("-"))
-numWords.ignore(CaselessLiteral("and"))
+numPart = ((((units + pp.Optional(hundreds)).setParseAction(wordprod)
+ + pp.Optional(tens)
+ ).setParseAction(sum)
+ ^ tens)
+ + pp.Optional(units)
+ ).setParseAction(sum)
+numWords = ((numPart + pp.Optional(mag)).setParseAction(wordprod)[...]).setParseAction(sum)
+numWords.setName("num word parser")
-def test(s,expected):
- try:
- fail_expected = (expected is None)
- success, results_tup = numWords.runTests(s, failureTests=fail_expected)
- assert success, "Failed test!"
- if not fail_expected:
- teststr, results = results_tup[0]
- observed = results[0]
- assert expected == observed, "incorrect parsed value, {0} -> {1}, should be {2}".format(teststr, observed, expected)
- except Exception as exc:
- print("{0}: {1}".format(type(exc).__name__, exc))
+numWords.ignore(pp.Literal("-"))
+numWords.ignore(pp.CaselessLiteral("and"))
-test("one hundred twenty hundred", None)
-test("one hundred and twennty", None)
-test("one hundred and twenty", 120)
-test("one hundred and three", 103)
-test("one hundred twenty-three", 123)
-test("one hundred and twenty three", 123)
-test("one hundred twenty three million", 123000000)
-test("one hundred and twenty three million", 123000000)
-test("one hundred twenty three million and three", 123000003)
-test("fifteen hundred and sixty five", 1565)
-test("seventy-seven thousand eight hundred and nineteen", 77819)
-test("seven hundred seventy-seven thousand seven hundred and seventy-seven", 777777)
-test("zero", 0)
-test("forty two", 42)
-test("fourty two", 42)
+tests = """
+ one hundred twenty hundred, None
+ one hundred and twennty, None
+ one hundred and twenty, 120
+ one hundred and three, 103
+ one hundred twenty-three, 123
+ one hundred and twenty three, 123
+ one hundred twenty three million, 123000000
+ one hundred and twenty three million, 123000000
+ one hundred twenty three million and three, 123000003
+ fifteen hundred and sixty five, 1565
+ seventy-seven thousand eight hundred and nineteen, 77819
+ seven hundred seventy-seven thousand seven hundred and seventy-seven, 777777
+ zero, 0
+ forty two, 42
+ fourty two, 42
+"""
+
+# use '| ...' to indicate "if omitted, skip to next" logic
+test_expr = (numWords('result') | ...) + ',' + (pp.pyparsing_common.integer('expected') | 'None')
+
+def verify_result(t):
+ if '_skipped' in t:
+ t['pass'] = False
+ elif 'expected' in t:
+ t['pass'] = t.result == t.expected
+test_expr.addParseAction(verify_result)
+
+test_expr.runTests(tests)