diff options
author | ptmcg <ptmcg@austin.rr.com> | 2021-08-01 12:57:10 -0500 |
---|---|---|
committer | ptmcg <ptmcg@austin.rr.com> | 2021-08-01 12:57:10 -0500 |
commit | f22dcdc9be6aebf7defc1ef43e39c53921ba7566 (patch) | |
tree | d40b225f53c90a0b4676c59323251c9c2c825df6 | |
parent | 1688592bd97e573174e9eab482846e0f1194652a (diff) | |
download | pyparsing-git-f22dcdc9be6aebf7defc1ef43e39c53921ba7566.tar.gz |
Update __versionTime__; blacken core code and examples
-rw-r--r-- | examples/LAparser.py | 32 | ||||
-rw-r--r-- | examples/adventureEngine.py | 15 | ||||
-rw-r--r-- | examples/apicheck.py | 6 | ||||
-rw-r--r-- | examples/bigquery_view_parser.py | 273 | ||||
-rw-r--r-- | examples/btpyparse.py | 4 | ||||
-rw-r--r-- | examples/decaf_parser.py | 48 | ||||
-rw-r--r-- | examples/eval_arith.py | 5 | ||||
-rw-r--r-- | examples/excelExpr.py | 13 | ||||
-rw-r--r-- | examples/idlParse.py | 7 | ||||
-rw-r--r-- | examples/invRegex.py | 9 | ||||
-rw-r--r-- | examples/left_recursion.py | 15 | ||||
-rw-r--r-- | examples/number_words.py | 31 | ||||
-rw-r--r-- | examples/pymicko.py | 154 | ||||
-rw-r--r-- | examples/rosettacode.py | 42 | ||||
-rw-r--r-- | examples/simpleSQL.py | 6 | ||||
-rw-r--r-- | examples/sparser.py | 6 | ||||
-rw-r--r-- | examples/statemachine/statemachine.py | 2 | ||||
-rw-r--r-- | pyparsing/__init__.py | 4 | ||||
-rw-r--r-- | pyparsing/actions.py | 22 | ||||
-rw-r--r-- | pyparsing/core.py | 148 | ||||
-rw-r--r-- | pyparsing/exceptions.py | 23 | ||||
-rw-r--r-- | pyparsing/results.py | 66 | ||||
-rw-r--r-- | pyparsing/testing.py | 8 | ||||
-rw-r--r-- | pyparsing/util.py | 28 |
24 files changed, 667 insertions, 300 deletions
diff --git a/examples/LAparser.py b/examples/LAparser.py index b72166f..31494b8 100644 --- a/examples/LAparser.py +++ b/examples/LAparser.py @@ -381,18 +381,18 @@ def parse(input_string): ##----------------------------------------------------------------------------------- def fprocess(infilep, outfilep): """ - Scans an input file for LA equations between double square brackets, - e.g. [[ M3_mymatrix = M3_anothermatrix^-1 ]], and replaces the expression - with a comment containing the equation followed by nested function calls - that implement the equation as C code. A trailing semi-colon is appended. - The equation within [[ ]] should NOT end with a semicolon as that will raise - a ParseException. However, it is ok to have a semicolon after the right brackets. - - Other text in the file is unaltered. - - The arguments are file objects (NOT file names) opened for reading and - writing, respectively. - """ + Scans an input file for LA equations between double square brackets, + e.g. [[ M3_mymatrix = M3_anothermatrix^-1 ]], and replaces the expression + with a comment containing the equation followed by nested function calls + that implement the equation as C code. A trailing semi-colon is appended. + The equation within [[ ]] should NOT end with a semicolon as that will raise + a ParseException. However, it is ok to have a semicolon after the right brackets. + + Other text in the file is unaltered. + + The arguments are file objects (NOT file names) opened for reading and + writing, respectively. + """ pattern = r"\[\[\s*(.*?)\s*\]\]" eqn = re.compile(pattern, re.DOTALL) s = infilep.read() @@ -408,10 +408,10 @@ def fprocess(infilep, outfilep): ##----------------------------------------------------------------------------------- def test(): """ - Tests the parsing of various supported expressions. Raises - an AssertError if the output is not what is expected. Prints the - input, expected output, and actual output for all tests. - """ + Tests the parsing of various supported expressions. Raises + an AssertError if the output is not what is expected. Prints the + input, expected output, and actual output for all tests. + """ print("Testing LAParser") testcases = [ ("Scalar addition", "a = b+c", "a=(b+c)"), diff --git a/examples/adventureEngine.py b/examples/adventureEngine.py index a6a44ad..efc096c 100644 --- a/examples/adventureEngine.py +++ b/examples/adventureEngine.py @@ -182,7 +182,14 @@ class MoveCommand(Command): def _doCommand(self, player):
rm = player.room
- nextRoom = rm.doors[{"N": 0, "S": 1, "E": 2, "W": 3,}[self.direction]]
+ nextRoom = rm.doors[
+ {
+ "N": 0,
+ "S": 1,
+ "E": 2,
+ "W": 3,
+ }[self.direction]
+ ]
if nextRoom:
player.moveTo(nextRoom)
else:
@@ -636,8 +643,10 @@ library = rooms["e"] patio = rooms["f"]
# create items
-itemNames = """sword.diamond.apple.flower.coin.shovel.book.mirror.telescope.gold bar""".split(
- "."
+itemNames = (
+ """sword.diamond.apple.flower.coin.shovel.book.mirror.telescope.gold bar""".split(
+ "."
+ )
)
for itemName in itemNames:
Item(itemName)
diff --git a/examples/apicheck.py b/examples/apicheck.py index 1905d4a..366ad06 100644 --- a/examples/apicheck.py +++ b/examples/apicheck.py @@ -25,7 +25,11 @@ def apiProc(name, numargs): # with FollowedBy allows us to quickly rule out non-api calls while scanning,
# since all of the api calls begin with a "["
apiRef = FollowedBy("[") + MatchFirst(
- [apiProc("procname1", 2), apiProc("procname2", 1), apiProc("procname3", 2),]
+ [
+ apiProc("procname1", 2),
+ apiProc("procname2", 1),
+ apiProc("procname3", 2),
+ ]
)
test = """[ procname1 $par1 $par2 ]
diff --git a/examples/bigquery_view_parser.py b/examples/bigquery_view_parser.py index 433a127..c9b8411 100644 --- a/examples/bigquery_view_parser.py +++ b/examples/bigquery_view_parser.py @@ -844,61 +844,98 @@ if __name__ == "__main__": """ SELECT x FROM y.a, b """, - [(None, "y", "a"), (None, None, "b",),], + [ + (None, "y", "a"), + ( + None, + None, + "b", + ), + ], ], [ """ SELECT x FROM y.a JOIN b """, - [(None, "y", "a"), (None, None, "b"),], + [ + (None, "y", "a"), + (None, None, "b"), + ], ], [ """ select * from xyzzy where z > 100 """, - [(None, None, "xyzzy"),], + [ + (None, None, "xyzzy"), + ], ], [ """ select * from xyzzy where z > 100 order by zz """, - [(None, None, "xyzzy"),], + [ + (None, None, "xyzzy"), + ], ], [ """ select * from xyzzy """, - [(None, None, "xyzzy",),], + [ + ( + None, + None, + "xyzzy", + ), + ], ], [ """ select z.* from xyzzy """, - [(None, None, "xyzzy",),], + [ + ( + None, + None, + "xyzzy", + ), + ], ], [ """ select a, b from test_table where 1=1 and b='yes' """, - [(None, None, "test_table"),], + [ + (None, None, "test_table"), + ], ], [ """ select a, b from test_table where 1=1 and b in (select bb from foo) """, - [(None, None, "test_table"), (None, None, "foo"),], + [ + (None, None, "test_table"), + (None, None, "foo"), + ], ], [ """ select z.a, b from test_table where 1=1 and b in (select bb from foo) """, - [(None, None, "test_table"), (None, None, "foo"),], + [ + (None, None, "test_table"), + (None, None, "foo"), + ], ], [ """ select z.a, b from test_table where 1=1 and b in (select bb from foo) order by b,c desc,d """, - [(None, None, "test_table"), (None, None, "foo"),], + [ + (None, None, "test_table"), + (None, None, "foo"), + ], ], [ """ @@ -914,25 +951,35 @@ if __name__ == "__main__": """ select a, db.table.b as BBB from db.table where 1=1 and BBB='yes' """, - [(None, "db", "table"),], + [ + (None, "db", "table"), + ], ], [ """ select a, db.table.b as BBB from test_table,db.table where 1=1 and BBB='yes' """, - [(None, None, "test_table"), (None, "db", "table"),], + [ + (None, None, "test_table"), + (None, "db", "table"), + ], ], [ """ select a, db.table.b as BBB from test_table,db.table where 1=1 and BBB='yes' limit 50 """, - [(None, None, "test_table"), (None, "db", "table"),], + [ + (None, None, "test_table"), + (None, "db", "table"), + ], ], [ """ select a, b from test_table where (1=1 or 2=3) and b='yes' group by zx having b=2 order by 1 """, - [(None, None, "test_table"),], + [ + (None, None, "test_table"), + ], ], [ """ @@ -947,31 +994,44 @@ if __name__ == "__main__": #yup, a comment group by zx having b=2 order by 1 """, - [(None, None, "test_table"),], + [ + (None, None, "test_table"), + ], ], [ """ SELECT COUNT(DISTINCT foo) FROM bar JOIN baz ON bar.baz_id = baz.id """, - [(None, None, "bar"), (None, None, "baz"),], + [ + (None, None, "bar"), + (None, None, "baz"), + ], ], [ """ SELECT COUNT(DISTINCT foo) FROM bar, baz WHERE bar.baz_id = baz.id """, - [(None, None, "bar"), (None, None, "baz"),], + [ + (None, None, "bar"), + (None, None, "baz"), + ], ], [ """ WITH one AS (SELECT id FROM foo) SELECT one.id """, - [(None, None, "foo"),], + [ + (None, None, "foo"), + ], ], [ """ WITH one AS (SELECT id FROM foo), two AS (select id FROM bar) SELECT one.id, two.id """, - [(None, None, "foo"), (None, None, "bar"),], + [ + (None, None, "foo"), + (None, None, "bar"), + ], ], [ """ @@ -981,7 +1041,13 @@ if __name__ == "__main__": ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) AS row_num FROM a """, - [(None, None, "a",),], + [ + ( + None, + None, + "a", + ), + ], ], [ """ @@ -989,7 +1055,13 @@ if __name__ == "__main__": RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING ) AS count_x FROM T """, - [(None, None, "T",),], + [ + ( + None, + None, + "T", + ), + ], ], [ """ @@ -997,7 +1069,9 @@ if __name__ == "__main__": RANK() OVER ( PARTITION BY department ORDER BY startdate ) AS rank FROM Employees """, - [(None, None, "Employees"),], + [ + (None, None, "Employees"), + ], ], # A fragment from https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions [ @@ -1334,7 +1408,9 @@ if __name__ == "__main__": FROM bar """, - [(None, None, "bar"),], + [ + (None, None, "bar"), + ], ], [ """ @@ -1387,7 +1463,13 @@ if __name__ == "__main__": case when (a) then b else c end FROM d """, - [(None, None, "d",),], + [ + ( + None, + None, + "d", + ), + ], ], [ """ @@ -1396,7 +1478,13 @@ if __name__ == "__main__": case when (f) then g else h end FROM i """, - [(None, None, "i",),], + [ + ( + None, + None, + "i", + ), + ], ], [ """ @@ -1404,7 +1492,13 @@ if __name__ == "__main__": case when j then k else l end FROM m """, - [(None, None, "m",),], + [ + ( + None, + None, + "m", + ), + ], ], [ """ @@ -1413,7 +1507,13 @@ if __name__ == "__main__": case when o then p else q end FROM r """, - [(None, None, "r",),], + [ + ( + None, + None, + "r", + ), + ], ], [ """ @@ -1421,7 +1521,13 @@ if __name__ == "__main__": case s when (t) then u else v end FROM w """, - [(None, None, "w",),], + [ + ( + None, + None, + "w", + ), + ], ], [ """ @@ -1430,7 +1536,13 @@ if __name__ == "__main__": case y when (z) then aa else ab end FROM ac """, - [(None, None, "ac",),], + [ + ( + None, + None, + "ac", + ), + ], ], [ """ @@ -1438,7 +1550,13 @@ if __name__ == "__main__": case ad when ae then af else ag end FROM ah """, - [(None, None, "ah",),], + [ + ( + None, + None, + "ah", + ), + ], ], [ """ @@ -1447,7 +1565,13 @@ if __name__ == "__main__": case aj when ak then al else am end FROM an """, - [(None, None, "an",),], + [ + ( + None, + None, + "an", + ), + ], ], [ """ @@ -1456,7 +1580,18 @@ if __name__ == "__main__": TWO AS (select a FROM b) SELECT y FROM onE JOIN TWo """, - [(None, None, "y",), (None, None, "b",),], + [ + ( + None, + None, + "y", + ), + ( + None, + None, + "b", + ), + ], ], [ """ @@ -1465,67 +1600,98 @@ if __name__ == "__main__": (SELECT b FROM oNE) FROM OnE """, - [(None, None, "oNE",), (None, None, "OnE",),], + [ + ( + None, + None, + "oNE", + ), + ( + None, + None, + "OnE", + ), + ], ], [ """ SELECT * FROM `a.b.c` """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM `b.c` """, - [(None, "b", "c"),], + [ + (None, "b", "c"), + ], ], [ """ SELECT * FROM `c` """, - [(None, None, "c"),], + [ + (None, None, "c"), + ], ], [ """ SELECT * FROM a.b.c """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM "a"."b"."c" """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM 'a'.'b'.'c' """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM `a`.`b`.`c` """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM "a.b.c" """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM 'a.b.c' """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ SELECT * FROM `a.b.c` """, - [("a", "b", "c"),], + [ + ("a", "b", "c"), + ], ], [ """ @@ -1534,14 +1700,21 @@ if __name__ == "__main__": WHERE t1.a IN (SELECT t2.a FROM t2 ) FOR SYSTEM_TIME AS OF t1.timestamp_column) """, - [(None, None, "t1"), (None, None, "t2"),], + [ + (None, None, "t1"), + (None, None, "t2"), + ], ], [ """ WITH a AS (SELECT b FROM c) SELECT d FROM A JOIN e ON f = g JOIN E ON h = i """, - [(None, None, "c"), (None, None, "e"), (None, None, "E"),], + [ + (None, None, "c"), + (None, None, "e"), + (None, None, "E"), + ], ], [ """ @@ -1561,7 +1734,11 @@ if __name__ == "__main__": select g from h """, - [(None, None, "d"), (None, None, "f"), (None, None, "h"),], + [ + (None, None, "d"), + (None, None, "f"), + (None, None, "h"), + ], ], [ """ @@ -1573,7 +1750,9 @@ if __name__ == "__main__": e AS DATE_ADD FROM x """, - [(None, None, "x"),], + [ + (None, None, "x"), + ], ], [ """ diff --git a/examples/btpyparse.py b/examples/btpyparse.py index 81ca4b0..3531761 100644 --- a/examples/btpyparse.py +++ b/examples/btpyparse.py @@ -24,7 +24,7 @@ from pyparsing import ( class Macro:
- """ Class to encapsulate undefined macro references """
+ """Class to encapsulate undefined macro references"""
def __init__(self, name):
self.name = name
@@ -43,7 +43,7 @@ LCURLY, RCURLY, LPAREN, RPAREN, QUOTE, COMMA, AT, EQUALS, HASH = map( def bracketed(expr):
- """ Return matcher for `expr` between curly brackets or parentheses """
+ """Return matcher for `expr` between curly brackets or parentheses"""
return (LPAREN + expr + RPAREN) | (LCURLY + expr + RCURLY)
diff --git a/examples/decaf_parser.py b/examples/decaf_parser.py index be3a1e9..d0a376d 100644 --- a/examples/decaf_parser.py +++ b/examples/decaf_parser.py @@ -118,19 +118,51 @@ rvalue = constant | call | read_integer | read_line | new_statement | new_array arith_expr = pp.infixNotation( rvalue, [ - ("-", 1, pp.opAssoc.RIGHT,), - (pp.oneOf("* / %"), 2, pp.opAssoc.LEFT,), - (pp.oneOf("+ -"), 2, pp.opAssoc.LEFT,), + ( + "-", + 1, + pp.opAssoc.RIGHT, + ), + ( + pp.oneOf("* / %"), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("+ -"), + 2, + pp.opAssoc.LEFT, + ), ], ) comparison_expr = pp.infixNotation( arith_expr, [ - ("!", 1, pp.opAssoc.RIGHT,), - (pp.oneOf("< > <= >="), 2, pp.opAssoc.LEFT,), - (pp.oneOf("== !="), 2, pp.opAssoc.LEFT,), - (pp.oneOf("&&"), 2, pp.opAssoc.LEFT,), - (pp.oneOf("||"), 2, pp.opAssoc.LEFT,), + ( + "!", + 1, + pp.opAssoc.RIGHT, + ), + ( + pp.oneOf("< > <= >="), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("== !="), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("&&"), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("||"), + 2, + pp.opAssoc.LEFT, + ), ], ) expr <<= ( diff --git a/examples/eval_arith.py b/examples/eval_arith.py index 4f6082f..23f40c8 100644 --- a/examples/eval_arith.py +++ b/examples/eval_arith.py @@ -162,7 +162,10 @@ arith_expr = infixNotation( comparisonop = oneOf("< <= > >= != = <> LT GT LE GE EQ NE") comp_expr = infixNotation( - arith_expr, [(comparisonop, 2, opAssoc.LEFT, EvalComparisonOp),] + arith_expr, + [ + (comparisonop, 2, opAssoc.LEFT, EvalComparisonOp), + ], ) diff --git a/examples/excelExpr.py b/examples/excelExpr.py index d7dac90..311a5a4 100644 --- a/examples/excelExpr.py +++ b/examples/excelExpr.py @@ -75,11 +75,20 @@ addOp = oneOf("+ -") numericLiteral = ppc.number
operand = numericLiteral | funcCall | cellRange | cellRef
arithExpr = infixNotation(
- operand, [(multOp, 2, opAssoc.LEFT), (addOp, 2, opAssoc.LEFT),]
+ operand,
+ [
+ (multOp, 2, opAssoc.LEFT),
+ (addOp, 2, opAssoc.LEFT),
+ ],
)
textOperand = dblQuotedString | cellRef
-textExpr = infixNotation(textOperand, [("&", 2, opAssoc.LEFT),])
+textExpr = infixNotation(
+ textOperand,
+ [
+ ("&", 2, opAssoc.LEFT),
+ ],
+)
expr <<= arithExpr | textExpr
diff --git a/examples/idlParse.py b/examples/idlParse.py index f5398b7..62becd2 100644 --- a/examples/idlParse.py +++ b/examples/idlParse.py @@ -170,9 +170,10 @@ def CORBA_IDL_BNF(): moduleItem = (
interfaceDef | exceptionDef | constDef | typedefDef | moduleDef
).setName("moduleItem")
- moduleDef << module_ + identifier + lbrace + ZeroOrMore(
- moduleItem
- ) + rbrace + semi
+ (
+ moduleDef
+ << module_ + identifier + lbrace + ZeroOrMore(moduleItem) + rbrace + semi
+ )
bnf = moduleDef | OneOrMore(moduleItem)
diff --git a/examples/invRegex.py b/examples/invRegex.py index b9d6cfb..0ec1cdf 100644 --- a/examples/invRegex.py +++ b/examples/invRegex.py @@ -237,10 +237,11 @@ def count(gen): def invert(regex):
- r"""Call this routine as a generator to return all the strings that
- match the input regular expression.
- for s in invert(r"[A-Z]{3}\d{3}"):
- print s
+ r"""
+ Call this routine as a generator to return all the strings that
+ match the input regular expression.
+ for s in invert(r"[A-Z]{3}\d{3}"):
+ print s
"""
invReGenerator = GroupEmitter(parser().parseString(regex)).makeGenerator()
return invReGenerator()
diff --git a/examples/left_recursion.py b/examples/left_recursion.py index f3977dc..5c7e398 100644 --- a/examples/left_recursion.py +++ b/examples/left_recursion.py @@ -18,9 +18,11 @@ item_list = pp.Forward() item = pp.Word(pp.alphas) item_list <<= item_list + item | item -item_list.runTests("""\ +item_list.runTests( + """\ To parse or not to parse that is the question - """) + """ +) # Define a parser for an expression that can be an identifier, a quoted string, or a # function call that starts with an expression @@ -35,11 +37,14 @@ LPAR, RPAR = map(pp.Suppress, "()") expr = pp.Forward() string = pp.quotedString function_call = expr + pp.Group(LPAR + pp.Optional(pp.delimitedList(expr)) + RPAR) -name = pp.Word(pp.alphas + '_', pp.alphanums + '_') +name = pp.Word(pp.alphas + "_", pp.alphanums + "_") # left recursion - call starts with an expr expr <<= function_call | string | name | pp.Group(LPAR + expr + RPAR) -expr.runTests("""\ +expr.runTests( + """\ print("Hello, World!") (lookup_function("fprintf"))(stderr, "Hello, World!") - """, fullDump=False) + """, + fullDump=False, +) diff --git a/examples/number_words.py b/examples/number_words.py index b1217cf..1d65c95 100644 --- a/examples/number_words.py +++ b/examples/number_words.py @@ -43,18 +43,32 @@ def define_numeric_word_range(s, vals): opt_dash = pp.Optional(pp.Suppress("-")).setName("optional '-'") -opt_and = pp.Optional((pp.CaselessKeyword("and") | "-").suppress()).setName("optional 'and'") +opt_and = pp.Optional((pp.CaselessKeyword("and") | "-").suppress()).setName( + "optional 'and'" +) zero = define_numeric_word_range("zero oh", [0, 0]) -one_to_9 = define_numeric_word_range("one two three four five six seven eight nine", range(1, 9 + 1)).setName("1-9") -eleven_to_19 = define_numeric_word_range("eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen", - range(11, 19 + 1)).setName("eleven_to_19") +one_to_9 = define_numeric_word_range( + "one two three four five six seven eight nine", range(1, 9 + 1) +).setName("1-9") +eleven_to_19 = define_numeric_word_range( + "eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen", + range(11, 19 + 1), +).setName("eleven_to_19") ten_to_19 = (define_numeric_word("ten", 10) | eleven_to_19).setName("ten_to_19") one_to_19 = (one_to_9 | ten_to_19).setName("1-19") -tens = define_numeric_word_range("twenty thirty forty fifty sixty seventy eighty ninety", range(20, 90+1, 10)) -hundreds = (one_to_9 | eleven_to_19 | (tens + opt_dash + one_to_9)) + define_numeric_word("hundred", 100) -one_to_99 = (one_to_19 | (tens + pp.Optional(opt_dash + one_to_9)).addParseAction(sum)).setName("1-99") -one_to_999 = ((pp.Optional(hundreds + opt_and) + one_to_99 | hundreds).addParseAction(sum)).setName("1-999") +tens = define_numeric_word_range( + "twenty thirty forty fifty sixty seventy eighty ninety", range(20, 90 + 1, 10) +) +hundreds = ( + one_to_9 | eleven_to_19 | (tens + opt_dash + one_to_9) +) + define_numeric_word("hundred", 100) +one_to_99 = ( + one_to_19 | (tens + pp.Optional(opt_dash + one_to_9)).addParseAction(sum) +).setName("1-99") +one_to_999 = ( + (pp.Optional(hundreds + opt_and) + one_to_99 | hundreds).addParseAction(sum) +).setName("1-999") thousands = one_to_999 + define_numeric_word("thousand", 1000) hundreds.setName("100s") thousands.setName("1000s") @@ -63,6 +77,7 @@ thousands.setName("1000s") def multiply(t): return mul(*t) + hundreds.addParseAction(multiply) thousands.addParseAction(multiply) diff --git a/examples/pymicko.py b/examples/pymicko.py index ddbf219..af7bb8c 100644 --- a/examples/pymicko.py +++ b/examples/pymicko.py @@ -273,9 +273,10 @@ exshared = ExceptionSharedData() class SemanticException(Exception):
- """Exception for semantic errors found during parsing, similar to ParseException.
- Introduced because ParseException is used internally in pyparsing and custom
- messages got lost and replaced by pyparsing's generic errors.
+ """
+ Exception for semantic errors found during parsing, similar to ParseException.
+ Introduced because ParseException is used internally in pyparsing and custom
+ messages got lost and replaced by pyparsing's generic errors.
"""
def __init__(self, message, print_location=True):
@@ -317,12 +318,13 @@ class SymbolTableEntry: """Class which represents one symbol table entry."""
def __init__(self, sname="", skind=0, stype=0, sattr=None, sattr_name="None"):
- """Initialization of symbol table entry.
- sname - symbol name
- skind - symbol kind
- stype - symbol type
- sattr - symbol attribute
- sattr_name - symbol attribute name (used only for table display)
+ """
+ Initialization of symbol table entry.
+ sname - symbol name
+ skind - symbol kind
+ stype - symbol type
+ sattr - symbol attribute
+ sattr_name - symbol attribute name (used only for table display)
"""
self.name = sname
self.kind = skind
@@ -363,8 +365,9 @@ class SymbolTable: self.shared = shared
def error(self, text=""):
- """Symbol table error exception. It should happen only if index is out of range while accessing symbol table.
- This exception is not handled by the compiler, so as to allow traceback printing
+ """
+ Symbol table error exception. It should happen only if index is out of range while accessing symbol table.
+ This exception is not handled by the compiler, so as to allow traceback printing
"""
if text == "":
raise Exception("Symbol table index out of range")
@@ -429,11 +432,12 @@ class SymbolTable: )
def insert_symbol(self, sname, skind, stype):
- """Inserts new symbol at the end of the symbol table.
- Returns symbol index
- sname - symbol name
- skind - symbol kind
- stype - symbol type
+ """
+ Inserts new symbol at the end of the symbol table.
+ Returns symbol index
+ sname - symbol name
+ skind - symbol kind
+ stype - symbol type
"""
self.table.append(SymbolTableEntry(sname, skind, stype))
self.table_len = len(self.table)
@@ -453,11 +457,12 @@ class SymbolTable: skind=list(SharedData.KINDS.keys()),
stype=list(SharedData.TYPES.keys()),
):
- """Searches for symbol, from the end to the beginning.
- Returns symbol index or None
- sname - symbol name
- skind - symbol kind (one kind, list of kinds, or None) default: any kind
- stype - symbol type (or None) default: any type
+ """
+ Searches for symbol, from the end to the beginning.
+ Returns symbol index or None
+ sname - symbol name
+ skind - symbol kind (one kind, list of kinds, or None) default: any kind
+ stype - symbol type (or None) default: any type
"""
skind = skind if isinstance(skind, list) else [skind]
stype = stype if isinstance(stype, list) else [stype]
@@ -470,12 +475,13 @@ class SymbolTable: return None
def insert_id(self, sname, skind, skinds, stype):
- """Inserts a new identifier at the end of the symbol table, if possible.
- Returns symbol index, or raises an exception if the symbol already exists
- sname - symbol name
- skind - symbol kind
- skinds - symbol kinds to check for
- stype - symbol type
+ """
+ Inserts a new identifier at the end of the symbol table, if possible.
+ Returns symbol index, or raises an exception if the symbol already exists
+ sname - symbol name
+ skind - symbol kind
+ skinds - symbol kinds to check for
+ stype - symbol type
"""
index = self.lookup_symbol(sname, skinds)
if index == None:
@@ -526,8 +532,9 @@ class SymbolTable: return index
def insert_constant(self, cname, ctype):
- """Inserts a constant (or returns index if the constant already exists)
- Additionally, checks for range.
+ """
+ Inserts a constant (or returns index if the constant already exists)
+ Additionally, checks for range.
"""
index = self.lookup_symbol(cname, stype=ctype)
if index == None:
@@ -558,10 +565,11 @@ class SymbolTable: return same
def same_type_as_argument(self, index, function_index, argument_number):
- """Returns True if index and function's argument are of the same type
- index - index in symbol table
- function_index - function's index in symbol table
- argument_number - # of function's argument
+ """
+ Returns True if index and function's argument are of the same type
+ index - index in symbol table
+ function_index - function's index in symbol table
+ argument_number - # of function's argument
"""
try:
same = (
@@ -680,8 +688,9 @@ class CodeGenerator: self.symtab = symtab
def error(self, text):
- """Compiler error exception. It should happen only if something is wrong with compiler.
- This exception is not handled by the compiler, so as to allow traceback printing
+ """
+ Compiler error exception. It should happen only if something is wrong with compiler.
+ This exception is not handled by the compiler, so as to allow traceback printing
"""
raise Exception("Compiler error: %s" % text)
@@ -720,10 +729,11 @@ class CodeGenerator: self.free_register(index)
def label(self, name, internal=False, definition=False):
- """Generates label name (helper function)
- name - label name
- internal - boolean value, adds "@" prefix to label
- definition - boolean value, adds ":" suffix to label
+ """
+ Generates label name (helper function)
+ name - label name
+ internal - boolean value, adds "@" prefix to label
+ definition - boolean value, adds ":" suffix to label
"""
return "{}{}{}".format(
self.internal if internal else "",
@@ -789,15 +799,18 @@ class CodeGenerator: self.text("\t\t\t")
def newline_text(self, text, indent=False):
- """Inserts a newline and text, optionally with indentation (helper function)"""
+ """
+ Inserts a newline and text, optionally with indentation (helper function)
+ """
self.newline(indent)
self.text(text)
def newline_label(self, name, internal=False, definition=False):
- """Inserts a newline and a label (helper function)
- name - label name
- internal - boolean value, adds "@" prefix to label
- definition - boolean value, adds ":" suffix to label
+ """
+ Inserts a newline and a label (helper function)
+ name - label name
+ internal - boolean value, adds "@" prefix to label
+ definition - boolean value, adds ":" suffix to label
"""
self.newline_text(
self.label(
@@ -813,14 +826,17 @@ class CodeGenerator: self.newline_text("WORD\t1", True)
def arithmetic_mnemonic(self, op_name, op_type):
- """Generates an arithmetic instruction mnemonic"""
+ """
+ Generates an arithmetic instruction mnemonic
+ """
return self.OPERATIONS[op_name] + self.OPSIGNS[op_type]
def arithmetic(self, operation, operand1, operand2, operand3=None):
- """Generates an arithmetic instruction
- operation - one of supporetd operations
- operandX - index in symbol table or text representation of operand
- First two operands are input, third one is output
+ """
+ Generates an arithmetic instruction
+ operation - one of supporetd operations
+ operandX - index in symbol table or text representation of operand
+ First two operands are input, third one is output
"""
if isinstance(operand1, int):
output_type = self.symtab.get_type(operand1)
@@ -851,9 +867,10 @@ class CodeGenerator: return output
def relop_code(self, relop, operands_type):
- """Returns code for relational operator
- relop - relational operator
- operands_type - int or unsigned
+ """
+ Returns code for relational operator
+ relop - relational operator
+ operands_type - int or unsigned
"""
code = self.RELATIONAL_DICT[relop]
offset = (
@@ -864,10 +881,11 @@ class CodeGenerator: return code + offset
def jump(self, relcode, opposite, label):
- """Generates a jump instruction
- relcode - relational operator code
- opposite - generate normal or opposite jump
- label - jump label
+ """
+ Generates a jump instruction
+ relcode - relational operator code
+ opposite - generate normal or opposite jump
+ label - jump label
"""
jump = (
self.OPPOSITE_JUMPS[relcode]
@@ -877,15 +895,17 @@ class CodeGenerator: self.newline_text("{}\t{}".format(jump, label), True)
def unconditional_jump(self, label):
- """Generates an unconditional jump instruction
- label - jump label
+ """
+ Generates an unconditional jump instruction
+ label - jump label
"""
self.newline_text("JMP \t{}".format(label), True)
def move(self, operand1, operand2):
- """Generates a move instruction
- If the output operand (opernad2) is a working register, sets it's type
- operandX - index in symbol table or text representation of operand
+ """
+ Generates a move instruction
+ If the output operand (opernad2) is a working register, sets it's type
+ operandX - index in symbol table or text representation of operand
"""
if isinstance(operand1, int):
output_type = self.symtab.get_type(operand1)
@@ -908,8 +928,9 @@ class CodeGenerator: self.newline_text("POP \t%s" % self.symbol(operand), True)
def compare(self, operand1, operand2):
- """Generates a compare instruction
- operandX - index in symbol table
+ """
+ Generates a compare instruction
+ operandX - index in symbol table
"""
typ = self.symtab.get_type(operand1)
self.free_if_register(operand1)
@@ -944,9 +965,10 @@ class CodeGenerator: self.newline_text("RET", True)
def function_call(self, function, arguments):
- """Generates code for a function call
- function - function index in symbol table
- arguments - list of arguments (indexes in symbol table)
+ """
+ Generates code for a function call
+ function - function index in symbol table
+ arguments - list of arguments (indexes in symbol table)
"""
# push each argument to stack
for arg in arguments:
diff --git a/examples/rosettacode.py b/examples/rosettacode.py index 5cbf203..fd3a0e0 100644 --- a/examples/rosettacode.py +++ b/examples/rosettacode.py @@ -53,13 +53,41 @@ char = pp.Regex(r"'\\?.'") expr = pp.infixNotation( identifier | integer | char, [ - (pp.oneOf("+ - !"), 1, pp.opAssoc.RIGHT,), - (pp.oneOf("* / %"), 2, pp.opAssoc.LEFT,), - (pp.oneOf("+ -"), 2, pp.opAssoc.LEFT,), - (pp.oneOf("< <= > >="), 2, pp.opAssoc.LEFT,), - (pp.oneOf("== !="), 2, pp.opAssoc.LEFT,), - (pp.oneOf("&&"), 2, pp.opAssoc.LEFT,), - (pp.oneOf("||"), 2, pp.opAssoc.LEFT,), + ( + pp.oneOf("+ - !"), + 1, + pp.opAssoc.RIGHT, + ), + ( + pp.oneOf("* / %"), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("+ -"), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("< <= > >="), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("== !="), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("&&"), + 2, + pp.opAssoc.LEFT, + ), + ( + pp.oneOf("||"), + 2, + pp.opAssoc.LEFT, + ), ], ) diff --git a/examples/simpleSQL.py b/examples/simpleSQL.py index ebed658..5c93191 100644 --- a/examples/simpleSQL.py +++ b/examples/simpleSQL.py @@ -56,7 +56,11 @@ whereCondition = Group( whereExpression = infixNotation( whereCondition, - [(NOT, 1, opAssoc.RIGHT), (AND, 2, opAssoc.LEFT), (OR, 2, opAssoc.LEFT),], + [ + (NOT, 1, opAssoc.RIGHT), + (AND, 2, opAssoc.LEFT), + (OR, 2, opAssoc.LEFT), + ], ) # define the grammar diff --git a/examples/sparser.py b/examples/sparser.py index 49617ff..ca4abf1 100644 --- a/examples/sparser.py +++ b/examples/sparser.py @@ -140,9 +140,11 @@ class ParseFileLineByLine: """
def __init__(self, filename, mode="r"):
- """Opens input file, and if available the definition file. If the
+ """
+ Opens input file, and if available the definition file. If the
definition file is available __init__ will then create some pyparsing
- helper variables. """
+ helper variables.
+ """
if mode not in ["r", "w", "a"]:
raise OSError(0, "Illegal mode: " + repr(mode))
diff --git a/examples/statemachine/statemachine.py b/examples/statemachine/statemachine.py index befa68e..761a181 100644 --- a/examples/statemachine/statemachine.py +++ b/examples/statemachine/statemachine.py @@ -277,7 +277,7 @@ class SuffixImporter: Define a subclass that specifies a :attr:`suffix` attribute, and implements a :meth:`process_filedata` method. Then call the classmethod :meth:`register` on your class to actually install it in the appropriate - places in :mod:`sys`. """ + places in :mod:`sys`.""" scheme = "suffix" suffix = None diff --git a/pyparsing/__init__.py b/pyparsing/__init__.py index e0f1a66..41a12db 100644 --- a/pyparsing/__init__.py +++ b/pyparsing/__init__.py @@ -1,6 +1,6 @@ # module pyparsing.py # -# Copyright (c) 2003-2020 Paul T. McGuire +# Copyright (c) 2003-2021 Paul T. McGuire # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -103,7 +103,7 @@ __version__ = ( __version_info__.releaseLevel == "final" ] ) -__versionTime__ = "24 December 2020 05:11 UTC" +__versionTime__ = "1 August 2021 17:56 UTC" __author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" from .util import * diff --git a/pyparsing/actions.py b/pyparsing/actions.py index 827c74f..7d1ecdc 100644 --- a/pyparsing/actions.py +++ b/pyparsing/actions.py @@ -5,11 +5,13 @@ from .util import col class OnlyOnce: - """Wrapper for parse actions, to ensure they are only called once. + """ + Wrapper for parse actions, to ensure they are only called once. """ def __init__(self, methodCall): from .core import _trim_arity + self.callable = _trim_arity(methodCall) self.called = False @@ -21,14 +23,16 @@ class OnlyOnce: raise ParseException(s, l, "OnlyOnce obj called multiple times w/out reset") def reset(self): - """Allow the associated parse action to be called once more. + """ + Allow the associated parse action to be called once more. """ self.called = False def matchOnlyAtCol(n): - """Helper method for defining parse actions that require matching at + """ + Helper method for defining parse actions that require matching at a specific column in the input text. """ @@ -40,7 +44,8 @@ def matchOnlyAtCol(n): def replaceWith(replStr): - """Helper method for common parse actions that simply return + """ + Helper method for common parse actions that simply return a literal value. Especially useful when used with :class:`transformString<ParserElement.transformString>` (). @@ -56,7 +61,8 @@ def replaceWith(replStr): def removeQuotes(s, l, t): - """Helper parse action for removing quotation marks from parsed + """ + Helper parse action for removing quotation marks from parsed quoted strings. Example:: @@ -72,7 +78,8 @@ def removeQuotes(s, l, t): def withAttribute(*args, **attrDict): - """Helper to create a validating parse action to be used with start + """ + Helper to create a validating parse action to be used with start tags created with :class:`makeXMLTags` or :class:`makeHTMLTags`. Use ``withAttribute`` to qualify a starting tag with a required attribute value, to avoid false @@ -153,7 +160,8 @@ withAttribute.ANY_VALUE = object() def withClass(classname, namespace=""): - """Simplified version of :class:`withAttribute` when + """ + Simplified version of :class:`withAttribute` when matching on a div class - made difficult because ``class`` is a reserved word in Python. diff --git a/pyparsing/core.py b/pyparsing/core.py index a3a6c96..1c76f95 100644 --- a/pyparsing/core.py +++ b/pyparsing/core.py @@ -434,9 +434,10 @@ class ParserElement(ABC): return newself def setBreak(self, breakFlag=True): - """Method to invoke the Python pdb debugger when this element is - about to be parsed. Set ``breakFlag`` to ``True`` to enable, ``False`` to - disable. + """ + Method to invoke the Python pdb debugger when this element is + about to be parsed. Set ``breakFlag`` to ``True`` to enable, ``False`` to + disable. """ if breakFlag: _parseMethod = self._parse @@ -549,17 +550,18 @@ class ParserElement(ABC): return self def setFailAction(self, fn): - """Define action to perform if parsing fails at this expression. - Fail acton fn is a callable function that takes the arguments - ``fn(s, loc, expr, err)`` where: + """ + Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + ``fn(s, loc, expr, err)`` where: - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown - The function returns no value. It may throw :class:`ParseFatalException` - if it is desired to stop parsing immediately.""" + The function returns no value. It may throw :class:`ParseFatalException` + if it is desired to stop parsing immediately.""" self.failAction = fn return self @@ -708,7 +710,9 @@ class ParserElement(ABC): # cache for left-recursion in Forward references recursion_lock = RLock() - recursion_memos = {} # type: dict[tuple[int, Forward, bool], tuple[int, ParseResults | Exception]] + recursion_memos = ( + {} + ) # type: dict[tuple[int, Forward, bool], tuple[int, ParseResults | Exception]] # argument cache for optimizing repeated calls when backtracking through recursive expressions packrat_cache = ( @@ -843,34 +847,35 @@ class ParserElement(ABC): @staticmethod def enablePackrat(cache_size_limit=128, *, force=False): - """Enables "packrat" parsing, which adds memoizing to the parsing logic. - Repeated parse attempts at the same string location (which happens - often in many complex grammars) can immediately return a cached value, - instead of re-executing parsing/validating code. Memoizing is done of - both valid results and parsing exceptions. - - Parameters: - - - cache_size_limit - (default= ``128``) - if an integer value is provided - will limit the size of the packrat cache; if None is passed, then - the cache size will be unbounded; if 0 is passed, the cache will - be effectively disabled. - - This speedup may break existing programs that use parse actions that - have side-effects. For this reason, packrat parsing is disabled when - you first import pyparsing. To activate the packrat feature, your - program must call the class method :class:`ParserElement.enablePackrat`. - For best results, call ``enablePackrat()`` immediately after - importing pyparsing. - - Example:: - - import pyparsing - pyparsing.ParserElement.enablePackrat() - - Packrat parsing works similar but not identical to Bounded Recursion parsing, - thus the two cannot be used together. Use ``force=True`` to disable any - previous, conflicting settings. + """ + Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + + - cache_size_limit - (default= ``128``) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method :class:`ParserElement.enablePackrat`. + For best results, call ``enablePackrat()`` immediately after + importing pyparsing. + + Example:: + + import pyparsing + pyparsing.ParserElement.enablePackrat() + + Packrat parsing works similar but not identical to Bounded Recursion parsing, + thus the two cannot be used together. Use ``force=True`` to disable any + previous, conflicting settings. """ if force: ParserElement.disable_memoization() @@ -1414,7 +1419,7 @@ class ParserElement(ABC): Note that ``expr[..., n]`` and ``expr[m, n]``do not raise an exception if more than ``n`` ``expr``s exist in the input stream. If this behavior is desired, then write ``expr[..., n] + ~expr``. - """ + """ # convert single arg keys to tuples try: @@ -1875,7 +1880,16 @@ class ParserElement(ABC): def create_diagram(expr: "ParserElement", output_html, vertical=3, **kwargs): """ + Create a railroad diagram for the parser. + + Parameters: + - output_html (str or file-like object) - output target for generated + diagram HTML + - vertical (int) - threshold for formatting multiple alternatives vertically + instead of horizontally (default=3) + Additional diagram-formatting keyword arguments can also be included; + see railroad.Diagram class. """ try: @@ -1948,7 +1962,8 @@ class Token(ParserElement): class Empty(Token): - """An empty token, will always match. + """ + An empty token, will always match. """ def __init__(self): @@ -1958,7 +1973,8 @@ class Empty(Token): class NoMatch(Token): - """A token that will never match. + """ + A token that will never match. """ def __init__(self): @@ -1972,7 +1988,8 @@ class NoMatch(Token): class Literal(Token): - """Token to exactly match a specified string. + """ + Token to exactly match a specified string. Example:: @@ -2025,7 +2042,8 @@ ParserElement._literalStringClass = Literal class Keyword(Token): - """Token to exactly match a specified string as a keyword, that is, + """ + Token to exactly match a specified string as a keyword, that is, it must be immediately followed by a non-keyword character. Compare with :class:`Literal`: @@ -2123,13 +2141,15 @@ class Keyword(Token): @staticmethod def setDefaultKeywordChars(chars): - """Overrides the default characters used by :class:`Keyword` expressions. + """ + Overrides the default characters used by :class:`Keyword` expressions. """ Keyword.DEFAULT_KEYWORD_CHARS = chars class CaselessLiteral(Literal): - """Token to match a specified string, ignoring case of letters. + """ + Token to match a specified string, ignoring case of letters. Note: the matched results will always be in the case of the given match string, NOT the case of the input text. @@ -3036,7 +3056,8 @@ class StringStart(_PositionToken): class StringEnd(_PositionToken): - """Matches if current position is at the end of the parse string + """ + Matches if current position is at the end of the parse string """ def __init__(self): @@ -4010,20 +4031,20 @@ class Located(ParseElementEnhance): [18, ['lkkjj'], 23] """ + def parseImpl(self, instring, loc, doActions=True): start = loc - loc, tokens = self.expr._parse( - instring, start, doActions, callPreParse=False - ) + loc, tokens = self.expr._parse(instring, start, doActions, callPreParse=False) ret_tokens = ParseResults([start, tokens, loc]) - ret_tokens['locn_start'] = start - ret_tokens['value'] = tokens - ret_tokens['locn_end'] = loc + ret_tokens["locn_start"] = start + ret_tokens["value"] = tokens + ret_tokens["locn_end"] = loc return loc, ret_tokens class NotAny(ParseElementEnhance): - """Lookahead to disallow matching with the given parse expression. + """ + Lookahead to disallow matching with the given parse expression. ``NotAny`` does *not* advance the parsing position within the input string, it only verifies that the specified parse expression does *not* match at the current position. Also, ``NotAny`` does @@ -4127,7 +4148,8 @@ class _MultipleMatch(ParseElementEnhance): class OneOrMore(_MultipleMatch): - """Repetition of one or more of the given expression. + """ + Repetition of one or more of the given expression. Parameters: - expr - expression that must match one or more times @@ -4157,7 +4179,8 @@ class OneOrMore(_MultipleMatch): class ZeroOrMore(_MultipleMatch): - """Optional repetition of zero or more of the given expression. + """ + Optional repetition of zero or more of the given expression. Parameters: - ``expr`` - expression that must match zero or more times @@ -4191,7 +4214,8 @@ class _NullToken: class Optional(ParseElementEnhance): - """Optional matching of the given expression. + """ + Optional matching of the given expression. Parameters: - ``expr`` - expression that must match zero or more times @@ -4255,7 +4279,8 @@ class Optional(ParseElementEnhance): class SkipTo(ParseElementEnhance): - """Token for skipping over all undefined text until the matched + """ + Token for skipping over all undefined text until the matched expression is found. Parameters: @@ -4380,7 +4405,8 @@ class SkipTo(ParseElementEnhance): class Forward(ParseElementEnhance): - """Forward declaration of an expression to be defined later - + """ + Forward declaration of an expression to be defined later - used for recursive grammars, such as algebraic infix notation. When the expression is known, it is assigned to the ``Forward`` variable using the ``'<<'`` operator. diff --git a/pyparsing/exceptions.py b/pyparsing/exceptions.py index 3a92fdf..6cd5c5e 100644 --- a/pyparsing/exceptions.py +++ b/pyparsing/exceptions.py @@ -95,10 +95,11 @@ class ParseBaseException(Exception): return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) def __getattr__(self, aname): - """supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text + """ + Supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text """ if aname == "lineno": return lineno(self.loc, self.pstr) @@ -127,8 +128,9 @@ class ParseBaseException(Exception): return str(self) def markInputline(self, markerString=">!<"): - """Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. + """ + Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. """ line_str = self.line line_column = self.column - 1 @@ -206,12 +208,15 @@ class ParseException(ParseBaseException): class ParseFatalException(ParseBaseException): - """user-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately""" + """ + user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately + """ class ParseSyntaxException(ParseFatalException): - """just like :class:`ParseFatalException`, but thrown internally + """ + just like :class:`ParseFatalException`, but thrown internally when an :class:`ErrorStop<And._ErrorStop>` ('-' operator) indicates that parsing is to stop immediately because an unbacktrackable syntax error has been found. diff --git a/pyparsing/results.py b/pyparsing/results.py index fa94a00..481f662 100644 --- a/pyparsing/results.py +++ b/pyparsing/results.py @@ -69,6 +69,7 @@ class ParseResults: - month: 12 - year: 1999 """ + _null_values = (None, "", [], ()) __slots__ = [ @@ -83,42 +84,42 @@ class ParseResults: class List(list): """ - Simple wrapper class to distinguish parsed list results that should be preserved - as actual Python lists, instead of being converted to :class:`ParseResults`: + Simple wrapper class to distinguish parsed list results that should be preserved + as actual Python lists, instead of being converted to :class:`ParseResults`: - LBRACK, RBRACK = map(pp.Suppress, "[]") - element = pp.Forward() - item = ppc.integer - element_list = LBRACK + pp.delimitedList(element) + RBRACK + LBRACK, RBRACK = map(pp.Suppress, "[]") + element = pp.Forward() + item = ppc.integer + element_list = LBRACK + pp.delimitedList(element) + RBRACK - # add parse actions to convert from ParseResults to actual Python collection types - def as_python_list(t): - return pp.ParseResults.List(t.asList()) - element_list.addParseAction(as_python_list) + # add parse actions to convert from ParseResults to actual Python collection types + def as_python_list(t): + return pp.ParseResults.List(t.asList()) + element_list.addParseAction(as_python_list) - element <<= item | element_list + element <<= item | element_list - element.runTests(''' - 100 - [2,3,4] - [[2, 1],3,4] - [(2, 1),3,4] - (2,3,4) - ''', postParse=lambda s, r: (r[0], type(r[0]))) + element.runTests(''' + 100 + [2,3,4] + [[2, 1],3,4] + [(2, 1),3,4] + (2,3,4) + ''', postParse=lambda s, r: (r[0], type(r[0]))) - prints: + prints: - 100 - (100, <class 'int'>) + 100 + (100, <class 'int'>) - [2,3,4] - ([2, 3, 4], <class 'list'>) + [2,3,4] + ([2, 3, 4], <class 'list'>) - [[2, 1],3,4] - ([[2, 1], 3, 4], <class 'list'>) + [[2, 1],3,4] + ([[2, 1], 3, 4], <class 'list'>) - (Used internally by :class:`Group` when `aslist=True`.) - """ + (Used internally by :class:`Group` when `aslist=True`.) + """ def __new__(cls, contained=None): if contained is None: @@ -143,7 +144,11 @@ class ParseResults: if toklist is None: self._toklist = [] elif isinstance(toklist, (list, _generator_type)): - self._toklist = [toklist[:]] if isinstance(toklist, ParseResults.List) else list(toklist) + self._toklist = ( + [toklist[:]] + if isinstance(toklist, ParseResults.List) + else list(toklist) + ) else: self._toklist = [toklist] self._tokdict = dict() @@ -252,8 +257,9 @@ class ParseResults: return ((k, self[k]) for k in self.keys()) def haskeys(self): - """Since ``keys()`` returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" + """ + Since ``keys()`` returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" return bool(self._tokdict) def pop(self, *args, **kwargs): diff --git a/pyparsing/testing.py b/pyparsing/testing.py index 43f23ab..f06dffc 100644 --- a/pyparsing/testing.py +++ b/pyparsing/testing.py @@ -62,7 +62,9 @@ class pyparsing_test: else: self._save_context["packrat_cache_size"] = None self._save_context["packrat_parse"] = ParserElement._parse - self._save_context["recursion_enabled"] = ParserElement._left_recursion_enabled + self._save_context[ + "recursion_enabled" + ] = ParserElement._left_recursion_enabled self._save_context["__diag__"] = { name: getattr(__diag__, name) for name in __diag__._all_names @@ -99,7 +101,9 @@ class pyparsing_test: ParserElement.enablePackrat(self._save_context["packrat_cache_size"]) else: ParserElement._parse = self._save_context["packrat_parse"] - ParserElement._left_recursion_enabled = self._save_context["recursion_enabled"] + ParserElement._left_recursion_enabled = self._save_context[ + "recursion_enabled" + ] __compat__.collect_all_And_tokens = self._save_context["__compat__"] diff --git a/pyparsing/util.py b/pyparsing/util.py index 875799d..cad3e09 100644 --- a/pyparsing/util.py +++ b/pyparsing/util.py @@ -38,16 +38,17 @@ class __config_flags: @lru_cache(maxsize=128) def col(loc, strg): - """Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See - :class:`ParserElement.parseString` for more - information on parsing strings containing ``<TAB>`` s, and suggested - methods to maintain a consistent view of the parsed string, the parse - location, and line and column positions within the parsed string. - """ + """ + Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See + :class:`ParserElement.parseString` for more + information on parsing strings containing ``<TAB>`` s, and suggested + methods to maintain a consistent view of the parsed string, the parse + location, and line and column positions within the parsed string. + """ s = strg return 1 if 0 < loc < len(s) and s[loc - 1] == "\n" else loc - s.rfind("\n", 0, loc) @@ -68,8 +69,9 @@ def lineno(loc, strg): @lru_cache(maxsize=128) def line(loc, strg): - """Returns the line of text containing loc within a string, counting newlines as line separators. - """ + """ + Returns the line of text containing loc within a string, counting newlines as line separators. + """ lastCR = strg.rfind("\n", 0, loc) nextCR = strg.find("\n", loc) return strg[lastCR + 1 : nextCR] if nextCR >= 0 else strg[lastCR + 1 :] @@ -126,6 +128,7 @@ class LRUMemo: The memo tracks retained items by their access order; once `capacity` items are retained, the least recently used item is discarded. """ + def __init__(self, capacity): self._capacity = capacity self._active = {} @@ -161,6 +164,7 @@ class UnboundedMemo(dict): """ A memoizing mapping that retains all deleted items """ + def __delitem__(self, key): pass |