SlideShare a Scribd company logo
1 of 21
Download to read offline
Pratt Parser in
Python
Maxim Eronin
1
An exercise in design and implementation
Use Case: Calculated Metrics
2
'2 + 3^4^5 * log2(8)'
'2', '+', '3', '^', '4', '^',
'5', '*', 'log2', '(', '8',
')'
ws = 's+'
name = '[a-z][w_]*'
infix = '[+-*/^]'
punct = '[(),]'
number = '(d*.)?d+'
3
Why write your own parser?
● It is not an as big a task as it might seem
● More control over the implementation
details/techniques
● Many of the existing python parsing libraries are lacking
in one or more areas
● Writing parsers is fun
4
What is a Pratt Parser and why
use it?
● Parsing technique designed for parsing operator
precedence correctly
● First appeared in “Top Down Operator Precedence” by
Vaughan Pratt (1973)
● A variation of a recursive descent parser but
○ Efficient
○ Modular and flexible
○ Easy to implement and and iterate upon
○ Beautiful
5
Why isn’t it more popular?
“One may wonder why such an "obviously" utopian approach has not been generally
adopted already. I suspect the root cause of this kind of oversight is our universal
preoccupation with BNF grammars and their various offspring grammars[...] together
with their related automata and a large body of theorems. I am personally enamored
of automata theory per se, but I am not impressed with the extent to which it has so
far been successfully applied to the writing of compilers or interpreters. Nor do I see a
particularly promising future in this direction. Rather, I see automata theory as
holding back the development of ideas valuable to language design that are not
visibly in the domain of automata theory.”
Vaughan R. Pratt “Top Down Operator Precedence”
6
Simple arithmetic expression grammar
expression ::= mul-expr ( ( '+' | '-' ) mul-expr )*
mul-expr ::= pow-expr ( ( '*' | '/' ) pow-expr )*
pow-expr ::= prefix-expr ['^' pow-expr]
prefix-expr ::= [ '-' ] primary
primary ::= '(' expr ')' | number | name [ '(' expr ( ',' expr )* ')' ]
7
Pratt parser: no grammar, only tokens
nilfix '<number>', '<name>'
infix '+', '-' 10
infix '*', '/' 20
infixr '^' 30
prefix '-' 40
infix '(' 50
8
from expr_parser.lexer import lex
from expr_parser.parser import Parser, Symbol, Literal, Infix, InfixR
expr = Parser(lex)
expr.define("<number>", 0, Literal)
expr.define("<name>", 0, Literal)
expr.define("+", 50, Infix)
expr.define("*", 60, Infix)
expr.define("/", 60, Infix)
expr.define("^", 70, InfixR)
@expr.define("-", 50)
class Minus(Infix, Prefix):
"""This combines both Prefix' nud and Infix' led"""
pass
9
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
10
class Symbol(object):
"""Base class for all nodes"""
id = None
lbp = 0
def __init__(self, parser, value=None):
self.parser = parser
self.value = value or self.id
self.first = None
self.second = None
def nud(self):
"""Null denotation. Prefix/Nilfix symbol"""
raise ParserError("Symbol action undefined for `%s'" % self.value)
def led(self, left):
"""Left denotation. Infix/Postfix symbol"""
raise ParserError("Infix action undefined for `%s'" % self.value)
11
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
class Literal(Symbol):
"""Simple literal (a number or a variable/function name)
just produces itself"""
def nud(self):
return self
class Prefix(Symbol):
"""Prefix operator.
For the sake of simplicity has fixed right binding power"""
def nud(self):
self.first = self.parser.expression(80)
return self
12
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
class Infix(Symbol):
"""Infix operator"""
def led(self, left):
self.first = left
self.second = self.parser.expression(self.lbp)
return self
class InfixR(Infix):
"""Infix (right associative) operator"""
def led(self, left):
self.first = left
self.second = self.parser.expression(self.lbp - 1)
return self
13
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
class Parser(object):
"""Main parser class. Contains both the grammar definition
and a pointer to the current token stream"""
def __init__(self, lex=lexer.lex):
self.lex = lex
self.symbol_table = {}
self.define("<end>")
self.tokens = iter(())
self.token = None
def expression(self, rbp):
tok = self.token
self.advance()
left = tok.nud()
while rbp < self.token.lbp:
tok = self.token
self.advance()
left = tok.led(left)
return left
14
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
def advance(self, value=None):
tok = self.token
if value and value not in (tok.value, tok.id):
raise ParserError(
"Expected `%s'; got `%s' instead" % (value, tok.value))
try:
tok = self.tokens.next()
symbol_table = self.symbol_table
# first look up token's value
if tok.value in symbol_table:
sym = symbol_table[tok.value]
elif tok.token_type in symbol_table:
# then token's type
sym = symbol_table[tok.token_type]
else:
raise ParserError("Undefined token %s" % repr(tok))
self.token = sym(self, tok.value)
except StopIteration:
self.token = self.symbol_table["<end>"](self)
return self.token
15
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
def define(self, sid, bp=0, symbol_class=Symbol):
symbol_table = self.symbol_table
sym = symbol_table[sid] = type(
symbol_class.__name__,
(symbol_class,),
{'id': sid, 'lbp': bp}
)
def wrapper(val):
val.id = sid
val.lbp = sym.lbp
symbol_table[sid] = val
return val
return wrapper
16
01
02
03
04
05
06
07
08
09
10
11
12
13
def parse(self, source):
try:
self.tokens = self.lex(source)
self.advance()
return self.expression(0)
finally:
self.tokens = iter(())
self.token = None
17
01
02
03
04
05
06
07
08
expr.define("<punct>")
@expr.define("(", 90)
class FunctionCall(Symbol):
"""Defining both function application and parenthesized expression"""
def nud(self):
e = self.parser.expression(0)
self.parser.advance(")")
return e
def led(self, left):
self.first = left
args = self.second = []
p = self.parser
while p.token.value != ")":
args.append(p.expression(0))
if p.token.value != ",":
break
p.advance(",")
p.advance(")")
return self
18
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
TOKENS = (
('ws', r's+'),
('name', r'[a-z][w_]*'),
('infix', r'[+-*/^]'),
('punct', r'[(),]'),
('number', r'(:?d*.)?d+'),
)
TOKEN_RE = '|'.join("(?P<%s>%s)" % t for t in TOKENS)
LEX_RE = re.compile(TOKEN_RE, re.UNICODE | re.IGNORECASE)
class Token(object):
def __init__(self, token_type, value, pos):
self.token_type = token_type
self.value = value
self.pos = pos
But what about lexing?
19
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
def lex(source, pat=LEX_RE):
i = 0
def error():
raise LexerException(
"Unexpected character at position %d: `%s`" % (i, source[i])
)
for m in pat.finditer(source):
pos = m.start()
if pos > i:
error()
i = m.end()
name = m.lastgroup
if name != "ws":
token_type = "<%s>" % name
yield Token(token_type, m.group(0), pos)
if i < len(source):
error()
20
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
● https://tdop.github.io/
Vaughan R. Pratt "Top Down Operator Precedence" (1973)
● http://javascript.crockford.com/tdop/tdop.html
Douglas Crockford "Top Down Operator Precedence" (2007)
● http://effbot.org/zone/simple-top-down-parsing.htm
Fredrik Lundh "Simple Top-Down Parsing in Python" (2008)
All code in this presentation can be found at:
https://github.com/percolate/pratt-parser
References
21
We are Percolate and we’re always hiring great engineers. Talk to us

More Related Content

What's hot

Functional Error Handling with Cats
Functional Error Handling with CatsFunctional Error Handling with Cats
Functional Error Handling with CatsMark Canlas
 
Type Theory and Practical Application
Type Theory and Practical ApplicationType Theory and Practical Application
Type Theory and Practical ApplicationJack Fox
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Scott Wlaschin
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)Scott Wlaschin
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 
線形代数の視覚的理解 V1.1-Gストラング勉強会
線形代数の視覚的理解 V1.1-Gストラング勉強会線形代数の視覚的理解 V1.1-Gストラング勉強会
線形代数の視覚的理解 V1.1-Gストラング勉強会Kenji Hiranabe
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?NAVER D2
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Scott Wlaschin
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/PrismNaoki Aoyama
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
5分でわかるGoのポインタ
5分でわかるGoのポインタ5分でわかるGoのポインタ
5分でわかるGoのポインタY N
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2Chris Ohk
 
Rとpythonとjuliaで機械学習レベル4を目指す
Rとpythonとjuliaで機械学習レベル4を目指すRとpythonとjuliaで機械学習レベル4を目指す
Rとpythonとjuliaで機械学習レベル4を目指すyuta july
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐりKazuyuki TAKASE
 
超簡単!TELNETの話
超簡単!TELNETの話超簡単!TELNETの話
超簡単!TELNETの話ogatay
 

What's hot (20)

Functional Error Handling with Cats
Functional Error Handling with CatsFunctional Error Handling with Cats
Functional Error Handling with Cats
 
Type Theory and Practical Application
Type Theory and Practical ApplicationType Theory and Practical Application
Type Theory and Practical Application
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
線形代数の視覚的理解 V1.1-Gストラング勉強会
線形代数の視覚的理解 V1.1-Gストラング勉強会線形代数の視覚的理解 V1.1-Gストラング勉強会
線形代数の視覚的理解 V1.1-Gストラング勉強会
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
Practical Object Oriented Models In Sql
Practical Object Oriented Models In SqlPractical Object Oriented Models In Sql
Practical Object Oriented Models In Sql
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/Prism
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
5分でわかるGoのポインタ
5分でわかるGoのポインタ5分でわかるGoのポインタ
5分でわかるGoのポインタ
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2
 
Rとpythonとjuliaで機械学習レベル4を目指す
Rとpythonとjuliaで機械学習レベル4を目指すRとpythonとjuliaで機械学習レベル4を目指す
Rとpythonとjuliaで機械学習レベル4を目指す
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
 
超簡単!TELNETの話
超簡単!TELNETの話超簡単!TELNETの話
超簡単!TELNETの話
 

Similar to Pratt Parser in Python

Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in goYusuke Kita
 
Elixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsElixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsHéla Ben Khalfallah
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with PythonHan Lee
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubyJason Yeo Jie Shun
 
Stupid Awesome Python Tricks
Stupid Awesome Python TricksStupid Awesome Python Tricks
Stupid Awesome Python TricksBryan Helmig
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)ujihisa
 
Sparse Matrix and Polynomial
Sparse Matrix and PolynomialSparse Matrix and Polynomial
Sparse Matrix and PolynomialAroosa Rajput
 
VTU DSA Lab Manual
VTU DSA Lab ManualVTU DSA Lab Manual
VTU DSA Lab ManualAkhilaaReddy
 
Javascript Basics
Javascript BasicsJavascript Basics
Javascript Basicsmsemenistyi
 
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...GkhanGirgin3
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...ssuserd6b1fd
 
Explorando el Diseño de la Memoria en Rust
Explorando el Diseño de la Memoria en RustExplorando el Diseño de la Memoria en Rust
Explorando el Diseño de la Memoria en RustGermán Küber
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisaujihisa
 
仕事で使うF#
仕事で使うF#仕事で使うF#
仕事で使うF#bleis tift
 
Build a compiler in 2hrs - NCrafts Paris 2015
Build a compiler in 2hrs -  NCrafts Paris 2015Build a compiler in 2hrs -  NCrafts Paris 2015
Build a compiler in 2hrs - NCrafts Paris 2015Phillip Trelford
 

Similar to Pratt Parser in Python (20)

LEX & YACC TOOL
LEX & YACC TOOLLEX & YACC TOOL
LEX & YACC TOOL
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in go
 
Elixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsElixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental Concepts
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
 
c programming
c programmingc programming
c programming
 
Stupid Awesome Python Tricks
Stupid Awesome Python TricksStupid Awesome Python Tricks
Stupid Awesome Python Tricks
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)
 
Sparse Matrix and Polynomial
Sparse Matrix and PolynomialSparse Matrix and Polynomial
Sparse Matrix and Polynomial
 
VTU DSA Lab Manual
VTU DSA Lab ManualVTU DSA Lab Manual
VTU DSA Lab Manual
 
Python
PythonPython
Python
 
Javascript Basics
Javascript BasicsJavascript Basics
Javascript Basics
 
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
 
Arrays
ArraysArrays
Arrays
 
Explorando el Diseño de la Memoria en Rust
Explorando el Diseño de la Memoria en RustExplorando el Diseño de la Memoria en Rust
Explorando el Diseño de la Memoria en Rust
 
CSE240 Pointers
CSE240 PointersCSE240 Pointers
CSE240 Pointers
 
Hacking Parse.y with ujihisa
Hacking Parse.y with ujihisaHacking Parse.y with ujihisa
Hacking Parse.y with ujihisa
 
仕事で使うF#
仕事で使うF#仕事で使うF#
仕事で使うF#
 
Build a compiler in 2hrs - NCrafts Paris 2015
Build a compiler in 2hrs -  NCrafts Paris 2015Build a compiler in 2hrs -  NCrafts Paris 2015
Build a compiler in 2hrs - NCrafts Paris 2015
 

More from Percolate

7 Project Management Tips from Across Disciplines
7 Project Management Tips from Across Disciplines7 Project Management Tips from Across Disciplines
7 Project Management Tips from Across DisciplinesPercolate
 
Moving from Stateful Components to Stateless Components
Moving from Stateful Components to Stateless ComponentsMoving from Stateful Components to Stateless Components
Moving from Stateful Components to Stateless ComponentsPercolate
 
Content Strategy in a Changing World
Content Strategy in a Changing WorldContent Strategy in a Changing World
Content Strategy in a Changing WorldPercolate
 
Moving From MySQL to Elasticsearch for Analytics
Moving From MySQL to Elasticsearch for AnalyticsMoving From MySQL to Elasticsearch for Analytics
Moving From MySQL to Elasticsearch for AnalyticsPercolate
 
Percolate: Content Marketing 360: From Planning to Performance
Percolate: Content Marketing 360: From Planning to PerformancePercolate: Content Marketing 360: From Planning to Performance
Percolate: Content Marketing 360: From Planning to PerformancePercolate
 
The 50 Most Important Marketing Charts of 2016
The 50 Most Important Marketing Charts of 2016The 50 Most Important Marketing Charts of 2016
The 50 Most Important Marketing Charts of 2016Percolate
 
The Secret to Brand Growth? Mental and Physical Availability
The Secret to Brand Growth? Mental and Physical AvailabilityThe Secret to Brand Growth? Mental and Physical Availability
The Secret to Brand Growth? Mental and Physical AvailabilityPercolate
 
Advertising for the Long Term
Advertising for the Long TermAdvertising for the Long Term
Advertising for the Long TermPercolate
 
Be Distinctive, Not Different
Be Distinctive, Not DifferentBe Distinctive, Not Different
Be Distinctive, Not DifferentPercolate
 
Why Mass Marketing Wins Over Targeted Efforts
Why Mass Marketing Wins Over Targeted EffortsWhy Mass Marketing Wins Over Targeted Efforts
Why Mass Marketing Wins Over Targeted EffortsPercolate
 
Small vs. Large Brands: How to Become a Market Leader
Small vs. Large Brands: How to Become a Market LeaderSmall vs. Large Brands: How to Become a Market Leader
Small vs. Large Brands: How to Become a Market LeaderPercolate
 
11 Charts that Predict the Future of Marketing
11 Charts that Predict the Future of Marketing11 Charts that Predict the Future of Marketing
11 Charts that Predict the Future of MarketingPercolate
 
Percolate's Company Values
Percolate's Company ValuesPercolate's Company Values
Percolate's Company ValuesPercolate
 
7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...
7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...
7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...Percolate
 
How Much Does Marketing Really Cost?
How Much Does Marketing Really Cost?How Much Does Marketing Really Cost?
How Much Does Marketing Really Cost?Percolate
 
Technology Macro Trends - What Marketers Need to Know in 2014
Technology Macro Trends - What Marketers Need to Know in 2014Technology Macro Trends - What Marketers Need to Know in 2014
Technology Macro Trends - What Marketers Need to Know in 2014Percolate
 
State of Content Marketing
State of Content MarketingState of Content Marketing
State of Content MarketingPercolate
 
How Percolate uses CFEngine to Manage AWS Stateless Infrastructure
How Percolate uses CFEngine to Manage AWS Stateless InfrastructureHow Percolate uses CFEngine to Manage AWS Stateless Infrastructure
How Percolate uses CFEngine to Manage AWS Stateless InfrastructurePercolate
 
IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...
IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...
IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...Percolate
 
Building Community with American Express OPEN
Building Community with American Express OPENBuilding Community with American Express OPEN
Building Community with American Express OPENPercolate
 

More from Percolate (20)

7 Project Management Tips from Across Disciplines
7 Project Management Tips from Across Disciplines7 Project Management Tips from Across Disciplines
7 Project Management Tips from Across Disciplines
 
Moving from Stateful Components to Stateless Components
Moving from Stateful Components to Stateless ComponentsMoving from Stateful Components to Stateless Components
Moving from Stateful Components to Stateless Components
 
Content Strategy in a Changing World
Content Strategy in a Changing WorldContent Strategy in a Changing World
Content Strategy in a Changing World
 
Moving From MySQL to Elasticsearch for Analytics
Moving From MySQL to Elasticsearch for AnalyticsMoving From MySQL to Elasticsearch for Analytics
Moving From MySQL to Elasticsearch for Analytics
 
Percolate: Content Marketing 360: From Planning to Performance
Percolate: Content Marketing 360: From Planning to PerformancePercolate: Content Marketing 360: From Planning to Performance
Percolate: Content Marketing 360: From Planning to Performance
 
The 50 Most Important Marketing Charts of 2016
The 50 Most Important Marketing Charts of 2016The 50 Most Important Marketing Charts of 2016
The 50 Most Important Marketing Charts of 2016
 
The Secret to Brand Growth? Mental and Physical Availability
The Secret to Brand Growth? Mental and Physical AvailabilityThe Secret to Brand Growth? Mental and Physical Availability
The Secret to Brand Growth? Mental and Physical Availability
 
Advertising for the Long Term
Advertising for the Long TermAdvertising for the Long Term
Advertising for the Long Term
 
Be Distinctive, Not Different
Be Distinctive, Not DifferentBe Distinctive, Not Different
Be Distinctive, Not Different
 
Why Mass Marketing Wins Over Targeted Efforts
Why Mass Marketing Wins Over Targeted EffortsWhy Mass Marketing Wins Over Targeted Efforts
Why Mass Marketing Wins Over Targeted Efforts
 
Small vs. Large Brands: How to Become a Market Leader
Small vs. Large Brands: How to Become a Market LeaderSmall vs. Large Brands: How to Become a Market Leader
Small vs. Large Brands: How to Become a Market Leader
 
11 Charts that Predict the Future of Marketing
11 Charts that Predict the Future of Marketing11 Charts that Predict the Future of Marketing
11 Charts that Predict the Future of Marketing
 
Percolate's Company Values
Percolate's Company ValuesPercolate's Company Values
Percolate's Company Values
 
7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...
7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...
7 Lessons Marketers Can Learn From MasterCard to become a Global Publishing P...
 
How Much Does Marketing Really Cost?
How Much Does Marketing Really Cost?How Much Does Marketing Really Cost?
How Much Does Marketing Really Cost?
 
Technology Macro Trends - What Marketers Need to Know in 2014
Technology Macro Trends - What Marketers Need to Know in 2014Technology Macro Trends - What Marketers Need to Know in 2014
Technology Macro Trends - What Marketers Need to Know in 2014
 
State of Content Marketing
State of Content MarketingState of Content Marketing
State of Content Marketing
 
How Percolate uses CFEngine to Manage AWS Stateless Infrastructure
How Percolate uses CFEngine to Manage AWS Stateless InfrastructureHow Percolate uses CFEngine to Manage AWS Stateless Infrastructure
How Percolate uses CFEngine to Manage AWS Stateless Infrastructure
 
IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...
IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...
IPG Media Lab's Jack Pollock presents employees as signals at Percolate's #SP...
 
Building Community with American Express OPEN
Building Community with American Express OPENBuilding Community with American Express OPEN
Building Community with American Express OPEN
 

Recently uploaded

MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINESIVASHANKAR N
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
UNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its PerformanceUNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its Performancesivaprakash250
 
UNIT-II FMM-Flow Through Circular Conduits
UNIT-II FMM-Flow Through Circular ConduitsUNIT-II FMM-Flow Through Circular Conduits
UNIT-II FMM-Flow Through Circular Conduitsrknatarajan
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdfONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdfKamal Acharya
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...roncy bisnoi
 
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...Call Girls in Nagpur High Profile
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...Call Girls in Nagpur High Profile
 
AKTU Computer Networks notes --- Unit 3.pdf
AKTU Computer Networks notes ---  Unit 3.pdfAKTU Computer Networks notes ---  Unit 3.pdf
AKTU Computer Networks notes --- Unit 3.pdfankushspencer015
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordAsst.prof M.Gokilavani
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxAsutosh Ranjan
 
Introduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxIntroduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxupamatechverse
 
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escortsranjana rawat
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSISrknatarajan
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSSIVASHANKAR N
 

Recently uploaded (20)

MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
 
UNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its PerformanceUNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its Performance
 
UNIT-II FMM-Flow Through Circular Conduits
UNIT-II FMM-Flow Through Circular ConduitsUNIT-II FMM-Flow Through Circular Conduits
UNIT-II FMM-Flow Through Circular Conduits
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdfONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
 
Roadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and RoutesRoadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and Routes
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024
 
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
 
AKTU Computer Networks notes --- Unit 3.pdf
AKTU Computer Networks notes ---  Unit 3.pdfAKTU Computer Networks notes ---  Unit 3.pdf
AKTU Computer Networks notes --- Unit 3.pdf
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
Introduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxIntroduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptx
 
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSIS
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
 

Pratt Parser in Python

  • 1. Pratt Parser in Python Maxim Eronin 1 An exercise in design and implementation
  • 3. '2 + 3^4^5 * log2(8)' '2', '+', '3', '^', '4', '^', '5', '*', 'log2', '(', '8', ')' ws = 's+' name = '[a-z][w_]*' infix = '[+-*/^]' punct = '[(),]' number = '(d*.)?d+' 3
  • 4. Why write your own parser? ● It is not an as big a task as it might seem ● More control over the implementation details/techniques ● Many of the existing python parsing libraries are lacking in one or more areas ● Writing parsers is fun 4
  • 5. What is a Pratt Parser and why use it? ● Parsing technique designed for parsing operator precedence correctly ● First appeared in “Top Down Operator Precedence” by Vaughan Pratt (1973) ● A variation of a recursive descent parser but ○ Efficient ○ Modular and flexible ○ Easy to implement and and iterate upon ○ Beautiful 5
  • 6. Why isn’t it more popular? “One may wonder why such an "obviously" utopian approach has not been generally adopted already. I suspect the root cause of this kind of oversight is our universal preoccupation with BNF grammars and their various offspring grammars[...] together with their related automata and a large body of theorems. I am personally enamored of automata theory per se, but I am not impressed with the extent to which it has so far been successfully applied to the writing of compilers or interpreters. Nor do I see a particularly promising future in this direction. Rather, I see automata theory as holding back the development of ideas valuable to language design that are not visibly in the domain of automata theory.” Vaughan R. Pratt “Top Down Operator Precedence” 6
  • 7. Simple arithmetic expression grammar expression ::= mul-expr ( ( '+' | '-' ) mul-expr )* mul-expr ::= pow-expr ( ( '*' | '/' ) pow-expr )* pow-expr ::= prefix-expr ['^' pow-expr] prefix-expr ::= [ '-' ] primary primary ::= '(' expr ')' | number | name [ '(' expr ( ',' expr )* ')' ] 7
  • 8. Pratt parser: no grammar, only tokens nilfix '<number>', '<name>' infix '+', '-' 10 infix '*', '/' 20 infixr '^' 30 prefix '-' 40 infix '(' 50 8
  • 9. from expr_parser.lexer import lex from expr_parser.parser import Parser, Symbol, Literal, Infix, InfixR expr = Parser(lex) expr.define("<number>", 0, Literal) expr.define("<name>", 0, Literal) expr.define("+", 50, Infix) expr.define("*", 60, Infix) expr.define("/", 60, Infix) expr.define("^", 70, InfixR) @expr.define("-", 50) class Minus(Infix, Prefix): """This combines both Prefix' nud and Infix' led""" pass 9 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
  • 10. 10
  • 11. class Symbol(object): """Base class for all nodes""" id = None lbp = 0 def __init__(self, parser, value=None): self.parser = parser self.value = value or self.id self.first = None self.second = None def nud(self): """Null denotation. Prefix/Nilfix symbol""" raise ParserError("Symbol action undefined for `%s'" % self.value) def led(self, left): """Left denotation. Infix/Postfix symbol""" raise ParserError("Infix action undefined for `%s'" % self.value) 11 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18
  • 12. class Literal(Symbol): """Simple literal (a number or a variable/function name) just produces itself""" def nud(self): return self class Prefix(Symbol): """Prefix operator. For the sake of simplicity has fixed right binding power""" def nud(self): self.first = self.parser.expression(80) return self 12 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
  • 13. class Infix(Symbol): """Infix operator""" def led(self, left): self.first = left self.second = self.parser.expression(self.lbp) return self class InfixR(Infix): """Infix (right associative) operator""" def led(self, left): self.first = left self.second = self.parser.expression(self.lbp - 1) return self 13 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
  • 14. class Parser(object): """Main parser class. Contains both the grammar definition and a pointer to the current token stream""" def __init__(self, lex=lexer.lex): self.lex = lex self.symbol_table = {} self.define("<end>") self.tokens = iter(()) self.token = None def expression(self, rbp): tok = self.token self.advance() left = tok.nud() while rbp < self.token.lbp: tok = self.token self.advance() left = tok.led(left) return left 14 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19
  • 15. def advance(self, value=None): tok = self.token if value and value not in (tok.value, tok.id): raise ParserError( "Expected `%s'; got `%s' instead" % (value, tok.value)) try: tok = self.tokens.next() symbol_table = self.symbol_table # first look up token's value if tok.value in symbol_table: sym = symbol_table[tok.value] elif tok.token_type in symbol_table: # then token's type sym = symbol_table[tok.token_type] else: raise ParserError("Undefined token %s" % repr(tok)) self.token = sym(self, tok.value) except StopIteration: self.token = self.symbol_table["<end>"](self) return self.token 15 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
  • 16. def define(self, sid, bp=0, symbol_class=Symbol): symbol_table = self.symbol_table sym = symbol_table[sid] = type( symbol_class.__name__, (symbol_class,), {'id': sid, 'lbp': bp} ) def wrapper(val): val.id = sid val.lbp = sym.lbp symbol_table[sid] = val return val return wrapper 16 01 02 03 04 05 06 07 08 09 10 11 12 13
  • 17. def parse(self, source): try: self.tokens = self.lex(source) self.advance() return self.expression(0) finally: self.tokens = iter(()) self.token = None 17 01 02 03 04 05 06 07 08
  • 18. expr.define("<punct>") @expr.define("(", 90) class FunctionCall(Symbol): """Defining both function application and parenthesized expression""" def nud(self): e = self.parser.expression(0) self.parser.advance(")") return e def led(self, left): self.first = left args = self.second = [] p = self.parser while p.token.value != ")": args.append(p.expression(0)) if p.token.value != ",": break p.advance(",") p.advance(")") return self 18 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
  • 19. TOKENS = ( ('ws', r's+'), ('name', r'[a-z][w_]*'), ('infix', r'[+-*/^]'), ('punct', r'[(),]'), ('number', r'(:?d*.)?d+'), ) TOKEN_RE = '|'.join("(?P<%s>%s)" % t for t in TOKENS) LEX_RE = re.compile(TOKEN_RE, re.UNICODE | re.IGNORECASE) class Token(object): def __init__(self, token_type, value, pos): self.token_type = token_type self.value = value self.pos = pos But what about lexing? 19 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
  • 20. def lex(source, pat=LEX_RE): i = 0 def error(): raise LexerException( "Unexpected character at position %d: `%s`" % (i, source[i]) ) for m in pat.finditer(source): pos = m.start() if pos > i: error() i = m.end() name = m.lastgroup if name != "ws": token_type = "<%s>" % name yield Token(token_type, m.group(0), pos) if i < len(source): error() 20 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19
  • 21. ● https://tdop.github.io/ Vaughan R. Pratt "Top Down Operator Precedence" (1973) ● http://javascript.crockford.com/tdop/tdop.html Douglas Crockford "Top Down Operator Precedence" (2007) ● http://effbot.org/zone/simple-top-down-parsing.htm Fredrik Lundh "Simple Top-Down Parsing in Python" (2008) All code in this presentation can be found at: https://github.com/percolate/pratt-parser References 21 We are Percolate and we’re always hiring great engineers. Talk to us