SlideShare ist ein Scribd-Unternehmen logo
1 von 17
Text parsing with Python and PLY 
Daniil Baturin <daniil@baturin.org> 
LVEE 2014
Formal language 
Set of strings composed of symbols of some alphabet. 
A language can be defined by a formal grammar. 
Two or more grammars may produce the same language. 
Forward problem: given a grammar, generate a string that 
belongs a language (trivial). 
Parsing is the inverse problem: given a string, decide if it 
belongs a language defined by a grammar.
Formal grammar 
Formal grammar is a set of production rules. 
A production rule has a one or more symbols at its left-hand and right-hand sides. 
You need to specify the start symbol. 
Example: 
<sentence> ::= <verb phrase> <noun phrase> 
<noun phrase> ::= <article> <adjective> <noun> 
<verb phrase> ::= <verb> <article> <noun> 
<article> ::= <”a” | “the” | empty> 
... 
“sentence” is the start symbol.
Lexers and tokens 
Lexer—breaks the text into tokens, string 
literals with metadata. 
Tokens are identified by regular expressions. 
Parsers usually operate on tokens rather than 
string literals. E.g. all numbers ([0-9]+) become 
TOKEN(NUMBER, value). 
Lexer can be autogenerated or hand-coded.
Symbols 
Terminal symbols are symbols that can't be 
further reduced (rewritten). 
Non-terminal symbols are composed from 
references to terminals and other non-terminals. 
<article> ::= <”a” | “the” | empty> 
“Article” is a non-terminal; “a”, “the”, empty are 
terminals.
Approaches to parsing 
● Hand-coded ad-hoc parser 
● Autogenerated parser 
● Hand-coded advanced algorithm
Regular grammar 
All production rules are of the following form: 
<some nonterminal> ::= <some terminal> 
<some nonterminal> ::= <some terminal> <another nonterminal> 
<some nonterminal> ::= <empty> 
Equivalent to regular expressions. 
“(a|b)*” regex: 
<start> ::= “a” <start> 
| “b” <start> 
| <empty> 
This is good for a hand-coded parser (or a regex library).
Context-free grammar 
All productions are of the following form: 
<some nonterminal> ::= <some terminals or nonterminals> 
Good for autogenerated parsers. Ad-hoc 
parsers tend to be messy.
More complex grammars 
Context-sensitive: rules may contain terminals 
and nonterminals in both sides. 
Can be conquered with special tools or lexer 
hacks. 
Not even context-sensitive: you are in trouble. ;)
Parser generators 
Usually use LALR(1) method. 
Read a token and push it on stack. 
If some rule is matched, empty the stack and 
proceed (reduce). 
If not, push the token on stack and proceed 
(shift).
PLY Lex—the lexer generator 
Token recognizers are functions. 
Token regexes are in docstrings. 
You should export a tuple of all tokens for use in 
a parser. 
def t_NUMBER(t): 
r'[0­9]+' 
t.value = int(t.value) 
return t
PLY YACC—the parser generator 
Production rule recognizers are functions. 
Rules are in docstrings. 
Rules can refer to other rules and can be recursive. 
You can refer to lexer tokens in rules. 
The argument is the token list. 
def p_expr(p): 
''' expr : NUMBER OPSIGN NUMBER ''' 
p[0] = (p[2], p[1], p[3])
Grammar “patterns” 
The rule form used by YACC doesn't have a 
notation for repetition etc. 
Empty: 
something : 
This or that: 
something : foo | bar 
One or more of something: 
list_of_something : list_of_something something 
| something
Common problems 
Shift-reduce conflict: two or more rules have more than 
one common token at the beginning. 
foo : baz quux xyzzy 
bar : baz quux fgsfds 
Usually can be solved by left factorization: 
foobar_start : baz quux 
foo : foobar_start xyzzy 
bar : foobar_start fgsfds 
Default resolution is shift. 
Reduce-reduce conflict: same string matches more 
than one rule. Often indicates a grammar design error.
What I didn't tell 
Exclusive lexer states. 
Precedence rules. 
Wrapping lexers and parsers into classes. 
Error recovery.
The sample code 
https://github.com/dmbaturin/ply-example
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

The Java Script Programming Language
The  Java Script  Programming  LanguageThe  Java Script  Programming  Language
The Java Script Programming Language
zone
 
Chapter Three(2)
Chapter Three(2)Chapter Three(2)
Chapter Three(2)
bolovv
 
Convention-Based Syntactic Descriptions
Convention-Based Syntactic DescriptionsConvention-Based Syntactic Descriptions
Convention-Based Syntactic Descriptions
Ray Toal
 
Chapter Two(1)
Chapter Two(1)Chapter Two(1)
Chapter Two(1)
bolovv
 

Was ist angesagt? (19)

Regular Expressions in PHP
Regular Expressions in PHPRegular Expressions in PHP
Regular Expressions in PHP
 
Lesson 03 python statement, indentation and comments
Lesson 03   python statement, indentation and commentsLesson 03   python statement, indentation and comments
Lesson 03 python statement, indentation and comments
 
The JavaScript Programming Language
The JavaScript Programming LanguageThe JavaScript Programming Language
The JavaScript Programming Language
 
The Java Script Programming Language
The  Java Script  Programming  LanguageThe  Java Script  Programming  Language
The Java Script Programming Language
 
Javascript
JavascriptJavascript
Javascript
 
Regular Expression in Compiler design
Regular Expression in Compiler designRegular Expression in Compiler design
Regular Expression in Compiler design
 
Python revision tour II
Python revision tour IIPython revision tour II
Python revision tour II
 
Chapter 9 python fundamentals
Chapter 9 python fundamentalsChapter 9 python fundamentals
Chapter 9 python fundamentals
 
Chapter Three(2)
Chapter Three(2)Chapter Three(2)
Chapter Three(2)
 
Programming with Python
Programming with PythonProgramming with Python
Programming with Python
 
Convention-Based Syntactic Descriptions
Convention-Based Syntactic DescriptionsConvention-Based Syntactic Descriptions
Convention-Based Syntactic Descriptions
 
Context Free Grammar
Context Free GrammarContext Free Grammar
Context Free Grammar
 
Chapter3pptx__2021_12_23_22_52_54.pptx
Chapter3pptx__2021_12_23_22_52_54.pptxChapter3pptx__2021_12_23_22_52_54.pptx
Chapter3pptx__2021_12_23_22_52_54.pptx
 
Python revision tour i
Python revision tour iPython revision tour i
Python revision tour i
 
Chapter Two(1)
Chapter Two(1)Chapter Two(1)
Chapter Two(1)
 
Compiler lecture 05
Compiler lecture 05Compiler lecture 05
Compiler lecture 05
 
Python syntax
Python syntaxPython syntax
Python syntax
 
Basic syntax supported by python
Basic syntax supported by pythonBasic syntax supported by python
Basic syntax supported by python
 
Types of Language in Theory of Computation
Types of Language in Theory of ComputationTypes of Language in Theory of Computation
Types of Language in Theory of Computation
 

Andere mochten auch

PyCon PH 2014 - GeoComputation
PyCon PH 2014 - GeoComputationPyCon PH 2014 - GeoComputation
PyCon PH 2014 - GeoComputation
Ranel Padon
 
Python Programming - X. Exception Handling and Assertions
Python Programming - X. Exception Handling and AssertionsPython Programming - X. Exception Handling and Assertions
Python Programming - X. Exception Handling and Assertions
Ranel Padon
 
Python for text processing
Python for text processingPython for text processing
Python for text processing
Xiang Li
 
Python Programming - VII. Customizing Classes and Operator Overloading
Python Programming - VII. Customizing Classes and Operator OverloadingPython Programming - VII. Customizing Classes and Operator Overloading
Python Programming - VII. Customizing Classes and Operator Overloading
Ranel Padon
 
Python Programming - IX. On Randomness
Python Programming - IX. On RandomnessPython Programming - IX. On Randomness
Python Programming - IX. On Randomness
Ranel Padon
 
Python Programming - VIII. Inheritance and Polymorphism
Python Programming - VIII. Inheritance and PolymorphismPython Programming - VIII. Inheritance and Polymorphism
Python Programming - VIII. Inheritance and Polymorphism
Ranel Padon
 

Andere mochten auch (20)

Text analysis using python
Text analysis using pythonText analysis using python
Text analysis using python
 
Views Unlimited: Unleashing the Power of Drupal's Views Module
Views Unlimited: Unleashing the Power of Drupal's Views ModuleViews Unlimited: Unleashing the Power of Drupal's Views Module
Views Unlimited: Unleashing the Power of Drupal's Views Module
 
PyCon PH 2014 - GeoComputation
PyCon PH 2014 - GeoComputationPyCon PH 2014 - GeoComputation
PyCon PH 2014 - GeoComputation
 
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
 
Generator Tricks for Systems Programmers
Generator Tricks for Systems ProgrammersGenerator Tricks for Systems Programmers
Generator Tricks for Systems Programmers
 
WAD : A Module for Converting Fatal Extension Errors into Python Exceptions
WAD : A Module for Converting Fatal Extension Errors into Python ExceptionsWAD : A Module for Converting Fatal Extension Errors into Python Exceptions
WAD : A Module for Converting Fatal Extension Errors into Python Exceptions
 
Understanding the Python GIL
Understanding the Python GILUnderstanding the Python GIL
Understanding the Python GIL
 
CKEditor Widgets with Drupal
CKEditor Widgets with DrupalCKEditor Widgets with Drupal
CKEditor Widgets with Drupal
 
SWIG : An Easy to Use Tool for Integrating Scripting Languages with C and C++
SWIG : An Easy to Use Tool for Integrating Scripting Languages with C and C++SWIG : An Easy to Use Tool for Integrating Scripting Languages with C and C++
SWIG : An Easy to Use Tool for Integrating Scripting Languages with C and C++
 
Generator Tricks for Systems Programmers, v2.0
Generator Tricks for Systems Programmers, v2.0Generator Tricks for Systems Programmers, v2.0
Generator Tricks for Systems Programmers, v2.0
 
Why Extension Programmers Should Stop Worrying About Parsing and Start Thinki...
Why Extension Programmers Should Stop Worrying About Parsing and Start Thinki...Why Extension Programmers Should Stop Worrying About Parsing and Start Thinki...
Why Extension Programmers Should Stop Worrying About Parsing and Start Thinki...
 
Python introduction
Python introductionPython introduction
Python introduction
 
Python Programming - X. Exception Handling and Assertions
Python Programming - X. Exception Handling and AssertionsPython Programming - X. Exception Handling and Assertions
Python Programming - X. Exception Handling and Assertions
 
Python for text processing
Python for text processingPython for text processing
Python for text processing
 
Python Programming - III. Controlling the Flow
Python Programming - III. Controlling the FlowPython Programming - III. Controlling the Flow
Python Programming - III. Controlling the Flow
 
The Synergy of Drupal Hooks/APIs (Custom Module Development with ChartJS)
The Synergy of Drupal Hooks/APIs (Custom Module Development with ChartJS)The Synergy of Drupal Hooks/APIs (Custom Module Development with ChartJS)
The Synergy of Drupal Hooks/APIs (Custom Module Development with ChartJS)
 
Python Programming - VII. Customizing Classes and Operator Overloading
Python Programming - VII. Customizing Classes and Operator OverloadingPython Programming - VII. Customizing Classes and Operator Overloading
Python Programming - VII. Customizing Classes and Operator Overloading
 
Switchable Map APIs with Drupal
Switchable Map APIs with DrupalSwitchable Map APIs with Drupal
Switchable Map APIs with Drupal
 
Python Programming - IX. On Randomness
Python Programming - IX. On RandomnessPython Programming - IX. On Randomness
Python Programming - IX. On Randomness
 
Python Programming - VIII. Inheritance and Polymorphism
Python Programming - VIII. Inheritance and PolymorphismPython Programming - VIII. Inheritance and Polymorphism
Python Programming - VIII. Inheritance and Polymorphism
 

Ähnlich wie LVEE 2014: Text parsing with Python and PLY

Introduction of bison
Introduction of bisonIntroduction of bison
Introduction of bison
vip_du
 
match the following attributes to the parts of a compilerstrips ou.pdf
match the following attributes to the parts of a compilerstrips ou.pdfmatch the following attributes to the parts of a compilerstrips ou.pdf
match the following attributes to the parts of a compilerstrips ou.pdf
arpitaeron555
 

Ähnlich wie LVEE 2014: Text parsing with Python and PLY (20)

Chapter-3 compiler.pptx course materials
Chapter-3 compiler.pptx course materialsChapter-3 compiler.pptx course materials
Chapter-3 compiler.pptx course materials
 
Control structure
Control structureControl structure
Control structure
 
Lex and Yacc ppt
Lex and Yacc pptLex and Yacc ppt
Lex and Yacc ppt
 
Lexical
LexicalLexical
Lexical
 
Pcd question bank
Pcd question bank Pcd question bank
Pcd question bank
 
3a. Context Free Grammar.pdf
3a. Context Free Grammar.pdf3a. Context Free Grammar.pdf
3a. Context Free Grammar.pdf
 
Syntax analysis
Syntax analysisSyntax analysis
Syntax analysis
 
9781284077247_PPTx_CH01.pptx
9781284077247_PPTx_CH01.pptx9781284077247_PPTx_CH01.pptx
9781284077247_PPTx_CH01.pptx
 
CH 2.pptx
CH 2.pptxCH 2.pptx
CH 2.pptx
 
Compiler Design
Compiler DesignCompiler Design
Compiler Design
 
Python Programming Basics for begginners
Python Programming Basics for begginnersPython Programming Basics for begginners
Python Programming Basics for begginners
 
Lexical analysis - Compiler Design
Lexical analysis - Compiler DesignLexical analysis - Compiler Design
Lexical analysis - Compiler Design
 
Parser
ParserParser
Parser
 
Quick start reg ex
Quick start reg exQuick start reg ex
Quick start reg ex
 
Programming_Language_Syntax.ppt
Programming_Language_Syntax.pptProgramming_Language_Syntax.ppt
Programming_Language_Syntax.ppt
 
lex and yacc.pdf
lex and yacc.pdflex and yacc.pdf
lex and yacc.pdf
 
Introduction of bison
Introduction of bisonIntroduction of bison
Introduction of bison
 
match the following attributes to the parts of a compilerstrips ou.pdf
match the following attributes to the parts of a compilerstrips ou.pdfmatch the following attributes to the parts of a compilerstrips ou.pdf
match the following attributes to the parts of a compilerstrips ou.pdf
 
Using ANTLR on real example - convert "string combined" queries into paramete...
Using ANTLR on real example - convert "string combined" queries into paramete...Using ANTLR on real example - convert "string combined" queries into paramete...
Using ANTLR on real example - convert "string combined" queries into paramete...
 
New compiler design 101 April 13 2024.pdf
New compiler design 101 April 13 2024.pdfNew compiler design 101 April 13 2024.pdf
New compiler design 101 April 13 2024.pdf
 

Kürzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Kürzlich hochgeladen (20)

The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 

LVEE 2014: Text parsing with Python and PLY

  • 1. Text parsing with Python and PLY Daniil Baturin <daniil@baturin.org> LVEE 2014
  • 2. Formal language Set of strings composed of symbols of some alphabet. A language can be defined by a formal grammar. Two or more grammars may produce the same language. Forward problem: given a grammar, generate a string that belongs a language (trivial). Parsing is the inverse problem: given a string, decide if it belongs a language defined by a grammar.
  • 3. Formal grammar Formal grammar is a set of production rules. A production rule has a one or more symbols at its left-hand and right-hand sides. You need to specify the start symbol. Example: <sentence> ::= <verb phrase> <noun phrase> <noun phrase> ::= <article> <adjective> <noun> <verb phrase> ::= <verb> <article> <noun> <article> ::= <”a” | “the” | empty> ... “sentence” is the start symbol.
  • 4. Lexers and tokens Lexer—breaks the text into tokens, string literals with metadata. Tokens are identified by regular expressions. Parsers usually operate on tokens rather than string literals. E.g. all numbers ([0-9]+) become TOKEN(NUMBER, value). Lexer can be autogenerated or hand-coded.
  • 5. Symbols Terminal symbols are symbols that can't be further reduced (rewritten). Non-terminal symbols are composed from references to terminals and other non-terminals. <article> ::= <”a” | “the” | empty> “Article” is a non-terminal; “a”, “the”, empty are terminals.
  • 6. Approaches to parsing ● Hand-coded ad-hoc parser ● Autogenerated parser ● Hand-coded advanced algorithm
  • 7. Regular grammar All production rules are of the following form: <some nonterminal> ::= <some terminal> <some nonterminal> ::= <some terminal> <another nonterminal> <some nonterminal> ::= <empty> Equivalent to regular expressions. “(a|b)*” regex: <start> ::= “a” <start> | “b” <start> | <empty> This is good for a hand-coded parser (or a regex library).
  • 8. Context-free grammar All productions are of the following form: <some nonterminal> ::= <some terminals or nonterminals> Good for autogenerated parsers. Ad-hoc parsers tend to be messy.
  • 9. More complex grammars Context-sensitive: rules may contain terminals and nonterminals in both sides. Can be conquered with special tools or lexer hacks. Not even context-sensitive: you are in trouble. ;)
  • 10. Parser generators Usually use LALR(1) method. Read a token and push it on stack. If some rule is matched, empty the stack and proceed (reduce). If not, push the token on stack and proceed (shift).
  • 11. PLY Lex—the lexer generator Token recognizers are functions. Token regexes are in docstrings. You should export a tuple of all tokens for use in a parser. def t_NUMBER(t): r'[0­9]+' t.value = int(t.value) return t
  • 12. PLY YACC—the parser generator Production rule recognizers are functions. Rules are in docstrings. Rules can refer to other rules and can be recursive. You can refer to lexer tokens in rules. The argument is the token list. def p_expr(p): ''' expr : NUMBER OPSIGN NUMBER ''' p[0] = (p[2], p[1], p[3])
  • 13. Grammar “patterns” The rule form used by YACC doesn't have a notation for repetition etc. Empty: something : This or that: something : foo | bar One or more of something: list_of_something : list_of_something something | something
  • 14. Common problems Shift-reduce conflict: two or more rules have more than one common token at the beginning. foo : baz quux xyzzy bar : baz quux fgsfds Usually can be solved by left factorization: foobar_start : baz quux foo : foobar_start xyzzy bar : foobar_start fgsfds Default resolution is shift. Reduce-reduce conflict: same string matches more than one rule. Often indicates a grammar design error.
  • 15. What I didn't tell Exclusive lexer states. Precedence rules. Wrapping lexers and parsers into classes. Error recovery.
  • 16. The sample code https://github.com/dmbaturin/ply-example