Mercurial > lbo > hg > pcombinators
changeset 26:25aab2c2a695 draft
Improve performance by removing function calls from the hot path.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Tue, 21 May 2019 01:26:22 +0200 |
parents | 9831b7c577a3 |
children | 6e9cf2fb5f49 |
files | pcombinators/json_test.py |
diffstat | 1 files changed, 32 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/pcombinators/json_test.py Tue May 21 01:18:21 2019 +0200 +++ b/pcombinators/json_test.py Tue May 21 01:26:22 2019 +0200 @@ -9,37 +9,39 @@ from combinators import * from primitives import * -def JString(): - return Last(Skip(String('"')) + NoneInSet('"') + Skip(String('"'))) +JString = Last(Skip(String('"')) + NoneInSet('"') + Skip(String('"'))) + +wrapl = lambda l: [l] + +# We moved out all the piece parsers out of functions to reduce allocation overhead. +# It improves performance by roughly 2x. + +# LISTS -def List(): - wrapl = lambda l: [l] - # An entry is any value. - entry = Value() - # A mid entry is a value followed by a comma. - midentry = entry + Skip(String(',')) - # A list is a [, followed by mid entries, followed by a final entry, and a - # closing ]. The list is wrapped in a list to prevent merging in other parsers. - return ( - Skip(String('[')) + - Repeat(midentry, -1) + - entry + - Skip(String(']'))) >> wrapl # Wrap list inside another list to protect it from flattening. +# An entry is any value. +entry = Value() +# A mid entry is a value followed by a comma. +midentry = entry + Skip(String(',')) +# A list is a [, followed by mid entries, followed by a final entry, and a +# closing ]. The list is wrapped in a list to prevent merging in other parsers. +List = (Skip(String('[')) + + Repeat(midentry, -1) + + entry + + Skip(String(']'))) >> wrapl # Wrap list inside another list to protect it from flattening. -def Dict(): - wrapl = lambda l: [l] - # A separator is whitespace, a colon, and more whitespace (Whitespace() also accepts empty string) - separator = Skip((Whitespace() + String(":") + Whitespace())) - # Entry is a String followed by a separator and a value. Wrap the value in a list to prevent merging. - # The two-element list is converted to a tuple. - entry = (JString() + separator + (Value() >> wrapl)) >> (lambda l: tuple(l)) - # A mid entry is followed by a comma. - midentry = entry + Skip(String(',') + Whitespace()) - # A dict is a {, followed by entries, followed by a final entry, followed by a closing } - dct = Skip(String("{")) + Repeat(midentry, -1) + entry + Skip(String("}")) - # Convert the list of tuples into a dict. - fulldict = dct >> dict - return fulldict +# DICTS + +# A separator is whitespace, a colon, and more whitespace (Whitespace() also accepts empty string) +separator = Skip((Whitespace() + String(":") + Whitespace())) +# Entry is a String followed by a separator and a value. Wrap the value in a list to prevent merging. +# The two-element list is converted to a tuple. +entry = (JString + separator + (Value() >> wrapl)) >> (lambda l: tuple(l)) +# A mid entry is followed by a comma. +midentry = entry + Skip(String(',') + Whitespace()) +# A dict is a {, followed by entries, followed by a final entry, followed by a closing } +dct = Skip(String("{")) + Repeat(midentry, -1) + entry + Skip(String("}")) +# Convert the list of tuples into a dict. +Dict = dct >> dict class Value(Parser): """Bare-bones, but fully functioning, JSON parser. Doesn't like escaped quotes. @@ -54,4 +56,4 @@ ParseState({"id":1,"name":"Foo","price":123,"tags":["Bar","Eek"],"stock":{"warehouse":300, "retail":20}}<>)) """ def parse(self, st): - return Last(Skip(Whitespace()) + (Dict() | List() | JString() | Float()) + Skip(Whitespace())).parse(st) \ No newline at end of file + return Last(Skip(Whitespace()) + (Dict | List | JString | Float()) + Skip(Whitespace())).parse(st) \ No newline at end of file