Skip to content

Commit

Permalink
Added pyleri and textx to benchmark.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Jul 29, 2018
1 parent e643121 commit 9018e06
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 15 deletions.
34 changes: 25 additions & 9 deletions examples/benchmarks/json/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
Parsing 'examples/benchmarks/json/data.json' 1 time(s) took:
PACKAGE SECONDS
textparser 0.100049
lark (LALR) 0.251040
funcparserlib 0.339087
parsimonious 0.380170
pyparsing 0.677518
parsy 0.938273
lark (Earley) 1.877682
parsita 2.326168
textparser 0.103197
lark (LALR) 0.265257
funcparserlib 0.354334
parsimonious 0.396413
textx 0.522437
pyparsing 0.663877
pyleri 0.809443
parsy 0.948944
lark (Earley) 1.855001
parsita 2.327958
$
"""
Expand All @@ -33,6 +35,7 @@
from parsers import pyparsing_json
from parsers import funcparserlib_json
from parsers import parsimonious_json
from parsers import textx_json

try:
from parsers import parsita_json
Expand All @@ -52,6 +55,15 @@ class parsy_json(object):
def parse_time(_json_string, _iterations):
return float('inf')

try:
from parsers import pyleri_json
except:
class pyleri_json(object):

@staticmethod
def parse_time(_json_string, _iterations):
return float('inf')


SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
DATA_JSON = os.path.relpath(os.path.join(SCRIPT_DIR, 'data.json'))
Expand All @@ -75,6 +87,8 @@ def parse_time(_json_string, _iterations):
funcparserlib_time = funcparserlib_json.parse_time(JSON_STRING, ITERATIONS)
parsy_time = parsy_json.parse_time(JSON_STRING, ITERATIONS)
parsimonious_time = parsimonious_json.parse_time(JSON_STRING, ITERATIONS)
pyleri_time = pyleri_json.parse_time(JSON_STRING, ITERATIONS)
textx_time = textx_json.parse_time(JSON_STRING, ITERATIONS)

# Parse comparison output.
measurements = [
Expand All @@ -85,7 +99,9 @@ def parse_time(_json_string, _iterations):
('parsita', parsita_time),
('funcparserlib', funcparserlib_time),
('parsy', parsy_time),
('parsimonious', parsimonious_time)
('parsimonious', parsimonious_time),
('pyleri', pyleri_time),
('textx', textx_time)
]

measurements = sorted(measurements, key=lambda m: m[1])
Expand Down
34 changes: 31 additions & 3 deletions examples/benchmarks/json/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
parsimonious: "Rule 'json_file' didn't match at '' (line 1, column 1)."
pyleri: "No exception raised!"
textx: "None:1:1: error: Expected '[' or '{' at position (1, 1) => '*'."
-----------------------------------------------------------------
Input string between BEGIN and END:
Expand All @@ -42,7 +46,7 @@
textparser: "Invalid syntax at line 3, column 10: " {"a": {>>!<<]}""
lark_lalr: "Unexpected token Token(RSQB, ']') at line 3, column 10.
Expected: string, RBRACE, ESCAPED_STRING, pair
Expected: ESCAPED_STRING, RBRACE, string, pair
"
lark_earley: "Unexpected token Token(RSQB, ']') at line 3, column 10.
Expand All @@ -61,6 +65,10 @@
]
' (line 3, column 10)."
pyleri: "No exception raised!"
textx: "None:3:10: error: Expected STRING or '}' at position (3, 10) => ' {"a": {*]} ] '."
-----------------------------------------------------------------
Input string between BEGIN and END:
Expand All @@ -75,7 +83,7 @@
textparser: "Invalid syntax at line 3, column 4: " {>>!<<3: null}""
lark_lalr: "Unexpected token Token(SIGNED_NUMBER, '3') at line 3, column 4.
Expected: RBRACE, pair, ESCAPED_STRING, string
Expected: RBRACE, pair, string, ESCAPED_STRING
"
lark_earley: "Unexpected token Token(SIGNED_NUMBER, '3') at line 3, column 4.
Expand All @@ -94,6 +102,10 @@
]
' (line 3, column 4)."
pyleri: "No exception raised!"
textx: "None:3:4: error: Expected STRING or '}' at position (3, 4) => '[ 1, {*3: null} ]'."
-----------------------------------------------------------------
Input string between BEGIN and END:
Expand Down Expand Up @@ -126,6 +138,10 @@
parsimonious: "Rule 'json_file' didn't match at 'nul
' (line 1, column 1)."
pyleri: "No exception raised!"
textx: "None:1:1: error: Expected '[' or '{' at position (1, 1) => '*nul '."
$
"""
Expand All @@ -137,6 +153,7 @@
from parsers import pyparsing_json
from parsers import funcparserlib_json
from parsers import parsimonious_json
from parsers import textx_json

try:
from parsers import parsita_json
Expand All @@ -157,6 +174,15 @@ class parsy_json(object):
def parse(_json_string):
raise Exception('Import failed!')

try:
from parsers import pyleri_json
except:
class pyleri_json(object):

@staticmethod
def parse(_json_string):
raise Exception('Import failed!')


def parse(string):
def _parse(function):
Expand All @@ -175,7 +201,9 @@ def _parse(function):
('parsita', _parse(parsita_json.parse)),
('funcparserlib', _parse(funcparserlib_json.parse)),
('parsy', _parse(parsy_json.parse)),
('parsimonious', _parse(parsimonious_json.parse))
('parsimonious', _parse(parsimonious_json.parse)),
('pyleri', _parse(pyleri_json.parse)),
('textx', _parse(textx_json.parse))
]

print('-----------------------------------------------------------------')
Expand Down
24 changes: 21 additions & 3 deletions examples/benchmarks/json/parse_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
[['"foo"', [['"bar"', [1, 2, 3]]]]]
parsita:
Import failed!
Success(['foo', [['bar', ['1', '2', '3']]]])
funcparserlib:
('"foo"', [('"bar"', ('1', ['2', '3']), [])])
parsy:
Import failed!
['foo', [('bar', ['1', '2', '3'])]]
parsimonious:
<Node called "json_file" matching "[
Expand Down Expand Up @@ -265,6 +265,12 @@
">
<RegexNode called "ws" matching "
">
pyleri:
<pyleri.noderesult.NodeResult object at 0x7fb4596a2480>
textx:
<textx:Array instance at 0x7fb4596deeb8>
$
"""
Expand All @@ -276,6 +282,7 @@
from parsers import pyparsing_json
from parsers import funcparserlib_json
from parsers import parsimonious_json
from parsers import textx_json

try:
from parsers import parsita_json
Expand All @@ -296,6 +303,15 @@ class parsy_json(object):
def parse(_json_string):
return 'Import failed!'

try:
from parsers import pyleri_json
except:
class pyleri_json(object):

@staticmethod
def parse(_json_string):
return 'Import failed!'


def parse(string):
results = [
Expand All @@ -306,7 +322,9 @@ def parse(string):
('parsita', parsita_json.parse(string)),
('funcparserlib', funcparserlib_json.parse(string)),
('parsy', parsy_json.parse(string)),
('parsimonious', parsimonious_json.parse(string))
('parsimonious', parsimonious_json.parse(string)),
('pyleri', pyleri_json.parse(string)),
('textx', textx_json.parse(string))
]

print('-----------------------------------------------------------------')
Expand Down
59 changes: 59 additions & 0 deletions examples/benchmarks/json/parsers/pyleri_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Based on
https://github.com/transceptor-technology/pyleri/blob/master/examples/json_grammar.py.
"""

import timeit

from pyleri import Ref
from pyleri import Choice
from pyleri import Grammar
from pyleri import Regex
from pyleri import Keyword
from pyleri import Sequence
from pyleri import List


class JsonGrammar(Grammar):
START = Ref()

# JSON strings should be enclosed in double quotes.
# A backslash can be used as escape character.
r_string = Regex('(")(?:(?=(\\\?))\\2.)*?\\1')

# JSON does not support floats or integers prefixed with a + sign
# and floats must start with a number, for example .5 is not allowed
# but should be written like 0.5
r_float = Regex('-?[0-9]+\.?[0-9]+')
r_integer = Regex('-?[0-9]+')

k_true = Keyword('true')
k_false = Keyword('false')
k_null = Keyword('null')

json_map_item = Sequence(r_string, ':', START)

json_map = Sequence('{', List(json_map_item), '}')
json_array = Sequence('[', List(START), ']')

START = Choice(r_string,
r_float,
r_integer,
k_true,
k_false,
k_null,
json_map,
json_array)


def parse_time(json_string, iterations):
grammar = JsonGrammar()

def _parse():
grammar.parse(json_string)

return timeit.timeit(_parse, number=iterations)


def parse(json_string):
return JsonGrammar().parse(json_string)
50 changes: 50 additions & 0 deletions examples/benchmarks/json/parsers/textx_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Based on
https://github.com/igordejanovic/textX/tree/master/examples/json.
"""

import timeit

from textx import metamodel_from_str


GRAMMAR = '''\
/*
A grammar for JSON data-interchange format.
See: http://www.json.org/
*/
File:
Array | Object
;
Array:
"[" values*=Value[','] "]"
;
Value:
STRING | FLOAT | BOOL | Object | Array | "null"
;
Object:
"{" members*=Member[','] "}"
;
Member:
key=STRING ':' value=Value
;
'''


def parse_time(json_string, iterations):
parser = metamodel_from_str(GRAMMAR)

def _parse():
parser.model_from_str(json_string)

return timeit.timeit(_parse, number=iterations)


def parse(json_string):
parser = metamodel_from_str(GRAMMAR)

return parser.model_from_str(json_string)

0 comments on commit 9018e06

Please sign in to comment.