PageSourceSearch

https://thoppe.github.io/Presentation_DCDW_Feb_2014_pyparsing/

html thoppe.github.io collected 2026-10-03 10:04:47 UTC 34,356 bytes, 501 lines download raw bytes

1<!doctype html>
2<html lang="en">
3
4  <head>
5    <meta charset="utf-8">
6
7    <title>DCDW: Pyparsing</title>
8    
9    <meta name="description" content="">
10    <meta name="author" content="Travis Hoppe">
11
12    <meta name="apple-mobile-web-app-capable" content="yes" />
13    <meta name="apple-mobile-web-app-status-bar-style" 
14	  content="black-translucent" />
15
16    <meta name="viewport" content="width=device-width, 
17				   initial-scale=1.0, 
18				   maximum-scale=1.0, 
19				   user-scalable=no">
20
21    <link rel="stylesheet" href="reveal.js/css/reveal.css">
22    <link rel="stylesheet" href="reveal.js/css/theme/simple.css" id="theme">
23
24    <!-- For syntax highlighting -->
25    <link rel="stylesheet" href="reveal.js/lib/css/zenburn.css">
26
27    <!-- For LaTeX formating highlighting -->
28    <link rel="stylesheet" href="md2reveal/css/latex_style.css">
29
30    <!--[if lt IE 9]>
31	
31<script src="reveal.js/lib/js/html5shiv.js"></script>
31
32	<![endif]-->
33  </head>
34
35  <body>
36
37    <div class="reveal"><div class="slides">
38	<section class="vertical-stack">
39<section class="vertical-slide"  data-background-transition="none">
40<link rel="stylesheet" href="reveal.js/css/theme/beige.css" id="theme">
41<br>
42<p>
43<h1>PYPARSING</h1><h3><em>helping data get its sexy back</em></h3></p>
44<br>
45<p>
46<strong><a href="http://thoppe.github.io/">Travis Hoppe</a></strong><br><em><a href="http://www.meetup.com/Data-Wranglers-DC/">DC Data Wranglers</a></em> / <a href="https://github.com/thoppe/DCDW_pres_feb_2014">(deck source)</a></p>
47</section>
48</section><section class="vertical-stack">
49<section class="vertical-slide"  data-background-transition="none">
50<p>
51<h2>What is parsing?</h2></p>
52<br>
53<p>
54<em>syntactic analysis of symbols</em><br><em>according to a formal grammar</em></p>
55<br>
56<br>
57<p>
58Analyzing a log file<br>Extracting data from a webpage<br>Sanitizing input from untrusted sources</p>
59</section><section class="vertical-slide"  data-background-transition="none">
60<p>
61<h2>don't do it!</h2></p>
62<br>
63<p>
64Write the <strong>grammar</strong> not the <strong>parser</strong>!</p>
65<br>
66<p>
67It's easier to construct/maintain<br>a mini-language. Really!</p>
68<br>
69<p>
70Traditional utilities: regex, lex, yacc.</p>
71</section><section class="vertical-slide"  data-background-transition="none">
72<p>
73<h2>Example problems</h2></p>
74<br>
75<p>
76<h3>Easy:</h3>Addresses, phone numbers, quoted strings</p>
77<br>
78<p>
79<h3>Hard:</h3>HTML, recursive descent parsers<br>(mathematical expressions, pdf's, meta-font, LISP)</p>
80</section>
81</section><section class="vertical-stack">
82<section class="vertical-slide"  data-background-transition="none">
83<p>
84<h2>Lifecycle of code</h2></p>
85<br>
86<ul><li>Time to code</li>
87<li>Time to run</li>
88<li>Time to maintain</li></ul>
89<br>
90<br>
91<p>
92<em>Which is more important?</em></p>
93</section><section class="vertical-slide"  data-background-transition="none">
94<p>
95This is not NLP (natural language processing)<br>This is a <strong>context-free</strong> grammar.<div class="fragment"><br></p>
96<br>
97<p>
98<h3>One morning I shot an elephant in my pajamas.</h3></div><div class="fragment"><h3>How he got into my pajamas I'll never know.</h3><em>(sometimes context matters!)</em><br></div></p>
99</section><section class="vertical-slide"  data-background-transition="none">
100<p>
101<h1>Backus-Naur Form</h1></p>
102<br>
103<p>
104"<em>... a notation for a context-free grammar, used to describe the syntax of languages used in computing, such as computer programming languages, document formats, instruction sets and communication protocols</em>" - Wikipedia</p>
105<br>
106<pre><code class=python><postal-address> ::= <name-part> <street-address> <zip-part>
107<name-part>      ::= <personal-part> <last-name> <opt-suffix-part> <EOL> 
108                   | <personal-part> <name-part>
109<personal-part>  ::= <first-name> | <initial> "." 
110<street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>
111<zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL></code></pre>
112</section>
113</section><section class="vertical-stack">
114<section class="vertical-slide"  data-background-transition="none">
115<p>
116<h2>Why not regex?</h2><em><a href="http://www.codinghorror.com/blog/2008/06/regular-expressions-now-you-have-two-problems.html">Now you have two problems</a></em></p>
117<br>
118<p>
119"<em>Regular expressions are like a particularly spicy hot sauce, to be used in moderation and with restraint only when appropriate. If you drench your plate in hot sauce, you're going to be very, very sorry later.</em>" - Jeff Atwood</p>
120</section><section class="vertical-slide"  data-background-transition="none">
121<p>
122Validating a phone number (<em>reasonable regex</em>)</p>
123<pre><code class=python>"^\(*\d{3}\)*( |-)*\d{3}( |-)*\d{4}$"</code></pre>
124<br>
125<p>
126Validating RFC822 email addresses (<em>have fun!</em>)</p>
127<pre><code>(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?
127:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>
127(?:(?:\r\n)?[ \t])*)(?:,\s*(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*))*)?;\s*)
128</code></pre>
129</section>
130</section><section class="vertical-stack">
131<section class="vertical-slide"  data-background-transition="none">
132<p>
133<h1>Pyparsing</h1>A free, pure python drop-in <a href="http://pyparsing.wikispaces.com/">parsing module</a>. Allows you to write/maintain the grammar, <em>abstracted</em> from the parser.</p>
134<a href=http://shop.oreilly.com/product/9780596514235.do><img class="" src="images/book.jpg" height="300px"></a>
135<p>
136Examples in this talk adapted from the <a href="http://shop.oreilly.com/product/9780596514235.do">book</a>.</p>
137</section>
138</section><section class="vertical-stack">
139<section class="vertical-slide"  data-background-transition="none">
140<p>
141<h3><a href="code/hello_world.py">hello_world.py</a></h3>Build the grammar iteratively, bottom up</p>
142<pre><code class=python>from pyparsing import *
143s = "Hello World!"
144word = Word(alphas)
145grammar = word
146print grammar.parseString(s)
147# Only grabs "Hello"</code></pre>
148<p>
149<div class="fragment"></p>
150<pre><code class=python>word_list = OneOrMore(word)
151grammar   = word_list
152# Now we get a list ["Hello", "World"]</code></pre>
153<p>
154</div><div class="fragment"></p>
155<pre><code class=python>end_punc = oneOf(". ! ?")
156grammar  = word_list + end_punc
157# Grabs the end symbol ["Hello", "World", "!"]</code></pre>
158<p>
159</div><div class="fragment"></p>
160<pre><code class=python>grammar = Group(word_list) + end_punc.suppress()
161# Group and suppress [["Hello", "World"]]</code></pre>
162<p>
163</div></p>
164</section><section class="vertical-slide"  data-background-transition="none">
165<p>
166<h3><a href="code/hello_world.py">hello_world.py</a></h3></p>
167<br>
168<p>
169Like OOP, each mini-grammar can be reused</p>
170<pre><code class=python>s2 = "Hello sir, how are you today?"
171phrase  = Group(word_list) + (Literal(",") | end_punc).suppress()
172grammar = OneOrMore(phrase)
173print grammar.parseString(s2)</code></pre>
174<p>
175<div class="fragment"></p>
176<pre><code class=python># [['Hello', 'sir'], ['how', 'are', 'you', 'today']]</code></pre>
177<p>
178</div></p>
179</section>
180</section><section class="vertical-stack">
181<section class="vertical-slide"  data-background-transition="none">
182<p>
183<h3><a href="code/records.py">records.py</a></h3>Take the raw data with missing values</p>
184<pre><code class=python>sue
185Travis Hoppe 31
186Marky Mark 42
187    
188James earl JONES 
189Rudolfo Alphonzo Raffaelo Pierre di Valentina D'Antonguolla 31</code></pre>
190<p>
191<div class="fragment">
191and transform it into a nicely type-casted JSON</p>
192<pre><code class=python>[{ "age": null, "name": "Sue"}, 
193 { "age": 31,   "name": "Travis Hoppe"}, 
194 { "age": 42,   "name": "Marky Mark"}, 
195 { "age": null, "name": "James Earl Jones"}, 
196 { "age": 31,   "name": "Rudolfo Alphonzo Raffaelo Pierre Di Valentina D'Antonguolla" }]</code></pre>
197<p>
198</div></p>
199</section><section class="vertical-slide"  data-background-transition="none">
200<p>
201<h3><a href="code/records.py">records.py</a></h3>The data guides the grammar</p>
202<pre><code class=python>sue
203Travis Hoppe 31
204Marky Mark 42
205
206James earl JONES 
207Rudolfo Alphonzo Raffaelo Pierre di Valentina D'Antonguolla 31</code></pre>
208<p>
209and self-documents the process for maintenance</p>
210<pre><code class=python>ParserElement.setDefaultWhitespaceChars(' \t')
211
212name      = Word(alphas + "'")
213full_name = Group(OneOrMore(name))("name")
214age = Word(nums)("age")
215EOL = LineEnd().suppress()
216
217record = full_name + Optional(age) + EOL
218record_list = OneOrMore(record | EOL)</code></pre>
219</section><section class="vertical-slide"  data-background-transition="none">
220<p>
221<h3><a href="code/records.py">records.py</a></h3>Our first attempt gives</p>
222<pre><code class=python>print record_list.parseString(data)
223# [['sue'], ['Travis', 'Hoppe'], '31', ['Marky', 'Mark'], '42', ['James', 'earl', 'JONES'], ['Rudolfo', 'Alphonzo', 'Raffaelo', 'Pierre', 'di', 'Valentina', "D'Antonguolla"], '31']</code></pre>
224<br>
225<p>
226Format the results</p>
227<pre><code class=python>def clean_record(tokens):
228  name = ' '.join(tokens["name"]).title()
229  if "age" in tokens:
230      age = int(tokens["age"])
231  else:
232      age = None
233  return {'name':name, 'age':age}
234
235record.setParseAction(clean_record)</code></pre>
236</section><section class="vertical-slide"  data-background-transition="none">
237<p>
238<h3><a href="code/records.py">records.py</a></h3>Proper type casting, string formatting, and a dictionary!</p>
239<pre><code class=python>sol = record_list.parseString(data)
240print sol        
241# [{'age': None, 'name': 'Sue'}, {'age': 31, 'name': 'Travis Hoppe'}, {'age': 42, 'name': 'Marky Mark'}, {'age': None, 'name': 'James Earl Jones'}, {'age': 31, 'name': "Rudolfo Alphonzo Raffaelo Pierre Di Valentina D'Antonguolla"}]</code></pre>
242<br>
243<p>
244Pretty-print the results in JSON</p>
245<pre><code class=python>import json
246js = json.dumps(sol.asList(),indent=2)
247print js
248
249# [{"age": null, "name": "Sue"}, 
250# { "age": 31,   "name": "Travis Hoppe"}, 
251# { "age": 42,   "name": "Marky Mark"}, 
252# { "age": null, "name": "James Earl Jones"}, 
253# { "age": 31, "name": "Rudolfo Alphonzo Raffaelo Pierre Di Valentina D'Antonguolla" }]</code></pre>
254</section>
255</section><section class="vertical-stack">
256<section class="vertical-slide"  data-background-transition="none">
257<p>
258<h3><a href="code/recursive.py">recursive.py</a></h3></p>
259<pre><code class=python>raw ='''(defun factorial (x)
260(if (zerop x) 1
261(* x (factorial (- x 1)))))'''</code></pre>
262<p>
263<div class="fragment"></p>
264<pre><code class=python>from pyparsing import *
265alpha  = Word(alphas)
266operation = oneOf("+ * - /")
267number = Word(nums)
268argument = alpha | number | operation</code></pre>
269<p>
270</div><div class="fragment">The expression is a recursive grammar!</p>
271<pre><code class=python>expr = Forward()
272LP,RP = map(Suppress, "()")
273expr << (argument | Group(LP + ZeroOrMore(expr) + RP))
274
275print expr.parseString(raw)    
276# [['defun', 'factorial', ['x'], ['if', ['zerop', 'x'], '1', ['*', 'x', ['factorial', ['-', 'x', '1']]]]]]</code></pre>
277<p>
278</div></p>
279</section>
280</section><section class="vertical-stack">
281<section class="vertical-slide"  data-background-transition="none">
282<p>
283<h3><a href="code/postfix_calc.py">postfix_calc.py</a></h3>Evaluate the string as a mathematical expression</p>
284<pre><code class=python>s = "((((3 4 +) 9 *) (8 9 +) *) 1050 -) 2 ^)"</code></pre>
285<p>
286<div class="fragment"></p>
287<pre><code class=python>from pyparsing import *
288expr = Forward()
289number    = Word(nums)("value")
290operation = oneOf("+ * ^ -")
291LP, RP = Literal("(").suppress(), Literal(")").suppress()
292nest = (LP + expr + RP)
293expr << Group(  (number | nest) 
294              + (number | nest) 
295              + operation)
296
297print expr.parseString(s)
298#[[[[[['3', '4', '+'], '9', '*'], ['8', '9', '+'], '*'], '1050', '-'], '2', '^']]</code></pre>
299<p>
300</div></p>
301</section><section class="vertical-slide"  data-background-transition="none">
302<p>
303<h3><a href="code/postfix_calc.py">postfix_calc.py</a></h3>Convert numbers into integers</p>
304<pre><code class=python>number.setParseAction(lambda x:int(x["value"]))</code></pre>
305<br>
306<p>
307Apply a function depending on the symbol</p>
308<pre><code class=python>actions = {"+":lambda x,y:x+y,
309           "*":lambda x,y:x*y,
310           "-":lambda x,y:x-y,
311           "^":lambda x,y:x**y}
312
313def apply(tokens):
314    a,b,op = tokens[0]
315    val = actions[op](a,b)
316    print "Evaluating {} {} {} = {}".format(a,op,b,val)
317    return val
318
319expr.setParseAction(apply)</code></pre>
320</section><section class="vertical-slide"  data-background-transition="none">
321<p>
322<h3><a href="code/postfix_calc.py">postfix_calc.py</a></h3></p>
323<pre><code class=python>s = "((((3 4 +) 9 *) (8 9 +) *) 1050 -) 2 ^)"</code></pre>
324<br>
325<p>
326Parse results, remove from last group</p>
327<pre><code class=python>result = expr.parseString(s)[0]
328print "Final value:", result</code></pre>
329<br>
330<p>
331Print statements help debug (use <a href="http://docs.python.org/2/l
331ibrary/logging.html">logging</a>!)</p>
332<pre><code class=python>Evaluating 3 + 4 = 7
333Evaluating 7 * 9 = 63
334Evaluating 8 + 9 = 17
335Evaluating 63 * 17 = 1071
336Evaluating 1071 - 1050 = 21
337Evaluating 21 ^ 2 = 441
338Final value: 441</code></pre>
339</section><section class="vertical-slide"  data-background-transition="none">
340<p>
341<h3><a href="code/postfix_calc.py">postfix_calc.py</a></h3></p>
342<br>
343<p>
344Extending the functionality is easy!</p>
345<br>
346<pre><code class=python>actions["%"]      = lambda a,b: a%b
347actions["choose"] = scipy.misc.comb</code></pre>
348<br>
349<br>
350<p>
351With a little work, we could make use of unary operators,<br>arbitrary length inputs, and floats!</p>
352</section>
353</section><section class="vertical-stack">
354<section class="vertical-slide"  data-background-transition="none">
355<p>
356<h3>Why pyparsing?</h3>Grammar specification is a natural-looking part of the python<br>Class/function names are easier than specialized typography<br>Easy-to-read and familiar in style<br>Processing <em>during</em> parsing<br>Whitespace is <em>optional</em><div class="fragment"><br><h3>Why not?</h3>Slow for complex grammars (memoization helps)<br>Specialized libraries may be better (xml, html)<br><em>Sometimes</em> overkill (<code>str.split</code>?)<br></div></p>
357</section>
358</section><section class="vertical-stack">
359<section class="vertical-slide"  data-background-transition="none">
360<p>
361<h1>Thanks, you.</h1></p>
362</section><section class="vertical-slide"  data-background-transition="none">
363<p>
364<div display='inline' align='left'><h2>How were these slides made?</h2></div></p>
365<br>
366<p>
367<div display='inline' align='left'><h3>Math Rendering: <svg class="latexSVG" height="100%" version="1.2" viewBox="0 0 25.00225 9.15575" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
368 <defs>
369  <g>
370   <symbol id="equation_WLNOJ_2" overflow="visible">
371    <path d="M 5.796875 -2.578125 L 5.546875 -2.578125 C 5.4375 -1.5625 5.296875 -0.3125 3.546875 -0.3125 L 2.734375 -0.3125 C 2.265625 -0.3125 2.25 -0.375 2.25 -0.703125 L 2.25 -6.015625 C 2.25 -6.359375 2.25 -6.5 3.1875 -6.5 L 3.515625 -6.5 L 3.515625 -6.8125 C 3.15625 -6.78125 2.25 -6.78125 1.84375 -6.78125 C 1.453125 -6.78125 0.671875 -6.78125 0.328125 -6.8125 L 0.328125 -6.5 L 0.5625 -6.5 C 1.328125 -6.5 1.359375 -6.390625 1.359375 -6.03125 L 1.359375 -0.78125 C 1.359375 -0.421875 1.328125 -0.3125 0.5625 -0.3125 L 0.328125 -0.3125 L 0.328125 0 L 5.515625 0 Z M 5.796875 -2.578125 " style="stroke:none;"/>
372   </symbol>
373   <symbol id="equation_WLNOJ_1" overflow="visible">
374    <path d="M 6.640625 -6.75 L 0.546875 -6.75 L 0.359375 -4.5 L 0.609375 -4.5 C 0.75 -6.109375 0.890625 -6.4375 2.40625 -6.4375 C 2.578125 -6.4375 2.84375 -6.4375 2.9375 -6.421875 C 3.15625 -6.375 3.15625 -6.265625 3.15625 -6.046875 L 3.15625 -0.78125 C 3.15625 -0.453125 3.15625 -0.3125 2.109375 -0.3125 L 1.703125 -0.3125 L 1.703125 0 C 2.109375 -0.03125 3.125 -0.03125 3.59375 -0.03125 C 4.046875 -0.03125 5.078125 -0.03125 5.484375 0 L 5.484375 -0.3125 L 5.078125 -0.3125 C 4.03125 -0.3125 4.03125 -0.453125 4.03125 -0.78125 L 4.03125 -6.046875 C 4.03125 -6.234375 4.03125 -6.375 4.21875 -6.421875 C 4.328125 -6.4375 4.59375 -6.4375 4.78125 -6.4375 C 6.296875 -6.4375 6.4375 -6.109375 6.578125 -4.5 L 6.828125 -4.5 Z M 6.640625 -6.75 " style="stroke:none;"/>
375   </symbol>
376   <symbol id="equation_WLNOJ_4" overflow="visible">
377    <path d="M 1.359375 -0.78125 C 1.359375 -0.421875 1.328125 -0.3125 0.5625 -0.3125 L 0.328125 -0.3125 L 0.328125 0 L 6.078125 0 L 6.5 -2.578125 L 6.25 -2.578125 C 6 -1.03125 5.765625 -0.3125 4.0625 -0.3125 L 2.734375 -0.3125 C 2.265625 -0.3125 2.25 -0.375 2.25 -0.703125 L 2.25 -3.375 L 3.140625 -3.375 C 4.109375 -3.375 4.21875 -3.046875 4.21875 -2.203125 L 4.46875 -2.203125 L 4.46875 -4.84375 L 4.21875 -4.84375 C 4.21875 -3.984375 4.109375 -3.671875 3.140625 -3.671875 L 2.25 -3.671875 L 2.25 -6.078125 C 2.25 -6.40625 2.265625 -6.46875 2.734375 -6.46875 L 4.015625 -6.46875 C 5.546875 -6.46875 5.8125 -5.921875 5.96875 -4.53125 L 6.21875 -4.53125 L 5.9375 -6.78125 L 0.328125 -6.78125 L 0.328125 -6.46875 L 0.5625 -6.46875 C 1.328125 -6.46875 1.359375 
377-6.359375 1.359375 -6 Z M 1.359375 -0.78125 " style="stroke:none;"/>
378   </symbol>
379   <symbol id="equation_WLNOJ_3" overflow="visible">
380    <path d="M 4 -3.84375 L 5.375 -5.859375 C 5.59375 -6.171875 5.9375 -6.484375 6.8125 -6.5 L 6.8125 -6.8125 C 6.4375 -6.796875 5.96875 -6.78125 5.71875 -6.78125 C 5.3125 -6.78125 4.828125 -6.78125 4.4375 -6.8125 L 4.4375 -6.5 C 4.828125 -6.484375 5.046875 -6.265625 5.046875 -6.046875 C 5.046875 -5.9375 5.03125 -5.921875 4.96875 -5.8125 L 3.828125 -4.125 L 2.546875 -6.046875 C 2.515625 -6.078125 2.46875 -6.15625 2.46875 -6.203125 C 2.46875 -6.3125 2.6875 -6.484375 3.125 -6.5 L 3.125 -6.8125 C 2.765625 -6.78125 2.046875 -6.78125 1.671875 -6.78125 C 1.359375 -6.78125 0.734375 -6.78125 0.375 -6.8125 L 0.375 -6.5 L 0.5625 -6.5 C 1.109375 -6.5 1.296875 -6.4375 1.484375 -6.15625 L 3.3125 -3.375 L 1.6875 -0.96875 C 1.546875 -0.765625 1.25 -0.3125 0.234375 -0.3125 L 0.234375 0 C 0.59375 -0.015625 1.015625 -0.03125 1.34375 -0.03125 C 1.71875 -0.03125 2.265625 -0.03125 2.625 0 L 2.625 -0.3125 C 2.15625 -0.3125 2 -0.59375 2 -0.765625 C 2 -0.859375 2.03125 -0.890625 2.09375 -1 L 3.515625 -3.09375 L 5.078125 -0.71875 C 5.109375 -0.671875 5.140625 -0.640625 5.140625 -0.609375 C 5.140625 -0.484375 4.921875 -0.3125 4.484375 -0.3125 L 4.484375 0 C 4.828125 -0.03125 5.5625 -0.03125 5.9375 -0.03125 C 6.359375 -0.03125 6.8125 -0.015625 7.234375 0 L 7.234375 -0.3125 L 7.046875 -0.3125 C 6.53125 -0.3125 6.3125 -0.359375 6.109375 -0.671875 Z M 4 -3.84375 " style="stroke:none;"/>
381   </symbol>
382   <symbol id="equation_WLNOJ_0" overflow="visible">
383    <path d="M 3.125 -4.8125 C 3.09375 -4.921875 3.0625 -4.96875 2.9375 -4.96875 C 2.796875 -4.96875 2.78125 -4.921875 2.734375 -4.8125 L 1.125 -0.734375 C 1.0625 -0.5625 0.9375 -0.25 0.3125 -0.25 L 0.3125 0 C 0.546875 -0.015625 0.796875 -0.03125 1.03125 -0.03125 C 1.3125 -0.03125 1.828125 0 1.875 0 L 1.875 -0.25 C 1.5625 -0.25 1.359375 -0.390625 1.359375 -0.578125 C 1.359375 -0.640625 1.375 -0.65625 1.40625 -0.71875 L 1.734375 -1.578125 L 3.71875 -1.578125 L 4.125 -0.5625 C 4.125 -0.53125 4.15625 -0.484375 4.15625 -0.453125 C 4.15625 -0.25 3.78125 -0.25 3.59375 -0.25 L 3.59375 0 C 3.9375 -0.015625 4.390625 -0.03125 4.625 -0.03125 C 4.953125 -0.03125 5.484375 0 5.546875 0 L 5.546875 -0.25 L 5.421875 -0.25 C 4.953125 -0.25 4.90625 -0.328125 4.828125 -0.515625 Z M 2.71875 -4.09375 L 3.609375 -1.828125 L 1.828125 -1.828125 Z M 2.71875 -4.09375 " style="stroke:none;"/>
384   </symbol>
385  </g>
386 </defs>
387 <g id="surface1">
388  <g>
389   <use x="-0.328125" xlink:href="#equation_WLNOJ_2" y="7.01075"/>
390  </g>
391  <g>
392   <use x="2.311875" xlink:href="#equation_WLNOJ_0" y="4.96875"/>
393  </g>
394  <g>
395   <use x="6.698875" xlink:href="#equation_WLNOJ_1" y="7.01075"/>
396  </g>
397  <g>
398   <use x="12.232875" xlink:href="#equation_WLNOJ_4" y="9.15575"/>
399  </g>
400  <g>
401   <use x="17.767875" xlink:href="#equation_WLNOJ_3" y="7.01075"/>
402  </g>
403 </g>
404</svg></h3></div><div display='inline' align='left'><h3>JavaScript : <a href="http://hakim.se/projects/reveal-js">reveal.js</a></h3></div><div display='inline' align='left'><h3>Markdown : <a href="http://daringfireball.net/">Daring Fireball</a></h3></div></p>
405<br>
406<hr>
407<br>
408<p>
409<div display='inline' align='left'><h3>Markdown to HTML: <a href="https://github.com/thoppe/md2reveal">md2reveal.py</a></h3></div><div display='inline' align='left'><em> (uses pyparsing to write a talk about pyparsing)</em></div></p>
410</section><section class="vertical-slide"  data-background-transition="none">
411<p>
412<h2>How does it work?</h2></p>
413<br>
414<p>
415A <strong>text-based</strong> human-readable markup.<br>SVG equations <svg class="latexSVG" height="100%" version="1.2" viewBox="0 0 37.61575 8.848375" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
416 <defs>
417  <g>
418   <symbol id="equation_YBWFB_5" overflow="visible">
419    <path d="M 1.859375 -2.296875 C 2.15625 -2.296875 2.890625 -2.328125 3.390625 -2.53125 C 4.09375 -2.828125 4.140625 -3.421875 4.140625 -3.5625 C 4.140625 -4 3.765625 -4.40625 3.078125 -4.40625 C 1.96875 -4.40625 0.453125 -3.4375 0.453125 -1.6875 C 0.453125 -0.671875 1.046875 0.109375 2.03125 0.109375 C 3.453125 0.109375 4.28125 -0.953125 4.28125 -1.0625 C 4.28125 -1.125 4.234375 -1.203125 4.171875 -1.203125 C 4.109375 -1.203125 4.09375 -1.171875 4.03125 -1.09375 C 3.25 -0.109375 2.15625 -0.109375 2.046875 -0.109375 C 1.265625 -0.109375 1.171875 -0.953125 1.171875 -1.265625 C 1.171875 -1.390625 1.1875 -1.6875 1.328125 -2.296875 Z M 1.390625 -2.515625 C 1.78125 -4.03125 2.8125 -4.1875 3.078125 -4.1875 C 3.53125 -4.1875 3.8125 -3.890625 3.8125 -3.5625 C 3.8125 -2.515625 2.21875 -2.515625 1.796875 -2.515625 Z M 1.390625 -2.515625 " style="stroke:none;"/>
420   </symbol>
421   <symbol id="equation_YBWFB_0" overflow="visible">
422    <path d="M 2.265625 -4.359375 C 2.265625 -4.46875 2.171875 -4.625 1.984375 -4.625 C 1.796875 -4.625 1.59375 -4.4375 1.59375 -4.234375 C 1.59375 -4.125 1.671875 -3.96875 1.875 -3.96875 C 2.0625 -3.96875 2.265625 -4.171875 2.265625 -4.359375 Z M 0.84375 -0.8125 C 0.8125 -0.71875 0.78125 -0.640625 0.78125 -0.515625 C 0.78125 -0.1875 1.046875 0.0625 1.4375 0.0625 C 2.125 0.0625 2.4375 -0.890625 2.4375 -1 C 2.4375 -1.09375 2.34375 -1.09375 2.328125 -1.09375 C 2.234375 -1.09375 2.21875 -1.046875 2.1875 -0.96875 C 2.03125 -0.40625 1.734375 -0.125 1.453125 -0.125 C 1.3125 -0.125 1.28125 -0.21875 1.28125 -0.375 C 1.28125 -0.53125 1.328125 -0.65625 1.390625 -0.8125 C 1.46875 -1 1.546875 -1.1875 1.609375 -1.375 C 1.671875 -1.546875 1.9375 -2.171875 1.953125 -2.265625 C 1.984375 -2.328125 2 -2.40625 2 -2.484375 C 2 -2.8125 1.71875 -3.078125 1.34375 -3.078125 C 0.640625 -3.078125 0.328125 -2.125 0.328125 -2 C 0.328125 -1.921875 0.421875 -1.921875 0.453125 -1.921875 C 0.546875 -1.921875 0.546875 -1.953125 0.578125 -2.03125 C 0.75 -2.625 1.0625 -2.875 1.3125 -2.875 C 1.421875 -2.875 1.484375 -2.828125 1.484375 -2.640625 C 1.484375 -2.46875 1.453125 -2.375 1.28125 -1.9375 Z M 0.84375 -0.8125 " style="stroke:none;"/>
423   </symbol>
424   <symbol id="equation_YBWFB_1" overflow="visible">
425    <path d="M 2.171875 -2.53125 L 3 -2.53125 C 2.890625 -2.109375 2.734375 -1.484375 2.734375 -0.921875 C 2.734375 -0.640625 2.78125 -0.453125 2.8125 -0.3125 C 2.921875 0.046875 3.015625 0.0625 3.125 0.0625 C 3.296875 0.0625 3.453125 -0.078125 3.453125 -0.25 C 3.453125 -0.296875 3.4375 -0.328125 3.40625 -0.390625 C 3.265625 -0.65625 3.140625 -1.046875 3.140625 -1.625 C 3.140625 -1.75 3.140625 -2.03125 3.234375 -2.53125 L 4.109375 -2.53125 C 4.234375 -2.53125 4.296875 -2.53125 4.375 -2.578125 C 4.46875 -2.65625 4.484375 -2.765625 4.484375 -2.796875 C 4.484375 -3 4.3125 -3 4.1875 -3 L 1.5625 -3 C 1.28125 -3 1.078125 -2.9375 0.765625 -2.640625 C 0.578125 -2.484375 0.3125 -2.109375 0.3125 -2.046875 C 0.3125 -1.96875 0.40625 -1.96875 0.4375 -1.96875 C 0.515625 -1.96875 0.515625 -1.984375 0.5625 -2.046875 C 0.90625 -2.53125 1.34375 -2.53125 1.5 -2.53125 L 1.921875 -2.53125 C 1.703125 -1.765625 1.328125 -0.9375 1.125 -0.515625 C 1.078125 -0.4375 1.015625 -0.28125 0.984375 -0.265625 C 0.984375 -0.234375 0.96875 -0.203125 0.96875 -0.15625 C 0.96875 -0.046875 1.046875 0.0625 1.21875 0.0625 C 1.484375 0.0625 1.5625 -0.25 1.734375 -0.875 Z M 2.171875 -2.53125 " style="stroke:none;"/>
426   </symbol>
427   <symbol id="equation_YBWFB_3" overflow="visible">
428    <path d="M 6.84375 -3.265625 C 7 -3.265625 7.1875 -3.265625 7.1875 -3.453125 C 7.1875 -3.65625 7 -3.65625 6.859375 
428-3.65625 L 0.890625 -3.65625 C 0.75 -3.65625 0.5625 -3.65625 0.5625 -3.453125 C 0.5625 -3.265625 0.75 -3.265625 0.890625 -3.265625 Z M 6.859375 -1.328125 C 7 -1.328125 7.1875 -1.328125 7.1875 -1.53125 C 7.1875 -1.71875 7 -1.71875 6.84375 -1.71875 L 0.890625 -1.71875 C 0.75 -1.71875 0.5625 -1.71875 0.5625 -1.53125 C 0.5625 -1.328125 0.75 -1.328125 0.890625 -1.328125 Z M 6.859375 -1.328125 " style="stroke:none;"/>
429   </symbol>
430   <symbol id="equation_YBWFB_2" overflow="visible">
431    <path d="M 2.9375 -6.375 C 2.9375 -6.625 2.9375 -6.640625 2.703125 -6.640625 C 2.078125 -6 1.203125 -6 0.890625 -6 L 0.890625 -5.6875 C 1.09375 -5.6875 1.671875 -5.6875 2.1875 -5.953125 L 2.1875 -0.78125 C 2.1875 -0.421875 2.15625 -0.3125 1.265625 -0.3125 L 0.953125 -0.3125 L 0.953125 0 C 1.296875 -0.03125 2.15625 -0.03125 2.5625 -0.03125 C 2.953125 -0.03125 3.828125 -0.03125 4.171875 0 L 4.171875 -0.3125 L 3.859375 -0.3125 C 2.953125 -0.3125 2.9375 -0.421875 2.9375 -0.78125 Z M 2.9375 -6.375 " style="stroke:none;"/>
432   </symbol>
433   <symbol id="equation_YBWFB_4" overflow="visible">
434    <path d="M 6.5625 -2.296875 C 6.734375 -2.296875 6.921875 -2.296875 6.921875 -2.5 C 6.921875 -2.6875 6.734375 -2.6875 6.5625 -2.6875 L 1.171875 -2.6875 C 1 -2.6875 0.828125 -2.6875 0.828125 -2.5 C 0.828125 -2.296875 1 -2.296875 1.171875 -2.296875 Z M 6.5625 -2.296875 " style="stroke:none;"/>
435   </symbol>
436  </g>
437 </defs>
438 <g id="surface1">
439  <g>
440   <use x="-0.453125" xlink:href="#equation_YBWFB_5" y="8.739"/>
441  </g>
442  <g>
443   <use x="4.185875" xlink:href="#equation_YBWFB_0" y="4.625"/>
444   <use x="7.004685" xlink:href="#equation_YBWFB_1" y="4.625"/>
445  </g>
446  <g>
447   <use x="15.178875" xlink:href="#equation_YBWFB_3" y="8.739"/>
448  </g>
449  <g>
450   <use x="25.694875" xlink:href="#equation_YBWFB_4" y="8.739"/>
451  </g>
452  <g>
453   <use x="33.443875" xlink:href="#equation_YBWFB_2" y="8.739"/>
454  </g>
455 </g>
456</svg>, and <a href="http://thoppe.github.io/">links</a>!<br>The code for <em>this particular slide</em> looks like this:</p>
457<br>
458<pre><code class=python>## How does it work?
459
460A *text-based* human-readable markup. 
461Equation rendering is simple $e^{i \pi} = -1$.
462and [links](http://thoppe.github.io/)!
463The code for this _particular slide_ looks like this:</code></pre>
464</section>
465</section>
466    </div></div>
467
468    
468<script src="reveal.js/lib/js/head.min.js"></script>
468
469    
469<script src="reveal.js/js/reveal.js"></script>
469
470
471    
471<script>
472      // Full list of configuration options available here:
473      // https://github.com/hakimel/reveal.js#configuration
474      Reveal.initialize({
475      overview: true, height: 900, keyboard: true, touch: true, hideAddressBar: true, rollingLinks: false, mouseWheel: false, controls: true, width: 1200, viewDistance: 3, rtl: false, progress: true, fragments: true, autoSlide: 0, autoSlideStoppable: true, backgroundtransition: "default", transitionSpeed: "default", center: true, embedded: true, transition: "default", maxScale: 1.2, minScale: 0.2, previewLinks: false, margin: 0.05, loop: false, history: true, 
476      
477      theme: Reveal.getQueryHash().theme, 
478      // available themes are in reveal.js/css/theme
479
480      // Optional libraries used to extend on reveal.js
481      dependencies: [ { src: 'reveal.js/lib/js/classList.js', condition: function() { 
482    return !document.body.classList; } },
483
484{ src: 'reveal.js/plugin/markdown/showdown.js', condition: function() { 
485    return !!document.querySelector( '[data-markdown]' ); } },
486
487{ src: 'reveal.js/plugin/markdown/markdown.js', condition: function() { 
488    return !!document.querySelector( '[data-markdown]' ); } },
489
490{ src: 'reveal.js/plugin/highlight/highlight.js', async: true, callback: 
491  function() { hljs.initHighlightingOnLoad(); } },
492
493{ src: 'reveal.js/plugin/zoom-js/zoom.js', async: true, condition: 
494  function() { return !!document.body.classList; } },
495 ]
496
497      });
498    </script>
498
499
500  </body>
501</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.