| @@ -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") | |||||
| ``` | |||||
|  | |||||
| ## 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 | ||||