@@ -1 +1 @@ | |||||
include README.md LICENSE docs/* examples/*.py tests/*.py | |||||
include README.md LICENSE docs/* examples/*.py tests/*.py examples/*.png |
@@ -74,9 +74,44 @@ Then, the transformer calculates the tree and returns a number: | |||||
1337.0 | 1337.0 | ||||
``` | ``` | ||||
### Fruit Flies Like Bananas | |||||
Lark can automatically resolve ambiguity by choosing the simplest solution. Or, you can ask it to return all the possible parse trees, wrapped in a meta "\_ambig" node. | |||||
Here's a toy example to parse the famously ambiguous phrase: "fruit flies like bananas" | |||||
```python | |||||
from lark import Lark | |||||
grammar = """ | |||||
sentence: noun verb noun -> simple | |||||
| noun verb "like" noun -> comparative | |||||
noun: adj? NOUN | |||||
verb: VERB | |||||
adj: ADJ | |||||
NOUN: "flies" | "bananas" | "fruit" | |||||
VERB: "like" | "flies" | |||||
ADJ: "fruit" | |||||
%import common.WS | |||||
%ignore WS | |||||
""" | |||||
parser = Lark(grammar, start='sentence', ambiguity='explicit') # Explicit ambiguity in parse tree! | |||||
tree = fruitflies.parser.parse('fruit flies like bananas') | |||||
from lark.tree import pydot__tree_to_png # Just a neat utility function | |||||
pydot__tree_to_png(tree, "examples/fruitflies.png") | |||||
``` | |||||
![fruitflies.png](examples/fruitflies.png) | |||||
## Learn more about using Lark | ## Learn more about using Lark | ||||
- **Read the [tutorial](/docs/json_tutorial.md)**, which shows how to write a JSON parser in Lark. | - **Read the [tutorial](/docs/json_tutorial.md)**, which shows how to write a JSON parser in Lark. | ||||
- Read a blog post: [How to write a DSL with Lark](http://blog.erezsh.com/how-to-write-a-dsl-in-python-with-lark/) | |||||
- Read the [reference](/docs/reference.md) | - Read the [reference](/docs/reference.md) | ||||
- Browse the [examples](/examples), which include a calculator, and a Python-code parser. | - Browse the [examples](/examples), which include a calculator, and a Python-code parser. | ||||
- Check out the [tests](/tests/test_parser.py) for more examples. | - Check out the [tests](/tests/test_parser.py) for more examples. | ||||
@@ -4,12 +4,13 @@ | |||||
from lark import Lark | from lark import Lark | ||||
g = """ | |||||
grammar = """ | |||||
sentence: noun verb noun -> simple | sentence: noun verb noun -> simple | ||||
| noun verb "like" noun -> comparative | | noun verb "like" noun -> comparative | ||||
noun: ADJ? NOUN | |||||
noun: adj? NOUN | |||||
verb: VERB | verb: VERB | ||||
adj: ADJ | |||||
NOUN: "flies" | "bananas" | "fruit" | NOUN: "flies" | "bananas" | "fruit" | ||||
VERB: "like" | "flies" | VERB: "like" | "flies" | ||||
@@ -19,11 +20,12 @@ g = """ | |||||
%ignore WS | %ignore WS | ||||
""" | """ | ||||
lark = Lark(g, start='sentence', ambiguity='explicit') | |||||
parser = Lark(grammar, start='sentence', ambiguity='explicit') | |||||
print(lark.parse('fruit flies like bananas').pretty()) | |||||
if __name__ == '__main__': | |||||
print(parser.parse('fruit flies like bananas').pretty()) | |||||
# Outputs: | |||||
# Output: | |||||
# | # | ||||
# _ambig | # _ambig | ||||
# comparative | # comparative | ||||
@@ -36,4 +38,5 @@ print(lark.parse('fruit flies like bananas').pretty()) | |||||
# flies | # flies | ||||
# verb like | # verb like | ||||
# noun bananas | # noun bananas | ||||
# | |||||
# (or view a nicer version at "./fruitflies.png") |
@@ -147,3 +147,35 @@ class Transformer_NoRecurse(Transformer): | |||||
def __default__(self, t): | def __default__(self, t): | ||||
return t | return t | ||||
def pydot__tree_to_png(tree, filename): | |||||
import pydot | |||||
graph = pydot.Dot(graph_type='digraph', rankdir="LR") | |||||
i = [0] | |||||
def new_leaf(leaf): | |||||
node = pydot.Node(i[0], label=repr(leaf)) | |||||
i[0] += 1 | |||||
graph.add_node(node) | |||||
return node | |||||
def _to_pydot(subtree): | |||||
color = hash(subtree.data) & 0xffffff | |||||
if not (color & 0x808080): | |||||
color |= 0x808080 | |||||
subnodes = [_to_pydot(child) if isinstance(child, Tree) else new_leaf(child) | |||||
for child in subtree.children] | |||||
node = pydot.Node(i[0], style="filled", fillcolor="#%x"%color, label=subtree.data) | |||||
i[0] += 1 | |||||
graph.add_node(node) | |||||
for subnode in subnodes: | |||||
graph.add_edge(pydot.Edge(node, subnode)) | |||||
return node | |||||
_to_pydot(tree) | |||||
graph.write_png(filename) | |||||
@@ -80,3 +80,7 @@ except NameError: | |||||
return 1 | return 1 | ||||
else: | else: | ||||
return -1 | return -1 | ||||