Skip to content

Commit b9fec8d

Browse files
author
Allen Short
committed
example trace visualizer
1 parent 937bd39 commit b9fec8d

File tree

5 files changed

+326
-4
lines changed

5 files changed

+326
-4
lines changed

examples/337141-steamcube.json

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
[
2+
{
3+
"pk": 337141,
4+
"model": "addons.addon",
5+
"fields": {
6+
"dev_agreement": false,
7+
"eula": null,
8+
"last_updated": "2011-10-18 16:28:24",
9+
"view_source": true,
10+
"enable_thankyou": false,
11+
"total_downloads": 0,
12+
"premium_type": 0,
13+
"app_slug": "something-something",
14+
"developer_comments": null,
15+
"_current_version": 1268829,
16+
"average_daily_downloads": 0,
17+
"_backup_version": null,
18+
"manifest_url": "http://micropipes.com/temp/steamcube.webapp",
19+
"app_domain": "micropipes.com",
20+
"admin_review_type": 1,
21+
"the_future": null,
22+
"trusted": false,
23+
"total_contributions": null,
24+
"locale_disambiguation": null,
25+
"guid": "214b364a-b419-4b26-8d50-6873bfd9e431",
26+
"weekly_downloads": 9999,
27+
"support_url": null,
28+
"disabled_by_user": false,
29+
"paypal_id": "",
30+
"average_rating": 0.0,
31+
"wants_contributions": false,
32+
"average_daily_users": 0,
33+
"bayesian_rating": 0.0,
34+
"share_count": 0,
35+
"ts_slowness": null,
36+
"homepage": null,
37+
"support_email": null,
38+
"public_stats": false,
39+
"status": 4,
40+
"privacy_policy": 2326784,
41+
"description": null,
42+
"default_locale": "en-US",
43+
"target_locale": null,
44+
"suggested_amount": null,
45+
"get_satisfaction_product": null,
46+
"prerelease": false,
47+
"thankyou_note": null,
48+
"admin_review": false,
49+
"auto_repackage": true,
50+
"slug": "app-337141",
51+
"external_software": false,
52+
"highest_status": 4,
53+
"get_satisfaction_company": null,
54+
"name": 2425897,
55+
"created": "2011-10-18 16:28:24",
56+
"type": 11,
57+
"icon_type": "image/png",
58+
"annoying": 0,
59+
"modified": "2011-10-18 16:29:46",
60+
"summary": 2425898,
61+
"nomination_message": null,
62+
"site_specific": false,
63+
"charity": null,
64+
"total_reviews": 0,
65+
"the_reason": null,
66+
"hotness": 0.0,
67+
"latest_version": 1268829
68+
}
69+
},
70+
{
71+
"pk": 1268829,
72+
"model": "versions.version",
73+
"fields": {
74+
"has_info_request": false,
75+
"license": null,
76+
"created": "2011-10-18 16:28:24",
77+
"has_editor_comment": false,
78+
"releasenotes": null,
79+
"approvalnotes": "",
80+
"modified": "2011-10-18 16:28:24",
81+
"version": "1.0",
82+
"version_int": 1000000200100,
83+
"reviewed": null,
84+
"nomination": null,
85+
"addon": 337141
86+
}
87+
},
88+
{
89+
"pk": 1,
90+
"model": "files.platform",
91+
"fields": {
92+
"modified": "2008-04-07 08:16:55",
93+
"created": "2007-03-05 13:09:27"
94+
}
95+
},
96+
{
97+
"pk": 81555,
98+
"model": "files.file",
99+
"fields": {
100+
"status": 4,
101+
"codereview": false,
102+
"hash": "sha256:3808b13ef8341378b9c8305ca648200954ee7dcd8dce09fef55f2673458bc31f",
103+
"created": "2009-10-21 09:58:52",
104+
"modified": "2009-10-21 10:02:38",
105+
"filename": "steamcube.webapp",
106+
"platform": 1,
107+
"version": 1268829,
108+
"size": 388096,
109+
"datestatuschanged": "2009-10-21 09:58:40"
110+
}
111+
},
112+
{
113+
"pk": 2527085,
114+
"model": "translations.translation",
115+
"fields": {
116+
"localized_string_clean": null,
117+
"created": "2011-10-18 16:28:24",
118+
"locale": "en-US",
119+
"modified": "2011-10-18 16:28:57",
120+
"id": 2425897,
121+
"localized_string": "Something Something Steamcube!"
122+
}
123+
},
124+
{
125+
"pk": 2527086,
126+
"model": "translations.translation",
127+
"fields": {
128+
"localized_string_clean": "A simple 2.5D brain teaser block puzzle game. Find out how far can you get before time runs out?",
129+
"created": "2011-10-18 16:28:24",
130+
"locale": "en-US",
131+
"modified": "2011-10-18 16:28:57",
132+
"id": 2425898,
133+
"localized_string": "A simple 2.5D brain teaser block puzzle game. Find out how far can you get before time runs out?"
134+
}
135+
},
136+
{
137+
"pk": 2527087,
138+
"model": "translations.translation",
139+
"fields": {
140+
"localized_string_clean": "",
141+
"created": "2011-10-18 16:28:57",
142+
"locale": "en-US",
143+
"modified": "2011-10-18 16:28:57",
144+
"id": 2425899,
145+
"localized_string": ""
146+
}
147+
},
148+
{
149+
"pk": 2425898,
150+
"model": "translations.translation",
151+
"fields": {
152+
"localized_string_clean": "",
153+
"created": "2011-07-26 14:16:26",
154+
"locale": "en-US",
155+
"modified": "2011-07-26 14:16:26",
156+
"id": 2326782,
157+
"localized_string": null
158+
}
159+
},
160+
{
161+
"pk": 2425900,
162+
"model": "translations.translation",
163+
"fields": {
164+
"localized_string": "We sell your ish \r\nhttp://omg.org/yes",
165+
"created": "2007-04-05 08:08:48",
166+
"locale": "en-US",
167+
"modified": "2009-03-26 07:41:10",
168+
"id": 2326784,
169+
"localized_string_clean": null
170+
}
171+
},
172+
173+
{
174+
"pk": 31337,
175+
"model": "auth.user",
176+
"fields": {
177+
"username": "[email protected]",
178+
"first_name": "Leet",
179+
"last_name": "User",
180+
"is_active": true,
181+
"is_superuser": false,
182+
"is_staff": false,
183+
"last_login": "2010-05-20 13:00:37",
184+
"groups": [],
185+
"user_permissions": [],
186+
"password": "",
187+
"email": "[email protected]",
188+
"date_joined": "2007-03-05 13:09:56"
189+
}
190+
},
191+
{
192+
"pk": 31337,
193+
"model": "users.userprofile",
194+
"fields": {
195+
"display_collections_fav": false,
196+
"display_collections": false,
197+
"averagerating": "3.11",
198+
"confirmationcode": "",
199+
"notifycompat": true,
200+
"picture_type": "",
201+
"occupation": "",
202+
"homepage": "",
203+
"email": "[email protected]",
204+
"location": "",
205+
"bio": null,
206+
"deleted": false,
207+
"emailhidden": true,
208+
"user": 31337,
209+
"password": "sha512$7b5436061f8c0902088c292c057be69fdb17312e2f71607c9c51641f5d876522$08d1d370d89e2ae92755fd03464a7276ca607c431d04a52d659f7a184f3f9918073637d82fc88981c7099c7c46a1137b9fdeb675304eb98801038905a9ee0600",
210+
"username": "31337",
211+
"display_name": "31337 \u0627\u0644\u062a\u0637\u0628",
212+
"resetcode_expires": null,
213+
"resetcode": "",
214+
"created": "2007-03-05 13:09:56",
215+
"notes": null,
216+
"modified": "2010-05-19 16:41:22",
217+
"notifyevents": true
218+
}
219+
},
220+
{
221+
"pk": 2818,
222+
"model": "addons.addonuser",
223+
"fields": {
224+
"position": 0,
225+
"addon": 337141,
226+
"role": 5,
227+
"listed": true,
228+
"user": 31337
229+
}
230+
}
231+
]

examples/parsley_json.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,8 @@
2727
floatPart :sign :ds = <('.' digits exponent?) | exponent>:tail
2828
-> float(sign + ds + tail)
2929
exponent = ('e' | 'E') ('+' | '-')? digits
30+
31+
top = (object | array) ws
3032
"""
33+
3134
JSONParser = makeGrammar(jsonGrammar, {})

examples/trace_json.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from parsley import makeGrammar
2+
from parsley_json import jsonGrammar
3+
4+
5+
def traceparse(jsonData):
6+
trace = []
7+
def traceit(*a):
8+
trace.append(a)
9+
JSONParser = makeGrammar(jsonGrammar, {},
10+
tracefunc=traceit)
11+
return JSONParser(jsonData).top(), trace

examples/trace_visualiser.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from ScrolledText import ScrolledText
2+
import Tkinter as tk
3+
4+
from trace_json import traceparse
5+
from parsley_json import jsonGrammar
6+
7+
jsonData = open('337141-steamcube.json').read()
8+
9+
10+
class Tracer(object):
11+
12+
def __init__(self, grammarWin, inputWin, logWin, trace):
13+
self.grammarWin = grammarWin
14+
self.inputWin = inputWin
15+
self.logWin = logWin
16+
self.trace = trace
17+
self.position = 0
18+
19+
def advance(self):
20+
if self.position < len(self.trace):
21+
self.position += 1
22+
self.display()
23+
24+
def rewind(self):
25+
if self.position > 0:
26+
self.position -= 1
27+
self.display()
28+
29+
def display(self):
30+
def updateHighlight(w, start, end=None):
31+
w.tag_remove("highlight", "1.0", tk.END)
32+
start = "1.0+%sc" % (start,)
33+
if end is not None:
34+
end = "1.0+%sc" % (end,)
35+
w.tag_add("highlight", start, end)
36+
w.tag_configure("highlight", background="yellow")
37+
38+
_, (grammarStart, grammarEnd), inputPos = self.trace[self.position]
39+
updateHighlight(self.grammarWin, grammarStart, grammarEnd)
40+
updateHighlight(self.inputWin, inputPos)
41+
42+
43+
def display(grammar, src, trace):
44+
r = tk.Tk()
45+
f = tk.Frame(master=r)
46+
lt = ScrolledText(master=f)
47+
rt = ScrolledText(master=f)
48+
lt.pack(side="left", expand=True, fill="both")
49+
rt.pack(side="right", expand=True, fill="both")
50+
51+
bot = ScrolledText(master=r, height=5)
52+
tracer = Tracer(lt, rt, bot, trace)
53+
toolbar = tk.Frame(master=r)
54+
tk.Button(toolbar, text="Next", width=5, command=tracer.advance).pack(
55+
side="left")
56+
tk.Button(toolbar, text="Prev", width=5, command=tracer.rewind).pack(
57+
side="left")
58+
f.pack(expand=1, fill="both")
59+
toolbar.pack(fill=tk.X)
60+
bot.pack(fill=tk.X)
61+
62+
lt.insert(tk.END, grammar)
63+
rt.insert(tk.END, src)
64+
tracer.display()
65+
return r
66+
67+
_, trace = traceparse(jsonData)
68+
root = display(jsonGrammar, jsonData, trace)
69+
70+
root.mainloop()

parsley.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,23 @@
77
__version__ = '1.1'
88

99

10-
def wrapGrammar(g):
10+
def wrapGrammar(g, tracefunc=None):
1111
def makeParser(input):
1212
"""
1313
Creates a parser for the given input, with methods for
1414
invoking each rule.
1515
1616
:param input: The string you want to parse.
1717
"""
18-
return _GrammarWrapper(g(input), input)
18+
parser = g(input)
19+
parser._trace = tracefunc
20+
return _GrammarWrapper(parser, input)
1921
makeParser._grammarClass = g
2022
return makeParser
2123

2224

2325
def makeGrammar(source, bindings, name='Grammar', unwrap=False,
24-
extends=wrapGrammar(OMetaBase)):
26+
extends=wrapGrammar(OMetaBase), tracefunc=None):
2527
"""
2628
Create a class from a Parsley grammar.
2729
@@ -33,13 +35,18 @@ def makeGrammar(source, bindings, name='Grammar', unwrap=False,
3335
subclassing. If False, return a wrapper with the
3436
friendly API.
3537
:param extends: The superclass for the generated parser class.
38+
39+
:param tracefunc: A 3-arg function which takes a fragment of
40+
grammar source, the start/end indexes in the grammar of this
41+
fragment, and a position in the input. Invoked for terminals and
42+
rule applications.
3643
"""
3744
g = OMeta.makeGrammar(source, name).createParserClass(
3845
unwrapGrammar(extends), bindings)
3946
if unwrap:
4047
return g
4148
else:
42-
return wrapGrammar(g)
49+
return wrapGrammar(g, tracefunc=tracefunc)
4350

4451

4552
def unwrapGrammar(w):

0 commit comments

Comments
 (0)