pax_global_header00006660000000000000000000000064141542744020014515gustar00rootroot0000000000000052 comment=eaa1062beced93061f1184682290136a82b6a490 baron-0.10.1/000077500000000000000000000000001415427440200126755ustar00rootroot00000000000000baron-0.10.1/.env000066400000000000000000000000761415427440200134710ustar00rootroot00000000000000#!/bin/zsh source $(/bin/readlink -f ${0%/*})/ve/bin/activate baron-0.10.1/.gitignore000066400000000000000000000001071415427440200146630ustar00rootroot00000000000000*.pyc *.swp *.swo __pycache__ .coverage .pytest_cache/ baron.egg-info/ baron-0.10.1/.travis.yml000066400000000000000000000003101415427440200150000ustar00rootroot00000000000000language: python install: "pip install -r requirements.txt" python: - "2.7" - "3.4" - "3.5" - "3.6" - "3.7" script: "py.test tests" notifications: irc: "chat.freenode.net#baron" baron-0.10.1/CHANGELOG000066400000000000000000000206551415427440200141170ustar00rootroot00000000000000Changelog ========= 0.10.1 (2021-12-08) ----------------- - bug fix: in "a._" the "._" part was incorrectly recognized as a float, by bram 0.10 (2021-12-08) ----------------- - bug fix: baron is now able to parse "class A(b, c=d): pass" by bram - some project cleaned and integration of tox with good pratices like flake8 and check-manifest - bug fix for missing edge case in inner formatting by EhsanKia https://github.com/PyCQA/baron/pull/156 - complet support for float with underscores in them by tamentis https://github.com/PyCQA/baron/pull/157 - bug fix for failure of parsing of "{**a}" by wavenator https://github.com/PyCQA/baron/pull/161 0.9 (2019-02-01) ---------------- First version of full python 3.7 grammar support. - BREAKING CHANGE: annotations are now member of {def,list,dict}_argument to flatten the data structure - add support for ... in from import by bram - add support for return annotation by bram - add support for exec function by bram - add support for variable annotation https://github.com/PyCQA/baron/pull/145 by scottbelden and additional work by bram - add support for *var expressions in tuple assignment by bram - add support for raise from https://github.com/PyCQA/baron/pull/120 by odcinek with additional work by bram - add support for arglist usage in class definition inheritence by bram - bug fix by https://github.com/PyCQA/baron/pull/126/commits/91e839a228293698cc755a7f28afeca2669cb66e kyleatmakrs 0.8 (2018-10-29) ---------------- - add typed parameters support https://github.com/PyCQA/baron/pull/140 by Scott Belden and and additional work by bram 0.7 (2018-08-21) ---------------- - fix line continuation https://github.com/PyCQA/baron/pull/92 by ibizaman - handle corrupt cache file situation https://github.com/PyCQA/baron/pull/76 by ryu2 - fix special crashing edge case in indentation marker https://github.com/PyCQA/bar by Ahuge - fixed incorrect tokenization case "d*e-1". Fixes #85 https://github.com/PyCQA/baron/pull/107 by boxed - fix endl handling inside groupings by kyleatmakrs (extracted from https://github.com/PyCQA/baron/pull/126) Python 3: - python 3 parsing extracted from https://github.com/PyCQA/baron/pull/126 - support ellipsis https://github.com/PyCQA/baron/pull/121 by odcinek - support matrix operator https://github.com/PyCQA/baron/pull/117 by odcinek - support f-strings https://github.com/PyCQA/baron/pull/110 by odcinek - support numeric literals https://github.com/PyCQA/baron/pull/111 by odcinek - support nonlocal statement https://github.com/PyCQA/baron/pull/112 by odcinek - support keyword only markers https://github.com/PyCQA/baron/pull/108 by boxed - support yield from statement https://github.com/PyCQA/baron/pull/113 by odcinek and additional work by bram - support async/await statements https://github.com/PyCQA/baron/pull/114 by odcinek and additional work by bram 0.6.6 (2017-06-12) ------------------ - fix situation where a deindented comment between a if and elif/else broken parsing, see https://github.com/PyCQA/baron/issues/87 - around 35-40% to 75% parsing speed improvment on big files by duncf https://github.com/PyCQA/baron/pull/99 0.6.5 (2017-01-26) ------------------ - fix previous regression fix was broken 0.6.4 (2017-01-14) ------------------ - fix regression in case a comment follow the ":" of a if/def/other 0.6.3 (2017-01-02) ------------------ - group formatting at start of file or preceded by space with comment 0.6.2 (2016-03-18) ------------------ - fix race condition when generating parser cache file - make all user-facing errors inherit from the same BaronError class - fix: dotted_name and float_exponant_complex were missing from nodes_rendering_order 0.6.1 (2015-01-31) ------------------ - fix: the string was having a greedy behavior on grouping the string tokens surrounding it (for string chains), this ends up creating an inconsistancy in the way string was grouped in general - fix: better number parsing handling, everything isn't fixed yet - make all (expected) errors inherit from the same BaronError class - fix: parsing fails correctly if a quoted string is not closed 0.6 (2014-12-11) ---------------- - FST structure modification: def_argument_tuple is no more and all arguments now have a coherent structure: * def_argument node name attribute has been renamed to target, like in assign * target attribute now points to a dict, not to a string * old name -> string are now target -> name_node * def_argument_tuple is now a def_argument where target points to a tuple * this specific tuple will only has name and comma and tuple members (no more def_argument for name) - new node: long, before int and long where merged but that was causing problems 0.5 (2014-11-10) ---------------- - rename "funcdef" node to "def" node to be way more intuitive. 0.4 (2014-09-29) ---------------- - new rendering type in the nodes_rendering_order dictionary: string. This remove an ambiguity where a key could be pointing to a dict or a string, thus forcing third party tools to do guessing. 0.3.1 (2014-09-04) ------------------ - setup.py wasn't working if wheel wasn't used because the CHANGELOG file wasn't included in the MANIFEST.in 0.3 (2014-08-21) ---------------- - path becomes a simple list and is easier to deal with - bounding box allows you to know the left most and right most position of a node see https://baron.readthedocs.io/en/latest/#bounding-box - redbaron is classified as supporting python3 https://github.com/PyCQA/baron/pull/51 - ensure than when a key is a string, it's empty value is an empty string and not None to avoid breaking libs that use introspection to guess the type of the key - key renaming in the FST: "delimiteur" -> "delimiter" - name_as_name and dotted_as_name node don't have the "as" key anymore as it was useless (it can be deduce from the state of the "target" key) - dotted_name node doesn't exist anymore, its existance was unjustified. In import, from_import and decorator node, it has been replaced from a key to a dict (with only a list inside of it) to a simple list. - dumps now accept a strict boolean argument to check the validity of the FST on dumping, but this isn't that much a public feature and should probably be changed of API in the futur - name_as_name and dotted_as_name empty value for target is now an empty string and not None since this is a string type key - boundingbox now includes the newlines at the end of a node - all raised exceptions inherit from a common base exception to ease try/catch constructions - Position's left and right functions become properties and thus attributes - Position objects can be compared to other Position objects or any iterables - make_position and make_bounding_box functions are deleted in favor of always using the corresponding class' constructor 0.2 (2014-06-11) ---------------- - Baron now provides documentation on https://baron.readthedocs.io - feature: baron now run in python3 (*but* doesn't implement the full python3 grammar yet) by Pierre Penninckx https://github.com/ibizaman - feature: drop the usage of ast.py to find print_function, this allow any version of python to parse any other version of python also by Pierre Penninckx - fix: rare bug where a comment end up being confused as an indentation level - 2 new helpers: show_file and show_node, see https://baron.readthedocs.io/en/latest/#show-file and https://baron.readthedocs.io/en/latest/#show-node - new dictionary that provides the informations on how to render a FST node: nodes_rendering_order see https://baron.readthedocs.io/en/latest/#rendering-the-fst - new utilities to find a node, see https://baron.readthedocs.io/en/latest/#locate-a-node - new generic class that provide templates to work on the FST see https://baron.readthedocs.io/en/latest/#rendering-the-fst 0.1.3 (2014-04-13) ------------------ - set sugar syntaxic notation wasn't handled by the dumper (apparently no one use this on pypi top 100) 0.1.2 (2014-04-08) ------------------ - baron.dumps now accept a single FST node, it was only working with a list of FST nodes - don't add a endl node at the end if not present in the input string - de-uniformise call_arguments and function_arguments node, this is just creating more problems that anything else - fix https://github.com/PyCQA/redbaron/issues/4 - fix the fact that baron can't parse "{1,}" (but "{1}" is working) 0.1.1 (2014-03-23) ------------------ - It appears that I don't know how to write MANIFEST.in correctly 0.1 (2014-03-22) ---------------- - Init baron-0.10.1/LICENSE000066400000000000000000000167431415427440200137150ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. baron-0.10.1/MANIFEST.in000066400000000000000000000002471415427440200144360ustar00rootroot00000000000000include *.md CHANGELOG LICENSE include tox.ini exclude *.txt recursive-include docs * graft tests prune docs/_build prune grammar reverse-exclude */__pycache__/* baron-0.10.1/README.md000066400000000000000000000153561415427440200141660ustar00rootroot00000000000000Introduction ============ Baron is a Full Syntax Tree (FST) library for Python. By opposition to an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) which drops some syntax information in the process of its creation (like empty lines, comments, formatting), a FST keeps everything and guarantees the operation fst\_to\_code(code\_to\_fst(source\_code)) == source\_code. Roadmap ======= Current roadmap is as boring as needed: * bug fixs * new small features (walker pattern, maybe code generation) and performance improvement. Installation ============ pip install baron Basic Usage =========== ```python from baron import parse, dumps fst = parse(source_code_string) source_code_string == dumps(fst) ``` Unless you want to do low level things, **use [RedBaron](https://github.com/PyCQA/redbaron) instead of using Baron directly**. Think of Baron as the "bytecode of python source code" and RedBaron as some sort of usable layer on top of it. If you don't know what Baron is or don't understand yet why it might be useful for you, read the [« Why is this important? » section](#why-is-this-important). Documentation ============= Baron documentation is available on [Read The Docs](http://baron.readthedocs.io/en/latest/). Contributing ============ If you want to implement new grammar elements for newer python versions, here are the documented steps for that: https://github.com/PyCQA/baron/blob/master/add_new_grammar.md Also note that reviewing most grammar modifications takes several hours of advanced focusing (we can't really afford bugs here) so don't despair if you PR seems to be hanging around, sorry for that :/ And thanks in advance for your work! Financial support ================= Baron and RedBaron are a very advanced piece of engineering that requires a lot of time of concentration to work on. Until the end of 2018, the development has been a full volunteer work mostly done by [Bram](https://github.com/psycojoker), but now, to reach the next level and bring those projects to the stability and quality you expect, we need your support. You can join our contributors and sponsors on our transparent [OpenCollective](https://opencollective.com/redbaron), every contribution will count and will be mainly used to work on the projects stability and quality but also on continuing, on the side, the R&D side of those projects. Our supporters -------------- [![badge with number of supporters at tier I like this, keep going!](https://opencollective.com/redbaron/tiers/i-like-this,-keep-going!/badge.svg) ![badge with number of supporters at tier it looks cool!](https://opencollective.com/redbaron/tiers/it-looks-cool!/badge.svg) ![badge with number of supporters at tier Oh god, that saved me so much time!](https://opencollective.com/redbaron/tiers/oh-god,-that-saved-me-so-much-time!/badge.svg)](https://opencollective.com/redbaron/tiers/) Why is this important? ====================== The usage of a FST might not be obvious at first sight so let's consider a series of problems to illustrate it. Let's say that you want to write a program that will: * rename a variable in a source file... without clashing with things that are not a variable (example: stuff inside a string) * inline a function/method * extract a function/method from a series of line of code * split a class into several classes * split a file into several modules * convert your whole code base from one ORM to another * do custom refactoring operation not implemented by IDE/rope * implement the class browser of smalltalk for python (the whole one where you can edit the code of the methods, not just showing code) It is very likely that you will end up with the awkward feeling of writing clumpsy weak code that is very likely to break because you didn't thought about all the annoying special cases and the formatting keeps bothering you. You may end up playing with [ast.py](https://docs.python.org/3/library/ast.html) until you realize that it removes too much information to be suitable for those situations. You will probably ditch this task as simply too complicated and really not worth the effort. You are missing a good abstraction that will take care of all of the code structure and formatting for you so you can concentrate on your task. The FST tries to be this abstraction. With it you can now work on a tree which represents your code with its formatting. Moreover, since it is the exact representation of your code, modifying it and converting it back to a string will give you back your code only modified where you have modified the tree. Said in another way, what I'm trying to achieve with Baron is a paradigm change in which writing code that will modify code is now a realist task that is worth the price (I'm not saying a simple task, but a realistic one: it's still a complex task). Other ----- Having a FST (or at least a good abstraction build on it) also makes it easier to do code generation and code analysis while those two operations are already quite feasible (using [ast.py](https://docs.python.org/3/library/ast.html) and a templating engine for example). Some technical details ====================== Baron produces a FST in the form of JSON (and by JSON I mean Python lists and dicts that can be dumped into JSON) for maximum interoperability. Baron FST is quite similar to Python AST with some modifications to be more intuitive to humans, since Python AST has been made for CPython interpreter. Since playing directly with JSON is a bit raw I'm going to build an abstraction on top of it that will looks like BeautifulSoup/jQuery. State of the project ==================== Currently, Baron has been tested on the top 100 projects and the FST converts back exactly into the original source code. So, it can be considered quite stable, but it is far away from having been battle tested. Since the project is very young and no one is already using it except my project, I'm open to changes of the FST nodes but I will quickly become conservative once it gets some adoption and will probably accept to modify it only once or twice in the future with clear indications on how to migrate. Baron is supporting python 2 grammar and up to python 3.7 grammar. Tests ===== Run either `py.test tests/` or `nosetests` in the baron directory. Community ========= You can reach us on [irc.freenode.net#baron](https://webchat.freenode.net/?channels=%23baron) or [irc.freenode.net##python-code-quality](https://webchat.freenode.net/?channels=%23%23python-code-quality). Code of Conduct =============== As a member of [PyCQA](https://github.com/PyCQA), Baron follows its [Code of Conduct](http://meta.pycqa.org/en/latest/code-of-conduct.html). Misc ==== [Old blog post announcing the project.](http://worlddomination.be/blog/2013/the-baron-project-part-1-what-and-why.html) Not that much up to date. baron-0.10.1/add_new_grammar.md000066400000000000000000000103201415427440200163220ustar00rootroot00000000000000# How to modify what Baron can parse This is a todo list of things to do to allows baron to parse new syntax. This is the full version, for minor things like adding a new binary operator (like the "@" for matrix multiplication) this is not needed. # Checklists ### Preparation - [ ] first of all start by comparing [the grammar from python 2.7](https://docs.python.org/2/reference/grammar.html) with the [targeted version](https://docs.python.org/3.7/reference/grammar.html) (also available in https://github.com/PyCQA/baron/tree/master/grammar) - [ ] check the reference page here https://baron.readthedocs.io/en/latest/grammar.html to see if things are already planned - [ ] look at [baron's grammar](https://github.com/PyCQA/baron/blob/master/grammar/baron_grammar) to check if it's not colyding with something already done (very low chance) - [ ] does the lexer needs to be modified? This is the case for new keywords and new statements - [ ] be mentally prepared that you'll need to write tests for everything ### Modification Lexer: - [ ] if you need to modify the lexer, stars with it, check all the lexer steps (found here: https://github.com/PyCQA/baron/blob/master/baron/baron.py#L69, the correct line might change in the futur, it's the tokenize function) - `split` only needs to be modified if python ever introduce new character like "?" for example - `group` is if 2 characters needs to be merged like "?" and "=" - `_tokenize` is for new token, obviously, like new keywords or new grouped characters - `space_group` will need to be modified for new keywords or statement, it's quite tricky, it's to group space on neighbour tokens (they will be unfold during grammar parsing) following the general rules of "a node needs to be responsible for its formatting" - `inner_group` is a variation of the previous one, it's for the case of tokens between `() [] {}` - `mark_indentation` is to handle inserting `IDENT`/`DEDENT` tokens, it very unlikely you'll ever need to work on this one except if python includes new statements (like the `with` statement) - [ ] have tests for everything regarding the lexer (if possible in a TDD fashion) Grammar: The hardest part is going to be to correctly design the extension of the tree with new or by modifying existing nodes (if needed). Before anything: RedBaron (and not Baron) is an API design project to make writing code that analyse and modify source code as easy as possible, Baron is here to support this task, this mean that this a tree designed to be intuitive to human, no easy to handle for interpreters. Therefor, when you design a modification or an addition to the tree, you need to answer to the question: what will be the easiest to handle and the more intuitive for humans. Here are some general advices: - when that makes sens, prefer flat structure with lower number of nodes instead of sub nodes. For example: for the "async" keyword, extend the related nodes instead of creating a subnode - prefer lists other single-child series of branches of a tree, for example, the python code "a.b.c.d" shouldn't be structured as "d->c->b->a" like in ast.py but as "[a, b, c, d]" - uses attributes and nodes name as close as possible to python keywords and what is used in the python community (and close to the grammar) Regarding the implementation: - [ ] try to find the good file in which to put your code, the name and content should be enough for that https://github.com/PyCQA/baron/tree/master/baron - [ ] write/update tests for everything regarding producing the new additions to the tree - [ ] implement the new grammar (if relevant) - [ ] modifying the rendering tree in [render.py](https://github.com/PyCQA/baron/blob/master/baron/render.py) - [ ] write rendering and, if needed, rendering after modification, tests for everything here https://github.com/PyCQA/baron/blob/master/tests/test_dumper.py And you should be good, congratz if you reached this point! ### Completion, documentation - [ ] modify the reference page https://baron.readthedocs.io/en/latest/grammar.html - [ ] [modify baron's grammar](https://github.com/PyCQA/baron/blob/master/grammar/baron_grammar) - [ ] consider implementing the new additions in [RedBaron](https://github.com/pycqa/redbaron) - [ ] udpate CHANGELOG baron-0.10.1/baron/000077500000000000000000000000001415427440200137765ustar00rootroot00000000000000baron-0.10.1/baron/__init__.py000066400000000000000000000006151415427440200161110ustar00rootroot00000000000000from . import grouper # noqa from . import spliter # noqa from .baron import parse, tokenize # noqa from .dumper import dumps # noqa from .inner_formatting_grouper import GroupingError, UnExpectedFormattingToken # noqa from .parser import ParsingError # noqa from .render import nodes_rendering_order # noqa from .spliter import UntreatedError # noqa from .utils import BaronError # noqa baron-0.10.1/baron/baron.py000066400000000000000000000062551415427440200154610ustar00rootroot00000000000000from .spliter import split from .grouper import group from .tokenizer import tokenize as _tokenize from .formatting_grouper import group as space_group from .future import has_print_function, replace_print_by_name from .grammator import generate_parse from .indentation_marker import mark_indentation from .inner_formatting_grouper import group as inner_group from .parser import ParsingError parse_tokens = generate_parse(False) parse_tokens_print_function = generate_parse(True) def _parse(tokens, print_function): parser = parse_tokens if not print_function else parse_tokens_print_function try: try: return parser(tokens) except ParsingError: # swap parsers for print_function situation where I failed to find it parser = parse_tokens if print_function else parse_tokens_print_function return parser(tokens) except ParsingError as e: raise except Exception as e: import sys import traceback traceback.print_exc(file=sys.stderr) sys.stderr.write("%s\n" % e) sys.stderr.write("\nBaron has failed to parse this input. If this is valid python code (and by that I mean that the python binary successfully parse this code without any syntax error) (also consider that python does not yet parse python 3 code integrally) it would be kind if you can extract a snippet of your code that make Baron fails and open a bug here: https://github.com/PyCQA/baron/issues\n\nSorry for the inconvenience.") def parse(source_code, print_function=None): # Python syntax requires source code to end with an ENDL token # the endl token is removed afterward if and only if it's the last token of the root level # It is possible that this token end up in a 'suite' grammar rule # which means that it is 'traped' in an indented block of code # I don't want to recursively cross the tree to hope to find it # This solution behave in the expected way for 90% of the case newline_appended = False linesep = "\r\n" if source_code.endswith("\r\n") else "\n" if source_code and not source_code.endswith(linesep): source_code += linesep newline_appended = True if print_function is None: tokens = tokenize(source_code, False) print_function = has_print_function(tokens) if print_function: replace_print_by_name(tokens) else: tokens = tokenize(source_code, print_function) if newline_appended: to_return = _parse(tokens, print_function) if to_return[-1]["type"] == "endl" and not to_return[-1]["formatting"]: return to_return[:-1] elif to_return[-1]["type"] == "endl" and to_return[-1]["formatting"]: return to_return[:-1] + to_return[-1]["formatting"] else: return to_return return _parse(tokens, print_function) def tokenize(pouet, print_function=False): splitted = split(pouet) grouped = group(splitted) print_tokenized = _tokenize(grouped, print_function) space_grouped = space_group(print_tokenized) inner_grouped = inner_group(space_grouped) indentation_marked = mark_indentation(inner_grouped) return indentation_marked baron-0.10.1/baron/dumper.py000066400000000000000000000006021415427440200156420ustar00rootroot00000000000000from .render import RenderWalker def dumps(tree, strict=False): return Dumper(strict=strict).dump(tree) class Dumper(RenderWalker): def before_string(self, string, key): self.dump += string def before_constant(self, constant, key): self.dump += constant def dump(self, tree): self.dump = '' self.walk(tree) return self.dump baron-0.10.1/baron/formatting_grouper.py000066400000000000000000000063761415427440200203010ustar00rootroot00000000000000from .utils import FlexibleIterator, BaronError class UnExpectedSpaceToken(BaronError): pass PRIORITY_ORDER = ( "IMPORT", "ENDL", ) BOTH = ( "SEMICOLON", "AS", "IMPORT", "DOUBLE_STAR", "DOT", "LEFT_SQUARE_BRACKET", "LEFT_PARENTHESIS", "STAR", "SLASH", "PERCENT", "DOUBLE_SLASH", "PLUS", "MINUS", "AT", "LEFT_SHIFT", "RIGHT_SHIFT", "AMPER", "CIRCUMFLEX", "VBAR", "LESS", "GREATER", "EQUAL_EQUAL", "LESS_EQUAL", "GREATER_EQUAL", "NOT_EQUAL", "IN", "IS", "NOT", "AND", "OR", "IF", "ELSE", "EQUAL", "PLUS_EQUAL", "MINUS_EQUAL", "STAR_EQUAL", "AT_EQUAL", "SLASH_EQUAL", "PERCENT_EQUAL", "AMPER_EQUAL", "VBAR_EQUAL", "CIRCUMFLEX_EQUAL", "LEFT_SHIFT_EQUAL", "RIGHT_SHIFT_EQUAL", "DOUBLE_STAR_EQUAL", "DOUBLE_SLASH_EQUAL", "ENDL", "COMMA", "FOR", "COLON", "BACKQUOTE", "RIGHT_ARROW", "FROM", ) STRING = ( "STRING", "RAW_STRING", "INTERPOLATED_STRING", "INTERPOLATED_RAW_STRING", "UNICODE_STRING", "UNICODE_RAW_STRING", "BINARY_STRING", "BINARY_RAW_STRING", ) GROUP_SPACE_BEFORE = BOTH + ( "RIGHT_PARENTHESIS", "COMMENT", ) + STRING GROUP_SPACE_AFTER = BOTH + ( "TILDE", "RETURN", "YIELD", "WITH", "DEL", "ASSERT", "RAISE", "EXEC", "GLOBAL", "NONLOCAL", "PRINT", "INDENT", "WHILE", "ELIF", "EXCEPT", "DEF", "CLASS", "LAMBDA", ) def less_prioritary_than(a, b): if b not in PRIORITY_ORDER: return False if a not in PRIORITY_ORDER: return True return PRIORITY_ORDER.index(a) < PRIORITY_ORDER.index(b) def group(sequence): return list(group_generator(sequence)) def group_generator(sequence): iterator = FlexibleIterator(sequence) while not iterator.end(): current = next(iterator) if current is None: return if current[0] == "SPACE" and iterator.show_next() and iterator.show_next()[0] in GROUP_SPACE_BEFORE: new_current = next(iterator) current = (new_current[0], new_current[1], [current]) if current[0] in GROUP_SPACE_AFTER + STRING and\ (iterator.show_next() and iterator.show_next()[0] == "SPACE") and\ (not iterator.show_next(2) or (iterator.show_next(2) and not less_prioritary_than(current[0], iterator.show_next(2)[0]))): # do not be greedy when you are grouping on strings if current[0] in STRING and iterator.show_next(2) and iterator.show_next(2)[0] in GROUP_SPACE_BEFORE: yield current continue after_space = next(iterator) current = (current[0], current[1], current[2] if len(current) > 2 else [], [after_space]) # in case of "def a(): # comment\n pass" # not really happy about this solution but that avoid a broken release if current[0] == "COLON" and iterator.show_next() and iterator.show_next()[0] == "COMMENT": comment = next(iterator) current = (current[0], current[1], ((current[2]) if len(current) > 2 else []), ((current[3]) if len(current) > 3 else []) + [comment]) yield current baron-0.10.1/baron/future.py000066400000000000000000000020531415427440200156620ustar00rootroot00000000000000def has_print_function(tokens): p = 0 while p < len(tokens): if tokens[p][0] != 'FROM': p += 1 continue if tokens[p + 1][0:2] != ('NAME', '__future__'): p += 1 continue if tokens[p + 2][0] != 'IMPORT': p += 1 continue current = p + 3 # ignore LEFT_PARENTHESIS token if tokens[current][0] == 'LEFT_PARENTHESIS': current += 1 while (current < len(tokens) and tokens[current][0] == 'NAME'): if tokens[current][1] == 'print_function': return True # ignore AS and NAME tokens if present # anyway, ignore COMMA token if current + 1 < len(tokens) and tokens[current + 1][0] == 'AS': current += 4 else: current += 2 p += 1 return False def replace_print_by_name(tokens): def is_print(token): return token[0] == 'PRINT' return [('NAME', 'print') if is_print(x) else x for x in tokens] baron-0.10.1/baron/grammator.py000066400000000000000000000742101415427440200163450ustar00rootroot00000000000000from .token import BaronToken from .parser import BaronParserGenerator from .tokenizer import TOKENS, tokenize, tokenize_current_keywords from .utils import create_node_from_token from .grammator_imports import include_imports from .grammator_control_structures import include_control_structures from .grammator_primitives import include_primivites from .grammator_operators import include_operators from .grammator_data_structures import include_data_structures from .parser import ParsingError def generate_parse(print_function): pg = BaronParserGenerator(tuple([x.upper() for x in tokenize_current_keywords(print_function)] + [x[1] for x in TOKENS] + ["ENDMARKER", "INDENT", "DEDENT"]), cache_id="baron") @pg.production("main : statements") def main(pack): (statements,) = pack return [x for x in statements if x] if statements else [] @pg.production("statements : statements statement") def statements_statement(pack): (statements, statement) = pack return statements + statement @pg.production("statements : statement SEMICOLON") def statement_semicolon(pack): (statement, semicolon) = pack return statement +\ [{ "type": "semicolon", "first_formatting": semicolon.hidden_tokens_before, "second_formatting": semicolon.hidden_tokens_after, "value": ";" }] @pg.production("statements : statement") def statement(pack): (statement,) = pack return statement @pg.production("statement : endl") def statement_endl(pack): (endl,) = pack return endl @pg.production("endl : ENDL") def endl(pack): (endl,) = pack indent = "" if endl.hidden_tokens_after and endl.hidden_tokens_after[0]["type"] == "space": indent = endl.hidden_tokens_after[0]["value"] endl.hidden_tokens_after = endl.hidden_tokens_after[1:] return [{ "type": "endl", "value": endl.value, "formatting": endl.hidden_tokens_before, "indent": indent, }] + endl.hidden_tokens_after @pg.production("left_parenthesis : LEFT_PARENTHESIS") def left_parenthesis(pack): (lp,) = pack return lp @pg.production("endl : COMMENT ENDL") def comment(pack): (comment_, endl) = pack return [{ "type": "comment", "value": comment_.value, "formatting": comment_.hidden_tokens_before, }, { "type": "endl", "formatting": endl.hidden_tokens_before, "indent": endl.hidden_tokens_after[0]["value"] if endl.hidden_tokens_after else "", "value": endl.value }] @pg.production("statement : ENDMARKER") def end(_): return [None] @pg.production("statement : simple_stmt") @pg.production("statement : compound_stmt") def statement_simple_statement(pack): (stmt,) = pack return stmt @pg.production("simple_stmt : small_stmt SEMICOLON endl") def simple_stmt_semicolon_endl(pack): (small_stmt, semicolon, endl) = pack return [small_stmt, { "type": "semicolon", "value": ";", "first_formatting": semicolon.hidden_tokens_before, "second_formatting": semicolon.hidden_tokens_after }] + endl @pg.production("simple_stmt : small_stmt endl") def simple_stmt(pack): (small_stmt, endl) = pack return [small_stmt] + endl @pg.production("simple_stmt : small_stmt SEMICOLON simple_stmt") def simple_stmt_semicolon(pack): (small_stmt, semicolon, simple_stmt) = pack return [small_stmt, { "type": "semicolon", "value": ";", "first_formatting": semicolon.hidden_tokens_before, "second_formatting": semicolon.hidden_tokens_after }] + simple_stmt @pg.production("small_stmt : flow_stmt") @pg.production("small_stmt : del_stmt") @pg.production("small_stmt : pass_stmt") @pg.production("small_stmt : assert_stmt") @pg.production("small_stmt : raise_stmt") @pg.production("small_stmt : global_stmt") @pg.production("small_stmt : nonlocal_stmt") @pg.production("compound_stmt : if_stmt") @pg.production("compound_stmt : while_stmt") @pg.production("compound_stmt : for_stmt") @pg.production("compound_stmt : try_stmt") @pg.production("compound_stmt : funcdef") @pg.production("compound_stmt : classdef") @pg.production("compound_stmt : with_stmt") @pg.production("compound_stmt : decorated") @pg.production("compound_stmt : async_stmt") def small_and_compound_stmt(pack): (statement,) = pack return statement @pg.production("async_maybe : ") def async_maybe(pack): return { "async": False, "formatting": [], } @pg.production("async_maybe : NAME") @pg.production("async : NAME") def async_without_space(pack): (async_,) = pack return { "async": True, "value": async_.value, "formatting": [], } @pg.production("async_maybe : NAME SPACE") @pg.production("async : NAME SPACE") def async_(pack): (async_, space) = pack return { "async": True, "value": async_.value, "formatting": [{'type': 'space', 'value': space.value}], } @pg.production("async_stmt : async with_stmt") @pg.production("async_stmt : async for_stmt") def async_stmt(pack): (async_, statement,) = pack if async_["value"] != "async": raise ParsingError("The only possible keyword before a '%s' is 'async', not '%s'" % (statement[0]["type"], async_["value"])) statement[0]["async"] = True statement[0]["async_formatting"] += async_["formatting"] return statement if not print_function: @pg.production("small_stmt : print_stmt") def print_statement(pack): (statement,) = pack return statement @pg.production("small_stmt : expr_stmt") @pg.production("expr_stmt : testlist_star_expr") @pg.production("testlist : test") @pg.production("testlist_argslist : test") @pg.production("testlist_star_expr : test_or_star_expr") @pg.production("test : or_test") @pg.production("test : lambdef") @pg.production("or_test : and_test") @pg.production("and_test : not_test") @pg.production("not_test : comparison") @pg.production("comparison : expr") @pg.production("expr : xor_expr") @pg.production("xor_expr : and_expr") @pg.production("and_expr : shift_expr") @pg.production("shift_expr : arith_expr") @pg.production("arith_expr : term") @pg.production("term : factor") @pg.production("factor : power") @pg.production("power : atom") @pg.production("exprlist : expr") def term_factor(pack): (level,) = pack return level @pg.production("with_stmt : WITH with_items COLON suite") def with_stmt(pack): (with_, with_items, colon, suite) = pack return [{ "type": "with", "async": False, "async_formatting": [], "value": suite, "first_formatting": with_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, "contexts": with_items }] @pg.production("with_items : with_items comma with_item") def with_items_with_item(pack): (with_items, comma, with_item,) = pack return with_items + [comma, with_item] @pg.production("with_items : with_item") def with_items(pack): (with_item,) = pack return [with_item] @pg.production("with_item : test") def with_item(pack): (test,) = pack return { "type": "with_context_item", "as": {}, "first_formatting": [], "second_formatting": [], "value": test } @pg.production("with_item : test AS expr") def with_item_as(pack): (test, as_, expr) = pack return { "type": "with_context_item", "as": expr, "first_formatting": as_.hidden_tokens_before, "second_formatting": as_.hidden_tokens_after, "value": test } @pg.production("classdef : CLASS NAME COLON suite") def class_stmt(pack,): (class_, name, colon, suite) = pack return [{ "type": "class", "name": name.value, "parenthesis": False, "first_formatting": class_.hidden_tokens_after, "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": colon.hidden_tokens_before, "sixth_formatting": colon.hidden_tokens_after, "inherit_from": [], "decorators": [], "value": suite, }] @pg.production("classdef : CLASS NAME LEFT_PARENTHESIS RIGHT_PARENTHESIS COLON suite") def class_stmt_parenthesis(pack,): (class_, name, left_parenthesis, right_parenthesis, colon, suite) = pack return [{ "type": "class", "name": name.value, "parenthesis": True, "first_formatting": class_.hidden_tokens_after, "second_formatting": left_parenthesis.hidden_tokens_before, "third_formatting": left_parenthesis.hidden_tokens_after, "fourth_formatting": right_parenthesis.hidden_tokens_before, "fifth_formatting": right_parenthesis.hidden_tokens_after + colon.hidden_tokens_before, "sixth_formatting": colon.hidden_tokens_after, "inherit_from": [], "decorators": [], "value": suite, }] @pg.production("classdef : CLASS NAME LEFT_PARENTHESIS testlist_argslist RIGHT_PARENTHESIS COLON suite") def class_stmt_inherit(pack,): def unfold_simple_call_arguments(node): if node.get("type") == "call_argument" and not node["target"]: return node["value"] return node (class_, name, left_parenthesis, testlist, right_parenthesis, colon, suite) = pack return [{ "type": "class", "name": name.value, "parenthesis": True, "first_formatting": class_.hidden_tokens_after, "second_formatting": left_parenthesis.hidden_tokens_before, "third_formatting": left_parenthesis.hidden_tokens_after, "fourth_formatting": right_parenthesis.hidden_tokens_before, "fifth_formatting": right_parenthesis.hidden_tokens_after + colon.hidden_tokens_before, "sixth_formatting": colon.hidden_tokens_after, "inherit_from": [unfold_simple_call_arguments(x) for x in (testlist if isinstance(testlist, list) else [testlist])], "decorators": [], "value": suite, }] @pg.production("decorated : decorators funcdef") @pg.production("decorated : decorators classdef") def decorated(pack): (decorators, funcdef) = pack funcdef[0]["decorators"] = decorators return funcdef @pg.production("decorators : decorators decorator") def decorators_decorator(pack): (decorators, decorator,) = pack return decorators + decorator @pg.production("decorators : decorator") def decorators(pack): (decorator,) = pack return decorator # TODO tests @pg.production("decorator : endl") def decorator_endl(pack): # thanks iPython devs, you appear to be the only one in the world that # split decorators with empty lines... like seriously. (endl,) = pack return endl @pg.production("decorator : AT dotted_name endl") def decorator(pack): (at, dotted_name, endl) = pack return [{ "type": "decorator", "value": { "value": dotted_name, "type": "dotted_name", }, "call": {}, "formatting": at.hidden_tokens_after, }] + endl @pg.production("decorator : AT dotted_name LEFT_PARENTHESIS RIGHT_PARENTHESIS endl") def decorator_empty_call(pack): (at, dotted_name, left_parenthesis, right_parenthesis, endl) = pack return [{ "type": "decorator", "value": { "value": dotted_name, "type": "dotted_name", }, "call": { "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "type": "call", "first_formatting": left_parenthesis.hidden_tokens_before, "value": [], "second_formatting": left_parenthesis.hidden_tokens_after }, "formatting": at.hidden_tokens_after, }] + endl @pg.production("decorator : AT dotted_name LEFT_PARENTHESIS argslist RIGHT_PARENTHESIS endl") def decorator_call(pack): (at, dotted_name, left_parenthesis, argslist, right_parenthesis, endl) = pack return [{ "type": "decorator", "value": { "value": dotted_name, "type": "dotted_name", }, "call": { "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "type": "call", "first_formatting": left_parenthesis.hidden_tokens_before, "value": argslist, "second_formatting": left_parenthesis.hidden_tokens_after }, "formatting": at.hidden_tokens_after, }] + endl @pg.production("funcdef : async_maybe DEF NAME LEFT_PARENTHESIS typed_parameters RIGHT_PARENTHESIS return_annotation COLON suite") def function_definition(pack): (async_maybe, def_, name, left_parenthesis, typed_parameters, right_parenthesis, return_annotation, colon, suite) = pack if async_maybe["async"] and async_maybe["value"] != "async": raise ParsingError("The only possible keyword before a 'def' is 'async', not '%s'" % async_maybe["value"]) return [{ "type": "def", "async": async_maybe["async"], "return_annotation": return_annotation["value"], "return_annotation_first_formatting": return_annotation["first_formatting"], "return_annotation_second_formatting": return_annotation["second_formatting"], "async_formatting": async_maybe.get("formatting", []), "decorators": [], "name": name.value, "first_formatting": def_.hidden_tokens_after, "second_formatting": left_parenthesis.hidden_tokens_before, "third_formatting": left_parenthesis.hidden_tokens_after, "fourth_formatting": right_parenthesis.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_before, "sixth_formatting": colon.hidden_tokens_after, "arguments": typed_parameters, "value": suite, }] @pg.production("return_annotation : ") def return_annotation_empty(pack): return { "value": {}, "first_formatting": [], "second_formatting": [], } @pg.production("return_annotation : RIGHT_ARROW test") def return_annotation(pack): right_arrow, test = pack return { "value": test, "first_formatting": right_arrow.hidden_tokens_before, "second_formatting": right_arrow.hidden_tokens_after, } @pg.production("argslist : argslist argument") @pg.production("testlist_argslist : argslist argument") @pg.production("typed_parameters : typed_parameters typed_parameter") @pg.production("parameters : parameters parameter") def parameters_parameters_parameter(pack,): (parameters, parameter,) = pack return parameters + parameter @pg.production("argslist : argument") @pg.production("testlist_argslist : argument") @pg.production("typed_parameters : typed_parameter") @pg.production("parameters : parameter") def parameters_parameter(pack,): (parameter,) = pack return parameter @pg.production("argument :") @pg.production("typed_parameter : ") @pg.production("parameter : ") def parameter_empty(p): return [] @pg.production("name : NAME") def name(pack): (name_,) = pack return { "type": "name", "value": name_.value, } @pg.production("typed_parameter : LEFT_PARENTHESIS name RIGHT_PARENTHESIS maybe_test") @pg.production("parameter : LEFT_PARENTHESIS name RIGHT_PARENTHESIS maybe_test") def parameter_fpdef(pack): (left_parenthesis, name, right_parenthesis, (equal, test)) = pack return [{ "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "value": test, "target": { "type": "associative_parenthesis", "first_formatting": left_parenthesis.hidden_tokens_before, "second_formatting": left_parenthesis.hidden_tokens_after, "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "value": name } }] @pg.production("typed_parameter : LEFT_PARENTHESIS fplist RIGHT_PARENTHESIS maybe_test") @pg.production("parameter : LEFT_PARENTHESIS fplist RIGHT_PARENTHESIS maybe_test") def parameter_fplist(pack): (left_parenthesis, fplist, right_parenthesis, (equal, test)) = pack return [{ "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "value": test, "target": { "type": "tuple", "with_parenthesis": True, "first_formatting": left_parenthesis.hidden_tokens_after, "second_formatting": left_parenthesis.hidden_tokens_before, "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "value": fplist, }, }] @pg.production("fplist : fplist parameter") def fplist_recur(pack): (fplist, name) = pack if name[0]["type"] == "def_argument": name = [name[0]["target"]] return fplist + name @pg.production("fplist : parameter comma") def fplist(pack): (name, comma) = pack if name[0]["type"] == "def_argument": name = [name[0]["target"]] return name + [comma] # really strange that left part of argument grammar can be a test # I guess it's yet another legacy mistake # python give me 'SyntaxError: keyword can't be an expression' when I try to # put something else than a name (looks like a custom SyntaxError) @pg.production("argument : test maybe_test") def named_argument(pack): (name, (equal, test)) = pack return [{ "type": "call_argument", "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "value": test if equal else name, "target": name if equal else {} }] @pg.production("typed_parameter : name COLON test maybe_test") def parameter_annotation_with_default(pack): # name, (equal, test) = pack name, colon, annotation, (equal, test) = pack return [{ "type": "def_argument", "annotation": annotation, "annotation_first_formatting": colon.hidden_tokens_before, "annotation_second_formatting": colon.hidden_tokens_after, "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "value": test, "target": name }] @pg.production("typed_parameter : name maybe_test") def parameter_alone_with_default(pack): name, (equal, test) = pack return [{ "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "value": test, "target": name }] @pg.production("parameter : name maybe_test") def parameter_with_default(pack): name, (equal, test) = pack return [{ "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "value": test, "target": name }] @pg.production("maybe_test : EQUAL test") def maybe_test(pack): return pack @pg.production("maybe_test : ") def maybe_test_empty(pack): return (None, {}) @pg.production("argument : test comp_for") def generator_comprehension(pack): (test, comp_for,) = pack return [{ "type": "argument_generator_comprehension", "result": test, "generators": comp_for, }] @pg.production("argument : STAR test") def argument_star(pack): (star, test,) = pack return [{ "type": "list_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": star.hidden_tokens_after, "value": test, }] @pg.production("argument : DOUBLE_STAR test") def argument_star_star(pack): (double_star, test,) = pack return [{ "type": "dict_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": double_star.hidden_tokens_after, "value": test, }] @pg.production("typed_parameter : STAR NAME COLON test") def typed_parameter_star(pack): (star, name, colon, test) = pack return [{ "type": "list_argument", "formatting": star.hidden_tokens_after, "annotation": test, "annotation_first_formatting": colon.hidden_tokens_before if colon else [], "annotation_second_formatting": colon.hidden_tokens_after if colon else [], "value": { "type": "name", "value": name.value, } }] @pg.production("typed_parameter : DOUBLE_STAR NAME COLON test") def typed_parameter_double_star(pack): (double_star, name, colon, test) = pack return [{ "type": "dict_argument", "formatting": double_star.hidden_tokens_after, "annotation": test, "annotation_first_formatting": colon.hidden_tokens_before if colon else [], "annotation_second_formatting": colon.hidden_tokens_after if colon else [], "value": { "type": "name", "value": name.value, } }] # TODO refactor those 2 to standardize with argument_star and argument_star_star @pg.production("typed_parameter : STAR NAME") @pg.production("parameter : STAR NAME") def parameter_star(pack): (star, name,) = pack return [{ "type": "list_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": star.hidden_tokens_after, "value": { "type": "name", "value": name.value, } }] # TODO refactor those 2 to standardize with argument_star and argument_star_star @pg.production("typed_parameter : STAR") @pg.production("parameter : STAR") def parameter_star_only(pack): (star, ) = pack return [{ "type": "kwargs_only_marker", "formatting": star.hidden_tokens_after, }] @pg.production("typed_parameter : DOUBLE_STAR NAME") @pg.production("parameter : DOUBLE_STAR NAME") def parameter_star_star(pack): (double_star, name,) = pack return [{ "type": "dict_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": double_star.hidden_tokens_after, "value": { "type": "name", "value": name.value, }, }] @pg.production("argument : comma") @pg.production("typed_parameter : comma") @pg.production("parameter : comma") def parameter_comma(pack): (comma,) = pack return [comma] @pg.production("suite : simple_stmt") def suite(pack): (simple_stmt,) = pack return simple_stmt @pg.production("suite : endls INDENT statements DEDENT") def suite_indent(pack): (endls, indent, statements, dedent,) = pack return endls + statements @pg.production("endls : endls endl") @pg.production("endls : endl") def endls(p): if len(p) == 1: return p[0] return p[0] + p[1] include_imports(pg) include_control_structures(pg) include_primivites(pg, print_function) include_operators(pg) include_data_structures(pg) @pg.production("atom : LEFT_PARENTHESIS yield_expr RIGHT_PARENTHESIS") def yield_atom(pack): (left_parenthesis, yield_expr, right_parenthesis) = pack return { "type": "yield_atom", "value": yield_expr["value"], "first_formatting": left_parenthesis.hidden_tokens_after, "second_formatting": yield_expr["formatting"], "third_formatting": right_parenthesis.hidden_tokens_before } @pg.production("atom : BACKQUOTE testlist1 BACKQUOTE") def repr_atom(pack): (backquote, testlist1, backquote2) = pack return { "type": "repr", "value": testlist1, "first_formatting": backquote.hidden_tokens_after, "second_formatting": backquote2.hidden_tokens_before, } @pg.production("testlist1 : test comma testlist1") def testlist1_double(pack): (test, comma, test2,) = pack return [test, comma] + test2 @pg.production("testlist1 : test") def testlist1(pack): (test,) = pack return [test] # TODO test all the things (except INT) @pg.production("atom : INT") @pg.production("atom : LONG") @pg.production("atom : OCTA") @pg.production("atom : HEXA") @pg.production("atom : BINARY") @pg.production("atom : FLOAT") @pg.production("atom : FLOAT_EXPONANT") @pg.production("atom : FLOAT_EXPONANT_COMPLEX") @pg.production("atom : COMPLEX") def int(pack): (int_,) = pack return create_node_from_token(int_, section="number") @pg.production("atom : name") def atom_name(pack): (name,) = pack return name @pg.production("atom : strings") def strings(pack): (string_chain,) = pack if len(string_chain) == 1: return string_chain[0] return { "type": "string_chain", "value": string_chain } @pg.production("strings : string strings") def strings_string_strings(pack): (string_, strings_) = pack return string_ + strings_ @pg.production("strings : string") def strings_string(pack): (string_,) = pack return string_ # TODO tests those other kind of strings @pg.production("string : STRING") @pg.production("string : RAW_STRING") @pg.production("string : INTERPOLATED_STRING") @pg.production("string : UNICODE_STRING") @pg.production("string : BINARY_STRING") @pg.production("string : UNICODE_RAW_STRING") @pg.production("string : BINARY_RAW_STRING") @pg.production("string : INTERPOLATED_RAW_STRING") def string(pack): (string_,) = pack return [{ "type": string_.name.lower(), "value": string_.value, "first_formatting": string_.hidden_tokens_before, "second_formatting": string_.hidden_tokens_after, }] @pg.production("comma : COMMA") def comma(pack): (comma,) = pack return { "type": "comma", "first_formatting": comma.hidden_tokens_before, "second_formatting": comma.hidden_tokens_after, } def parse(tokens): if print_function: new_tokens = [] for token in tokens: if token[0] in ("PRINT", "EXEC"): token = list(token) token[0] = "NAME" token = tuple(token) new_tokens.append(token) tokens = [BaronToken(*x) if x else x for x in new_tokens] + [None] else: tokens = [BaronToken(*x) if x else x for x in tokens] + [None] return parser.parse(iter(tokens)) parser = pg.build() return parse def fake_lexer(sequence): for i in tokenize(sequence): if i is None: yield None yield BaronToken(*i) def parse(sequence): parser = generate_parse(print_function=False) return parser.parse(fake_lexer(sequence)) baron-0.10.1/baron/grammator_control_structures.py000066400000000000000000000253611415427440200224130ustar00rootroot00000000000000def include_control_structures(pg): @pg.production("try_stmt : TRY COLON suite excepts") def try_excepts_stmt(pack): (try_, colon, suite, excepts) = pack return [{ "type": "try", "value": suite, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "else": {}, "finally": {}, "excepts": excepts, }] @pg.production("try_stmt : TRY COLON suite excepts else_stmt") def try_excepts_else_stmt(pack): (try_, colon, suite, excepts, else_stmt) = pack return [{ "type": "try", "value": suite, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "else": else_stmt, "finally": {}, "excepts": excepts, }] @pg.production("try_stmt : TRY COLON suite excepts finally_stmt") def try_excepts_finally_stmt(pack): (try_, colon, suite, excepts, finally_stmt) = pack return [{ "type": "try", "value": suite, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "else": {}, "finally": finally_stmt, "excepts": excepts, }] @pg.production("try_stmt : TRY COLON suite excepts else_stmt finally_stmt") def try_excepts_else_finally_stmt(pack): (try_, colon, suite, excepts, else_stmt, finally_stmt) = pack return [{ "type": "try", "value": suite, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "else": else_stmt, "finally": finally_stmt, "excepts": excepts, }] @pg.production("try_stmt : TRY COLON suite finally_stmt") def try_stmt(pack): (try_, colon, suite, finally_stmt) = pack return [{ "type": "try", "value": suite, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "else": {}, "finally": finally_stmt, "excepts": [], }] @pg.production("excepts : excepts except_stmt") def excepts(pack): (excepts_, except_stmt) = pack return excepts_ + except_stmt @pg.production("excepts : except_stmt") def excepts_except_stmt(pack): (except_stmt,) = pack return except_stmt @pg.production("except_stmt : EXCEPT test AS test COLON suite") def except_as_stmt(pack): (except_, test, as_, test2, colon, suite) = pack return [{ "type": "except", "first_formatting": except_.hidden_tokens_after, "second_formatting": as_.hidden_tokens_before, "third_formatting": as_.hidden_tokens_after, "fourth_formatting": colon.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_after, "delimiter": "as", "target": test2, "exception": test, "value": suite }] @pg.production("except_stmt : EXCEPT test COMMA test COLON suite") def except_comma_stmt(pack): (except_, test, comma, test2, colon, suite) = pack return [{ "type": "except", "first_formatting": except_.hidden_tokens_after, "second_formatting": comma.hidden_tokens_before, "third_formatting": comma.hidden_tokens_after, "fourth_formatting": colon.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_after, "delimiter": ",", "target": test2, "exception": test, "value": suite }] @pg.production("except_stmt : EXCEPT COLON suite") def except_stmt_empty(pack): (except_, colon, suite) = pack return [{ "type": "except", "first_formatting": except_.hidden_tokens_after, "second_formatting": [], "third_formatting": [], "fourth_formatting": colon.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_after, "delimiter": "", "target": {}, "exception": {}, "value": suite }] @pg.production("except_stmt : EXCEPT test COLON suite") def except_stmt(pack): (except_, test, colon, suite) = pack return [{ "type": "except", "first_formatting": except_.hidden_tokens_after, "second_formatting": [], "third_formatting": [], "fourth_formatting": colon.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_after, "delimiter": "", "target": {}, "exception": test, "value": suite }] @pg.production("finally_stmt : FINALLY COLON suite") def finally_stmt(pack): (finally_, colon, suite) = pack return { "type": "finally", "value": suite, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, } @pg.production("else_stmt : ELSE COLON suite") def else_stmt(pack): (else_, colon, suite) = pack return { "type": "else", "value": suite, "first_formatting": else_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_after, } @pg.production("for_stmt : FOR exprlist IN testlist COLON suite") def for_stmt(pack,): (for_, exprlist, in_, testlist, colon, suite) = pack return [{ "type": "for", "async": False, "async_formatting": [] + for_.hidden_tokens_before, "value": suite, "iterator": exprlist, "target": testlist, "else": {}, "first_formatting": for_.hidden_tokens_after, "second_formatting": in_.hidden_tokens_before, "third_formatting": in_.hidden_tokens_after, "fourth_formatting": colon.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_after, }] @pg.production("for_stmt : FOR exprlist IN testlist COLON suite else_stmt") def for_else_stmt(pack,): (for_, exprlist, in_, testlist, colon, suite, else_stmt) = pack return [{ "type": "for", "value": suite, "async": False, "async_formatting": [] + for_.hidden_tokens_before, "iterator": exprlist, "target": testlist, "else": else_stmt, "first_formatting": for_.hidden_tokens_after, "second_formatting": in_.hidden_tokens_before, "third_formatting": in_.hidden_tokens_after, "fourth_formatting": colon.hidden_tokens_before, "fifth_formatting": colon.hidden_tokens_after, }] @pg.production("while_stmt : WHILE test COLON suite") def while_stmt(pack): (while_, test, colon, suite) = pack return [{ "type": "while", "value": suite, "test": test, "else": {}, "first_formatting": while_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, }] @pg.production("while_stmt : WHILE test COLON suite else_stmt") def while_stmt_else(pack): (while_, test, colon, suite, else_stmt) = pack return [{ "type": "while", "value": suite, "test": test, "else": else_stmt, "first_formatting": while_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, }] @pg.production("if_stmt : IF test COLON suite") def if_stmt(pack): (if_, test, colon, suite) = pack return [{ "type": "ifelseblock", "value": [{ "type": "if", "value": suite, "test": test, "first_formatting": if_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, }] }] @pg.production("if_stmt : IF test COLON suite elifs") def if_elif_stmt(pack): (if_, test, colon, suite, elifs) = pack return [{ "type": "ifelseblock", "value": [{ "type": "if", "value": suite, "test": test, "first_formatting": if_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, }] + elifs }] @pg.production("elifs : elifs ELIF test COLON suite") def elifs_elif(pack,): (elifs, elif_, test, colon, suite) = pack return elifs + [{ "type": "elif", "first_formatting": elif_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, "value": suite, "test": test, }] @pg.production("elifs : ELIF test COLON suite") def elif_(pack,): (elif_, test, colon, suite) = pack return [{ "type": "elif", "first_formatting": elif_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, "value": suite, "test": test, }] @pg.production("if_stmt : IF test COLON suite else_stmt") def if_else_stmt(pack): (if_, test, colon, suite, else_stmt) = pack return [{ "type": "ifelseblock", "value": [{ "type": "if", "value": suite, "test": test, "first_formatting": if_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, }, else_stmt] }] @pg.production("if_stmt : IF test COLON suite elifs else_stmt") def if_elif_else_stmt(pack): (if_, test, colon, suite, elifs, else_stmt) = pack return [{ "type": "ifelseblock", "value": [{ "type": "if", "value": suite, "test": test, "first_formatting": if_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, }] + elifs + [else_stmt] }] baron-0.10.1/baron/grammator_data_structures.py000066400000000000000000000341361415427440200216440ustar00rootroot00000000000000def include_data_structures(pg): # TODO remove left_parenthesis and use LEFT_PARENTHESIS instead @pg.production("atom : left_parenthesis testlist_comp RIGHT_PARENTHESIS") def tuple(pack): (left_parenthesis, testlist_comp, right_parenthesis,) = pack return { "type": "tuple", "value": testlist_comp, "first_formatting": left_parenthesis.hidden_tokens_before, "second_formatting": left_parenthesis.hidden_tokens_after, "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "with_parenthesis": True, } @pg.production("atom : left_parenthesis test RIGHT_PARENTHESIS") def associative_parenthesis(pack): (left_parenthesis, test, right_parenthesis,) = pack return { "type": "associative_parenthesis", "first_formatting": left_parenthesis.hidden_tokens_before, "second_formatting": left_parenthesis.hidden_tokens_after, "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "value": test } @pg.production("testlist : test comma") @pg.production("testlist_star_expr : test_or_star_expr comma") @pg.production("exprlist : expr comma") @pg.production("subscriptlist : subscript comma") def implicit_tuple_alone(pack): (test, comma) = pack return { "type": "tuple", "value": [test, comma], "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "with_parenthesis": False, } @pg.production("testlist : test testlist_part") @pg.production("testlist_star_expr : test_or_star_expr testlist_star_expr_part") @pg.production("exprlist : expr exprlist_part") @pg.production("subscriptlist : subscript subscriptlist_part") def implicit_tuple(pack): (test, testlist_part) = pack return { "type": "tuple", "value": [test] + testlist_part, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "with_parenthesis": False, } @pg.production("testlist_part : COMMA test") @pg.production("testlist_star_expr_part : COMMA test_or_star_expr") @pg.production("exprlist_part : COMMA expr") @pg.production("subscriptlist_part : COMMA subscript") def testlist_part(pack): (comma, test) = pack return [{ "type": "comma", "first_formatting": comma.hidden_tokens_before, "second_formatting": comma.hidden_tokens_after, }, test] @pg.production("testlist_part : COMMA test COMMA") @pg.production("testlist_star_expr_part : COMMA test_or_star_expr COMMA") @pg.production("exprlist_part : COMMA expr COMMA") @pg.production("subscriptlist_part : COMMA subscript COMMA") def testlist_part_comma(pack): (comma, test, comma2) = pack return [{ "type": "comma", "first_formatting": comma.hidden_tokens_before, "second_formatting": comma.hidden_tokens_after, }, test, { "type": "comma", "first_formatting": comma2.hidden_tokens_before, "second_formatting": comma2.hidden_tokens_after, }] @pg.production("testlist_part : COMMA test testlist_part") @pg.production("testlist_star_expr_part : COMMA test_or_star_expr testlist_star_expr_part") @pg.production("exprlist_part : COMMA expr exprlist_part") @pg.production("subscriptlist_part : COMMA subscript subscriptlist_part") def testlist_part_next(pack): (comma, test, testlist_part) = pack return [{ "type": "comma", "first_formatting": comma.hidden_tokens_before, "second_formatting": comma.hidden_tokens_after, }, test] + testlist_part @pg.production("testlist_comp :") def testlist_comp_empty(empty): return [] @pg.production("testlist_comp : test comma test") def testlist_comp_two(pack): (test, comma, test2) = pack return [test, comma, test2] @pg.production("testlist_comp : test comma testlist_comp") def testlist_comp_more(pack): (test, comma, testlist_comp) = pack return [test, comma] + testlist_comp @pg.production("atom : LEFT_SQUARE_BRACKET listmaker RIGHT_SQUARE_BRACKET") def list_(pack): (left_bracket, listmaker, right_bracket,) = pack return { "type": "list", "first_formatting": left_bracket.hidden_tokens_before, "second_formatting": left_bracket.hidden_tokens_after, "third_formatting": right_bracket.hidden_tokens_before, "fourth_formatting": right_bracket.hidden_tokens_after, "value": listmaker } @pg.production("listmaker :") def listmaker_empty(empty): return [] @pg.production("listmaker : test") def listmaker_one(pack): (test,) = pack return [test] @pg.production("listmaker : test comma listmaker") def listmaker_more(pack): (test, comma, listmaker) = pack return [test, comma] + listmaker @pg.production("atom : LEFT_BRACKET dictmaker RIGHT_BRACKET") def dict(pack): (left_bracket, dictmaker, right_bracket,) = pack return { "type": "dict", "first_formatting": left_bracket.hidden_tokens_before, "second_formatting": left_bracket.hidden_tokens_after, "third_formatting": right_bracket.hidden_tokens_before, "fourth_formatting": right_bracket.hidden_tokens_after, "value": dictmaker } @pg.production("dictmaker : ") def dict_empty(empty): return [] @pg.production("dictmaker : test COLON test") def dict_one_colon(pack): (test, colon, test2) = pack return [{ "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "key": test, "value": test2, "type": "dictitem" }] @pg.production("dictmaker : DOUBLE_STAR test") def dict_one_double_star(pack): (double_star, test) = pack return [{ "type": "dict_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": double_star.hidden_tokens_after, "value": test, }] @pg.production("dictmaker : test COLON test comma dictmaker") def dict_more_colon(pack): (test, colon, test2, comma, dictmaker) = pack return [{ "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "key": test, "value": test2, "type": "dictitem" }, comma] + dictmaker @pg.production("dictmaker : DOUBLE_STAR test comma dictmaker") def dict_more_double_star(pack): (double_star, test, comma, dictmaker) = pack return [{ "type": "dict_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": double_star.hidden_tokens_after, "value": test, }, comma] + dictmaker @pg.production("atom : LEFT_BRACKET setmaker RIGHT_BRACKET") def set(pack): (left_bracket, setmaker, right_bracket,) = pack return { "type": "set", "first_formatting": left_bracket.hidden_tokens_before, "second_formatting": left_bracket.hidden_tokens_after, "third_formatting": right_bracket.hidden_tokens_before, "fourth_formatting": right_bracket.hidden_tokens_after, "value": setmaker } @pg.production("setmaker : ") def set_empty(empty): return [] @pg.production("setmaker : test comma setmaker") def set_more(pack): (test, comma, setmaker) = pack return [test, comma] + setmaker @pg.production("setmaker : test") def set_one(pack): (test,) = pack return [test] @pg.production("atom : left_parenthesis test comp_for RIGHT_PARENTHESIS") def generator_comprehension(pack): (left_parenthesis, test, comp_for, right_parenthesis,) = pack return { "type": "generator_comprehension", "first_formatting": left_parenthesis.hidden_tokens_before, "second_formatting": left_parenthesis.hidden_tokens_after, "third_formatting": right_parenthesis.hidden_tokens_before, "fourth_formatting": right_parenthesis.hidden_tokens_after, "result": test, "generators": comp_for, } @pg.production("atom : LEFT_SQUARE_BRACKET test list_for RIGHT_SQUARE_BRACKET") def list_comprehension(pack): (left_square_bracket, test, list_for, right_square_bracket) = pack return { "type": "list_comprehension", "first_formatting": left_square_bracket.hidden_tokens_before, "second_formatting": left_square_bracket.hidden_tokens_after, "third_formatting": right_square_bracket.hidden_tokens_before, "fourth_formatting": right_square_bracket.hidden_tokens_after, "result": test, "generators": list_for, } @pg.production("atom : LEFT_BRACKET test COLON test comp_for RIGHT_BRACKET") def dict_comprehension(pack): (left_bracket, test, colon, test2, list_for, right_bracket) = pack return { "type": "dict_comprehension", "first_formatting": left_bracket.hidden_tokens_before, "second_formatting": left_bracket.hidden_tokens_after, "third_formatting": right_bracket.hidden_tokens_before, "fourth_formatting": right_bracket.hidden_tokens_after, "result": { "key": test, "type": "dictitem", "value": test2, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, }, "generators": list_for, } @pg.production("atom : LEFT_BRACKET test comp_for RIGHT_BRACKET") def set_comprehension(pack): (left_bracket, test, list_for, right_bracket) = pack return { "type": "set_comprehension", "first_formatting": left_bracket.hidden_tokens_before, "second_formatting": left_bracket.hidden_tokens_after, "third_formatting": right_bracket.hidden_tokens_before, "fourth_formatting": right_bracket.hidden_tokens_after, "result": test, "generators": list_for, } @pg.production("list_for : FOR exprlist IN old_test") @pg.production("comp_for : FOR exprlist IN or_test") def comp_for(pack): (for_, exprlist, in_, or_test) = pack return [{ "type": "comprehension_loop", "first_formatting": for_.hidden_tokens_before, "second_formatting": for_.hidden_tokens_after, "third_formatting": in_.hidden_tokens_before, "fourth_formatting": in_.hidden_tokens_after, "target": or_test, "iterator": exprlist, "ifs": [], }] @pg.production("list_for : FOR exprlist IN old_test") @pg.production("list_for : FOR exprlist IN testlist_safe") def comp_for_implicite_tuple(pack): (for_, exprlist, in_, testlist_safe) = pack return [{ "type": "comprehension_loop", "first_formatting": for_.hidden_tokens_before, "second_formatting": for_.hidden_tokens_after, "third_formatting": in_.hidden_tokens_before, "fourth_formatting": in_.hidden_tokens_after, "target": { "type": "tuple", "value": testlist_safe, "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], }, "iterator": exprlist, "ifs": [], }] @pg.production("comp_for : FOR exprlist IN or_test comp_iter") @pg.production("list_for : FOR exprlist IN old_test list_iter") @pg.production("list_for : FOR exprlist IN testlist_safe list_iter") def comp_for_iter(pack): (for_, exprlist, in_, or_test, comp_iter) = pack my_ifs = [] for i in comp_iter: if i["type"] != "comprehension_if": break my_ifs.append(i) comp_iter = comp_iter[1:] return [{ "type": "comprehension_loop", "first_formatting": for_.hidden_tokens_before, "second_formatting": for_.hidden_tokens_after, "third_formatting": in_.hidden_tokens_before, "fourth_formatting": in_.hidden_tokens_after, "target": or_test, "iterator": exprlist, "ifs": my_ifs, }] + comp_iter @pg.production("list_iter : list_for") @pg.production("comp_iter : comp_for") def comp_iter_comp_for(pack): (comp_for,) = pack return comp_for @pg.production("list_iter : IF old_test") @pg.production("comp_iter : IF old_test") def comp_iter_if(pack): (if_, old_test) = pack return [{ "type": "comprehension_if", "first_formatting": if_.hidden_tokens_before, "second_formatting": if_.hidden_tokens_after, "value": old_test }] @pg.production("list_iter : IF old_test list_iter") @pg.production("comp_iter : IF old_test comp_iter") def comp_iter_if_comp_iter(pack): (if_, old_test, comp_iter) = pack return [{ "type": "comprehension_if", "first_formatting": if_.hidden_tokens_before, "second_formatting": if_.hidden_tokens_after, "value": old_test }] + comp_iter baron-0.10.1/baron/grammator_imports.py000066400000000000000000000133601415427440200201210ustar00rootroot00000000000000from .utils import create_node_from_token def include_imports(pg): @pg.production("small_stmt : import") @pg.production("small_stmt : from_import") def separator(pack): (statement,) = pack return statement @pg.production("import : IMPORT dotted_as_names") def importeu(pack): (import_, dotted_as_names) = pack return { "type": "import", "value": dotted_as_names, "first_formatting": import_.hidden_tokens_before, "second_formatting": import_.hidden_tokens_after } @pg.production("from_import : FROM dotted_name IMPORT from_import_target") def from_import_with_space(pack): (from_, dotted_name, import_, from_import_target) = pack return { "type": "from_import", "targets": from_import_target, "first_formatting": from_.hidden_tokens_after, "second_formatting": import_.hidden_tokens_before, "third_formatting": import_.hidden_tokens_after, "value": dotted_name } @pg.production("from_import_target : name_as_names") def from_import_target_name_as_names(pack): (name_as_names,) = pack return name_as_names @pg.production("from_import_target : LEFT_PARENTHESIS name_as_names RIGHT_PARENTHESIS") def from_import_parenthesis(pack): (left_parenthesis, name_as_names, right_parenthesis) = pack return left_parenthesis.hidden_tokens_before +\ [{"type": "left_parenthesis", "value": "("}] +\ left_parenthesis.hidden_tokens_after +\ name_as_names +\ right_parenthesis.hidden_tokens_before +\ [{"type": "right_parenthesis", "value": ")"}] +\ right_parenthesis.hidden_tokens_after @pg.production("from_import_target : STAR") def from_import_star(pack): (star,) = pack return [{ "type": "star", "value": "*", "first_formatting": star.hidden_tokens_before, "second_formatting": star.hidden_tokens_after }] @pg.production("name_as_names : name_as_names name_as_name") def name_as_names_name_as_name(pack): (name_as_names, name_as_name) = pack return name_as_names + name_as_name @pg.production("name_as_names : name_as_name") def name_as_names(pack): (name_as_name,) = pack return name_as_name @pg.production("name_as_name : NAME AS NAME") def name_as_name_name_as_name(pack): (name, as_, name2) = pack return [{ "type": "name_as_name", "value": name.value, "first_formatting": as_.hidden_tokens_before, "second_formatting": as_.hidden_tokens_after, "target": name2.value }] @pg.production("name_as_name : NAME") def name_as_name_name(pack): (name,) = pack return [{ "type": "name_as_name", "value": name.value, "target": "", "first_formatting": [], "second_formatting": [] }] @pg.production("name_as_name : NAME SPACE") def name_as_name_name_space(pack): (name, space) = pack return [{ "type": "name_as_name", "target": None, "value": name.value, "first_formatting": [], "second_formatting": [] }] + [create_node_from_token(space)] @pg.production("name_as_name : comma") def name_as_name_comma_space(pack): (comma,) = pack return [comma] @pg.production("dotted_as_names : dotted_as_names comma dotted_as_name") def dotted_as_names_dotted_as_names_dotted_as_name(pack): (dotted_as_names, comma, dotted_as_names2) = pack return dotted_as_names + [comma] + dotted_as_names2 @pg.production("dotted_as_names : dotted_as_name") def dotted_as_names_dotted_as_name(pack): (dotted_as_name,) = pack return dotted_as_name @pg.production("dotted_as_name : dotted_name AS NAME") def dotted_as_name_as(pack): (dotted_name, as_, name) = pack return [{ "type": "dotted_as_name", "value": dotted_name, "first_formatting": as_.hidden_tokens_before, "second_formatting": as_.hidden_tokens_after, "target": name.value, }] @pg.production("dotted_as_name : dotted_name") def dotted_as_name(pack): (dotted_name,) = pack return [{ "type": "dotted_as_name", "value": dotted_name, "first_formatting": [], "second_formatting": [], "target": "" }] @pg.production("dotted_name : dotted_name dotted_name_element") def dotted_name_elements_element(pack): (dotted_name, dotted_name_element) = pack return dotted_name + dotted_name_element @pg.production("dotted_name : dotted_name_element") def dotted_name_element(pack): (dotted_name_element,) = pack return dotted_name_element @pg.production("dotted_name_element : NAME") @pg.production("dotted_name_element : SPACE") def dotted_name(pack): (token,) = pack return [create_node_from_token(token)] @pg.production("dotted_name_element : DOT") def dotted_name_dot(pack): (dot,) = pack return [{ "type": "dot", "first_formatting": dot.hidden_tokens_before, "second_formatting": dot.hidden_tokens_after, }] @pg.production("dotted_name_element : ELLIPSIS") def dotted_name_dot_dot_dot(pack): ellipsis = pack[0] return [{ "type": "ellipsis", "first_formatting": ellipsis.hidden_tokens_before, "second_formatting": ellipsis.hidden_tokens_after, }] baron-0.10.1/baron/grammator_operators.py000066400000000000000000000445351415427440200204520ustar00rootroot00000000000000from .parser import ParsingError def include_operators(pg): @pg.production("old_test : or_test") @pg.production("old_test : old_lambdef") def old_test(pack): (level,) = pack return level @pg.production("testlist_safe : old_test comma old_test") def testlist_safe(pack): (old_test, comma, old_test2) = pack return [old_test, comma, old_test2] @pg.production("testlist_safe : old_test comma testlist_safe") def testlist_safe_more(pack): (old_test, comma, testlist_safe) = pack return [old_test, comma] + testlist_safe @pg.production("expr_stmt : test COLON test") def alone_annotation(pack): target, colon, annotation = pack return { "type": "standalone_annotation", "target": target, "annotation": annotation, # not called "value" in case someone # wants to work on both assignment and # standalone annotations "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, } @pg.production("expr_stmt : test COLON test EQUAL test") def augmented_assignment_node(pack): target, colon, annotation, equal, test = pack return { "type": "assignment", "first_formatting": equal.hidden_tokens_before if equal else [], "second_formatting": equal.hidden_tokens_after if equal else [], "target": target, "value": test, "operator": "", "annotation": annotation, "annotation_first_formatting": colon.hidden_tokens_before, "annotation_second_formatting": colon.hidden_tokens_after, } @pg.production("expr_stmt : testlist_star_expr augassign_operator testlist") @pg.production("expr_stmt : testlist_star_expr augassign_operator yield_expr") def augmented_assignment_node_2(pack): (target, operator, value) = pack return { "type": "assignment", "first_formatting": operator.hidden_tokens_before, "second_formatting": operator.hidden_tokens_after, "operator": operator.value[:-1], "target": target, "value": value, "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], } @pg.production("test_or_star_expr : test") @pg.production("test_or_star_expr : star_expr") def test_or_star_expr(pack): return pack[0] @pg.production("star_expr : STAR expr") def star_expr(pack): star, expr = pack return { "type": "star_expression", "formatting": star.hidden_tokens_after, "value": expr, } @pg.production("augassign_operator : PLUS_EQUAL") @pg.production("augassign_operator : MINUS_EQUAL") @pg.production("augassign_operator : STAR_EQUAL") @pg.production("augassign_operator : SLASH_EQUAL") @pg.production("augassign_operator : PERCENT_EQUAL") @pg.production("augassign_operator : AMPER_EQUAL") @pg.production("augassign_operator : AT_EQUAL") @pg.production("augassign_operator : VBAR_EQUAL") @pg.production("augassign_operator : CIRCUMFLEX_EQUAL") @pg.production("augassign_operator : LEFT_SHIFT_EQUAL") @pg.production("augassign_operator : RIGHT_SHIFT_EQUAL") @pg.production("augassign_operator : DOUBLE_STAR_EQUAL") @pg.production("augassign_operator : DOUBLE_SLASH_EQUAL") def augassign_operator(pack): (operator,) = pack return operator @pg.production("expr_stmt : testlist_star_expr EQUAL yield_expr") @pg.production("expr_stmt : testlist_star_expr EQUAL expr_stmt") def assignment_node(pack): (target, equal, value) = pack return { "type": "assignment", "operator": "", "value": value, "target": target, "first_formatting": equal.hidden_tokens_before, "second_formatting": equal.hidden_tokens_after, "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], } @pg.production("test : or_test IF or_test ELSE test") def ternary_operator_node(pack): (first, if_, second, else_, third) = pack return { "type": "ternary_operator", "first": first, "second": third, "value": second, "first_formatting": if_.hidden_tokens_before, "second_formatting": if_.hidden_tokens_after, "third_formatting": else_.hidden_tokens_before, "fourth_formatting": else_.hidden_tokens_after, } @pg.production("or_test : and_test OR or_test") @pg.production("and_test : not_test AND and_test") def and_or_node(pack): (first, operator, second) = pack return { "type": "boolean_operator", "value": operator.value, "first": first, "second": second, "first_formatting": operator.hidden_tokens_before, "second_formatting": operator.hidden_tokens_after, } @pg.production("not_test : NOT not_test") def not_node(pack): (not_, comparison) = pack return { "type": "unitary_operator", "value": "not", "target": comparison, "formatting": not_.hidden_tokens_after } @pg.production("comparison : expr LESS comparison") @pg.production("comparison : expr GREATER comparison") @pg.production("comparison : expr EQUAL_EQUAL comparison") @pg.production("comparison : expr LESS_EQUAL comparison") @pg.production("comparison : expr GREATER_EQUAL comparison") @pg.production("comparison : expr NOT_EQUAL comparison") @pg.production("comparison : expr IN comparison") @pg.production("comparison : expr IS comparison") def comparison_node(pack): (expr, comparison_operator, comparison_) = pack return { "type": "comparison", "first": expr, "value": { "type": "comparison_operator", "first": comparison_operator.value, "second": "", "formatting": [], }, "second": comparison_, "first_formatting": comparison_operator.hidden_tokens_before, "second_formatting": comparison_operator.hidden_tokens_after } @pg.production("comparison : expr IS NOT comparison") @pg.production("comparison : expr NOT IN comparison") def comparison_advanced_node(pack): (expr, comparison_operator, comparison_operator2, comparison_) = pack return { "type": "comparison", "value": { "type": "comparison_operator", "first": comparison_operator.value, "second": comparison_operator2.value, "formatting": comparison_operator.hidden_tokens_after }, "first": expr, "second": comparison_, "first_formatting": comparison_operator.hidden_tokens_before, "second_formatting": comparison_operator2.hidden_tokens_after, } @pg.production("expr : xor_expr VBAR expr") @pg.production("xor_expr : and_expr CIRCUMFLEX xor_expr") @pg.production("and_expr : shift_expr AMPER and_expr") @pg.production("shift_expr : arith_expr RIGHT_SHIFT shift_expr") @pg.production("shift_expr : arith_expr LEFT_SHIFT shift_expr") @pg.production("arith_expr : term PLUS arith_expr") @pg.production("arith_expr : term MINUS arith_expr") @pg.production("term : factor STAR term") @pg.production("term : factor SLASH term") @pg.production("term : factor PERCENT term") @pg.production("term : factor DOUBLE_SLASH term") @pg.production("term : factor AT term") @pg.production("power : atom DOUBLE_STAR factor") @pg.production("power : atom DOUBLE_STAR power") def binary_operator_node(pack): (first, operator, second) = pack return { "type": "binary_operator", "value": operator.value, "first": first, "second": second, "first_formatting": operator.hidden_tokens_before, "second_formatting": operator.hidden_tokens_after } @pg.production("factor : PLUS factor") @pg.production("factor : MINUS factor") @pg.production("factor : TILDE factor") def factor_unitary_operator_space(pack): (operator, factor,) = pack return { "type": "unitary_operator", "value": operator.value, "formatting": operator.hidden_tokens_after, "target": factor, } @pg.production("power : atomtrailers DOUBLE_STAR factor") @pg.production("power : atomtrailers DOUBLE_STAR power") def power_atomtrailer_power(pack): (atomtrailers, double_star, factor) = pack return { "type": "binary_operator", "value": double_star.value, "first": { "type": "atomtrailers", "value": atomtrailers, }, "second": factor, "first_formatting": double_star.hidden_tokens_before, "second_formatting": double_star.hidden_tokens_after } @pg.production("power : atomtrailers") def power_atomtrailers(pack): (atomtrailers,) = pack return { "type": "atomtrailers", "value": atomtrailers } @pg.production("power : NAME SPACE atomtrailers") def power_atomtrailers_await(pack): (await_, space, atomtrailers,) = pack if await_.value != "await": raise ParsingError("The only possible keyword before an atomtrailers is 'await', not '%s'" % await_.value) return { "type": "await", "formatting": [{'type': 'space', 'value': space.value}], "value": { "type": "atomtrailers", "value": atomtrailers, } } @pg.production("atomtrailers : atom") def atomtrailers_atom(pack): (atom,) = pack return [atom] @pg.production("atomtrailers : atom trailers") def atomtrailer(pack): (atom, trailers) = pack return [atom] + trailers @pg.production("trailers : trailer") def trailers(pack): (trailer,) = pack return trailer @pg.production("trailers : trailers trailer") def trailers_trailer(pack): (trailers, trailer) = pack return trailers + trailer @pg.production("trailer : DOT NAME") def trailer(pack): (dot, name,) = pack return [{ "type": "dot", "first_formatting": dot.hidden_tokens_before, "second_formatting": dot.hidden_tokens_after, }, { "type": "name", "value": name.value, }] @pg.production("trailer : LEFT_PARENTHESIS argslist RIGHT_PARENTHESIS") def trailer_call(pack): (left, argslist, right) = pack return [{ "type": "call", "value": argslist, "first_formatting": left.hidden_tokens_before, "second_formatting": left.hidden_tokens_after, "third_formatting": right.hidden_tokens_before, "fourth_formatting": right.hidden_tokens_after, }] @pg.production("trailer : LEFT_SQUARE_BRACKET subscript RIGHT_SQUARE_BRACKET") @pg.production("trailer : LEFT_SQUARE_BRACKET subscriptlist RIGHT_SQUARE_BRACKET") def trailer_getitem_ellipsis(pack): (left, subscript, right) = pack return [{ "type": "getitem", "value": subscript, "first_formatting": left.hidden_tokens_before, "second_formatting": left.hidden_tokens_after, "third_formatting": right.hidden_tokens_before, "fourth_formatting": right.hidden_tokens_after, }] @pg.production("subscript : ELLIPSIS") @pg.production("atom : ELLIPSIS") def subscript_ellipsis(pack): ellipsis = pack[0] return { "type": "ellipsis", "first_formatting": ellipsis.hidden_tokens_after, "second_formatting": ellipsis.hidden_tokens_after, } @pg.production("subscript : test") @pg.production("subscript : slice") def subscript_test(pack): (test,) = pack return test @pg.production("slice : COLON") def slice(pack): (colon,) = pack return { "type": "slice", "lower": {}, "upper": {}, "step": {}, "has_two_colons": False, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": [], "fourth_formatting": [], } @pg.production("slice : COLON COLON") def slice_colon(pack): (colon, colon2) = pack return { "type": "slice", "lower": {}, "upper": {}, "step": {}, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : test COLON") def slice_lower(pack): (test, colon,) = pack return { "type": "slice", "lower": test, "upper": {}, "step": {}, "has_two_colons": False, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": [], "fourth_formatting": [], } @pg.production("slice : test COLON COLON") def slice_lower_colon_colon(pack): (test, colon, colon2) = pack return { "type": "slice", "lower": test, "upper": {}, "step": {}, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : COLON test") def slice_upper(pack): (colon, test,) = pack return { "type": "slice", "lower": {}, "upper": test, "step": {}, "has_two_colons": False, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": [], "fourth_formatting": [], } @pg.production("slice : COLON test COLON") def slice_upper_colon(pack): (colon, test, colon2) = pack return { "type": "slice", "lower": {}, "upper": test, "step": {}, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : COLON COLON test") def slice_step(pack): (colon, colon2, test) = pack return { "type": "slice", "lower": {}, "upper": {}, "step": test, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : test COLON test") def slice_lower_upper(pack): (test, colon, test2,) = pack return { "type": "slice", "lower": test, "upper": test2, "step": {}, "has_two_colons": False, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": [], "fourth_formatting": [], } @pg.production("slice : test COLON test COLON") def slice_lower_upper_colon(pack): (test, colon, test2, colon2) = pack return { "type": "slice", "lower": test, "upper": test2, "step": {}, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : test COLON COLON test") def slice_lower_step(pack): (test, colon, colon2, test2) = pack return { "type": "slice", "lower": test, "upper": {}, "step": test2, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : COLON test COLON test") def slice_upper_step(pack): (colon, test, colon2, test2) = pack return { "type": "slice", "lower": {}, "upper": test, "step": test2, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } @pg.production("slice : test COLON test COLON test") def slice_lower_upper_step(pack): (test, colon, test2, colon2, test3) = pack return { "type": "slice", "lower": test, "upper": test2, "step": test3, "has_two_colons": True, "first_formatting": colon.hidden_tokens_before, "second_formatting": colon.hidden_tokens_after, "third_formatting": colon2.hidden_tokens_before, "fourth_formatting": colon2.hidden_tokens_after, } baron-0.10.1/baron/grammator_primitives.py000066400000000000000000000250411415427440200206160ustar00rootroot00000000000000from .utils import create_node_from_token def include_primivites(pg, print_function): if not print_function: @pg.production("print_stmt : PRINT") def print_stmt_empty(pack): (print_,) = pack return { "type": "print", "value": [], "destination": None, "destination_formatting": [], "formatting": [], } @pg.production("print_stmt : PRINT testlist") def print_stmt(pack): (print_, testlist) = pack return { "type": "print", "value": testlist["value"] if testlist["type"] == "tuple" and testlist["with_parenthesis"] is False else [testlist], "destination": None, "destination_formatting": [], "formatting": print_.hidden_tokens_after, } @pg.production("print_stmt : PRINT RIGHT_SHIFT test") def print_stmt_redirect(pack): (print_, right_shift, test) = pack return { "type": "print", "value": [], "destination": test, "destination_formatting": right_shift.hidden_tokens_after, "formatting": print_.hidden_tokens_after, } @pg.production("print_stmt : PRINT RIGHT_SHIFT test COMMA testlist") def print_stmt_redirect_testlist(pack): (print_, right_shift, test, comma, testlist) = pack value = [{ "type": "comma", "first_formatting": comma.hidden_tokens_before, "second_formatting": comma.hidden_tokens_after, }] value += testlist["value"] if testlist["type"] == "tuple" else [testlist] return { "type": "print", "value": value, "destination": test, "destination_formatting": right_shift.hidden_tokens_after, "formatting": print_.hidden_tokens_after, } @pg.production("assert_stmt : EXEC expr") def exec_stmt(pack): (exec_, expr) = pack return { "type": "exec", "value": expr, "globals": None, "locals": None, "first_formatting": exec_.hidden_tokens_after, "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [] } @pg.production("assert_stmt : EXEC expr IN test") def exec_stmt_in(pack): (exec_, expr, in_, test) = pack return { "type": "exec", "value": expr, "globals": test, "locals": None, "first_formatting": exec_.hidden_tokens_after, "second_formatting": in_.hidden_tokens_before, "third_formatting": in_.hidden_tokens_after, "fourth_formatting": [], "fifth_formatting": [] } @pg.production("assert_stmt : EXEC expr IN test COMMA test") def exec_stmt_in_comma(pack): (exec_, expr, in_, test, comma, test2) = pack return { "type": "exec", "value": expr, "globals": test, "locals": test2, "first_formatting": exec_.hidden_tokens_after, "second_formatting": in_.hidden_tokens_before, "third_formatting": in_.hidden_tokens_after, "fourth_formatting": comma.hidden_tokens_before, "fifth_formatting": comma.hidden_tokens_after } @pg.production("flow_stmt : return_stmt") @pg.production("flow_stmt : break_stmt") @pg.production("flow_stmt : continue_stmt") @pg.production("flow_stmt : yield_stmt") @pg.production("yield_stmt : yield_expr") def flow(pack): (flow_stmt,) = pack return flow_stmt @pg.production("return_stmt : RETURN") def return_empty(pack): (token,) = pack return { "type": token.name.lower(), "value": None, "formatting": token.hidden_tokens_after, } @pg.production("yield_expr : YIELD") def yield_expr(pack): (yield_,) = pack return { "type": yield_.name.lower(), "value": None, "formatting": yield_.hidden_tokens_after, } @pg.production("break_stmt : BREAK") @pg.production("continue_stmt : CONTINUE") @pg.production("pass_stmt : PASS") def break_stmt(pack): (token,) = pack return {"type": token.name.lower()} @pg.production("raise_stmt : RAISE") def raise_stmt_empty(pack): (raise_,) = pack return { "type": "raise", "value": None, "instance": None, "traceback": None, "first_formatting": raise_.hidden_tokens_after, "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "comma_or_from": None, } @pg.production("raise_stmt : RAISE test") def raise_stmt(pack): (raise_, test) = pack return { "type": "raise", "value": test, "instance": None, "traceback": None, "first_formatting": raise_.hidden_tokens_after, "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "comma_or_from": None, } @pg.production("raise_stmt : RAISE test FROM test") def raise_stmt_from(pack): (raise_, test, from_, test2) = pack return { "type": "raise", "value": test, "instance": test2, "traceback": None, "first_formatting": raise_.hidden_tokens_after, "second_formatting": from_.hidden_tokens_before, "third_formatting": from_.hidden_tokens_after, "fourth_formatting": [], "fifth_formatting": [], "comma_or_from": "from", } @pg.production("raise_stmt : RAISE test COMMA test") def raise_stmt_instance(pack): (raise_, test, comma, test2) = pack return { "type": "raise", "value": test, "instance": test2, "traceback": None, "first_formatting": raise_.hidden_tokens_after, "second_formatting": comma.hidden_tokens_before, "third_formatting": comma.hidden_tokens_after, "fourth_formatting": [], "fifth_formatting": [], "comma_or_from": ",", } @pg.production("raise_stmt : RAISE test COMMA test COMMA test") def raise_stmt_instance_traceback(pack): (raise_, test, comma, test2, comma2, test3) = pack return { "type": "raise", "value": test, "instance": test2, "traceback": test3, "first_formatting": raise_.hidden_tokens_after, "second_formatting": comma.hidden_tokens_before, "third_formatting": comma.hidden_tokens_after, "fourth_formatting": comma2.hidden_tokens_before, "fifth_formatting": comma2.hidden_tokens_after, "comma_or_from": ",", } @pg.production("assert_stmt : ASSERT test") def assert_stmt(pack): (assert_, test) = pack return { "type": "assert", "value": test, "message": None, "first_formatting": assert_.hidden_tokens_after, "second_formatting": [], "third_formatting": [] } @pg.production("assert_stmt : ASSERT test COMMA test") def assert_stmt_message(pack): (assert_, test, comma, test2) = pack return { "type": "assert", "value": test, "message": test2, "first_formatting": assert_.hidden_tokens_after, "second_formatting": comma.hidden_tokens_before, "third_formatting": comma.hidden_tokens_after } @pg.production("global_stmt : GLOBAL names") def global_stmt(pack): (global_, names) = pack return { "type": "global", "formatting": global_.hidden_tokens_after, "value": names, } @pg.production("nonlocal_stmt : NONLOCAL names") def nonlocal_stmt(pack): (token, names) = pack return { "type": "nonlocal", "formatting": token.hidden_tokens_after, "value": names, } @pg.production("names : NAME") def names_name(pack): (name,) = pack return [create_node_from_token(name)] @pg.production("names : names comma name") def names_names_name(pack): (names, comma, name,) = pack return names + [comma, name] @pg.production("return_stmt : RETURN testlist") @pg.production("yield_expr : YIELD testlist") @pg.production("del_stmt : DEL exprlist") def return_testlist(pack): (token, testlist) = pack return { "type": token.name.lower(), "value": testlist, "formatting": token.hidden_tokens_after, } @pg.production("yield_expr : YIELD FROM test") def yield_from_expr(pack): (yield_, from_, test) = pack return { "type": "yield_from", "first_formatting": from_.hidden_tokens_after, "value": test, "formatting": yield_.hidden_tokens_after, } @pg.production("lambdef : LAMBDA COLON test") @pg.production("old_lambdef : LAMBDA COLON old_test") def lambdef(pack): (lambda_, colon, test) = pack return { "type": "lambda", "arguments": [], "first_formatting": lambda_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, "value": test } @pg.production("lambdef : LAMBDA parameters COLON test") @pg.production("old_lambdef : LAMBDA parameters COLON old_test") def lambdef_arguments(pack): (lambda_, parameters, colon, test) = pack return { "type": "lambda", "arguments": parameters, "first_formatting": lambda_.hidden_tokens_after, "second_formatting": colon.hidden_tokens_before, "third_formatting": colon.hidden_tokens_after, "value": test } baron-0.10.1/baron/grouper.py000066400000000000000000000074721415427440200160450ustar00rootroot00000000000000# encoding: utf-8 import re from .utils import FlexibleIterator to_group = ( ("+", "="), ("-", "="), ("*", "="), ("/", "="), ("%", "="), ("&", "="), ("|", "="), ("^", "="), ("@", "="), ("/", "/"), ("*", "*"), ("<", "<"), (">", ">"), ("=", "="), ("!", "="), ("<", ">"), ("<", "="), (">", "="), ("**", "="), ("//", "="), ("<<", "="), (">>", "="), ("\r", "\n"), (".", "."), ("..", "."), ("-", ">"), ) to_group_keys, _ = list(zip(*to_group)) def group(sequence): return list(group_generator(sequence)) def match_on_next(regex, iterator): return iterator.show_next() and re.match(regex, iterator.show_next()) def group_generator(sequence): iterator = FlexibleIterator(sequence) current = None while True: if iterator.end(): return current = next(iterator) if current in to_group_keys and matching_found(to_group, current, iterator.show_next()): current += next(iterator) if current in to_group_keys and matching_found(to_group, current, iterator.show_next()): current += next(iterator) if current in list('uUfFrRbB') and str(iterator.show_next()).startswith(('"', "'")): current += next(iterator) if str(current).lower() in ["ur", "br", "fr", "rf"] and str(iterator.show_next()).startswith(('"', "'")): current += next(iterator) if any([re.match(x, current) for x in (r'^\d+[eE]$', r'^\d+\.\d*[eE]$', r'^\.\d+[eE]$')]): current += next(iterator) current += next(iterator) # It's required in a case where I have something like that: # ['123.123e', '[+-]', '123'] assert re.match(r'^\d+[eE][-+]?\d+[jJ]?$', current) or re.match(r'^\d*.\d*[eE][-+]?\d+[jJ]?$', current) if current == "\\" and iterator.show_next() in ('\n', '\r\n'): current += next(iterator) if re.match(r'^\s+$', str(iterator.show_next())): current += next(iterator) if current == "\\" and iterator.show_next() == "\r" and iterator.show_next(2) == "\n": current += next(iterator) current += next(iterator) if re.match(r'^\s+$', str(iterator.show_next())): current += next(iterator) if re.match(r'^\s+$', current) and iterator.show_next() == "\\": current += next(iterator) current += next(iterator) if iterator.show_next() == "\n": current += next(iterator) if re.match(r'^\s+$', str(iterator.show_next())): current += next(iterator) if (re.match(r'^[_\d]+$', current) and match_on_next(r'^\.$', iterator)) or\ (current == "." and match_on_next(r'^\d+[_\d]*([jJ]|[eE]\d*)?$', iterator)): current += next(iterator) if match_on_next(r'^[_\d]*[jJ]?$', iterator) and match_on_next(r'^[_\d]*[jJ]?$', iterator).group(): current += next(iterator) if re.match(r'^\d+\.$', current) and match_on_next(r'^\d*[eE]\d*$', iterator): current += next(iterator) if re.match(r'^\d+\.?[eE]$', current) and match_on_next(r'^\d+$', iterator): current += next(iterator) if re.match(r'^\d*\.?\d*[eE]$', current) and not re.match('[eE]', current) and match_on_next(r'^[-+]$', iterator) and iterator.show_next(2) and re.match(r'^\d+$', iterator.show_next(2)): current += next(iterator) current += next(iterator) # edge case where 2 dots follow themselves but not 3 (an ellipsis) if current == "..": yield "." yield "." continue yield current def matching_found(to_group, current, target): return target in [x[1] for x in to_group if x[0] == current] baron-0.10.1/baron/helpers.py000066400000000000000000000006301415427440200160110ustar00rootroot00000000000000import json import sys from os import linesep from . import parse def show(source_code): sys.stdout.write(json.dumps(parse(source_code), indent=4) + linesep) def show_file(target_file): with open(target_file, "r") as source_code: sys.stdout.write(json.dumps(parse(source_code.read()), indent=4) + linesep) def show_node(node): sys.stdout.write(json.dumps(node, indent=4) + linesep) baron-0.10.1/baron/indentation_marker.py000066400000000000000000000074341415427440200202350ustar00rootroot00000000000000from .utils import FlexibleIterator """ Objective: add an INDENT token and a DEDENT token arround every block. Strategy: put after every ":" that is not in a slice/dictionary declaration/lambda. Slice and dictionary are easy: increase a number when a "[" or "{" is found, decrease it for a "]" or "}". If the number is != 0, we are in a dictionary or slice -> do not put a INDENT when a ":" is found. Lambda are a bit different: increase another number when a "lambda" is found, if the number is != 0 and a ":" is found, decrease this number, otherwise put a INDENT. For the DEDENT, I'm probably going to need to keep a list of indentation and decheck the last one every time I encounter a meaningfull line. Still need to test this idea. """ def mark_indentation(sequence): return list(mark_indentation_generator(sequence)) def transform_tabs_to_spaces(string): return string.replace("\t", " " * 8) def get_space(node): """ Return space formatting information of node. If the node does not have a third formatting item - like in a ('ENDL', '\n') node - then we return None as a flag value. This is maybe not the best behavior but it seems to work for now. """ if len(node) < 4 or len(node[3]) == 0: return None return transform_tabs_to_spaces(node[3][0][1]) def mark_indentation_generator(sequence): iterator = FlexibleIterator(sequence) current = None, None indentations = [] while True: if iterator.end(): return current = next(iterator) if current is None: return # end of the file, I need to pop all indentations left and put the # corresponding dedent token for them if current[0] == "ENDMARKER" and indentations: while len(indentations) > 0: yield ('DEDENT', '') indentations.pop() # if were are at ":\n" like in "if stuff:\n" if current[0] == "COLON" and iterator.show_next(1)[0] == "ENDL": # if we aren't in "if stuff:\n\n" if iterator.show_next(2)[0] not in ("ENDL",): indentations.append(get_space(iterator.show_next())) yield current yield next(iterator) yield ('INDENT', '') continue else: # else, skip all "\n" yield current for i in iterator: if i[0] == 'ENDL' and iterator.show_next()[0] not in ('ENDL',): indentations.append(get_space(i)) yield ('INDENT', '') yield i break yield i continue # if we were in an indented situation and that the next line has a lower indentation if indentations and current[0] == "ENDL": the_indentation_level_changed = get_space(current) is None or get_space(current) != indentations[-1] if the_indentation_level_changed and iterator.show_next()[0] not in ("ENDL", "COMMENT"): new_indent = get_space(current) if len(current) == 4 else "" yield current # pop until reaching the matching indentation level while indentations and string_is_bigger(indentations[-1], new_indent): indentations.pop() yield ('DEDENT', '') yield next(iterator) continue yield current def string_is_bigger(s1, s2): """ Return s1 > s2 by taking into account None values. None is always smaller than any string. None > "string" works in python2 but not in python3. This function makes it work in python3 too. """ if s1 is None: return False elif s2 is None: return True else: return s1 > s2 baron-0.10.1/baron/inner_formatting_grouper.py000066400000000000000000000122051415427440200214600ustar00rootroot00000000000000from .utils import FlexibleIterator, BaronError class UnExpectedFormattingToken(BaronError): pass class GroupingError(BaronError): pass GROUP_THOSE = ( "ENDL", # TODO test those 2 "COMMENT", "SPACE", ) ENTER_GROUPING_MODE = ( "LEFT_PARENTHESIS", "LEFT_BRACKET", "LEFT_SQUARE_BRACKET", ) QUIT_GROUPING_MODE = ( "RIGHT_PARENTHESIS", "RIGHT_BRACKET", "RIGHT_SQUARE_BRACKET", ) GROUP_ON = ( "COMMA", "COLON", # TODO test everything bellow "STRING", "RAW_STRING", "INTERPOLATED_STRING", "INTERPOLATED_RAW_STRING", "BINARY_STRING", "BINARY_RAW_STRING", "UNICODE_STRING", "UNICODE_RAW_STRING", "AS", "IMPORT", "DOUBLE_STAR", "DOT", "LEFT_SQUARE_BRACKET", "STAR", "SLASH", "PERCENT", "DOUBLE_SLASH", "PLUS", "MINUS", "LEFT_SHIFT", "RIGHT_SHIFT", "AMPER", "CIRCUMFLEX", "VBAR", "LESS", "GREATER", "EQUAL_EQUAL", "LESS_EQUAL", "GREATER_EQUAL", "NOT_EQUAL", "IN", "IS", "NOT", "AND", "OR", "AT", "IF", "ELSE", "FROM", "EQUAL", "PLUS_EQUAL", "MINUS_EQUAL", "AT_EQUAL", "STAR_EQUAL", "SLASH_EQUAL", "PERCENT_EQUAL", "AMPER_EQUAL", "VBAR_EQUAL", "CIRCUMFLEX_EQUAL", "LEFT_SHIFT_EQUAL", "RIGHT_SHIFT_EQUAL", "DOUBLE_STAR_EQUAL", "DOUBLE_SLASH_EQUAL", "ENDL", "FOR", "COLON", "RAW_STRING", "UNICODE_STRING", "UNICODE_RAW_STRING", ) + ENTER_GROUPING_MODE + QUIT_GROUPING_MODE def append_to_token_after(token, to_append_list): if len(token) == 2: return (token[0], token[1], [], to_append_list) elif len(token) == 3: return (token[0], token[1], token[2], to_append_list) elif len(token) == 4: return (token[0], token[1], token[2], token[3] + to_append_list) def append_to_token_before(token, to_append_list): if len(token) == 2: return (token[0], token[1], to_append_list, []) elif len(token) == 3: return (token[0], token[1], to_append_list + token[2], []) elif len(token) == 4: return (token[0], token[1], to_append_list + token[2], token[3]) def group(sequence): return list(group_generator(sequence)) def fail_on_bad_token(token, debug_file_content, in_grouping_mode): if token[0] in GROUP_ON: return debug_file_content += _append_to_debug_file_content(token) debug_file_content = debug_file_content.split("\n") debug_file_content = list(zip(range(1, len(debug_file_content) + 1), debug_file_content)) debug_file_content = debug_file_content[-8:] debug_file_content = "\n".join(["%4s %s" % (x[0], x[1]) for x in debug_file_content]) raise GroupingError("Fail to group formatting tokens, here:\n%s <----\n\n'%s' should have been in: %s\n\nCurrent value of 'in_grouping_mode': %s" % (debug_file_content, token, ', '.join(sorted(GROUP_ON)), in_grouping_mode)) def _append_to_debug_file_content(token): before_debug = "".join(map(lambda x: x[1], token[2] if len(token) >= 3 else [])) after_debug = "".join(map(lambda x: x[1], token[3] if len(token) >= 4 else [])) return before_debug + token[1] + after_debug def group_generator(sequence): iterator = FlexibleIterator(sequence) current = None, None in_grouping_mode = 0 debug_file_content = "" while True: if iterator.end(): return current = next(iterator) debug_file_content += _append_to_debug_file_content(current) if current[0] in ENTER_GROUPING_MODE: in_grouping_mode += 1 elif current[0] in QUIT_GROUPING_MODE: in_grouping_mode -= 1 assert in_grouping_mode >= 0 if in_grouping_mode: if current[0] in GROUP_THOSE: to_group = [current] while iterator.show_next() and iterator.show_next()[0] in GROUP_THOSE: to_group.append(next(iterator)) debug_file_content += _append_to_debug_file_content(to_group[-1]) # XXX don't remember how (:() but I can end up finding a # DEDENT/INDENT token in this situation and I don't want to # group on it. Need to do test for that. if iterator.show_next()[0] in ("INDENT", "DEDENT"): yield next(iterator) fail_on_bad_token(iterator.show_next(), debug_file_content, in_grouping_mode) current = append_to_token_before(next(iterator), to_group) if current[0] in ENTER_GROUPING_MODE: in_grouping_mode += 1 # TODO test if current[0] in QUIT_GROUPING_MODE: in_grouping_mode -= 1 assert in_grouping_mode >= 0 yield current continue if current[0] in GROUP_ON: while iterator.show_next() and iterator.show_next()[0] in GROUP_THOSE: debug_file_content += _append_to_debug_file_content(iterator.show_next()) current = append_to_token_after(current, [next(iterator)]) yield current baron-0.10.1/baron/parser.py000066400000000000000000000142361415427440200156520ustar00rootroot00000000000000import errno import os import json import stat import tempfile import warnings from .token import BaronToken from rply import ParserGenerator from rply.parser import LRParser from rply.parsergenerator import LRTable from rply.errors import ParserGeneratorWarning from rply.grammar import Grammar from .utils import BaronError class ParsingError(BaronError): pass class BaronParserGenerator(ParserGenerator): def build(self): g = Grammar(self.tokens) for level, (assoc, terms) in enumerate(self.precedence, 1): for term in terms: g.set_precedence(term, assoc, level) for prod_name, syms, func, precedence in self.productions: g.add_production(prod_name, syms, func, precedence) g.set_start() for unused_term in g.unused_terminals(): warnings.warn( "Token %r is unused" % unused_term, ParserGeneratorWarning, stacklevel=2 ) for unused_prod in g.unused_productions(): warnings.warn( "Production %r is not reachable" % unused_prod, ParserGeneratorWarning, stacklevel=2 ) g.build_lritems() g.compute_first() g.compute_follow() # win32 temp directories are already per-user if os.name == "nt": cache_file = os.path.join( tempfile.gettempdir(), "rply-%s-%s-%s.json" % (self.VERSION, self.cache_id, self.compute_grammar_hash(g)) ) else: cache_file = os.path.join( tempfile.gettempdir(), "rply-%s-%s-%s-%s.json" % (self.VERSION, os.getuid(), self.cache_id, self.compute_grammar_hash(g)) ) table = None if os.path.exists(cache_file): with open(cache_file) as f: try: data = json.load(f) except Exception: os.remove(cache_file) data = None if data is not None: stat_result = os.fstat(f.fileno()) if ( os.name == "nt" or ( stat_result.st_uid == os.getuid() and stat.S_IMODE(stat_result.st_mode) == 0o0600 ) ): if self.data_is_valid(g, data): table = LRTable.from_cache(g, data) if table is None: table = LRTable.from_grammar(g) try: fd = os.open(cache_file, os.O_RDWR | os.O_CREAT | os.O_EXCL, 0o0600) except OSError as e: if e.errno != errno.EEXIST: raise else: with os.fdopen(fd, "w") as f: json.dump(self.serialize_table(table), f) # meh :( # if table.sr_conflicts: # warnings.warn( # "%d shift/reduce conflict%s" % (len(table.sr_conflicts), "s" if len(table.sr_conflicts) > 1 else ""), # ParserGeneratorWarning, # stacklevel=2, # ) # if table.rr_conflicts: # warnings.warn( # "%d reduce/reduce conflict%s" % (len(table.rr_conflicts), "s" if len(table.rr_conflicts) > 1 else ""), # ParserGeneratorWarning, # stacklevel=2, # ) return BaronLRParser(table, self.error_handler) class BaronLRParser(LRParser): def parse(self, tokenizer, state=None): lookahead = None lookaheadstack = [] statestack = [0] symstack = [BaronToken("$end", "$end")] current_state = 0 parsed_file_content = "" while True: if self.lr_table.default_reductions[current_state]: t = self.lr_table.default_reductions[current_state] current_state = self._reduce_production(t, symstack, statestack, state) continue if lookahead is None: if lookaheadstack: lookahead = lookaheadstack.pop() else: try: lookahead = next(tokenizer) except StopIteration: lookahead = None if lookahead is None: lookahead = BaronToken("$end", "$end") else: parsed_file_content += lookahead.render() ltype = lookahead.gettokentype() if ltype in self.lr_table.lr_action[current_state]: t = self.lr_table.lr_action[current_state][ltype] if t > 0: statestack.append(t) current_state = t symstack.append(lookahead) lookahead = None continue elif t < 0: current_state = self._reduce_production(t, symstack, statestack, state) continue else: n = symstack[-1] return n else: debug_output = parsed_file_content.split("\n") debug_output = list(zip(range(1, len(debug_output) + 1), debug_output)) debug_output = debug_output[-8:] debug_output = "\n".join(["%4s %s" % (x[0], x[1]) for x in debug_output]) debug_output += "<---- here" debug_output = "Error, got an unexpected token %s here:\n\n" % ltype + debug_output debug_output += "\n\nThe token %s should be one of those: %s" % (ltype, ", ".join(sorted(self.lr_table.lr_action[current_state].keys()))) debug_output += "\n\nBaron has failed to parse this input. If this is valid python code (and by that I mean that the python binary successfully parse this code without any syntax error) (also consider that baron does not yet parse python 3 code integrally) it would be kind if you can extract a snippet of your code that make Baron fails and open a bug here: https://github.com/PyCQA/baron/issues\n\nSorry for the inconvenience." raise ParsingError(debug_output) baron-0.10.1/baron/path.py000066400000000000000000000225431415427440200153120ustar00rootroot00000000000000from .render import RenderWalker, child_by_key from .utils import is_newline, split_on_newlines, total_ordering from copy import deepcopy def position_to_path(tree, position): """Path to the node located at the given line and column This function locates a node in the rendered source code """ return PositionFinder().find(tree, position) def path_to_node(tree, path): """FST node located at the given path""" if path is None: return None node = tree for key in path: node = child_by_key(node, key) return node def position_to_node(tree, position): """FST node located at the given line and column""" return path_to_node(tree, position_to_path(tree, position)) def node_to_bounding_box(node): """Bounding box of the given node The bounding box of a node represents its left most and right most position in the rendered source code. Its left position is here always (1, 1). """ return BoundingBoxFinder().compute(node) def path_to_bounding_box(tree, path): """Absolute bounding box of the node located at the given path""" return BoundingBoxFinder().compute(tree, path) @total_ordering class Position(object): """Handles a cursor's line and column Operations requiring another Position as argument can be given an indexable object of len >= 2 where the index 0 contains the line and the index 1 contains the column. For example a tuple of len 2. """ def __init__(self, position): if hasattr(position, 'line') and hasattr(position, 'column'): self.line = position.line self.column = position.column elif len(position) >= 2: self.line = position[0] self.column = position[1] else: raise AttributeError(position) def advance_columns(self, columns): """(3, 10) -> (3, 11)""" self.column += columns def advance_line(self): """(3, 10) -> (4, 1)""" self.line += 1 self.column = 1 @property def left(self): """(3, 10) -> (3, 9)""" return Position((self.line, self.column - 1)) @property def right(self): """(3, 10) -> (3, 11)""" return Position((self.line, self.column + 1)) def __add__(self, other): """(1, 1) + (1, 1) -> (2, 2)""" other = Position(other) return Position((self.line + other.line, self.column + other.column)) def __neg__(self): """(1, -1) -> (-1, 1)""" return Position((-self.line, -self.column)) def __sub__(self, other): """(1, 1) - (1, 1) -> (0, 0)""" other = Position(other) return Position((self.line - other.line, self.column - other.column)) def __nonzero__(self): return self.line >= 0 and self.column >= 0 def __bool__(self): return self.__nonzero__() def __eq__(self, other): """Compares Positions or Position and tuple Will not fail if other is an unsupported type""" if not (hasattr(other, 'line') and hasattr(other, 'column')) and len(other) < 2: return False other = Position(other) return self.line == other.line and self.column == other.column def __lt__(self, other): """Compares Position with Position or indexable object""" other = Position(other) return (self.line, self.column) < (other.line, other.column) def __repr__(self): return 'Position (%s, %s)' % (str(self.line), str(self.column)) def to_tuple(self): return (self.line, self.column) class BoundingBox(object): """Handles a selection's top_left and bottom_right position Operations requiring another BoundingBox as argument can be given an indexable object of len >= 2 where the index 0 contains the top_left position, either as a Position or an indexable object. The index 1 must contain, in a similar manner, the bottom_right position. """ def __init__(self, bounding_box): if hasattr(bounding_box, 'top_left') and hasattr(bounding_box, 'bottom_right'): self.top_left = Position(bounding_box.top_left) self.bottom_right = Position(bounding_box.bottom_right) elif len(bounding_box) >= 2: self.top_left = Position(bounding_box[0]) self.bottom_right = Position(bounding_box[1]) else: raise AttributeError(bounding_box) def __eq__(self, other): """Compares BoundingBox with BoundingBox or indexable object""" if not (hasattr(other, 'top_left') and hasattr(other, 'bottom_right')) and len(other) < 2: return False other = BoundingBox(other) return self.top_left == other.top_left and self.bottom_right == other.bottom_right def __repr__(self): return 'BoundingBox (%s, %s)' % (str(self.top_left), str(self.bottom_right)) class PathWalker(RenderWalker): """Gives the current path while walking the rendered tree It adds an attribute "current_path" which is updated each time the walker takes a step. """ def walk(self, tree): self.current_path = [] super(PathWalker, self).walk(tree) def before(self, key_type, item, render_key): if render_key is not None: self.current_path.append(render_key) return super(PathWalker, self).before(key_type, item, render_key) def after(self, key_type, item, render_key): stop = super(PathWalker, self).after(key_type, item, render_key) if render_key is not None: self.current_path.pop() return stop class PositionFinder(PathWalker): """Find a node by line and column and return the path to it. First, walk through all the nodes while maintaining the current line and column. When the targetted node is found, stop there and build the path while going back up the tree. """ def find(self, tree, position): self.current = Position((1, 1)) self.target = Position(position) self.found_path = None self.walk(tree) return self.found_path def before_constant(self, constant, key): """Determine if we're on the targetted node. If the targetted column is reached, `stop` and `path_found` are set. If the targetted line is passed, only `stop` is set. This prevents unnecessary tree travelling when the targetted column is out of bounds. """ newlines_split = split_on_newlines(constant) for c in newlines_split: if is_newline(c): self.current.advance_line() # if target line is passed if self.current.line > self.target.line: return self.STOP else: advance_by = len(c) if self.is_on_targetted_node(advance_by): self.found_path = deepcopy(self.current_path) return self.STOP self.current.advance_columns(advance_by) before_string = before_constant def is_on_targetted_node(self, advance_by): return self.target.line == self.current.line \ and self.target.column >= self.current.column \ and self.target.column < self.current.column + advance_by class BoundingBoxFinder(PathWalker): """Compute the bounding box of the given node. First, walk to the target path while incrementing the position. When reached, the top-left position is set to the current position. Then walk the whole node, still incrementing the position. When arriving at the end of the node, store the previous position, not the current one, as the bottom-right position. If no target path is given, assume the targetted node is the whole tree. """ def compute(self, tree, target_path=None): self.target_path = target_path self.current_position = Position((1, 1)) self.left_of_current_position = Position((1, 0)) self.top_left = None self.bottom_right = None self.found = True if self.target_path is None or len(target_path) == 0 else False self.walk(tree) if self.found and self.top_left is None and self.bottom_right is None: return BoundingBox((Position((1, 1)), self.left_of_current_position)) return BoundingBox((self.top_left, self.bottom_right)) def before(self, key_type, item, render_key): stop = super(BoundingBoxFinder, self).before(key_type, item, render_key) if self.current_path == self.target_path: self.found = True self.top_left = deepcopy(self.current_position) if key_type not in ['constant', 'string']: return stop newlines_split = split_on_newlines(item) for c in newlines_split: if is_newline(c): self.current_position.advance_line() self.left_of_current_position = self.current_position.left elif c != "": self.current_position.advance_columns(len(c)) self.left_of_current_position = self.current_position.left return stop def after(self, key_type, item, render_key): if self.bottom_right is None and self.found and self.current_path == self.target_path: self.bottom_right = deepcopy(self.left_of_current_position) return super(BoundingBoxFinder, self).after(key_type, item, render_key) baron-0.10.1/baron/render.py000066400000000000000000001162451415427440200156400ustar00rootroot00000000000000import sys import json def render(node, strict=False): """Recipe to render a given FST node. The FST is composed of branch nodes which are either lists or dicts and of leaf nodes which are strings. Branch nodes can have other list, dict or leaf nodes as childs. To render a string, simply output it. To render a list, render each of its elements in order. To render a dict, you must follow the node's entry in the nodes_rendering_order dictionary and its dependents constraints. This function hides all this algorithmic complexity by returning a structured rendering recipe, whatever the type of node. But even better, you should subclass the RenderWalker which simplifies drastically working with the rendered FST. The recipe is a list of steps, each step correspond to a child and is actually a 3-uple composed of the following fields: - `key_type` is a string determining the type of the child in the second field (`item`) of the tuple. It can be one of: - 'constant': the child is a string - 'node': the child is a dict - 'key': the child is an element of a dict - 'list': the child is a list - 'formatting': the child is a list specialized in formatting - `item` is the child itself: either a string, a dict or a list. - `render_key` gives the key used to access this child from the parent node. It's a string if the node is a dict or a number if its a list. Please note that "bool" `key_types` are never rendered, that's why they are not shown here. """ if isinstance(node, list): return render_list(node) elif isinstance(node, dict): return render_node(node, strict=strict) else: raise NotImplementedError("You tried to render a %s. Only list and dicts can be rendered." % node.__class__.__name__) def render_list(node): for pos, child in enumerate(node): yield ('node', child, pos) def render_node(node, strict=False): if node["type"] not in nodes_rendering_order: raise Exception("There are no defined rules for rendering a node of type '%s', has it been defined in render.py?" % node["type"]) for key_type, render_key, dependent in nodes_rendering_order[node['type']]: if not dependent: continue elif key_type == "bool": raise NotImplementedError("Bool keys are only used for dependency, they cannot be rendered. Please set the \"%s\"'s dependent key in \"%s\" node to False" % ((key_type, render_key, dependent), node['type'])) elif isinstance(dependent, str) and not node.get(dependent): continue elif isinstance(dependent, list) and not all([node.get(x) for x in dependent]): continue if strict: try: if key_type == "key": assert isinstance(node[render_key], (dict, type(None))), "Key '%s' is expected to have type of 'key' (dict/None) but has type of '%s' instead" % (render_key, type(node[render_key])) elif key_type == "string": assert isinstance(node[render_key], str), "Key '%s' is expected to have type of 'string' but has type of '%s' instead" % (render_key, type(node[render_key])) elif key_type in ("list", "formatting"): assert isinstance(node[render_key], list), "Key '%s' is expected to have type of 'list' but has type of '%s' instead" % (render_key, type(node[render_key])) elif key_type == "constant": pass else: raise Exception("Invalid key_type '%s', should be one of those: key, string, list, formatting" % key_type) if dependent is True: pass elif isinstance(dependent, str): assert dependent in node elif isinstance(dependent, list): assert all([x in node for x in dependent]) except AssertionError as e: sys.stdout.write("Where node.type == '%s', render_key == '%s' and node ==\n%s\n" % (node["type"], render_key, json.dumps(node, indent=4, sort_keys=True))) raise e if key_type in ['key', 'string', 'list', 'formatting']: yield (key_type, node[render_key], render_key) elif key_type in ['constant', 'string']: yield (key_type, render_key, render_key) else: raise NotImplementedError("Unknown key type \"%s\" in \"%s\" node" % (key_type, node['type'])) node_types = set(['node', 'list', 'key', 'formatting', 'constant', 'bool', 'string']) def node_keys(node): return [key for (_, key, _) in nodes_rendering_order[node['type']]] def child_by_key(node, key): if isinstance(node, list): return node[key] if key in node: return node[key] if key in node_keys(node): return key raise AttributeError("Cannot access key \"%s\" in node \"%s\"" % (key, node)) # for a surprising exception, we won't honnor pep8 here because it really increase lisibility nodes_rendering_order = { "int": [("string", "value", True)], # noqa "long": [("string", "value", True)], # noqa "name": [("string", "value", True)], # noqa "hexa": [("string", "value", True)], # noqa "octa": [("string", "value", True)], # noqa "float": [("string", "value", True)], # noqa "space": [("string", "value", True)], # noqa "binary": [("string", "value", True)], # noqa "complex": [("string", "value", True)], # noqa "float_exponant": [("string", "value", True)], # noqa "left_parenthesis": [("string", "value", True)], # noqa "right_parenthesis": [("string", "value", True)], # noqa "float_exponant_complex": [("string", "value", True)], # noqa "break": [("string", "type", True)], # noqa "continue": [("string", "type", True)], # noqa "pass": [("string", "type", True)], # noqa "dotted_name": [("list", "value", True)], # noqa "ifelseblock": [("list", "value", True)], # noqa "atomtrailers": [("list", "value", True)], # noqa "string_chain": [("list", "value", True)], # noqa "endl": [ ("formatting", "formatting", True), # noqa ("string", "value", True), # noqa ("string", "indent", True), # noqa ], "star": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "star_expression": [ ("constant", "*", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", True), # noqa ], "string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "raw_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "binary_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "unicode_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "binary_raw_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "interpolated_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "interpolated_raw_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], "unicode_raw_string": [ ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ], # FIXME ugly, comment can end up in formatting of another # node or being standalone, this is bad "comment": [ ("formatting", "formatting", "formatting"), # noqa ("string", "value", True), # noqa ], "ternary_operator": [ ("key", "first", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", "if", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "else", True), # noqa ("formatting", "fourth_formatting", True), # noqa ("key", "second", True), # noqa ], "ellipsis": [ ("constant", ".", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ".", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", ".", True), # noqa ], "dot": [ ("formatting", "first_formatting", True), # noqa ("constant", ".", True), # noqa ("formatting", "second_formatting", True), # noqa ], "semicolon": [ ("formatting", "first_formatting", True), # noqa ("constant", ";", True), # noqa ("formatting", "second_formatting", True), # noqa ], "comma": [ ("formatting", "first_formatting", True), # noqa ("constant", ",", True), # noqa ("formatting", "second_formatting", True), # noqa ], "call": [ ("formatting", "first_formatting", True), # noqa ("constant", "(", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", ")", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "decorator": [ ("constant", "@", True), # noqa ("key", "value", True), # noqa ("key", "call", "call"), # noqa ], "class": [ ("list", "decorators", True), # noqa ("constant", "class", True), # noqa ("formatting", "first_formatting", True), # noqa ("string", "name", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", "(", "parenthesis"), # noqa ("formatting", "third_formatting", True), # noqa ("list", "inherit_from", True), # noqa ("formatting", "fourth_formatting", True), # noqa ("constant", ")", "parenthesis"), # noqa ("formatting", "fifth_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "sixth_formatting", True), # noqa ("list", "value", True), # noqa ("bool", "parenthesis", False), # noqa ], "repr": [ ("constant", "`", True), # noqa ("formatting", "first_formatting", True), # noqa ("list", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", "`", True), # noqa ], "list": [ ("formatting", "first_formatting", True), # noqa ("constant", "[", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "]", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "associative_parenthesis": [ ("formatting", "first_formatting", True), # noqa ("constant", "(", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", ")", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "tuple": [ ("formatting", "first_formatting", "with_parenthesis"), # noqa ("constant", "(", "with_parenthesis"), # noqa ("formatting", "second_formatting", "with_parenthesis"), # noqa ("list", "value", True), # noqa ("formatting", "third_formatting", "with_parenthesis"), # noqa ("constant", ")", "with_parenthesis"), # noqa ("formatting", "fourth_formatting", "with_parenthesis"), # noqa ("bool", "with_parenthesis", False), # noqa ], "await": [ ("constant", "await", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", True), # noqa ], "def": [ ("list", "decorators", True), # noqa ("bool", "async", False), # noqa ("constant", "async", "async"), # noqa ("formatting", "async_formatting", "async"), # noqa ("constant", "def", True), # noqa ("formatting", "first_formatting", True), # noqa ("string", "name", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", "(", True), # noqa ("formatting", "third_formatting", True), # noqa ("list", "arguments", True), # noqa ("formatting", "fourth_formatting", True), # noqa ("constant", ")", True), # noqa ("formatting", "return_annotation_first_formatting", "return_annotation"), # noqa ("constant", "->", "return_annotation"), # noqa ("formatting", "return_annotation_second_formatting", "return_annotation"), # noqa ("key", "return_annotation", "return_annotation"), # noqa ("formatting", "fifth_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "sixth_formatting", True), # noqa ("list", "value", True), # noqa ], "call_argument": [ ("key", "target", "target"), # noqa ("formatting", "first_formatting", "target"), # noqa ("constant", "=", "target"), # noqa ("formatting", "second_formatting", "target"), # noqa ("key", "value", True), # noqa ], "def_argument": [ ("key", "target", True), # noqa ("formatting", "annotation_first_formatting", "annotation"), # noqa ("constant", ":", "annotation"), # noqa ("formatting", "annotation_second_formatting", "annotation"), # noqa ("key", "annotation", "annotation"), # noqa ("formatting", "first_formatting", "value"), # noqa ("constant", "=", "value"), # noqa ("formatting", "second_formatting", "value"), # noqa ("key", "value", "value"), # noqa ], "list_argument": [ ("constant", "*", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "annotation_first_formatting", "annotation"), # noqa ("constant", ":", "annotation"), # noqa ("formatting", "annotation_second_formatting", "annotation"), # noqa ("key", "annotation", "annotation"), # noqa ], "kwargs_only_marker": [ ("constant", "*", True), # noqa ("formatting", "formatting", True), # noqa ], "dict_argument": [ ("constant", "**", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "annotation_first_formatting", "annotation"), # noqa ("constant", ":", "annotation"), # noqa ("formatting", "annotation_second_formatting", "annotation"), # noqa ("key", "annotation", "annotation"), # noqa ], "return": [ ("constant", "return", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", "value"), # noqa ], "raise": [ ("constant", "raise", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "value", "value"), # noqa ("formatting", "second_formatting", "instance"), # noqa ("string", "comma_or_from", "instance"), # noqa ("formatting", "third_formatting", "instance"), # noqa ("key", "instance", "instance"), # noqa ("formatting", "fourth_formatting", "traceback"), # noqa ("constant", ",", "traceback"), # noqa ("formatting", "fifth_formatting", "traceback"), # noqa ("key", "traceback", "traceback"), # noqa ], "assert": [ ("constant", "assert", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "second_formatting", "message"), # noqa ("constant", ",", "message"), # noqa ("formatting", "third_formatting", "message"), # noqa ("key", "message", "message"), # noqa ], "set_comprehension": [ ("formatting", "first_formatting", True), # noqa ("constant", "{", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "result", True), # noqa ("list", "generators", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "}", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "dict_comprehension": [ ("formatting", "first_formatting", True), # noqa ("constant", "{", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "result", True), # noqa ("list", "generators", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "}", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "argument_generator_comprehension": [ ("key", "result", True), # noqa ("list", "generators", True), # noqa ], "generator_comprehension": [ ("formatting", "first_formatting", True), # noqa ("constant", "(", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "result", True), # noqa ("list", "generators", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", ")", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "list_comprehension": [ ("formatting", "first_formatting", True), # noqa ("constant", "[", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "result", True), # noqa ("list", "generators", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "]", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "comprehension_loop": [ ("formatting", "first_formatting", True), # noqa ("constant", "for", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "iterator", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "in", True), # noqa ("formatting", "fourth_formatting", True), # noqa ("key", "target", True), # noqa ("list", "ifs", True), # noqa ], "comprehension_if": [ ("formatting", "first_formatting", True), # noqa ("constant", "if", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", True), # noqa ], "getitem": [ ("formatting", "first_formatting", True), # noqa ("constant", "[", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "]", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "slice": [ ("key", "lower", "lower"), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "upper", "upper"), # noqa ("formatting", "third_formatting", "has_two_colons"), # noqa ("constant", ":", "has_two_colons"), # noqa ("formatting", "fourth_formatting", "has_two_colons"), # noqa ("key", "step", ["has_two_colons", "step"]), # noqa ("bool", "has_two_colons", False), # noqa ], "assignment": [ ("key", "target", True), # noqa ("formatting", "annotation_first_formatting", "annotation"), # noqa ("constant", ":", "annotation"), # noqa ("formatting", "annotation_second_formatting", "annotation"), # noqa ("key", "annotation", "annotation"), # noqa ("formatting", "first_formatting", True), # noqa # FIXME should probably be a different node type # noqa ("string", "operator", "operator"), # noqa ("constant", "=", "target"), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", True), # noqa ], "standalone_annotation": [ ("key", "target", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "annotation", True), # noqa ], "unitary_operator": [ ("string", "value", True), # noqa ("formatting", "formatting", True), # noqa ("key", "target", True), # noqa ], "binary_operator": [ ("key", "first", True), # noqa ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "second", True), # noqa ], "boolean_operator": [ ("key", "first", True), # noqa ("formatting", "first_formatting", True), # noqa ("string", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "second", True), # noqa ], "comparison_operator": [ ("string", "first", True), # noqa ("formatting", "formatting", True), # noqa ("string", "second", "second"), # noqa ], "comparison": [ ("key", "first", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "second", True), # noqa ], "with": [ ("bool", "async", False), # noqa ("constant", "async", "async"), # noqa ("formatting", "async_formatting", "async"), # noqa ("constant", "with", True), # noqa ("formatting", "first_formatting", True), # noqa ("list", "contexts", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "third_formatting", True), # noqa ("list", "value", True), # noqa ], "with_context_item": [ ("key", "value", True), # noqa ("formatting", "first_formatting", "as"), # noqa ("constant", "as", "as"), # noqa ("formatting", "second_formatting", "as"), # noqa ("key", "as", "as"), # noqa ], "nonlocal": [ ("constant", "nonlocal", True), # noqa ("formatting", "formatting", True), # noqa ("list", "value", True), # noqa ], "del": [ ("constant", "del", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", True), # noqa ], "yield": [ ("constant", "yield", True), # noqa ("formatting", "formatting", True), # noqa ("key", "value", "value"), # noqa ], "yield_from": [ ("constant", "yield", True), # noqa ("formatting", "formatting", True), # noqa ("constant", "from", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "value", "value"), # noqa ], "yield_atom": [ ("constant", "(", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", "yield", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", "value"), # noqa ("formatting", "third_formatting", True), # noqa ("constant", ")", True), # noqa ], "exec": [ ("constant", "exec", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "value", True), # noqa ("formatting", "second_formatting", "globals"), # noqa ("constant", "in", "globals"), # noqa ("formatting", "third_formatting", "globals"), # noqa ("key", "globals", "globals"), # noqa ("formatting", "fourth_formatting", "locals"), # noqa ("constant", ",", "locals"), # noqa ("formatting", "fifth_formatting", "locals"), # noqa ("key", "locals", "locals"), # noqa ], "global": [ ("constant", "global", True), # noqa ("formatting", "formatting", True), # noqa ("list", "value", True), # noqa ], "while": [ ("constant", "while", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "test", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "third_formatting", True), # noqa ("list", "value", True), # noqa ("key", "else", "else"), # noqa ], "for": [ ("bool", "async", False), # noqa ("constant", "async", "async"), # noqa ("formatting", "async_formatting", "async"), # noqa ("constant", "for", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "iterator", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", "in", True), # noqa ("formatting", "third_formatting", True), # noqa ("key", "target", True), # noqa ("formatting", "fourth_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "fifth_formatting", True), # noqa ("list", "value", True), # noqa ("key", "else", "else"), # noqa ], "if": [ ("constant", "if", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "test", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "third_formatting", True), # noqa ("list", "value", True), # noqa ], "elif": [ ("constant", "elif", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "test", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "third_formatting", True), # noqa ("list", "value", True), # noqa ], "else": [ ("constant", "else", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ], "lambda": [ ("constant", "lambda", True), # noqa ("formatting", "first_formatting", True), # noqa ("list", "arguments", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "third_formatting", True), # noqa ("key", "value", True), # noqa ], "try": [ ("constant", "try", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ("list", "excepts", True), # noqa ("key", "else", "else"), # noqa ("key", "finally", "finally"), # noqa ], "except": [ ("constant", "except", True), # noqa ("formatting", "first_formatting", True), # noqa ("key", "exception", "exception"), # noqa ("formatting", "second_formatting", "delimiter"), # noqa ("string", "delimiter", "delimiter"), # noqa ("formatting", "third_formatting", "delimiter"), # noqa ("key", "target", "delimiter"), # noqa ("formatting", "fourth_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "fifth_formatting", True), # noqa ("list", "value", True), # noqa ], "finally": [ ("constant", "finally", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ], "dict": [ ("formatting", "first_formatting", True), # noqa ("constant", "{", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "}", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "set": [ ("formatting", "first_formatting", True), # noqa ("constant", "{", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ("formatting", "third_formatting", True), # noqa ("constant", "}", True), # noqa ("formatting", "fourth_formatting", True), # noqa ], "dictitem": [ ("key", "key", True), # noqa ("formatting", "first_formatting", True), # noqa ("constant", ":", True), # noqa ("formatting", "second_formatting", True), # noqa ("key", "value", True), # noqa ], "import": [ ("formatting", "first_formatting", True), # noqa ("constant", "import", True), # noqa ("formatting", "second_formatting", True), # noqa ("list", "value", True), # noqa ], "from_import": [ ("constant", "from", True), # noqa ("formatting", "first_formatting", True), # noqa ("list", "value", True), # noqa ("formatting", "second_formatting", True), # noqa ("constant", "import", True), # noqa ("formatting", "third_formatting", True), # noqa ("list", "targets", True), # noqa ], "dotted_as_name": [ ("list", "value", True), # noqa ("formatting", "first_formatting", "target"), # noqa ("constant", "as", "target"), # noqa ("formatting", "second_formatting", "target"), # noqa ("string", "target", "target"), # noqa ], "name_as_name": [ ("string", "value", True), # noqa ("formatting", "first_formatting", "target"), # noqa ("constant", "as", "target"), # noqa ("formatting", "second_formatting", "target"), # noqa ("string", "target", "target"), # noqa ], "print": [ ("constant", "print", True), # noqa ("formatting", "formatting", True), # noqa ("constant", ">>", "destination"), # noqa ("formatting", "destination_formatting", "destination"), # noqa ("key", "destination", "destination"), # noqa ("list", "value", "value"), # noqa ], } class RenderWalker(object): """Inherit me and overload the methods you want. When calling walk() on a FST node, this class will traverse all the node's subtree by following the recipe given by the `render` function for the node and recursively for all its childs. At each recipe step, it will call methods that you can override to make a specific process. For every "node", "key", "list", "formatting" and "constant" childs, it will call the `before` method when going down the tree and the `after` method when going up. There are also specific `before_[node,key,list,formatting,constant]` and `after_[node,key,list,formatting,constant]` methods provided for convenience. The latter are called on specific steps: * before_list: called before encountering a list of nodes * after_list: called after encountering a list of nodes * before_formatting: called before encountering a formatting list * after_formatting: called after encountering a formatting list * before_node: called before encountering a node * after_node: called after encountering a node * before_key: called before encountering a key type entry * after_key: called after encountering a key type entry * before_leaf: called before encountering a leaf of the FST (can be a constant (like "def" in a function definition) or an actual value like the value a name node) * after_leaf: called after encountering a leaf of the FST (can be a constant (like "def" in a function definition) or an actual value like the value a name node) Every method has the same signature: (self, node, render_pos, render_key). """ STOP = True def __init__(self, strict=False): self.strict = strict def before_list(self, node, render_key): pass def after_list(self, node, render_key): pass def before_formatting(self, node, render_key): pass def after_formatting(self, node, render_key): pass def before_node(self, node, render_key): pass def after_node(self, node, render_key): pass def before_key(self, node, render_key): pass def after_key(self, node, render_key): pass def before_constant(self, node, render_key): pass def after_constant(self, node, render_key): pass def before_string(self, node, render_key): pass def after_string(self, node, render_key): pass def before(self, key_type, item, render_key): if key_type not in node_types: raise NotImplementedError("Unknown key type: %s" % key_type) to_call = getattr(self, 'before_' + key_type) return to_call(item, render_key) def after(self, key_type, item, render_key): if key_type not in node_types: raise NotImplementedError("Unknown key type: %s" % key_type) to_call = getattr(self, 'after_' + key_type) return to_call(item, render_key) def walk(self, node): return self._walk(node) def _walk(self, node): for key_type, item, render_key in render(node, strict=getattr(self, "strict", False)): stop = self._walk_on_item(key_type, item, render_key) if stop == self.STOP: return self.STOP def _walk_on_item(self, key_type, item, render_key): stop_before = self.before(key_type, item, render_key) if stop_before: return self.STOP stop = self._walk(item) if key_type not in ['constant', 'string'] else False stop_after = self.after(key_type, item, render_key) if stop or stop_after: return self.STOP baron-0.10.1/baron/setup.cfg000066400000000000000000000000261415427440200156150ustar00rootroot00000000000000[wheel] universal = 1 baron-0.10.1/baron/spliter.py000066400000000000000000000056731415427440200160450ustar00rootroot00000000000000import string from .utils import FlexibleIterator, BaronError def split(sequence): return list(split_generator(sequence)) class UntreatedError(BaronError): pass def split_generator(sequence): iterator = FlexibleIterator(sequence) # Pay attention that if a next() call fails, a StopIteration error # is raised. This coincidently is the same error used by python to # understand that a function using yield has finished processing. # It's not a bad thing, but it must be kept in mind. while not iterator.end(): not_found = True if iterator.next_in("#"): not_found = False result = iterator.grab(lambda iterator: (iterator.show_next() not in "\r\n")) yield result for section in ("'", '"'): if iterator.next_starts_with(section * 3): not_found = False result = next(iterator) result += next(iterator) result += next(iterator) result += iterator.grab_string(lambda iterator: not iterator.next_starts_with(section * 3)) # This next() call can fail if no closing quote exists. We # still want to yield so we catch it. try: result += next(iterator) result += next(iterator) result += next(iterator) except StopIteration: pass yield result elif iterator.next_in(section): not_found = False result = next(iterator) result += iterator.grab_string(lambda iterator: iterator.show_next() not in section) # This next() call can fail if no closing quote exists. We # still want to yield so we catch it. try: result += next(iterator) except StopIteration: pass yield result for section in (string.ascii_letters + "_" + "1234567890", " \t"): if iterator.next_in(section): not_found = False yield iterator.grab(lambda iterator: iterator.show_next() in section) for one in "@,.;()=*:+-/^%&<>|\r\n~[]{}!``\\": if iterator.next_in(one): not_found = False yield next(iterator) if iterator.show_next().__repr__().startswith("'\\x"): # guys, seriously, how do you manage to put this shit in your code? # I mean, I don't even know how this is possible! # example of guilty file: ve/lib/python2.7/site-packages/tests/test_oauth.py # example of crapy unicode stuff found in some source files: \x0c\xef\xbb\xbf not_found = False # let's drop that crap next(iterator) if not_found: raise UntreatedError("Untreated elements: %s" % iterator.rest_of_the_sequence().__repr__()[:50]) baron-0.10.1/baron/token.py000066400000000000000000000052651415427440200155000ustar00rootroot00000000000000from rply.token import BaseBox class BaronToken(BaseBox): """ Represents a syntactically relevant piece of text. :param name: A string describing the kind of text represented. :param value: The actual text represented. :param source_pos: A :class:`SourcePosition` object representing the position of the first character in the source from which this token was generated. """ def __init__(self, name, value, hidden_tokens_before=None, hidden_tokens_after=None): self.name = name self.value = value self.hidden_tokens_before = list(map(self._translate_tokens_to_ast_node, hidden_tokens_before if hidden_tokens_before else [])) self.hidden_tokens_after = list(map(self._translate_tokens_to_ast_node, hidden_tokens_after if hidden_tokens_after else [])) def _translate_tokens_to_ast_node(self, token): if token[0] == "ENDL": return { "type": token[0].lower(), "value": token[1], "indent": token[3][0][1] if len(token) == 4 and token[3] else "", "formatting": list(map(self._translate_tokens_to_ast_node, token[2]) if len(token) >= 3 else []), } if len(token) >= 3: return { "type": token[0].lower(), "value": token[1], "formatting": list(map(self._translate_tokens_to_ast_node, token[2]) if len(token) >= 3 else []), } if token[0] == "COMMENT": return { "type": token[0].lower(), "value": token[1], "formatting": [], } return { "type": token[0].lower(), "value": token[1], } def __repr__(self): return "Token(%r, %r, %s, %s)" % (self.name, self.value, self.hidden_tokens_before, self.hidden_tokens_after) def __eq__(self, other): if not isinstance(other, BaronToken): return NotImplemented return self.name == other.name and self.value == other.value def render(self): before = "".join([(x["indent"] if x["type"] == "endl" else "") + x["value"] for x in self.hidden_tokens_before]) after = "".join([(x["indent"] if x["type"] == "endl" else "") + x["value"] for x in self.hidden_tokens_after]) # print self.hidden_tokens_before, self.value, self.hidden_tokens_after return before + self.value + after def gettokentype(self): """ Returns the type or name of the token. """ return self.name def getstr(self): """ Returns the string represented by this token. """ return self.value baron-0.10.1/baron/tokenizer.py000066400000000000000000000076511415427440200163730ustar00rootroot00000000000000import re from .utils import BaronError class UnknowItem(BaronError): pass KEYWORDS = ("and", "as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from", "global", "nonlocal", "if", "import", "in", "is", "lambda", "not", "or", "pass", "print", "raise", "return", "try", "while", "with", "yield") TOKENS = ( (r'[a-zA-Z_]\w*', 'NAME'), (r'0', 'INT'), (r'[-+]?\d+[eE][-+]?\d+[jJ]', 'FLOAT_EXPONANT_COMPLEX'), (r'[-+]?\d+.\d?[eE][-+]?\d+[jJ]', 'FLOAT_EXPONANT_COMPLEX'), (r'[-+]?\d?.\d+[eE][-+]?\d+[jJ]', 'FLOAT_EXPONANT_COMPLEX'), (r'\d+[eE][-+]?\d*', 'FLOAT_EXPONANT'), (r'\d+\.\d*[eE][-+]?\d*', 'FLOAT_EXPONANT'), (r'\.\d+[eE][-+]?\d*', 'FLOAT_EXPONANT'), (r'\d*\.\d+[jJ]', 'COMPLEX'), (r'\d+\.[jJ]', 'COMPLEX'), (r'\d+[jJ]', 'COMPLEX'), (r'\d+\.', 'FLOAT'), (r'\d*[_\d]*\.[_\d]+[lL]?', 'FLOAT'), (r'\d+[_\d]+\.[_\d]*[lL]?', 'FLOAT'), (r'\.', 'DOT'), (r'[1-9]+[_\d]*[lL]', 'LONG'), (r'[1-9]+[_\d]*', 'INT'), (r'0[xX][\d_a-fA-F]+[lL]?', 'HEXA'), (r'(0[oO][0-7]+)|(0[0-7_]*)[lL]?', 'OCTA'), (r'0[bB][01_]+[lL]?', 'BINARY'), (r'\(', 'LEFT_PARENTHESIS'), (r'\)', 'RIGHT_PARENTHESIS'), (r':', 'COLON'), (r',', 'COMMA'), (r';', 'SEMICOLON'), (r'@', 'AT'), (r'\+', 'PLUS'), (r'-', 'MINUS'), (r'\*', 'STAR'), (r'/', 'SLASH'), (r'\|', 'VBAR'), (r'&', 'AMPER'), (r'@', 'AT'), (r'<', 'LESS'), (r'>', 'GREATER'), (r'=', 'EQUAL'), (r'%', 'PERCENT'), (r'\[', 'LEFT_SQUARE_BRACKET'), (r'\]', 'RIGHT_SQUARE_BRACKET'), (r'\{', 'LEFT_BRACKET'), (r'\}', 'RIGHT_BRACKET'), (r'`', 'BACKQUOTE'), (r'==', 'EQUAL_EQUAL'), (r'<>', 'NOT_EQUAL'), (r'!=', 'NOT_EQUAL'), (r'<=', 'LESS_EQUAL'), (r'>=', 'GREATER_EQUAL'), (r'~', 'TILDE'), (r'\^', 'CIRCUMFLEX'), (r'<<', 'LEFT_SHIFT'), (r'>>', 'RIGHT_SHIFT'), (r'\*\*', 'DOUBLE_STAR'), (r'\+=', 'PLUS_EQUAL'), (r'-=', 'MINUS_EQUAL'), (r'@=', 'AT_EQUAL'), (r'\*=', 'STAR_EQUAL'), (r'/=', 'SLASH_EQUAL'), (r'%=', 'PERCENT_EQUAL'), (r'&=', 'AMPER_EQUAL'), (r'\|=', 'VBAR_EQUAL'), (r'\^=', 'CIRCUMFLEX_EQUAL'), (r'<<=', 'LEFT_SHIFT_EQUAL'), (r'>>=', 'RIGHT_SHIFT_EQUAL'), (r'\.\.\.', 'ELLIPSIS'), (r'->', 'RIGHT_ARROW'), (r'\*\*=', 'DOUBLE_STAR_EQUAL'), (r'//', 'DOUBLE_SLASH'), (r'//=', 'DOUBLE_SLASH_EQUAL'), (r'\n', 'ENDL'), (r'\r\n', 'ENDL'), (r'#.*', 'COMMENT'), (r'(\s|\\\n|\\\r\n)+', 'SPACE'), (r'["\'](.|\n|\r)*["\']', 'STRING'), (r'[uU]["\'](.|\n|\r)*["\']', 'UNICODE_STRING'), (r'[fF]["\'](.|\n|\r)*["\']', 'INTERPOLATED_STRING'), (r'[rR]["\'](.|\n|\r)*["\']', 'RAW_STRING'), (r'[bB]["\'](.|\n|\r)*["\']', 'BINARY_STRING'), (r'[uU][rR]["\'](.|\n|\r)*["\']', 'UNICODE_RAW_STRING'), (r'[bB][rR]["\'](.|\n|\r)*["\']', 'BINARY_RAW_STRING'), (r'[fF][rR]["\'](.|\n|\r)*["\']', 'INTERPOLATED_RAW_STRING'), (r'[rR][fF]["\'](.|\n|\r)*["\']', 'INTERPOLATED_RAW_STRING'), ) TOKENS = [(re.compile('^' + x[0] + '$'), x[1]) for x in TOKENS] def tokenize(sequence, print_function=False): return list(tokenize_generator(sequence, print_function)) def tokenize_current_keywords(print_function=False): if print_function is True: return [x for x in KEYWORDS if x not in ("print", "exec")] else: return KEYWORDS def tokenize_generator(sequence, print_function=False): current_keywords = tokenize_current_keywords() for item in sequence: if item in current_keywords: yield (item.upper(), item) continue for candidate, token_name in TOKENS: if candidate.match(item): yield (token_name, item) break else: raise UnknowItem("Can't find a matching token for this item: '%s'" % item) yield ('ENDMARKER', '') yield baron-0.10.1/baron/utils.py000066400000000000000000000104121415427440200155060ustar00rootroot00000000000000import sys import re python_version = sys.version_info[0] python_subversion = sys.version_info[1] string_instance = str if python_version == 3 else basestring class BaronError(Exception): pass class FlexibleIterator(): def __init__(self, sequence): self.sequence = sequence self.position = -1 def __iter__(self): return self def next(self): return self.__next__() def __next__(self): self.position += 1 if self.position == len(self.sequence): raise StopIteration return self.sequence[self.position] def next_starts_with(self, sentence): size_of_choice = len(sentence) return self.sequence[self.position + 1: self.position + 1 + size_of_choice] == sentence def next_in(self, choice): if self.position + 1 >= len(self.sequence): return False return self.sequence[self.position + 1] in choice def show_next(self, at=1): if self.position + at >= len(self.sequence): return None return self.sequence[self.position + at] def rest_of_the_sequence(self): return self.sequence[self.position + 1:] def end(self): return self.position == (len(self.sequence) - 1) def grab(self, test): to_return = "" current = None while self.show_next() is not None and test(self): current = next(self) to_return += current return to_return def grab_string(self, test): to_return = "" current = None escaped = False while self.show_next() is not None and (escaped or test(self)): current = next(self) to_return += current if escaped: escaped = False elif current == "\\": escaped = True return to_return def create_node_from_token(token, **kwargs): result = {"type": token.name.lower(), "value": token.value} if kwargs: result.update(kwargs) return result def create_node(name, value, **kwargs): result = {"type": name, "value": value} if kwargs: result.update(kwargs) return result newline_regex = re.compile("(\r\n|\n|\r)") def is_newline(text): return newline_regex.match(text) def split_on_newlines(text): newlines = newline_regex.finditer(text) if not newlines: yield text else: current_position = 0 for newline in newlines: yield text[current_position:newline.start(1)] yield text[newline.start(1):newline.end(1)] current_position = newline.end(1) yield text[current_position:] # Thanks to # https://github.com/nvie/rq/commit/282f4be9316d608ebbacd6114aab1203591e8f95 if python_version >= 3 or python_subversion >= 7: from functools import total_ordering else: def total_ordering(cls): """Class decorator that fills in missing ordering methods""" convert = { '__lt__': [('__gt__', lambda self, other: other < self), ('__le__', lambda self, other: not other < self), ('__ge__', lambda self, other: not self < other)], '__le__': [('__ge__', lambda self, other: other <= self), ('__lt__', lambda self, other: not other <= self), ('__gt__', lambda self, other: not self <= other)], '__gt__': [('__lt__', lambda self, other: other > self), ('__ge__', lambda self, other: not other > self), ('__le__', lambda self, other: not self > other)], '__ge__': [('__le__', lambda self, other: other >= self), ('__gt__', lambda self, other: not other >= self), ('__lt__', lambda self, other: not self >= other)] } roots = set(dir(cls)) & set(convert) if not roots: raise ValueError('must define at least one ordering operation: < > <= >=') # noqa root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__ for opname, opfunc in convert[root]: if opname not in roots: opfunc.__name__ = opname opfunc.__doc__ = getattr(int, opname).__doc__ setattr(cls, opname, opfunc) return cls baron-0.10.1/docs/000077500000000000000000000000001415427440200136255ustar00rootroot00000000000000baron-0.10.1/docs/Makefile000066400000000000000000000126701415427440200152730ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Baron.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Baron.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Baron" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Baron" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." baron-0.10.1/docs/advanced.rst000066400000000000000000000104631415427440200161300ustar00rootroot00000000000000Advanced Usage ============== The topics presented here are less often needed but are still very useful. Locate a Node ------------- Since Baron produces a tree, a path is sufficient to locate univocally a node in the tree. A common task where a path is involved is when translating a position in a file (a line and a column) into a node of the FST. Baron provides 2 helper functions for that: * :file:`position_to_node(fst, line, column)` * :file:`position_to_path(fst, line, column)` Both take a FST tree as first argument, then the line number and the column number. Line and column numbers **start at 1**, like in a text editor. :file:`position_to_node` returns an FST node. This is okay if you only want to know which node it is but not enough to locate the node in the tree. Indeed, there can be mutiple identical nodes within the tree. That's where :file:`position_to_path` is useful. It returns a list of int and strings which represent either the key to take in a Node or the index in a ListNode. For example: :file:`["target", "value", 0]`) Let's first see the difference between the two functions: .. ipython:: python from baron import parse from baron.path import position_to_node, position_to_path from baron.helpers import show_node some_code = """from baron import parse\nfrom baron.helpers import show_node\nfst = parse("a = 1")\nshow_node(fst)""" print some_code tree = parse(some_code) node = position_to_node(tree, (3, 8)) show_node(node) path = position_to_path(tree, (3, 8)) path The first one gives the node and the second one the node's path in the tree. The latter tells you that to get to the node, you must take the 4th index of the root ListNode, followed twice by the "value" key of first the "assignment" Node and next the "atomtrailers" Node. Finally, take the 0th index in the resulting ListNode: .. ipython:: python show_node(tree[4]["value"]["value"][0]) Neat. This is so common that there is a function to do that: .. ipython:: python from baron.path import path_to_node show_node(path_to_node(tree, path)) With the two above, that's a total of three functions to locate a node. You can also locate easily a "constant" node like a left parenthesis in a :file:`funcdef` node: .. ipython:: python from baron.path import position_to_path fst = parse("a(1)") position_to_path(fst, (1, 1)) position_to_path(fst, (1, 2)) position_to_path(fst, (1, 3)) position_to_path(fst, (1, 4)) By the way, out of bound positions are handled gracefully: .. ipython:: python print(position_to_node(fst, (-1, 1))) print(position_to_node(fst, (1, 0))) print(position_to_node(fst, (1, 5))) print(position_to_node(fst, (2, 4))) Bounding Box ------------ Sometimes you want to know what are the left most and right most position of a rendered node or part of it. It is not a trivial task since you do not know easily each rendered line's length. That's why baron provides two helpers: * :file:`node_to_bounding_box(fst)` * :file:`path_to_bounding_box(fst, path)` Examples are worth a thousand words so: .. ipython:: python from baron.path import node_to_bounding_box, path_to_bounding_box from baron import dumps fst = parse("a(1)\nb(2)") fst print dumps(fst) node_to_bounding_box(fst) path_to_bounding_box(fst, []) fst[0] print dumps(fst[0]) node_to_bounding_box(fst[0]) path_to_bounding_box(fst, [0]) fst[0]["value"] print dumps(fst[0]["value"]) node_to_bounding_box(fst[1]) path_to_bounding_box(fst, [1]) fst[0]["value"][1] print dumps(fst[0]["value"][1]) node_to_bounding_box(fst[0]["value"][1]) path_to_bounding_box(fst, [0, "value", 1]) fst[0]["value"][1]["value"] print dumps(fst[0]["value"][1]["value"]) node_to_bounding_box(fst[0]["value"][1]["value"]) path_to_bounding_box(fst, [0, "value", 1, "value"]) The bounding box's `top_left` and `bottom_right` positions follow the same convention as for when locating a node: the line and column start at 1. As you can see, the major difference between the two functions is that :file:`node_to_bounding_box` will always give a left position of :file:`(1, 1)` since it considers you want the bounding box of the whole node while :file:`path_to_bounding_box` takes the location of the node in the fst into account. baron-0.10.1/docs/basics.rst000066400000000000000000000032641415427440200156300ustar00rootroot00000000000000Basic Usage =========== Baron provides two main functions: * :file:`parse` to transform a string into Baron's FST; * :file:`dumps` to transform the FST back into a string. .. ipython:: python :suppress: import sys sys.path.append("..") .. ipython:: python from baron import parse, dumps source_code = "def f(x = 1):\n return x\n" fst = parse(source_code) generated_source_code = dumps(fst) generated_source_code source_code == generated_source_code Like said in the introduction, the FST keeps the formatting unlike ASTs. Here the following 3 codes are equivalent but their formatting is different. Baron keeps the difference so when dumping back the FST, all the formatting is respected: .. ipython:: python dumps(parse("a = 1")) dumps(parse("a=1")) dumps(parse("a = 1")) Helpers ------- Baron also provides 3 helper functions `show`, `show_file` and `show_node` to explore the FST (in iPython for example). Those functions will print a formatted version of the FST so you can play with it to explore the FST and have an idea of what you are playing with. Show ~~~~ :file:`show` is used directly on a string: .. ipython:: python from baron.helpers import show show("a = 1") show("a += b") Show_file ~~~~~~~~~ :file:`show_file` is used on a file path: :: from baron.helpers import show_file show_file("/path/to/a/file") Show_node ~~~~~~~~~ :file:`show_node` is used on an already parsed string: .. ipython:: python from baron.helpers import show_node fst = parse("a = 1") show_node(fst) Under the hood, the FST is serialized into JSON so the helpers are simply encapsulating JSON pretty printers. baron-0.10.1/docs/conf.py000066400000000000000000000216411415427440200151300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Baron documentation build configuration file, created by # sphinx-quickstart on Sat May 10 02:16:20 2014. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'IPython.sphinxext.ipython_directive', 'IPython.sphinxext.ipython_console_highlighting', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Baron' copyright = u'2014, Laurent Peuch' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '0.6' # The full version, including alpha/beta/rc tags. release = '0.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Barondoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Baron.tex', u'Baron Documentation', u'Laurent Peuch', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'baron', u'Baron Documentation', [u'Laurent Peuch'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Baron', u'Baron Documentation', u'Laurent Peuch', 'Baron', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. epub_title = u'Baron' epub_author = u'Laurent Peuch' epub_publisher = u'Laurent Peuch' epub_copyright = u'2014, Laurent Peuch' # The language of the text. It defaults to the language option # or en if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. #epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. #epub_identifier = '' # A unique identification for the text. #epub_uid = '' # A tuple containing the cover image and cover page html template filenames. #epub_cover = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] # A list of files that should not be packed into the epub file. #epub_exclude_files = [] # The depth of the table of contents in toc.ncx. #epub_tocdepth = 3 # Allow duplicate toc entries. #epub_tocdup = True baron-0.10.1/docs/grammar-python-2.7-3.6-diff-1.png000066400000000000000000006726721415427440200212000ustar00rootroot00000000000000PNG  IHDR{MsBITO IDATx^|TR{(APD |hP,C@Z@E@ $@萐޶Mmِ¹`w3޳gժ!8@ @ qu:ŮjD@ … ^9qDrɑr @<womq˰#WQ( @ @G@#n汙cdp@Gvٻ&7#q 'PuNsک_|~@ ʛ{8g@T%U'Vzl@ @ /.ؘOی,2bll='P??N]9ET,~m Ӈtccx{EQ_lw*׿e>pYa;|pw)lb<יKc޶p`-ڮ^y:*BS~x@=*o?{8'+O@tXI{j[v%/^^?٪yW cS]jwvQ[_ m߬i&o8nH5okꩈܺЬP6|}w,.- @ "Pe ǜv@&FWܷZv"ؔj=5sڹ?Ok;ݞZ|FʽsA{aHDe^1.&Y^u"GHȺy%C~gdrM;Vgrs|x._8Vq sRy̬M -UcP @<|U̹?5h 7Si]NLC`椻^z BG~w=G*E-K"J[3I۟`*! #2YmBNbU[C_BfMOR fMxp)ь).*(q y.tq;'ퟋC,Wӿ;a7NUQ>T؈5fQ!)"`k8itN 'PE 1'0c(D eD)>V]C")UP5V9fً/W(5L:}?P]SC>A8xGjB3Y/DȠg->;s{oR8MYbB_>yOeXi?=gğ#w: 4xC!X8 @@7$6B@< *y#|Hx(]ɑUv)?w;bj4A0h/ewsSQ7}>ϵғHL;ٷ5RLPhw5QqAl@ϼo7iT t՘cxcNY+-tpW]PUHH12,26@<sG3 @e#M oU9~{ώKe_m _|BԺamS>s^zn=})¾#8! ?y39cY'{>Yr{wo˗'Θ3ǭ[o{<g;tr?66-H#jaCԮwN|w^dzm+g@ P TY1gp= Xtr@ 0",,LV @@`…VKn[ UĘ8qG. @HMNr8r^\G@ @  ovN*@ (/*(.Sy @7A_  RZ?V xp)FVP 7h V 3u" f:@ @ Jqc} J_ɩ XR>69ntG]j0|OgַWz~!-E[Ιߵ^f?$޵x*;Ki6ʔaq?\9ٻ&iSw2+}% L|h"sRc cVY=5YRҜ^pOc}. }"UZ1*Zkqn+IrjاӴV_ͣjve+Yү͘ߗMߔȕEe-SC+(c?XY}9OI@} !rC|hEE#ǜuce{S"daӢ?XZX]q@Mu&ۢMx6x( ܟ)$܆U*kZ-jx* N1] 8 V4}TI4%^b^Ѳȗq{+rpw xF07t32GhúdZZڜtu\aU,U &/%=iמizպfa9QדzZ;/.~g==gzj/lk98;sFma,9`fPJĭJdD3ٓN -8{a݈ <1l~XK^okMaڿj_7W0w I/ Uƽ[ow$lގ7p)#Xv}3ds_~md?ܱ UW;Dž z#9$'DKW-~ {e԰۟t}p؃eK0AH:q36lp7e#&ZـaóCLtjᩈ2.#/G~O$:pk՗}ꌯ%w̺~\ 45 k{͉]Nɐ*8O/ ls9W49+݄l:/?|cj5nJW|:oY)'#:J>M?m,`;*Pn\5T|1USYSir7کPYSb@sik֛LWMJh\~N̾"*u>vCWJQܯľoHt*W:V5k^N<pV* nںfʑqVp=C6pCi`J:Uj,@Yo`k݇͢g޻pQ hu;45x&$W": f 4E ) 8f;4#خJ5 rĻ>r6le̩w.UIN\sHEJX#Tˈ洸kw2]/ )K 7^+_9}{/sp'q][h1O+Z( !h>@# k#+1?zx鏕J1n)L~^fI@nGT@P`+̳31Hm%e9jE D 78%~L_Ik2[}BMc^5,8~LS?Y,ZnYK-L͙q΄?]v`$kve<1=\pi@orHNfپDk^R*GؿHZ%S2"~dbs԰52A9%W) ;YE/=mX VW!dNɑk8xzgúmԓ=OYO<~0v԰CepJwL~A0gZj HжP>`yV$s̰s gǤlw8sóyj0ydA6˲g/?ˌˌC(i$,$Z> v jυv&}˦K.9SHI`'Fiݼ!x[ ,p]"K$_ERQ#Dh{-ۧdId bR nvT@9o"nBN ժ(?KV3S MHR(sF Ө.1ˈTtAZxTZ,jg}QIf9rҤ6H>ڱI<[Y8x[*f9GWLHsG }&ff qId1v5bN^'NRđ$DR,>=}pJ^@$cG@09=dx^EQNw˞ N6Vo<,a|*?V: "P.m|vMŢٌ]$/:oFS(?ivk}ءUJ%riLK]jR"I?(Y+Ppq+,| $~y y1)Y(E7t-7(ZKykSX @*.WC < lڥkrcyC"JUnR ]>޿_x(Ѣ{(׉Y7O*ڼ6DIP { }ƒUJA*%iHW#:V80kj ((GNZ,>lv/'G)ggumF}Jw@?e#=,1S#'G"cf!|2Ywp򀐉lRER ùBqiE&nV7ItѲ+šYQ}ر6 %c͋"C&;N `20føͿhDn-38CqxvDi:Im.j a@xI S ?5P"@Ztk^[UAҚ {5GQT n*/կ%ʊu^ qguiPhU̹PR73Vw< @ W9nvC1~[ߐ.bެ3@)XmFH /KI[W(rPERա횷R%x@V[@Gq$$~mn>6!TvtzDmǧ̊LCj&bA!VxƼbE03"'`^fr=?Y,4mcăqݵl>ٟ݆@^@YӜx'1祾;zVJe&JM\M p6h6]dw;e۲NGj?I=modJ:_2ܜڸӃR'P,~績>$zfkM~W6+\h5%,T3d&(7ўEQ3y8@ @2"U?ӹFUw6H9SΗ6c[P)tWMfyOQhCg-OߟCWJQܯľo.c}p?- |g,|f[5*8k{+X%"?1ͿW }d{j%_e77?Bp߬{_0!ݳzGo*-)ߩR|NbKF O%5<kJtYRo)LLF l9nx{NE(7u3Uz*O➙˙Tfөx1iTqCV5xijT ץ!TꯖU#/[C_P4^nqƭ6O"?5B1!rC~0>L}ŧS:rz2t#Z&_b^Ss) /e;>f~džc̻jD8@ @*Ƨln5Pۃݚ=2 IDATU3}ΪcZP3˾ۦ1bmA BrtB' !Dą/7!j%OzѾ&XgQK>OhVu2)a9*-._N+ͱ(_ncj+U6%Yt3d#,2m8qXr|UQ4Dd*2M[ꚵӸ`5g܅zTA\lL3b*9nGRY(▰:g"ޔ98ZlnXo~i؁:{ܲ,q;Ӳ=ހ|X1}X xfyZ1q|Kܯ?Ëgv[.!FAX] @ n*"͙RH)YwB$ń2=k&+~UZmI:lWBw{:e3RZ Þ'r9{~WvBiI-5)GҌN$L%/v+ں7PE$" n ("ȣu~(yr̸8Ҏ&L2-@^!$M_缎>էD[|Kԅ @ @|q',*4XT-5.?MS &IBm+P5ӵh/T9nGYjJkn4"9RJH@dK};WG#9 {Nؿ:cS^L=έ0|Qö1~lzg$U4NS5%/Rxdy#P+%2.gT,* \-_yj.r~(7Dp# } 9 kh(dwnIϑ]{HZ8@ @2$ӈ5I1=?>YYS6m2Ow$1#loHph;m<;3S_"WWu6O(P/_hMj6D(%eAa8gJ|?U,fSa]ibΆ#)qby_/W|6qo!XnMv$LTqsTq>r#u}oBQq [c7q>R @ @w|2ǚE0L"vPoWA7lvjTvldxCixWì+>6ΣAhiّBiRDR>&iz0'ܠ~baN#8ϘH -;uˆ OB"]L7ЀL0luܐ5m[-E Ѧ":4߰3ՐڽㅓLDڷ0ul(zVw兿StzI [K\whU~x;p!8g7G xX&ZWiy v^~f=>Ձ@ @9DXXZ;*L y]| G./Wm}Md#h5 8`SOtꦾuP}ń'z=@ |K`UԷLnGUoui@ @ @Ҫ @  :K 1@ D*D7T,%e5VT lK#@ >zzld14_@U @E#@"@GYz@ @ #Q 8Mƴ/J1X^RV2F#.hoͮ^͆blRPjLܒV7 k 9ۃ>jVY( 87;S ⑯ O|L'gF2=h!ϣE9_@ ~Jz{t4oavZF6Xx@*$ڍQG/oX31'5O=R%5ErP$[k\@5qy,kf]QݢI.NEw$ ^27 < Us:;+Sҷ-&Y;LϲqJcӛ5$^VL/B<)ߕדy Iגr˯l1huN,'}GkE U ʩlS+9 53)/i+Q^1ΚWpQH qLp2EmJ. h2@{^E1_WHvTFm*7}6xVi&WqoUKvJ{12mYK#[ؤ_i2AS&~&ݖtoƯOJ@%ChF?{eB5!TvtzD"/bf1B.GOQ<]2e# 'bS174I11R;lxmJE|ЎYn(oZPfu@ {;|niU&,Ÿb#U{_n\+MUQEңv[m'K5(۩m}Cr.#7zoJ>a$~z.K;{_mcăq՞Fs ôƙƸ#R_L+ynGѣIaBI/}2 sԸdYn]; @<kvS.DcߌPR[MmbjHJ ^fQ6.K8 EG Ѻ%h񂢱S E'5bӨXw(lVf6EIMB䧆3 8L>L}ŧSif,4"׬[#Rwj }" h ^GDnjqq}wZœ[9+" 1s]kGhKG;m6g^B599@E$jZEw-@g='""؎ |*/!mAb\}wWMfoS,0L"kl_#MFKϝƙ3 s: nRtnT#%9hԗG~]]Ddgc43 o8A|L=Jhx3ȝB geNܱUŻw:+b/ʋ>P@ *g 9.ԣU:b3d 4W]u;ʕ| s&- 86xò~#Hᄞ&ڍbo#"-68msܲ,^8Ӳ=Ů|eϊR D#g޾֙ㄌΞS)jqDXJd9_B<ݱ7B "=_~G`ZӲk~ =ɋgv[.!FMfSNS€oYZPlACs@ |FGv]fo_3KM!Ci%~5C1W*N1U.~d]v6yk( 9%ʧln5PNJ<8jٺ[tg w%h՞9޶{^{8@|]?ˮT~)?5F&}`:% iZ$p.fs3ʗ-BkJ-9" @)"nwEJ$ВZ )j2S CI0x2ρHPޡ+HD$Ž(i8b|d6QUbXg/?ˌˌC(i¤\ 7Uf iK0bm"SB4.4؞iWoב@ ]$~qX@Ղp%:=ByYQWrJJv@ |C{n5@C@%֟0s t߲RAǜ)9\Q#H)ǍF dsx'6w4vTv)p鞤ד9j ez2+~S϶$vEH_Ҋyeۆܪ+L$ik]uR|+D|:` dp/"ٹVp @&P[PSRMB q>C˸p]Sh6SlG/4I_ &%1jkh/a"]Ļ/*~ϋ~">zZF~ҡE%TRq䝻 B1OU_/ǶqcԠ~L@g5"~)R_D=Ѱ&AĊ:s OQ4x-gqp"]N,P"0X @i8y=7EZkFvtRnmCZ4҄tjץj)q9nD|g>x/Qmq*a/4oE97=-wf!tn竈 ?ЏRGqd85-KCװ!)SaLǹ( WYg,Wt+5sW*BT-릻2!()Ax記=2* ZJqS>^КԒmPJ4w˂lFJz?U,V=v}ZKl1-}٘Ș_>isx1{q EzeKjr͠n> H5ւa5o֨x/Y7'C/e9,弨: w ȗ$~3aEhrxZn"TRFȺ:.(3};44n Gc"&TG(RgG; x(N,;ؗ*~{BVUߑ[N9 ܬI3S!C\'˵.H ox vׯ#I_ønLhBL}%g|NXtauq÷x@ ,fR UY`(30;Ђ` C%7xiVif=|OjaDuIro@%~oP b`V-A:?Ds(#˛eB9@ *!G[U# JNe%7@}?&wADՅhլ}i^l&$ue .\NU_?g3$jt^p})FvMGn*['\׋u i~`~Z@ wN8~ڴ9eWxCȄioZ]>ID&wwUeLX^]gU*C!juڼsT|j@@ ⑯ OdLǼ8B5IcwH%꼦Ξt M'IHp޿3Z/L*KdEr]_qiu˴ߓ%=_/ue-`pj(+fs7Îz5;A{hkDq_֖גBXW*QtNu@MpKn =fPaJü5Eᵕ.eA x x/3RMQ$`cjF%F<lZtpDY>+x!@#@#4[bDn{`\H&UbEIqfT{ᖙ|hAC; L@"Ǎ ^[J 2e#Qo~m~BE3+<u÷2+2a=9Xk&yNHef̈L8D}*(ztPێ2!wBgdw_jz[ gMsffl(UfY'-tvQV`GodJ:( IDAT%kmG=2|)3{tjKp9SP*x/W#<⿳핿|J ʅQ%4k@|N _ᙿOB+Ş9Ebɏ)[dAt6 f=S ջ8|`VsG$hp><Ѩ/XSϒh<{ĭ4lT TF [;n/gRz?;WK-(CёAQ-/(/7\ko$@^S٨ X+T]'ܕdI9ꗊ{O̝(&q4PŒI?g6M2Tm­Jq{pԲuwYY; Vs]GOutӏgjδCb$qG(&="b.ꎃ+1N{jΞS"2 UWNBݗn(^_=v]d7WPfgE#|Pգ[dZ NTs eV~98 x 8L_8ŘTɺm)+_Aa]$".| Q#-yҋvwO3Gĥ'P4YMF^ͺ{?蔰m Egz6L8@|]#~]x8|,e9h( wl7mbcqb}oy7,7ROHݏ4o NiY*Ʊ?,_?/Sge4;y~wxe+'~a"q?ZO==o%Nb-PæeIY/-a d~gy 5'<@T(^E܄4.4؞iWoב@ ]񒻠cޛAϸDJ1<_"1V̋HH`?ǧ˳rwN>Cs՘Pg ܤbů [Գ-]JZnOl_WKzaؓ{\N2go{R 3kHEP(QqߍBDߋgB­59ex;$|NCW^7"a]u8SsKvC7m5S'=r h}_(qq6>bl؎"_(K"HѰ&AĊ:/᯳nD?;A=򃞖QJE#(u>QNHyivM"R\NJgC\Pmu]ן?ctkE@*/Z,dsbd$`_m|b~%lZFaYN.ux8'vyՏ}Lb`sFn+? u D|`߇Ş&jץj)q9n *DE ] 2%ckȑ|> WYg,Wt-3Ss+ ?_Ed Gl~p{glzg$J*q+i{ ,On:Ӝplڎ;%DVN}mX$^Fu+S oòppjoq9nZv5&, d_n /Og-Wޟp *="n]'1=aNRb)Ga}vЇyrfa)<ԍ#x 5/gP zJ!븠@("nԀtxln^Lh89bB'uYG5ċKOh7_{F-;&^}&@"ᓹmJvٞxhag!{ 'oqS (a.4OBJ1='Y 9"n_*5Hw\誜7-/ N7όq"Zl?O%6Ҭ>2-ǼW?OeY BkD;p |⹺(!W!㯆Ym53W|mG#rm̌6P69QyZk[wLHLU~p$Ƿ(ZT'ghou| ṯE!'U*y;Շos?ސU((?Iڀ^A!̉C4z&7f<_|n3N3&q;27r7 #&H< =CSԹiC3=.fㆬ/]E܊{"*k[οtG9OsT7ey~Qб7˛xT4PNj2l7<|s? C"@jZ;-o ٢QOi|Egm3sٔTkj;o;B`vxwO^FdEqۗRO&qaE2H4rqt3鴤QQ{'WlLQbe1i4\[:T@)UQ_Ue9osܜ6Yf'g(#\|pA}.RLR N20m%BiBOȚY[/ #^GiB4Wp͛(ݑd+"fv_ 9g@ P gs^%kZyU#%旊G1V@Q"Pc;%:nTó_*C sJf<jc jWsLe%0cjD,)eA1@Tm*(v]1u@p͝zU XaJ F 6q(I8F/_)flYG۲od\Lu?W̭4&JU(pHe`hi ץ>WhLId=XVdA @AZCh @ @Tq@})"˞>l(0;0DvMG@TqU y>fz.ޱ׍mMG^AmZ﹟ di <%wN8~n=<@ *,qS6;^A*|av|a9m5R3#?)c$w+1E~qc bbO.ah5q}g$D1T0C*9'yM'=ANusm_";0@՗dnapNK4;1d+çRp>!˺>M@@ @ ʖkv@Mu{uKӇ:R+9~Bα꞊^֭E5կ%ʊu^ q:2 4BӾ%"hC긵IOUg7Q}ķ pCn '@ @D"n7 MR;ĴYt;9}fkP62܆r=?/Eж`1UsrCi(Ogz[7 M55͙T!SхV=r|+&7ct}$dKr* @ (N"nʼn{&y}2_I)%=Վ?5Y1x. |H=k@6nnG$hp~Ѩ/XSϒh |Kge6*P^` [;mVחIUi=LIUs009{(@ @ Tu+I(+|BȤ7pٳ{T,ƄCիˡxQ#!'Kw~W\l a_nSh8ٻ+, v l_ NAl"!( e@d-TZhKFK4,$ii$3iҦן{=9s.H[!5l9R)WH.m TLdMZ-}v |]11+OGL^wJPqj5$(WKvLJ/=@ ;1Sz&iP  @ .k4jC;kfb@'/eK2 ,۹@wPq^9>+[U)Ҽ BV1a}U|xWƖǓ/]l*g>>|Mߡ9Byql>@ @ |C ~O}oj (:eo7Ϲ{J򶲓]ghq!Dmlٝwldi[D>nU\0/Dy( #uCNV ]BfY6@aU rD\ߓ^3@ # d36ф6p6U#ϕaZv );Li7DJCO6mlԓ|LbC$jhx)ZGnC4~զq]iA @ @@xUw|{ɷJު򊲸ڳv|.%k3/9S/V{rb7w#m%$m*R}pĿigpK1e7<<%ٛ$1u @ " @M$07;1p[e NkTNud Iٰ=,ڏ=7bg2fCr@'G/,@ @  rlǔvA*>I @ ' |%my@c%!t8X<MO~J|jΝ\#*9rTxQG~dZ8^W C?}17_GY"J~ކA> @L=q6t[:P(_0'];6 FsogP&;~w.);fQm5%-eY/YD:ֲuḘSSuŹ xqSthΠp+L/݉4-^hX^oݛ߼mJMP{*N^FLd9c%EN~u^^r屳d>9uͧ"qBHW%]_*6eU.ĶK}ͱ]AԞ5ءu 'ߐFٟ2V/v׺Wl$ٚ0i±/p8Vٶܑ_7 6trJZ9׌7e C}cd3jш[^㒽Th_+:]4@Y(c4Z+ê0@x *b?Ng| TYM״l(m┷B:vLwռl_f*}_rLⶇ^Eѳ[:|eH7; >ɶ*S;jL']yFr2~-G>n|~ g?qs&g_Х|0_}2EwKm\%DՂӭ[í:%Y*2-(bYWR'#0@`Qk+g l\uS4!rÊ3P|:|tjɓQB8 y:e͋?w_/) +wSʉNua߾K;p筏I[o~-tgvmJ[eX.#ZwLa ZM0 c)rnWv C=S?\|l},yXk IDATЉhiI}g}x&|<8XyЩV4@Jе&3)OmL`R[L2(^0|b ukIs7-\";b>rK~"M&J2o͐?*CzwnC}L'{>}&hTܚT1`U.O)ۊAIN{ ny!9 %#F+/Q޲~rT`>Uv(~|DSAMwyF F a6g8+}m4F6>z%.D,"C*^yA@Q Y*Q8`S;lĭe[S|qzҸX9j@L܊y8f*b&H#f"ʣ J`Q-c1ŭ~H&(DkB5 [5Ymgl-;L vbj,Dʜo޹r).&v9 ӏ5hE!)Ta{St)L̎WP>P1vۈ vTg)e-i˃u3! FGOJ L]G+jDWޏ%~jg1Dn>'pxJUݻv,.WHny1uܿP>˱ew0E<)Q zf]鈸#}c#߱GK498O?o/^d0v ˀb$X.&ԎëmoјvUr7^y@&@r͚{0>׫V +H0KiZO~WKPPtu[+7f=F`c>@]\alDH1@RPR;FV_Moy*&K-NCqӌY.h(гY ox< GUzkcw؟RFIk I&pR0,>S_b4 ,@6Q+FƫT`RbVuAȿ\/ᑷ]EM&4"0E[=i}^A@cF.p?X:N2?r-V_QIy@x1Ύ REoIU֟ G+=k%!>}O&@1  rM5pdς%I5pFaD,I ZO2Ŷl󝃣x`ә%+}+ʤH)7 wJb#"7??ּd 7L}(}pV1 -A}[3ƀ8xwhP^\SH.z18֑[|zF@cW=1~G?\(u:j̦gtßa{`F47]'bʗų  mx~]]Cvҭ6UX !Tt23{Hdz\nljzMQF9wO\P!tCNV ]Ba'w{\^ 7 =[$1N̛.?Ӷv,LH#SL+(ܛ4ibZQ~".HPʟy]̾hq ĸ%g3KLbsxikPpWCCq+vjظAy>?X`i>/}{ p/0'fN:H!q9- #Nu0bSʈOןR)-s)D]\ \l76z%[ktG|ߏ Eɸ =iıcR; O!Ue.^sӏ||Qv#sì4[/Oy.KF ڷ^["4pB_bfdZ뾈ϘZ{rY\(&Mm ժxx²>EHϸDIEMÔvF_0 ~hfLm b̙`\h| L Pa}7xCނ@ `H.6`7p`qbF(Mđ-cMAe+Dҙ%C0J_?\H ͭ+B_rkp2 ^4Y:v-4  $T*unU9@ p{۫AR4xpLh0;"(@ #(@ NQ"T s)]һ-m< L;~'&Y;EBJW`G1=ʓozsIK٦#G; Q'AḘSSu]Q'+0@`ON8q63D&mdqU);0!P6 EgOy$1ao˛:) #^q4*qBa4?)9w*+8uo;xeȴVw$旯~ucw44I/f@"nVt'nӴxaNY?`6lחR{GUI>:K*N7ڃJ >y-vV/jl BAw@U*-+]7Az4&;hxMW05Z_Uֹ(A>i[ ռi?Y~Aͭj_d`bhWThJ/UCDw2*yvgXqFnVvV8KO?]0OoPH:Ov oLȸz?Ɋ3~S=H&K|.?*@ @`!iURt1v`KW^ks3vylb>";LkFs(Šu}c?{RY`>Ofb_Pz8 9޲~ȵ#[:FD5O([I/ jb4HD9n^)^qpr*Ѱm~Zm֤۷F[k!G9K>ڳ_;T.6-v(D_>g/I6KHC2rI-nәeH7Nss*OS'UupmGs'UtMZrVd![n BƧS"ӂ"u;ޓB@ И g%$mtҕgt)'">?뿩)_h8i3:M嗻~U?Bv, ONi[OJU"ҟ:JD2U~?Odn"d:*8_(-L]^>oq~="e7trJZ9kZda8t3&QFT=+5.ًLuE Bm" pj5wÕ3`~6:qha](>E> y\I(!wd\}UDzEZ;/LZ䗔{m[*L ENƎ^~$8j-WMv<#ecm+x"Οİr 1TZ(lAd~|9~AݵpXlmaۗtnsʦivI ښ9"G T,X;J^>4NLQ Ps19_,Љh)g03L"3Bljq=!#|d!ULκCF Y%ZUZ۸t=i܃@~Ij5TB &qnżLBW3^aQ%0qݱƘV k|Qs=j0O,vweO ɜ:<32_Z Hw^qY/ֲtl Q \] KF^6M1g,ZajGن8X9߼s#XYp²,-vbegq.i1Ih;MFčWE3$ hJ,KݱD v~Ǿ1po)6RfF29t9@޺q[_1Cj?X bDiW9YzCxjtJ3֏u~EkB5\BV9ev֚ͯW;4יq Vٞ/ʴ2U7(HYdf+MH ;mM8;G8 poEIþt!{Rj j;Nny& G,2v]-:<5.ai}ބZdMZB+>WEa]=:J1Y{-))BcH|dzИe^bs_il^Jiy4cBq'!9kcľ,<  H.p?X:N2?r-VPRL㿱SŊѽ"*ɿTPh8G_ʶ-ɠx+;="IFhvu3_YU]7 E3]?k/ jqK8{N8-A ZT)NJ5$n '~wUEf^7h=ۂ/xLI :Rb oL長qʤz:"SтʹTI_%Jyiέ6pa7ߒJ|ehzu<+ qPIZZtwgv/41qSk㮉bBWXa3Ts+|2ʍN+ q+*bʗ RB@  ,Üh-,{Bխu[y1#a}UOF{lQJNZbTZ̺X( hZ{J_ύ?D?0l1oCSGqw;Ov[LݪR*j8q:dl ZG1,59ѷDߡ9ByqNFr# PI7@ժ]e*:Bf=$O2j"e33hsjxId.EuAc6в]gq6.ܶٲ;!}tҶ }`^^O`R%g>5ǿs9J[3LО˯{N!}0y3m0bS s|5||QrRٻjr)&="v\>S+%*I8fC@ ewl\v&ˮZ~\on 9El>Npl^34 >8hVsav^~HI. >%ow3ΜOvS,OVWj[RaDߖ#rݍ.=. Cݛbe){}W=7T_R4wb_2o?'أ]`׀|q%`ȃ M欮Q[,û=?./tʎ'aMi[PM&mai$~vm9eא2&Pyu!k!?>SZ|PSaUhYe?L(Żv :db*G9\6$lj5#}C)uY0;!B_7VčibZQ~w01ŵ;𾉷/! n7}D7GɖZP\F:0.W>1[w:A Ꭳ7m%&QLƍp~YaNTtrkP >*'״/(Ňw7xȀ̐Q $ΦO6Gy~z`81tzbWy͸T  =]83 =[LUX_nW *SK$]H9^uo5\: IDATɚi*v!&F[p!p'͟bǖf&MoxwbMAS4Go'2lb Qv3 <[R{o}2e>z'fuE}n\5ܣ Ԝ@*&Xnf-c< %S@;L)I\4GzǷI=4q*$j8ZamY{ a"+8fo}T'=j;C䇑D*cO$D yriJu32Q*Rϑ.>IwIxP2* 䆂m@@$-  UJ}Y(IC  @S MM pv@CpLh@Y@@ @ @\D_Rt))w ޭG |6z.MGEIb [%~JA=O|qꅝ:rdk;hu^֌ `?ݴma{G9ؓY@gؓNj~\4_bEK0nol[y) 3\hTtl#3޽l_4w߬iYRE28$Y38d*dFZ;4!A @"nVt'nӴxaNwK{9abi$#f&;c<7νPk#Z,?kmn"+]7AZ`Nh;̙éX-gs k&TƗH]1FmrdG? -<t h'/3(_E96* 7t+,;?鷸%.'ȸ~gz5KX}ŵ!q|čn=Xd$Q{D{Ws+Xn/omVI5}_1k現T4x!Wa_E0 |hg xFb_?[͛a2[2uLȸ:á}`ݫ_d(3D)Po~l YN⇋+õÂ#xVI3g,Wvvy_RHrO1luGV/IwP8O[X`BCFfۏ>`4Z+A5.ًLuE BmnB&@ Ш:[.>z.xɆ,7 J?Cy^@^='Mկ> 'fG>$ @8x5͚i;dk?WcT* 8ܰ."]DhJ_- !#m+_6W*òt` [pI[o~-tзm[*Lj?qՒ' qr-XW˚j09k_Rsa]b4u2s*&ppyv90t -1t6YޡR~$޾3>` A @ _lc o"X#d9XY^/ >q|7n%sͨ%]}?gy>yy~W>n4q2<\9{*@$Uč*~Ngݡ`#n,j*-m\4A?v$VF^[H1g,ZajGYj] 2gwnd NX%b^EN,Hg1q˩VC%bV;t(n135A1VePwhk)n8[SӱZiWKdgy q% o` S0Lkk%6.e)#c**uxqAQ<{H@ P%o;1hjk#/ܞC8AWyyI[O!|7 n5!ŚZ7c!r^;e??4 ڕ?/]ujTWn#ז#V޽6@"n 0ƍ.d_ qE., WI3Y:mtB7f2-wyYdd;/Bmҩm7dAECT{^"fW:FF\nB9`X}ꢾL(4NZcHy@!@ 5`|u6l9R)WH.m TG(wF@`IAI[}?/x#_w}KN.>6( @! WaFIJݠ7 cdpR 9bBWXa3Ts+|2 ؈;3 wRт9qޑqdm><& *kl:}zm20˴ Nyһ; ?+}ݩFr.kk @QG,_bjy:(fv}IU`MAYnUX|z\T)rVkU+A(v\XW옠 qs=$O2j"e33h9{̩⁲'ɲAOj~/d(2O[\R4wb_2e[>2I7ZlVonB.@FFе?{]$_+t?M|+-g0f";ߚ$֛__͸5Տ_84C/_;~![vsVW(ϫM?L(Ż!Q2@x^U+\6Lj5#}C)uY0;!B_7VčibZQ~𢏏t߸nϠߋ!Fg+m.;b07]6~mw߲l2i# ܛDJ5L' / ʎIlBU bǏ9gJyĶ!onY@#@'7+(~.>| L>žWWz#^c>4U XLLJ85[㚤%{l`Z(7Dỳ _yޟ4pB_bfd`=p%O(Boܠ[[Dl@z}M8%@ߌŒrCم@ P7LcW@L=#ZḏϜ9S sD ܏rWt`D/t|l"pg4(7K , Ⱥy>cR7ELsɎ BΗ}5q587.IW"u^n'y{Q?T9|,#ZojP}1^AVf\`u_s8r~fZo5>r2#cHnW3"^Is&%QV|dHn{ @ @ rS&=k~j}h=”6VL=8H]Ufr&_||.Z3;%!mq41'֥Yl͢)6wbAca@h `XB%\,~Rd|/a=3XtAvFMxCA  K͙)u@ 'p? "{lFT|6f`pGaECn948@fU7 %@ hD6GsZ+vUiez|Xv𿜪LD @nnfU}9|@ @ XU# "8 h@J=+-a|BY>mqc^ ? D @9nP @;EsT_ws}{.Cl0dėΧBU{-]撋ys=lp7 ^sM\{Bvt5>cna7_mMh1tC@ v[t34 &߭H N[hUYa[OfZ @@<XU*@ r,9U -1Ei4u4Cm },דLqӂmd::*˜2NO^y׾ވ9Y9J9ϒuێTD{^bٙ e8Yiર}oh(a:3 D  h, Xz @ @#@_dwZmDX˰%A|&zYYrS®*%󏟿5J7x#j2ۂ,2ŇSʇ^٢^/#t_oKZw[9F\5lʃHS^;I3M,2O?SJXy@ *@ pJ9w6/d9UrMӯ05ɤl|VգW)lupuy܃i/cMμB N}6re2d!Z "J5c'1TQR)QuxИF sL -UN߂A@ DbbbT* s7˂ @ @5/S="gΜ) Se 4jȞKL-wDsJ:`Yi Hr ɮ*9Pt[RmN6v{ +6pd͹6M{t Ixb upMuCv|BdzPv(5y8K \ˋ/_~2~<|m/8ĵ]gX4ơw1ь@ @ `6c#J1tjjF;\p ZfJ?&G5CgP@$d @-/FY W]m2wjPÛ)|v]E \$@> u @`,ǒs[ZStwF$jv6JVXcfIiFx62ZOhaL'Rk_|o蜬PgɺO"ET_5,FZP*+qUg74fM^}ʙ w$A(Ҋ|CMVz6/k̯#̄J]ubo"D:U$??Rպl㼜="=b Q,8&;SoJBwQPU㪇쪇F^|>msST *m8P3@ STXt``t29}Cr:Ym\룁գWdb]ktxܐS{؎_ɡaʇ<04HvJcKOcecU;F7 'Ǵ rݷPpub93E/R IqU~v@{^qudeI}{FHwtp\:]w$cMμN+ 1诲K;%Ӏe($ JTs>ˌ,OZÃƼ6jcNhbujOqjłp%` Oqsd+jo Ϙ,K ?;>ĻO1j8̱X^W1)E!˭ɠQxKzڐskFw}K&8 P B눛%r2dHw@[ IDAT7 ]v]"] s3Z 8p]\ T&(j*c LDCIZ#%3HZnI–b؜+)EL Ƒg!7ո97ks.A`,IǓ)76mݴ&$kƛ30{oeU ioUU!S ~pnuw}Kd1 PJV6֞@ T C#20$S2,,@=o0ƌ$q̓7k&mYc o]aBd]IQ[b^Z^=KxF͹LqNWͿ~*2ʇ<1=[@I=dopũQZa}]qu-]5k.ہsn8F @ `I[yś*Ieb|S?3s, StFm`9Vb?Od]aRd*y,qOwcPz4"(ȂIڵ{4\V܍K)z\'pE9R ixڗC{cBQ+Z_^>W7nE_h5ҁ@QZ\}M @ PM`sD u3T{hvݣ3sLQ".%_%,0k #дԋhO7I/7߶O>frZqz;"c.Z!(dKΝEn[&o`Pߟ\y,,2Ų7RKCFL\Li6n-@e i(qՈaǹk) FvGK\\1%#R6>7(%|ք`qu,r`WʸB~$0 #}>(?NЦdK *XU$mLsJ\eص.iGI"/WM/#6n /L 7 $"7.*@ё[U-T_V-iJUUO/hJ W  @!FU`(@ Єh}<9[dٺ~Z7MV1pk] A9  F @ @4qk<} M{r‰9&{r͏j2L۱ǚ=f"zn7-Raa"k"ѻȋgw:n4~HZ8ha7TC7+@ @=ԃ)P@ @ zlٶ+a.Ɉ/O^wU{-]撋ys=l̊.QH!@ |N.)9 P@ c9Sުń֘׿4R|E}5sB@_,13SwܴA#grMӯ05lWE/\=z%F̓tiQ$aуoI'Kk/V6h;嗟ROҴ4񷫆N┾ƮKl{#*3!2DVgo(@ D x=MEcJWgtH~p}\:@c+kr 6b_evK7/>JWU£L&,=P*Ռ9GoPEE~RDAc^51m'TZ:,tK- $)aP@/`111*kƛ^E@ 6G!P7SOejV8B&3g'r2QUFJKPFzU~ JwDksNG$T*VTbӿ^j 5~s3Mno?`Ci3XB*釅m+}5澬ܶqh}_C_'&$ 9[ge\`Ւ_s8rA!@ @ Cc@O0W>>,LH (Ⱦ9И1$&U9]3ylpmxG ZOd/I{uhR{S0k\- u@?^Us@+@ mOD73U>⪃F9Йg,Y$z);},a_-&:7ss芝PwE=EI1.sd{R#߹H@v@ {q=S@ p[磏T[Wy΃ m:%#II4W C"n` @ pёT_Nрۺ5h<@ۇDn CWEG69toUe^!*A1@ <<3 @ @ q $@ +S=T҃i;v^Zp]Tmci**{PZoٸʷsh]pzد1LiiXھѝ~  7  K@}uys=lp7 u/˚綋{A]8}}UWrYNRG 舓k4Dc{]5ct ~ H(QWnh#<'~4䣍: @Q̸9*| @CbO@" >_%Y3'Ọf'jiMk nR+N(R7@Źr݅SPe3dE5My2ĀʙgehӚ2&xx%r+}1ݾom$а'g>_W7ˋSuv9/+6,`5h*#Cz[{3rSºLO_, U%E~y|oFꅓ @pf% @}kY^2.7km2v}c/p6\4͛4 G|샧*&-Upwxʫȸ5K#yZSYe,gѫ)&)dTAەi?|1}n!Ezwכ>UHC#wW5Y3/*7pV`ZX]x͗0o](c19  @)L8  mC;C I.jBi^% zWIsUvXZWOlΆ}DOϐ6kUî^h Md"O%EF@ [[0Te*I̟?U]?_Ʊaָ[Jq{);7b Wgl{W\nJ ;q!ѯꂣ{7SY]fUM%Ic7뗷~ME^T"ܵIc;go4zuw_8_K^H~>7u抦ٯ %)K}1fcEn/mgsS->(~m͢#?Oz7>>r@ @S_Zkӛ ꏓ @ *_?_Ȱ#8 `|TIK+JK5qqd 3-y>3DHw{hHrx/>qloC뵾=ՠܻ*fxߜ,{7%h'4P^<e'#j#<4A~b'mqe1;SH$әތ.gꅳ!@pӻJ]_D @`%-&=tS O:/cQv+Y6ֿNT/3FnSy%U?#4cN h.wЕ3 Mr fQX 7M9&)^tĖ 4#s\_oiN`w:gIQhϥCLڜo44JM UJʋ @6*e[4=;fXEJ}T=ޙ?xv8ϤMYU^r!@U5n]f  @fcM4 ~V= *s7 @YI֙C X$A 7 P0˸-^numY"ʂ @]Xr˜h: @ @q  @m/`>U$& ۾,Q }|xAnSn?922u[TNv/G.=+tU_1 J}/9pA8:}¾VGdfm,(1u !k繄o~0tƫE*g-ηI/bx QFbsw?;>C:M" ŷ*L~wKMpA¨{,PiڃB^J;} tA~ĠK,ߟ"@m}X~`+ƄQ>,D ymS{x{s{4z/if=6WspOEfŮRq!1\ؿP Cgj^<⡊ז=|(эP#E5JѸcyT-?=cMMJ2} %WJ8rWpJY_ $j̄$(EAuDASL|>1 r&Y*Ƿ%gu8lzLƃ8Tۗꈔ&bgB;ĶmqB,%1$Q▎U;lU;bWggg`ղhez-˴l W8~b3AM($TIv}c/p6\ٴ(~) y?tQ3੊IkKis$&2nH^u(iփsxY,K=;}ik+ yW kt9џ]Sȶ~!u]M:v8PyXA(jJʤC{ ՚Z**&$Mkc#'lc8tr*C 5#a9˻ i{5ZW]3]ۼC+3ṋ3&4U.?70arkk: MvF'DIZw-,ۼǩ8ڛ/ޘұ2)~n9QitтKUڣie^7(ltm%<ڜFN`ڭOˍ:yButT뷷7+NdpDh'@6ksG0QOFsv95C?8љ9Gy$l:I?H@:5?oopp\yע/ "N_ʲׇ$D]fм8ÁÕjsDSWjC}OW̳Y2)v㒢i3Vl`=R/v.}f< b|:^[qjۯiՇw̖>:[Fu_JFo5Ot2lx %$g_&}7}M\hnC [|fLC$% А v,ΉteI޲vqsSr6Q%'xDfm y }{G"qlXqbVjKĈK7ݵ.WTqtf @Y \vq[7 ~(9I^T+2rUn '_fݷKNuQ/Y"IQhϥCLڜo|-ns@\;:eSNx"x`pglі\Z)XJ$ /4  =ױKMF1eG2N^O^\9zzw_ 1r0R+5vQ׿ ɪ!AU~d/orO1nJȥgάJHώ4Μ~Mw'^CuDvW~:销x2׈oA3Ut3Vﯵ,+pȈs>)uuVHjqBZǨqŸZodь#;m32P}r.ޚ1%bNqՑwn__oʍָ1!@ bYhkZn'O~#?1;V̑*);31jM+l:;GVtƸK]ԻmⷓVHbrոr@0A@ iHapԫ!__/*8G͑Ky/uC:U; X P0erIQc.+*{cVvDb݊PT0NbIG}UStUr憿*jĜIB'en}ڊ`hbwxZ쇼37υQ  c-sZl#\̩REUi:w]@pP @ >8-OJ{dL0g. ^yL/=4fmmE[yׂ1T \]Vml}R$bL羝t/?;ĖXca-Q} ys_R+wcx,*d΁p{ʮLl8dd=ىƺOnc^kimi9 }t2Cgc O'&@:ɿ/@h~ё=FڬMp"޾tŗj, jSG;>S$ȏQR=ڭo %z-6}8QX4V5Lb?q[3 ;; @2Kjz>)*.u. X|~W-b}JѸcyT-?=cMMJ2} %WJ8rWpJY $j̄$(EAMDASL|>1 r&Y*Ƿ\@cIݕ1Jޒ6/n:υ{ *Ym,=tp*ԭ` })BPURVmıY3n=.5LϨ~ nQv[uʁ]6 L,q !;q @n0^-,ޮiOK$y\O;66mlϮj>cq!=^Cj;v;*lEMOɪ a5GN8jcc^=M1yMq!>7kD~?yYɳq4gmGkez-˴t W8~y$x)A/y!~uc1qB Bőzas2+-TVk*k7[oaGغ٫eL,X/ܺ R!g:Jtg @(`=}LI>+Yqp+>ɍ%NdmW|M7?~PYg["*zDX.+ y 7ur7h%6cѴ2nl~|6[ͶԒzZwqmNc8OGkn>-7{ Q11HA羱q8GD~do7#H0 @4O, Z~Yy#GTG5(āM?>)?)5^w|9l3")1E=s39a]7c cFMDz :Lo:B6ݵeEh]fQiYZYhکUWO]}4jT雹Z{SFqA%\#yS(mD(/''5l8CgiWV(Q]%teH{E#銒oO]S{}-}DOϐ6kUckAI ^_ijQ~ = Y~QiTPHκA9Y+@UNϸi3'2 (pC˯ƃ_^{ѕ߈ 1n_Sk\6 P[骲ҽdI_~姲z]؍@6p֚v }u05tI/M"><>^*׭LV0 (ufn[gM"@Ybo{5=tk/;2BrBNn7u &hK.I]yzCc(!h}mNɷTWIıZ^S"6OlX6T;'?<' rpG-ʕL_t3i\dU ]=6kJjGfLhyR憡ݧ[1+pȈs>)mZX5 m\;RnJ68B{?clH-Vt ׽f|l^/ 6mUUWs?0DL*W721"!{rUΖz8t:TWCn__oK+7rXyz5 @`#@^7푗;w7ےI=wY"_UʲnsVE+蛷y,>[:qD=E[}.k9LйGNtN̸u~C!@08L9M˳;^P#Vy/`u2Cƕ}Ցzu*q*=vB Б(AP#Uu.W[ycHe xƹ%Z8 @ @<q>E @ߜkX yLXp)ejs>_=3&AB/b2o%wM}S#*zv)/K'QX8JWE01)Q{k~kG  ^#>%- @]KkܺV @]-asWX' H&ҙⰩ)/%zhR{8#D|*xm[OmλL"ooAS_Wm4j Lj-ClX q^E @@' "M@7:(-Lm&+xHumhj#, @΀ @p=YR#HqNVq?EuYV1hҀ5iө^=޶)E掙ד'QS&57)c'\) \])ee3dEײC<|b@GwL{2T4Ay[b,{!@E3nPO@ yƫ5NX"ϫz2<ȷOu9&L,XҖ#wHp!=^Cj;v;*lEMO)BJj^{,p>xbRoڜ!yǭ[4a.%zp/eg4>c^=M1yMq!jMuM[d @va@ Ѕ չ/itCWܬ8QcF'26\\+Wg*)VqjWQE 6{$n^fC-dZf=VƍՏOpFwٖZr]O.il'0h٧Fc6د_zp7͵iUӭ]=~zϔզ)č=ø~1{6xN\iH{͔m֦,ۄg8~pЌwmLUotIKI3~X^1Dg.*fCp 䛚ʍHJ4  t1_AwI=FuZZUA Wޚncl63DHw{hHoq=^#4ԆE8@U@ A.?o;XtJzVM}˿d茑ۇje^1Q׿ ɪ!A^E:|~w'ZP>,,2Vy]uGz|k9i4QQUO /0fl<@DsUV>Y&ZNOޖN 'Q{ Ok!@q A @:͏{8+" Q,k|σIݱsw[f2w;d%ݨ!6[fG  @V0f @08L/tg5kgare_M}S#*S)Z|$d|B{< xt3yc'5v/ܘSvWTl핵9;(y=zx ?̺5N8sا7NƯW3_Oz)*㜮JWE01)y! 8t:(Xu- @8-GJ{dL0o}jcM%zhR{8#ۘ6aضZ~] SVLйuB `Q) @ H}q=HB?(ntdQ"6sxܵlUI/bx QFt Nf RVWDV{=Fc6;c>0D4@  tZ{,Gsprj\|~ĠK,ߟ"MQzܽmS3'Ọf'jiMk nR+N(R7@Źr݅Ss!Qf&$x5E) h%% dݕ3Pm=~J5ۗ)C.S(Whc顃wVnG*}nՁ*:U!c>09K0dY3n( t`]y'R, jr=ۧX?UϮq>c n#Ĺ'khVb.^wGmع()Y6HiXkOULZ[M3$1W5qkF25DIzeYWOSL^S\idϮM| RC-8CX}ez-˴t W8~y$x)A/y!~uc\8PyXA(2Be +9zS=UGNc>qL -X/ܺ R!*]gP/@ t͊5[$7—8r^5-Cem#aTl|£LɌGʸ nPn5RKiyŵ9MF<ݺ9h)TGGŸ|;Ol}bj IDATnD~do7#0Xv9y7RjdrlgjESzc`8Lz8gjms>v#! жNq41d+~ψ\pu:ж{-e_츪ՓyW78j8UfTQh\gh4| bDi^eF**Qrb?{I (P)njª}Z-A M,m^tEI7 Ok[󡏨isWfj}`\l:´LH~i)q+J\WneʶJNc _0mm'"e?o+lb7^Aዖ ۈ(&h[z|h=雧~:t}`JgdO,@_- @t:-*|̠yq+K ġ㓤KZB_Qx\i mX'e(ޒ3cJT$)Ipf\Qɉ2ᗸ=^#ܾ]1n\8[-OG8?# W_,bTF'K>ŝ>-UWsO"7&;8g_tج*Bn« s2Cc+ACn__oK+7rX!:  @]Q@yX}7ܨ!6=K*[YVm.uqvgP^whjNZIv"U3 Ws$vE펝ke1Cc9!kq4@ ^R&j|{-̭uZֆ-T7^I B[:U+r !i0i  @(APc,>Y庭Hb݊cc k!qԮA @ @ho̸w|@ gJ4.I=KӛlyDi9~Yԉo%uN7u,e|)_#ړgg%^ c:΀ @]OiJp@ v HӺpRګ d))Nv~DM`YG|t口s"^M|{Elk-I[ 7ӎ2C ̸! @@W "Iё=FLgJw +xHumhj#, @On)x @|Z{,GsprjLfJg)uiS;nzܽmS3'Ọf'jiMk nR+N(R7@Źr݅Ss!Qf&$x5E) eMy2ĀʙgehX C 7@ &]y'R, jr=ۧHL -X/Q[Wgb`Z#{8dz MЪ]_ \ ;eϯ߰AJj^{,p>xbRoڜ!yǭ[4a>%zp/eg4>c^=M1yMq!jMuM[d @;C ,@Wܬ8QcKpMs9_n~37"S#aTl|£LK،Gʸ nPn5RKiyŵ9MF<ݺ9h)TGGmwe\up @m.7~,H;Bc^W6 }8{:u\X ,*7M_L鬋6^=wѨy{SojLFqAMbbDi^G**Jb=䤆e{GbL7 a@@ e2H[(.Zҥx@ S U٧$`gR*V2-Rީ$ӌcUkM\C\jҟn*?{6N'n%?س46wJCڣ_GVol6fv}<)j4:xW #K4~  w n__o*E9*u?C 0Ҫ g8ptc 2lx %$g_}7}MQ&Gsf6 [|fLC$% А 6#&y }{G"i cp N/Nr4 @C s::bG2N^O^\ozw_ 1r0R+52~w?Y5$GhU:nm[dHnThڝn t̸u@E @Fy `*>^E:|~w'ZP>,,2Vy]uGz|k9h !sr|GH(Z`<{ʡMx29@hqh=@ tubu* Q,k|σbS<8 @@G[G  O aRƇaC Wgnk +ХR{F@!@]G3n]R@:% Cu3ۡ\W[a}ۊD`@ `_d*@ @ t"@@0Te)K21nI*0 @p̸yxy x7Όc<2@:f:g @ ʐE'@ @# `ƭ#@X ~: !@+7": @pܿZ\KpgOsk t≠u>G!@ !|̸yP) t~M4Kc^W!p\pu@mKiZA @kHL&X+\U~d @h=SEa">!]i; @ n__o:W9*uNgA  @b9n*@ f̸a0@ *@=娿 @)7W  . -=7 uF!@TN9S @(J} l@:f:} tBR& Pe@ `_3n ZI] @:A:Հ @ @̸yHG t*CUv J~Yԉo%u7u"r.@w|]ܸLO_^{yYgcEA@ `UѧzX= @"-+#0q!M j;~m_|xl\CFJj>)oOHHө~ I,:6'~_ոr%zpN`˾g~z:z4Y)Ar#yP /^k{Czwכ>s)41"#CNQvd @#qG @#a9-+ \2-a3M+'AalK-yq#nݜ}Zn4Sb⍉ +.p3G2T]_߳4o5%Jz'PEWoEoax|^!Jw_mq ~5O5mLb8@-R~,H#5ze3m?H:ؾ45^=wѨy{SojMsU ]r7FKG(u%Js2mo*~䗓N8CgWfu'R4?;ʉs*B->RHk5 GM( ZCWIsUvXZWdUd @n e2H+[]hj @t67P}H? Lаr/}tj_|ׯz=\{h6Z;*lO2~+ʭLQX4gz8/f{brTo܉+ i~UV[=r5jo*ҷz/=u٘ _=| Ñ#Z1zLwL@ *M~>7u抦б C  //7ʍv: @@ iiUc͋38sȰ#8 `|TIK+JK5qqd 3-y>3DHw{hH;G^KO1[vlJ{U s{¯M6e{C 8%W99ņ @ @ 7$C 7 ϔhӍU@h@  `m @ @ %0% @ @pfF @ @]R3n]h@ @  `m @ @ %0% @ @pfF @ @]R3n]h@ @  `m @ @ %0% @ @pfF @ @]R%[FC  aR/.پ@ @{\ AaR[p  @ `Wi'i~[z鬋Oq:L{(_fFz;@]LP~DCwfԸC{U 8*7ѽ BGk6qo^?Ա? ѥ q!ցm~59zߵuz@hkOϾ=co`;zh1 .xP}k{"l@ p?@rNqes3wߥ$ߠ)k9r/"}&ͿgVΟk&ɸ;As%^VC~;rTŌJCzI:'۹kSog)%?~3ŋS=ώz%cxuNe_u׵|̽ ʿ;cjnL+Ouj>m׹ 1{E/܆1RMSy퓍;R8A B &3=bVƅ6m 2@LC~< p?fBXÿ;pa t;3D 5D':魝y!^^̈G^ÌC˔ϲ6bϦ[y'Cܻrl/ *3Uz}CGX9 'ߕVp  $&~tO} ).G@ ؚbM4/ o`!*=s$fUEe~qB@#󵷡6{rWG >vfiPc'0?:Uo|o]M65?/!z(c$PmU?S oA_ܙ6nYN%ݿVY4!@f6{ cǺ`~љG! @w*܌&y>si_5{8Ao G3ftF˱xm\X\0qcPkD|*{s¦7 <1 ɖMFȁ IDAT~8$W_$/)Zհ^Ш^K%%kFZ55u SMqCWW5Y3Ktf h>VccH ![3*m~{~d>bb tV*f>V3'qVĚrE~#[ꪮTe}4 aC y~WV6ցm~F:bP^%5#k1n(h_CWS݃x5vfx2ǩ)ѩW)h@\\@o; :k6ê?41(V<~̆$AX؞` ď5nX/?>IjUuFCֆ>Z/&ymQ b_zF9[ajC:'Ye^q#1*/_>nͻa /#|޲wpI'H|l@?[>PQXM9~O!qTS?'I#xC_[޼V Zdz ׄOol!}_ #&>۴Fsgo!@5܏YoNl .-`o:77q>bwoٶNu6n=ΜN߱8/[$?@-Vc`xżC}kf+才'NmyF>T9̋9PP}̯5:sЦ7z [Oc`F6?[ogZqgS=uxެV'}O4MH2Gu곏z][>}Lyk7B^ձn/U([oQq$@k"+ c9@p)D"Q6hn<ל];XS;mn X|5}R'D  ~YSEagq̟?Us=p?j#3 @C T䛪ʍsk:tQ9@ @ @CڱUW&jnnx{J-ն&xo@,08LUm|\/qp?־îk@`R&C  4*mJ[g@ бcj@ @ Yxp[?}-=tŋ'wxU׀lϦWB %DP (UAQQ@HQ)bD銀$$DJBPCzfٔMvdg)>>G=sι3s-6Uj!'U^gIGkyU^5sܥkH_=o}t~5"LX?7RƵl H=9!:*YxJ*GW$ vU;b0#O:tvz**xf]ϻ+4KUr(>r;L` gr;= 3)7}mN E(Ψr 剐d0::&j:uBz7o^VkP\F/o_PP`.fKHut!%gv%w5}eIY'nH]^$FO406?Xp@B 2>.S;RPyVcH!xgA@udܨ{#RɮysoUg^^:*KIʦ ^^6lP 7ӓ}%.on.*Ow,[z57Z*_ ;wrQǘwy8:kn;_q][bV+נ P iNi6 Fs̸>}x2&>fh>{Ϲ o&X*uCl'bgn<*BݿNmXqudbi`g\9PJSrgiϘO;w.|Ϭv(?Qŝ)k?kkyX"nNPv1Ljҗ{O]f&\;ոU_X%NPEj}C15u梡&3Egk{,=?J9ɟN6{ghu'KQ'GdQו|Ceߺj+u\`/[ IڵdL/m:#0I؎v @u|acVX0ߢ JM*+ID1Æ=T?p{̠>OyW%fZ5[w%V\_(n;9#!a#MUYvhl?UjvfMޝrC!;Prݝ;ϗ/^|-ݥiһC$S٦>-3,2''BMg۴ypuEH| n=&)Hң;Cg!x?Q|夂BnTSR1QHUWıC[l/]?48YU#=c/؝حas߸s`2(U/,+RwÛI~^Q;fJxn٨Mwmvj-wC):  k(+O=8Gcu;%drzyTl&m { c!3>$a#NŅA<7>zJ9nuF<׹ӀD?9g#/sEP/YjcserV٭Sgm ydXB h8? ׍~:nݺ#V5ڋGh{iIlBVTTo+d۪ ^c\_K{yY<035e$dǷS/*.nFz zڃx -x{ oٴ-cqރP@&`_MҸ=$8chJS{!$}{@T>5fڳKprj=կt|⧘Fpt/?Ґ|ۧI姨ڴ5U=5go?pr?֐p+{+>Hn5՚YZ?l/"L<>x|io.Y|nV=Ꮣ"`8*stZmqD"-MEFn@Wj OR$(iJSo T*O4i+.-uF@*^5O=x?>"!x qB1} ¥Ѕ"LqzMר{lM~|::‘B5;Q0q{Mm%5+N5YzFSu1|[-oܼy-|ǃHxX",2kݟG/^>4)YQ!)K+Rz6M%Zi.%-kQ0>c**цvheb[./ |*;׺Y?饜ٰs'9B yc#]~~a$ q[_/KTB'uL>sEujߟ'쌾z٭}@TX%`WՏx8v~c|Ah|x 1=@kxPPB6{PϏwih8V)ovJ>k iL[cJLjûMWIR|)?5hoRR]2LXcW6~%?7ҮtQ%!gSuzW;/}᫄GB7p4規F|K3ˡA?B+T^? 9* Ts˯)"_A% .)ύkomW4-<.W:J.#:|7 \||$ӈ+N>WK0gtp=+U _ܿtb~ф9ܥˊyo=L| |Mg6U w _NfFһJֳC$Sҿ_I֜VV)K)-wD~MZ.OL{mrڷHXa7 H')%naFanZw^h|( z?-U5yQ]U_\ܨȰA!M{crIL[sa9ƕu!KbQ8\Bٶ]0up+7Scul<\³/%1&T&h䦉_V&NlbLc;IA>x̲+ >0!~(bЁ ؗqKո ig ]7*N?Zz9Tٵ'o[l1ؑElΦ^6ЃolD\ڸW[苋f[lEw IĶxv5u5T|w~?\ 16ްKY,SMw%xJZVI[jF/U5Qwo2 n}ef_\jԔn8evv, nFO:xlySdr)a`nmW|&FX\B=ۅar!ny?Pm/r/-]sIp77}- Cq2-/} k~ȼyxZZ-K:$"Ǖ$HZ }p9x⇲{s 4@1}TC1O@CJL2O0*;50#Mw?KH C_Wnh(vٽ\6RW(PW!DS!@R[翏cb "~Iӷ}7L(?td6DnO$:wih!6d 5+ʨRx2nXM)*QpDb~b5 #j,)ӕp*ݞjcpqc9*Ja~^8{Bz!Í<>?xPoȃטJS>[4G6Ys_c >sp7<*#vlu\yFB-;ϸ⼏%TP(nBy.lW[9lV'&UKSw>'ѥ\v n 'ݺ-tAbwFWLO@>BsdârΟM8%$ch],N yYQ|Ls3lhTJ i r>]>&KFq#ë[ExxR4 ˉN-dYFiSώ|0+ Qg PCh\qG]r4'J픳JiT]Fҩ -}Oe۷S7U?N'>B9瞣"A@1 ~ ე*˸a*֟.lm,ʋqe@߭`+3t3;2l#HvrN+LbY-B9=Œ.La#/Faq΅VSN|>jbmDܐo|O%\\HCWi,VA2m| W.njlo[BSXabӹ-FS"ŜJ7_+dO:&Lz쒯Ի|-T)16ZCB qhJsߏ֜g\qG<%TPpB^y([ZS^#7qٳQgF5^{X`0]X5 @ ໏]A?LYZ? O|(9x=W*Ns;Qe@89ƝOF2#,xspw1Br r ,xVarm]Q.Tv}pylƝ ,E.^'ESN3-qWsO6r/!y) ucyIu-43 KKwL^;͞7~ؾkTmeLs m)#q)t;H_n~k=^=e$4}%?c|>9k8f-ZZB'i_Z&}f<37g2:S.}uĝYk4.͸YcJmWJCƙG&>g?av h0(}|.T9.s\n-ϳ\_Z@^^g3&Տs)/hbrEM?ǘAt %?AcTM@O R(v3helAB7%ZGjө[񴍧5ؠDm{Ɩ2`GYkr͂ ݈̂Ղṳ?w_$mF1뎭 'Pz6zґNڌC "۶STuuW.ǀrUOj/rujVg  $KyJ6c)|i^QjurVxzEdUiFյU/U P#|@>UWM":J@ @ KjnPv>X< 9vGO)9Tx+-^]KV| #բ]m]#T8*t7uOOWnQKmg0'{rBtcm $FyU(4^xCՒĄqqE]S>*ʥ[xh^CW/QlGԚvSkkK?qȉLc%9Zrƭv]pJtLU_@\짱:̦@!XKh{JgvUC [C%U%^U @8i,Fw>vƻn ¶uEd]'2[o${y y)v7.gzVBA<|әg3_Kb,L ?˩U)K>rŷ{h+WL{mCݧ~_ᢐconmgd;3Ɏh=h=%?WA#B-cW(yqÐs/TsVO,/ʩ mNʗȽvvrY"F֦0"{&8 Ooll3pLEG,ڐbMRw s]wO!-21,zS4qI}ǰsz=b.t>>序r\s{*E}߄+(WNt2K2Ũ<$OB@x8PhA<W )wD~MZ.OLaɖ/|~/@ˣra7QoT,azqݧKt$8㢺={ʁ f3*2QWFVNN`ga}v| Ĝbe&;H-K_q:UT |Mۥ٣V .l1\qDĸo`y[dܜcs_$ϮNfU84.M^ZucX)2kfŔ^wN0NI?v=I_#`!OZZF>O{.7PDȭ۸:긿AE.*ro_^')C9qC;uV]W!|*Ō.VbR:ZE}U*0[Fgf5‚CE¯P{Ṯm|*)x]&0R.F#$>Ç}&kS´WT,.H;u/5 ,xwwS(9 翏cbeܿ㴋m Pԡx.G3!C&#rۅ|ӹ!GtL̲7%! up^i@B,t<=cH4U3lD` @KJbxABߑyEf*ʣlJO"~,!~ݗeq ʐu9w\d-WZy.z{BW!pu9&nܐ'UNp p!v3T1ZS^l}Ro%yi0W-mr̨.lV\vqn_Fz*o9w ]ZxYD.>R8&fsi1UL)eFJ߭`+3t3;ybK3'I3 _ޑX<_TEM`ih#7йlؔ n%HM9x(7:,ORHS |@~pxCx I1$GV0Xv2xmkjϥsGf +<)K:BhNJ!X1ͪCt"Giì;.*B|YAW{uyU)*C$#UQKvqC5*ӹz2IKݭS PZ ciO/BQ[S7czo.¥C;5.HO{mZ`^n MZ34.uv;­3},Y9x2gcx)~ɶ~L$ISe d=>Uo6 )5mN6K|9r:3.2sAn$򀦝4bӽ!]~!zLW q*(T=ji[ @ N/r! C|YΑ?oI(dUbⰐmaƽ\Ē~+K gYͤŷ$f ?2BIbB~M)Ràʢi8F$ HbG3ӹ̄(T;$o<廡na9e9taH.keep+Jr ng~? @U d cyc- "erc_h>?ĿO.wd aSt!Jg0=:E(Mr{!Cg ]mpX6H/{ޢe~r↵3:ʮ_?ݾ5Onf?yy/ز@&v彗&A y~pZ6#UoZ'A$5ܸGQt1|FТ :vjX<ƌ ,H^K9!b*5ިx 埣!s:: 3M\ekJ5m*=7+JI%@$o7H9*h@8)ǜm O=~>P l"PWj$ަV'kuUbWTE$=[X5_Me ?Wrr(ȷJ1Fp?jkmMOJN{tV%7ǶM6 mZGsxjNk&GN :wSHꉌ$-eŹK@R}aNi!>7&|t6ygkAో obsI51]pJttSHFiu:߆ápTt~`#jF/꿘c8%L/z~=-@<>zZYOݐ:6$j/ >G ;ۋ`ݱ̸ʠS>3P)eD&^+_3dqEjItg*ןN/:wbGvm*i-߸.Vh=h=%?WAY/BkOfSTd"ϑ!/6.f@ny%:eqM5o eGpt8}w+mKW'PlQu'-4r̰6 }A.>0˙!}}]/4Iv"gp,MK(547~QhF8#vk}mH1`&)PdT߻TC]×onDj罯/ܮ .yWſ;%krxzflM *z0n0a њ"zct)TѿI.+0O'UgiE8⃈!>{|?Qؕq#ݻ}}$b[k<Κ:yzƚUq*?WEdl.roإ,1!25= Lmڡ%',N`ga}v| ĜEŮ <|1iPv1F ¨+tr~V'wCݲzv۹z/-8ị/v 3">󇵾gڦ}LOCMq;..O;ï7=2z\aC.ޙ-@ KcR̅^:IaOPcSM}go_C[&b~ewu$/ $(|?֛Og|w5y;*@29ҕMW4܈P\f N[&Vj/`yq|),v]o!ՉƑ[ߓZ&N١] h/%~Y tWS]35uozg"ZM&GFV'#Po&WnťFWF&a.rSdr)a(~s#`ܜ1 Q|j,5[UF{*6LRzU̦=-1aA*8SvY >wes龟B|TVhӾwws6#v_>8$iO;Q6N?̾iխD. -6\Ɯf 1<bH7J1˹d(cq]XλUegh^ʚ{'?OeP-q~܃E3%i"{¯P4{Ṯm|ٴC}|RT9i]VJ?i_/tmQyY*h=i9*G_+fto!gGk\{ۧthbfG2cIG<71yY/=߾IaM2 ˩ g٫j|XE.~sjzooiXI]F>ǩMa+ hVlo^fKʪlk?EEi7k̊?(=(Ψrbb3Z3B,@^fR%ضːۮC}? EEG`W&b0h?:EdTJ|/о#3*Hܔ(M}<+E<[_.nrLSP팱0SG'c(=(QxvM~ 4"FNCnTvyߛ2(qqk?`>I#2F]P-mWޏB֏JH4cM@_1x{m-*T< rgjc Rix2و,%Ë-ZI<+[V6ރdwFew_O`o{q>fhV.%l[Gjy.a[TQp/ Qz 1/_8tX]#ٟfK?XTVퟨ[+:NFArvYy}?}!کs>PTɸQj}gXvol ?$~{($FXiTXcl> Q%]Ӆؿ퐥^y1nݾ[{ֆ^*RYQ;gF3;g~D&]\f$vqWV:F`̙WL].Ѕ;0"(]փGs:)\i!`=I_uٯLޝ!6wH,KֺukJ9jI]ʧ"zN?)__*MYn:gOH G髨[Q~vF1R J4xb}oˆE) qNJ!X1ͪCt"GyT,L1&/WH,g L|Q "[ \eG3f5| }촺LZe1&f- *qy890X^il kҵR΋Q!><[w-G5lsP\lKo9 7Iy@})LHvg͑=+#1_l/+ }nZб1#֩UCg(@Mق;0O3\3Wv &YA =]ٶ G?j27)#F%ce:^;pkL_b(Mcg@lZ&~36٫"\Ka秩 >7Dٚz j=s0*7_P7М[ǏbpI>tw|EyCfNe\v_oU G;͝ 2?h}FEƨ@jx/5.kyNJ1:S.}uĝ NO_;tiƍ>N23EgIE.WB>rKg|Q~II&0-[d ҖevwfuJ0hõqڬ"=)t;H_n~dqa.gTWOٲ҄dg*^ꓳs~pYh$1vlcds^!>/ yb$y^O!>345xPPBQt͟aG,[$(~z}k6tMR*TUqӖ|یDZjcrwޚTsapM~wHfԡKf3fټvWO>(Sg(mpK7?Zo>a#DRIB-\/9ԛ crhTNn;5,^0c A :YX%ysv=H2m޻:a5ǭ[k@ffb5mx?1IG6+J\Y#)Gۥ 7 ,Gٯqzė5"{560 r @Ɵ5䦕RnUc.EJ 'ꞣB|n+y #P2nbWYS?xh"ߑ|̈́:{ NJ~W}I8W-GhX~N^_Pge2cu[) poZkYwj5jXN'm-xycqye7`ªşjH?%&NJ.W#m8my3ޟj7NF[^?5?MU Y9`G).n>֡ @&Pb+}UiE]7u.j)<l?=xm73`2kPRO 8fRո8* @ pR.a*6NI{ v \~S2 P{WC\V'*­o~Fiqi,BZGnx%uGجRsU`wdH;[>!#n0f%VT0|Lb9 "1j(=P ѱkhhi4qK{2Maڠ6F_ d.Ϸ2 |m?;MAƎf*}+⊍'R9'dMi˖;MNJ.6IJZ>6s.̡TlH;]+ T4G"}>S'}tlp%X A"@<Vjq`_8D<&O 9G\r+<ğu P XͅU1M꺄h 4ׄ_O5/FܸWSGiKu g&[+?lOY?=|Mވ_>~tCI R:}~Wth @< {G@;&{ҠB8<Cj LAZェ^6Ds痂ҳ2EMn9s2ABblvƻn ¶KOfǕA=}gRˈMPQבaBJ䒘ԏ+_3dqEjItg*ןN/jeż\U&^[q \Q著W(؛[*-Y5ң1>CW2(=f(g3cMMl(s2k=՜{~feW0K2Ũ<N #0A1@x ͔3x?C$0#0Z7x-k־D+# (qs'E@XOr.^hx2X 6/fy1)BrgzzE̤0ҧwσ& vb {&u$z_u3֬C.R?e¯+'[{gYGo/*%cp1hؐ{.a&;HT}񞸹t|q+*7"$H1?>M q^.h2٧}wW'GnJm8evv, γ򟾔ew3]OuPԽ]z.-=h5VḩhD'#Po&WnťFMHA؅y+A P3nT+yU"H'9?taݢܵ úaΉÑiYy~g0\*S:]*A#:y2 y8EO"d}aIh#EW7k_ێ ίk{E ~ýj2ӷBe[nNԣO&ƸDb^[wJficNFPDYǘC1O@Ce[9z쨴O?p\cy2n^Kb4rBNpoρ]x2J9FOqE DL;P%@O8qϏ16JU䊓q%)fbN1GdЛ[Y%fa)rSڴ;!ȸn/tHIb?9T<Ŵ>Bb&NGaa0*fv֧"ĘP6AYo J.g )g8啁~~>: IQg&U(1j&P4CR.w)B'vQ㊪4etv!=tnYd$cup1l2VPVBg&N I=r>2LrufwhuA /#)URAUE1$|ߏ&xQiյș~|MF٩ČAccg$R1~5}hcě{qܹ%! unC @”H~8lcl $ +&abݢ-SӖaXNvLmlZix2وt]L[i F)*I<[VădeFew_O`okRci.ğȮ A.g 9R'72+E{jynqeFt-7h(ob1q6Ӹ(,g݉2j`xq́DM0*?[O99 C FB0_5Uq,}2 -O{cdQ7$C%4% LkL=zLS,L<0 [t+/ƭۗQҝ{šObEAJպdנJSV,.ORHC u  w<Zqx E' ,J1R J4xb}ſU(@qNJ!X1ͪCt"GyԻ#\d/c—w$3&hjlnc7R -aϴmK(p!2iŷ]?w JIV!5f`|TIvޕLabZwLެ#OxБTɔFgE&xx=4ȍqRдsFutAzޓ0*flWh/_Kҧm` PD'5G$ƌ}&y_.6\ g Us ,)Ȼ[V "zM4޴c6g͇ӍB{ˆjc2+K%*lSAZi6ʣ5@ PD8G:xxtݷYOEqP2Tĸiұc$/ٸ\@]Md|B 6E_g_gm+ b@['mLM,is67_P7Μ[Ǐ*M5筘ۺf#!#^ai sR'a~\Ҽ7G!Bʀp(ȸ9.ܸ+KǮ!]\ޮg_ڻZ[9RQ|l즓 wi" 6C+*("({MTH!}7@;wM&{ș;?wfϞMrG @ И@>֘ ?:t n7BRy=%޽8+뽧צ5BwMđ&uoN~PiyzU>MU…@ Ppyd\T$I@h>{,c^@zEdWk|Bմީ[Qn1\ GW(.a2g.o┃ @UN @%pnj^ϙ3SN5cX@(pP¥aMCnoc,ڢ<.B nc_H8~Th\lFE0 h koO$;\~U۔o dݡC?H|\U+d2D(ۑblD9ɟ+STҦӻS|NY+zRz|N>l-<4S=cr īwK4) dOu;*Dtjo$Ak]@hDz NNY,?+_0EAѵL$_ ? F]*7;Hc .׿N&boζ<mi}6/P}6oDk IDATbkP^$"LiO߻th"#+vz  \^Bt_x"\s~K} BOQl޺ڄ, f2Pa9n? 1vԖݯdqґk]7àaX6g{KŒhOM |wxq-xyS撵OPw57Jj?}&ĹnmTj岎Rr۰ۇFރ@@}c~wDH B }݆5ܑl3].$` @>!=qʸqRª~pƯOL5$JQ/{ަbR<|o4EQ(@ܥ4ǦWO-WLOF+1B'4؜0'mC5r能A|RçT=/X$7_2VEbqJ`I9F0^nm-:K٬b*$D)i( N1 5͔Xk 6neÄf-b[ߩfsvEerDLsvpc*2}D-q Nn3xɎWC9r’W(s @ <%C>8ZQneV]>pe!Nh/( 7)[_S~5.ܚgEh=H Nˏ@ P|SYG/ȔkC<@lJOm8U̖{2GSL{dOfZJ,nnygM&zexb3Sk4k&~yqX+P:H:ˌ?LP<:H@ˬ+ք6\7m!}<㝤8Pla˕oJbN+~e8-%1Q8.RaQ RϢQͪ_l}xH~jIJhvTTt k8h*5:BRO ΛRt-ڷLlߴG`. nl-ڳZRh ,2ƫκx"oK"_[Ua/U(}V_$5^'Jc>8/7| /1#fOQB,V]m1?%F(SMoZn:44zPҤضc+SʯIS4w۠vo/H;_(U@ ꕀo7kގuȊ~H1^ս͊mіr3&ʫ҄l5efRl=.3gk#ŜaZ ٯ8u:&}#f܊fބa4Ns92ٝUd먏J;'YS' KZZv=c!*qsWLbuݑ[iBhvq:|M{=}kR쬈i9̈́9?&4 &{.FrqjU]bęGK]=!J쭙v= MGe'Z܅j'. P|=q^.5| g< q^q;eKS+qٳİ`:ܡ;Aj*"_E`Sag=@ PUȐ^C>Эe}Dq,,-1З'SZ;pH/,MAE^3W͋xl +=fzf l:ۛI.4%Oˌ9r*A nl7'H\a7Lw IkѨg/%7_4sBٸPKv|1L [S-HAh",D-#u9ʲ^&{rtkk[k&^³nY*o$eIzA}$ %' M~źDyѧɌ=zC+%4!ȧNj6`flכ8Z9Lt(An |#C,5arkV`D[e/3I2}=櫮zЖ;綫Bh @^TqeJFu~CRB=HHx5L.ʅ.ߚ 8g4yxfGlW |(xD/\.oA_RfamLdO1IMI㛬w4m-CV93/YJ*na?OE!8{Zq)B"sWDSoNVEA-I^FHd'rX/ܦ6;)M|"C9̈́]>n _a͈iTu%ZK`ɝJ7(OcNz#]$N}A̮>6kQV"%;zugA޼R Ej7*~ԇ-C*6/ +t0΁>O5o_M}zA˙kϒVb BJtP,>!0K8m##?r 4t|c%5c~;;UU~|է%ͱũmZXSX @ PxBq&s&N]fs̠ ;hߧ"oٜo,E^uoJS wa%|He[H>U7NQ3ݜO 9#6%ۇAS)j{S}&?RoqkrsYۉ-A nw*M95N|>̙3zl)㼠uՁ#u> >h#Q/ޠ y?[̏fY2|.x N3Y/s$~W)}Ė%L1 kHkf$D/.d!ą'/́@@]c%e̙FSɳXgz̄n[@@̃4@En*n6:^e>3$2v+aTUXiNy;U|>< Bx#0@Y/;e_ކbg9~ P.2VX0`GP:lQ{ c@/J3_W@@ n"9]廪4z@@ P727 E @ @4rPqk@A`ߜpl޹#^tv cg?{J 9Cd}bڃ!0=*$HuvSrX7k.&lƔra.`SیM)=+-Upr#jk系-t#8+07LΉ Kɼ+˾x9CY/ or4^@!b*n!^19.$BH;R(nuY ƢM07?ߧ Kaw5V+n/gʆt?<*#{JO[u@4,PqkXk@ `'`K~jA2zǭ/,$Mz7ާlu[d'=ꪅmwL%F"CL BtaJx9;!$JT @ lgki M5;e%v/sbh2ƚm~ʾmi:-X7ׅr8]ҹW]֨M"+!hnZ+&?w>4&HF*;߈6ٗ/ز Z ムV\hD XzT\Z%&**00Ņ'ر*^"hƎOYVv#I\˯ㄐI;IͅƷTb_M۾q7I:Jus9>QPPܸQ2 A 1Q2qBs+W竇1-7O$, 2$ w:a NnRL($ ڳbzO[fR'r|y,⫧Ņ[dZa}\8/]h`-xx}*fof N] m:'YXtYG_cp+n$ˉ$P wB /ྸ ;w U6Nc-nَݦQцl\I#8ok=U.z1 CcȋnC7_TǏ]Ӿzċ bale]y۩F0{EOR*{y/'BKIDscZe h9jqQL^U<ą߄e ł :`<> Sar̹#d! Sx~ 3(@.j<'@ h<lAҖ^yP֧^E8lrOy"[Bh)LfoZ08QZMUuGk?+bIa30/H̥Fnq7Z}Uɢw>>cqq: YQѶgӉÞ~u⟳⃽*E&H4w};FڡsY^6 7HwojwqGk|1R|}AXj;ayd4~ 5/ҧZ @ Ax켷qmf<\_c0avΝ.8m5HSU>.ڄ*ӹQajSUokV[>Edmd@I stm%G"sܐ@ gr6׳{QuO\!1e.F&||P'4Ns6:-7~(56qk)uM*nuM@ L-r[JR3Uێk6Mo{K7mxq%m(6.Ր4 Ҟ.hx03| '=/XUZw @"PkXUJ@  x^U *v: @ @F*n -b`/@ oN8~6F iQ&\~0{lۇ]nٝ槬.`_M%xֆٵwd޾˘wW~SB8^^'; @FNHA7@ @]rO@y]F險Յ'CW'_`v-/BA}؉Z7o.+Ib/̭;o';wZFԸr(k=ׂC?.QMQ=uaKwEp= K\NDCwjx77SSFEgNr@ 8509yWC#8'ز !j?\TU9]J%.ұLy'hux G.o w)EsX-JD2o¨” ň7k:FZxg~6&u2PJ<4&ᅦ53b^j!ul @?8@4Xda޼;}SN\X˕&41n@cdchyj״&nɞcٙibZ2߀!cg?{J 9Cd}bU<۠GI3k8uyZ꥘vQҴE+NT~qzi='f~sS!R`TVCj=;M+FhEM6}$!5jYF;#L١tG5yk ¦E[:V-bJ,Ԛcޱ8qRSCGhF mY[9+^ V ȂkOn=v!Mvo{4x pxK*nޒv@ *s2&UC]tRrNQC:4n5]| ZVx#j?4Y93l☄ceg?v'*fmo,ۖLxyi7Uڏ""0/,a\} }=FuA ăꮡbɦM#[Id5yc;M3/gRdfORT#&5-c;oa'd☽4T1ndǓt IDATnκM9mDw%u6[ndtM:^WNY^v4yv4)/^PB@ w #@]ٗtũ,qĶj%FD6|u=`'wz{agԉkƼ(97~tƑT(ùTӳ~Kҗ.V!%$f)%_s\"#YA)&fOB̹( ]Zf*'C]ڲ=ˌg- %/_|ƾ %v /۞1mΊEcI4ሻ VJ[fR`*ޢ:}ۖ^Y.'y%C<3خL{ tf)5)]YjeZ_`aىJR\1yI1tpzB3⊹ShR_\+zzt#CXh"MiּL(}GB+ASws<5wb'|@ ~/p|q^ M@ hGE:|JSNet9fvQmV$N\lf nʲ@iD ʫK\UzرC!5٘ZR҅#Pu%HqWvlv/fS4mNscI_Wqkx sSw.,xL1LgV3bg#v9RFwkwfdr%v/wRqSr|cE{zj< MYKerYŦM9i'1FSq`ĔXj1 6,\¤}v}O9&S.O\e|q.:wq`+o60fCʰRas.wf?@\}4H855< n|[z @U|KǍu3W&n6><߆eK7ZrfWu%YwᦳKޱݯgz5;RV{y=1- #(c31 >d{9^l)/H ?kfŝ{\ 6.6;)TIt @ @˅&Z vǕ2-^;;PܿzZҍ_70~i/oKE{ʦ?TKi.7Csr/f1E7 pY FI*~ sX8LКjE-aM*m%t)-NjA,aB0z+ʹk A7 D @n Aq}c$1ifOX‚Vn~K^mC`謴+ Z%7;̊ p)eeg( @4xiL @DGEKE>&%M_xtP3);Mwx/ѷA݉cI͂t[IF GAmyk35?5pYV]f'}#'783A%Iw @Txw9Y}W)wsv B @ yxW)*,\@ @ 8@ōJ# O&4؅` L-Ε+rS] H*M9~65 18 Bu&@@@7Y'[y~Eϙ0A琣Zv1JְBҏjWQ?>u͏zPr9)߸;zr<8 p[thw~$ w^PQ=G](9G! " @C$ [C 6 qy;7$2g Ov `߻/O@ɽw*xN$ @ /TޅwjC](C>=+h 2StHuf= ̬-٤=4EiO(y[j]t`B5Sяm[窉m^/emkuPr>3ԅAD)-@Hw#*BbW PyJzpF](9!C  Kn%X 3g\N[VdPt}F#LsjωW=S. qOcW߹KeCk쮎CVtjДȄ=e.13Hg {vɲPrH׌AED\b  *B=8ʩC{ L2w7C> b @C" Uvł(pE{n <(a3R8߷+>:_gY\r2ߒOk#:=YaaTu~vmɻIM}frw%.Y$(1B";ǻ;z@+˺ o).n e% w<:oç.02QF/~[B @#|)cs͇!L pr͚oS^#h."ElpiIfZZNFvQnc*<DwMwX 3sZƵۤira9(4sGcgm£:" ?9Ot>~H)gR#*nQ? M RDwvظ]0|NyCg@J@7q ݙ^[@w.KEkt>/w:`ZBgU.޵*zpQXb!{ : eΝr@%CN9_XWI_O]d;Lֵ =pn"^Zf`" :_ ~A>Xde< sYA>Q C@C@72uNāRhV3g|v×!1:Gi&Ngޝs26P^_sU-Sv ~9mTG' =awMڏ4 @8 uN Rs̻  U"_@ZΕwj?c @!W BwĮHoʞH ^u_59E j.-nyeA|CL%B7+OFuaWu|r} & =ޡ @xC1o(s@͝wpiX #uGrӇzB,4nY(yc(r ^mKڌߎl[uPr_uaB  .^B](y;G](/ \ &I@PY5ԥsYD_\>f #Tޅ1E@ jX,aEӻg6&*K=u!0v1\rJ`~ wqRV,8ؾ};/u:_ ~^Pm bԊ?*B=Z'@0 =}# //u̫=4@ pcF/Nsᔣz@^ɇem'N @!U;h  @ @Tji+?IE> R w3=krǏvV4k?8n·Y:Qp ԽT|=&{nokhG5h@JSi[=&"uy/{@*jH= U#.wx|{Vl]ޏ^n/҃?g ?# xOoN`=35"x^nB+zA=7;_i CnNӿT>0a0E .ȦlxB0kf<憶=QMuEˏZ??=(k.'%GV![,.n=KhZ7zi=/Iɴ~4A{+䖽[~6&@!qˍo{߬U/=&7kPǏ7<"gP& ZM+{)C1VRgSO#kSz[NQ&\)=_~oKh_i ,?~ϰp;Ǯ~3W}jҊ'4ukYt 2YND,ER7gS4%"V"l:-'(sY֣j5 Ҟ{BۓTɁ~Ka0I7y|R0~g) &-?q,=V.PQrvWԈcOKgK"}=럢t5o q>o?rn=)^n=W9G>qGG=OP*uv@%l6d\pkO{]|̿XE` 52}=<%wϙTDGdA7\{tI='&=|ZKC闡Ү|C}k"F$ ZJ3u韊ث≞]{h ]rXWj}Êq,¸'vi!P(9[o~@-z>-~jV~Lg?.-xUrK=*–pk{H67[v,4V~մ/ԙ2Iebma*to (9;2x#A62WK(PRvVa>W7d(ddΘ4s"Jwh;IDy%F3׏VPߐV6 ZeZ"+vFᴇ(%(vdqHt &:`gzov|mzf8IOgt {mwe s_T{KGR0щ%wnXa~lXԦ2CPrN:'pE=9"y MX\$n3ǖh F(wu6ڶXm䏼81y߸\c >y3&ْ{_\ҙ/I!D8qǚMnϭ.T8s_+]jr#h<Ϡƕ&ɇ~i}7t)"K^͓_H>|3 7ݸ!itq4 ٜ`SM!o$zJ:/C֌at)~7U/[_ܬpj׍"VNQ4I4~U=wm_~Wjjzc*bb-c(-X>ilў(JbOczoUe6ǜ  r eXb{k^[-WďШ~3Vek9Cbcy~C~}?>#-Bps@Hp^% }7B_q~kjW.W!sSm/'hh3H\]ZY_ 0]`5 i{HIb8'H52"̨a"uefo~B%{rxsC@Rŭk= n'k%P{#.;P;{?~`xyソ~1hypeWr$Qㅲ]gm$/A'V:vtlcOm@cՠxysٕ4#=ƌC^=6r駞.vm71òQi^d*Ҧ~w۳/|yթhR;oy_x[PVyۉǗq {J Gpgqc]EJҖuEX"9>P1ᴁ:Uk|PvJċ12vo9ðjjk9ꪘ8d+\P?iϢ8p&gW> Ӟ~R`Z6)d~rEO"MᴯRr[3&hǶ٧xQqp76+} ~g?RԭԜgsգ5lΊo+4xfTJW.Cɑs؏lsܢwAaB#Q_QtCRlW͂~<=̭ ejrrSDQ&S [Ճ?/,;9Z=easr /~T{TܫN7suRTI:`_G~OZ|w/ uTf ٞg>x c@~[woQnc9P(xa2и>HSjhGOT c6|=VP=/K]U #)]g3z9lJSNetsase^3xƞ vypem'j]co@$-䷂_Κf[ɑ_U*H'(i'n¾e#:ZR"~:E IPn NǛGO wA!@4R6[@o!ӪRfC:(JJ0Zj!D(eb QZ%5o Р ȸhp ) p[stҗUo6N@ L`(%g|W'H @_{Vk @ @>nM5;k Dة˗=lu}qmѫQ޸[\v폐zbݥ^Wy'ێPy&+c& MKFfb/2lz?;Zc޴;eH5,/4@~ oN8~6$W@N.kTs(xLnvx݊=]{w[JF[xw)]kYxUÛ蕷=V _,b[54g%梹_|kz+ ^r#Wmo?=sc0a{ZsC吢MOGE9 @ @ˊSgVN6MIBK]oN ՜leP&d7ٸd' PKoPxd3=J Gʺtt5@ @ ꐀOKDo&yW}wα*\0~VƩmm&ȔRۖ\t )~f׽_AsZ꥘vQҴE+N0+oB.cR~<й\ar;S4'듕Ƕ(=ö_1tzwpǾL+j_q謗S|b79Vq: Ֆ(b+\~ũKtGΓ4# EɓߔЪ:Te7ґ;/- R%(eA'13}D 6hc .M5VY"b*^!EŅ/2cHk٤%k|x8Pe=qc~ u֑yzTLmTgi?)yDc)>m e2ȁ@ @Zf.Xz0*wMnyE W̌\Bd_Vv>n}r1lƲmɔꁗGv|S%/깿y>QɒϹa$ U wx~ܳaǿreɢB{ED*ab!g^hV_̟H}w0F_q9$.?:Fqnu纺WJIgpBхF.|vUݨf]qiTV+חy.R T\zۨO+;ϚTcfɫ0_%aMqe0oיBM*4AZ"}G+Tb$;t)V.J/8 @ @!yU)y$#~ 7ٗ/زK:-FmֽQq$Ӯf8j op,yiFNk^z~sZ4`,2^,$VY Kҗ^Ymł).,>7grdh,-޼JEPf?i3_q衭Ŷ`8AYJ ڗdxY6rZCfmv yCT"lrxyķ*K[fL|sY)!mYwÓ ;.ܡobY7_G r @  sh}y-d2IBd g.7w XQ!;LQ# .hC-)@4XCɓJYcU& w8/xs~ I+nDHT+kRi5WOR8Pqݞ0iD zm߬^yɉo{$]J!"1+KK$ik6??v%^rЛ$"1k TuʅMXK[wi~68Xe=Ι*>MĔ* ud{D82r}[˽ woju_\ԶZqKmИԾՋs*%)t <=t9ýff䀥\¶k!5OSGFpiC_(嵳rl;ˢg*5ni2]bִ(5%?>b̌^K/zrOBMň1c:tix sSwUl߽wXo1V@Wx;eCX3@@ kǒ 0 ! @4`޼  @ @:&:5h;1޺ľow6l;zcC^Eǯxwÿ&HŸ'nZ27;vp[Ρ}c~ثwb/Ƽi:ܹ~T8gsL{M @wY'I1L/kn[j/~zzog_j>(%c0~}Bu@zaQjt̍%je{#Ɔb0/cKt=;>   @ !We`l&3 -#C>aZڨwpM}a/EۺG:Pu=ZH.jqUkEBq8@E6ȸ@ܑ_>Ƿ=\ȟ'r tP@ @P@''BtILK, nL. O]O1eI78AXl"ÄU;lvxed4q4nLJɗR~G.~cܿŬ'M&r2ɥ˺,䫗 /GծIUP @ 0AWĸI:y۔V}ڷ!z-!iLΠ^Ҍ2q('Nk$T%ōrx\6L+!]d@qz\c^H ,LEi885kgnf;Y~ա-UҵO۬L#3'=IU܌Hj(ji}_JQONM}ioJzB/ԴŴ^QmWהC{[OzENoe]7mA 2khZ?9!?9url <|WekԹL,18&ҜugMiy]0L+`Hxi7" @ *Pg$7NUӟe _ :YvVUchh26z2ۘH7goc2gjS"aզt H,b ~Dй3liL_xc09X|{\.˿ʧ|u)+cp2ŘnIVv΅x uخ4=@1~U;{jζeX^۠)r3'JW>La}^v-)^T[E\UzvtWZ锋?Գ/f+8)ƢF֌vݡ ZJG`li[{/,./|x`Qz,&iʗ^wEMM;2ӍMA'(G2M;#^}d 0xPi~_qHpz% HdDmgwuuը)K6Ө1( @ꠀⅱ/bɎKwHJ٦M;.JC`>L+?61Mx841b\pG1{y<&d"-sG7Ĉde~]{Ϭ<&C*OZ((~CYV;+5WR&C3ǩM+wT~؇i8'29xZJ&*HI{.&6mDuM*aJZ̎@ @F@?kMё% 2f^]T۵lՓ]!6?y+%_TH&<ޘO7bedeܽzpO` Yri~tȿA%USGQ&+['ԙarXyMQ*SaaO*ZTQD|У#r'Zͮ|*H,1NW @ @v `ƭv\&W>jm% S}]W&$bȋCQp39.h?Yt%>{z(˔DC1z2[J]~·ݴgzU,%?9Oݮ2{ȧZfNgT8o[0pʧxDϮ(Hcl[F.#?讃˼Eڢ{NӪU!@ @@q!&B%7 o4, 2& WT87Yt\x{.bs~HR?f>D}7՟c GBo M@Y@ @yƭ kiT#>=nU^ SN4 vA5DoekTv5h& @{<) @@7*iRM5Rl @Z =5>T.@@ @ |4[Bu7A!!"cb|Ggɻ͇=>Mmz{30ȼ.]TdA!A+:lW婛(?h?e(zs^JUVR*j'^ܲ 5SwZ@ P,PfP~kZ5ΗQb @:ONa7JDj C(@ i /5nL&<τDDd-i7˸"bbb\9SS3ؖ0sbf7ob9+088qO Q!}#.t?k|QkZ^lC˜_ioM_2 3g<}vMJ IDATR}* ,#a^}qpͺu3.^ukn |/;w[!^YYL3wCc_GxQ@@>B>Vt S̓  Ռ";i/?a!_C7=~6-ۏKU.ԠzΪɂ:hѦ)EQj<^U` @ S:!+:_A)@f>ccb"wI(t^/䭘~aYaבm \&s͝5җ ƒ#2(щ o㲳^L*Z0ޭyԽe1$0898۬sn*%r&Qbv$Yr$2qk7 L޲qΏ3o}ڄ=GoG@j{Lv"]Z<ֶ+e9OTd15/h @@ǔFNJckP !*RQ=#yfBFԌ\U6aOvW oLDIwW~[A9vo/~vk=fRG*Jîkgn yW8%gd  YL\3=p;G ZgiUGsJ'MU6M-|bn)$-AhE!@PWR X|LA>63n,(p$e(r稑GT\ލAN/Y#i>L=~o[1+dM4-V BD~Z.)e Yu4Z.dq(3y1mEq̽%,l RK x㥮?A1#+y4- m&~I/9 И\(iwB7}e"`܅ZsLCڛOc {w$ϡߠLyL$_(¢d<-]E/AY^ D[ّc~Fz(̻ _61hճ}sbi"/!Qbݩzs*:G̱nm Z4g/w?5*dۏbg=$/*_Eқ>xU, @PD@>Ve7 @fƍ|y+sۿ΍-^H7mw?GDG?ydIG޻6 t\y="&:pYwS AGn?ӽ O*jNyC-hU(3yv bHml7O쑗\_J.M ,]|o}3}n}P๐#3U_fl[diDAۺ[=g&q3Nj7($qLu=$eX@1#C>V7 Pvvvڷ Ѭs~}vw&UJơ h*Yxoܶm5򮮮B/|Z@б@zjjX2tDNktB @ @@PjUY~Ӈ7*R}'Uţ @>S֚x|! ,Uyt7@@ҲªҲ" To*A @ .ǭv'z@@ ‡׌ޠ @ Ԟ7A!A+:;š+?ذKT͞UoQ!@WXyǪZ{ @gƭzx @ @u]@gr:w~t̥Fc? /o:yo1dSrHb۲Mf//Hri%g4۩Ee^+H&M<6c(^Eg5k+=x7h\gƍc\O8./R֪mI,nnm_~m`gN2յM,iƳv+*14ǎMAnN c#|{!@bfmb49o"/77L$'{Z)b跞j`ψ6mڙ+SuZuy3U 7pq/:`0[G/h/'.}m8?!E16N CWou$'Q+b[YܶԴm y:hh".="2LEb\3BWϮXC]Yz '|dLUEj9Aj֫Jg "]Z*nVs3aR$މ,:64`2kԬ\Qxv*>8Tщ o㲳^L*dsּsi^F> N&-JXrLvYF\r8o`!!f?bh_#9Vf|y~ˇlWV @JWe^|V @z T4DzinjrZM-|bQ6ph 8&>QDl:mgW-oy4vZ5-ϐRDFJd,AEdx Ii1S9>l!pSnָXyjIH ~T@@@>F?F} *7rgakX-a<8K.]|>nOQ4%~1mX\m8'AǴMM4-O(9EWq $RӨ _ɂF T3nl1]lVgvE3|#v擨DrM$ۼ˸!i5 ȔǔK"/^Et<-뤊Q^'nlg]X̜֟kO_3\fN\.v,_u.kݲW{+#.SNrB$Q^6l @. uc> @@ hT?g֬=n7Lm!odoQtA44ũW.u{XWo'Jߚ*^uSWEjښ!Mmc_g*1YĶ[C6oa$k;?t>lSGtUkZ^ݸյմ7u;ʼn?c*0۩0InkMoOuk?qOM4-3Nm򹣩uHuRXvM?hZcayl\r7b&ݖx?)ղniZ^umn烦Ѵ"oPjתQ*RJ?lQ 8fNfdF @@5I?0^@>ӡZ Ȳ -D чBbqcی+0Ɓ6}_5~)۪Ԉ`5 ߺk5loυ n۲ׂ}Wâb#yQ|FM,G{͹y;6>{CG]~((2:hH;e"-n>79eaWØXӲx--b#c8x+8+: ,vן*\*o:yPr9n _q- 4l=[G80O*5J0,w%4*&&_ {{+L+41uى5lPzU)ESM 4+LSߴr Щ_V}zw56.'+{S/˼ൿo}MԹv6{?ظ؜asV_޶zy7 e2uUGM|/ct')1:샀.ƍHz.3oVvNDaCLoF̆wXy<Ӱ o>ʔQo=gd= lڴ3WDkbo/jsg#?[G/h/'.}m8?!E16N CnDukmLi ':es9sd)ԯ.qWwu8bؤel&;T' ǓԩQK&=dɠT`3\\˼LTšj6xQPSWPa0ŧG5ܓx_SK{ Nu'*W{8'nدyI\:XutvnaG淙{{ }j} {7Ǵ8GKk{z+5kid۬zNo"h>d㌙&WsZX޲hİ;{_I W_._T䣥n! DY&e*U,3My]MJ9w@9LG%|7Kj'S¼.Rqimyer1y"uC>F˃Ёd:^i ;<#$){D#=at`UזG;hn2kԬ\A=%y&:.;;ΤI0n͛=FA^F"!}SmXwsnmiRt^/䭘~aYaבm h1G:-IR8ʢcÒ=?1c;tyϨӷVn'K3".}-cP'ʘ~g !閭^G PUl'U鷗_XZs>_S}PHQs~Ct5otM8_;,&2yGLUN`W5RE۴| ]zYcu6o<7乛)"JO~4jܵwHrHv,/kd!ifff_? ^;›;=K ^zuH`,3ri={c =*&!Oiګ7ɹSsR,]u4Z6_/,|Mu>CS+ vA@M?a=fVbr&M&|*16f셨scی';b ,>w9u.Ϯz-[_Q9!%AHd, ѩkWG#Qhg1r뒴طor5s4cN .㨪hG+ь vA@qS3ȉw#)r;k0rePߒC0D/"}^۶/z$^D$o1ǃgom+38Q ?#YLhZ^%7ƄP\5m`(NK7U!x)9jQŃ]߽XVmBCcڬmמݸ囇LHGVbȚ(^P\XǧqU=YVi*7TFPnTHܥiyh핥>x{1ֻn&u;,:c1m Yc3ctx%<1?zFlal>W"Eo4BqJ^,2 cr jJ/]+Eݯﺽɵn3bq9S ܌=YC>V! @2_UJd<-ݩ^d<#taYC X\SJ 99s$0vM#3cνTOtCA=rIP$# y[Z{y;eyVO O''FMs Z Kr8$asjma2 jof0&F'QBmeܐn-'zm-ڡ3JWA|(E.KQb lc"FqGڣIdtkEުeah_K9D5^ԁkW3lٞkUK?.QT1BlӴVGS$Gig2Xmg$ȳDuй>mޢץWm:d"#;J\Fy)1`OLu5R)!Kyx#⫙L6M:u"O~q,ހÔ"1!W4m[ >|-ONc2j kW^ IDAT\A!"qƆW,$>/In]TSYxtAGn?ӽ O*=9R |v\T&T A@7L;;;|p2^a= 9db0^\%vmݭ>)Mv-Q$2B۶Ssuuը43=PgLtї/_҆Sן6vSAC7c1( ƾ%CSE"W׸ P˸7ӛ=;|:mk @н1ݛ""Jt >Q3y{ߡ[ekW_qٿ2i aVŸGӽTLY>8%p yjS֚ӷxW_6$Kq&&c&5sSIk1 VjM!@ūJUeE3 @XUZ @ @]ZǍG'G`u-\{3By'aue6 lx+o_rW`ppna 9w]#8*kxyi6j$2pg<}NѨͤ}9v=Kz{9lMV9kȖe< /xۘ.Nutˊ7rZѣyÆ2gOq!7rl3 n{ޞ}Ɔ]x_^I1Y?n|o;f?j},Os3q]NJU{FtII<:zA}?usl֧Q/:ɷtqbJT#9?cȎ Bہ߬yijµԗy}l^;~$k~;f⑯CgqILtv~1s.ƊK[vq N%JTF @*  P h}xbF)6AIS9}??Mm[}!oD lkH/9יlLrW\ƶ8rT5wjJ_.L PTNNNMxBhdgRc~{ǞKSDބ.^\ e4ۤԵ{yOyM6]^KM ns98hMw70K_ O1u/ʍmH{o6(S>@ Ge|B7 @M3QƗf%e)$ɹ܎|#Gy9$-mujdvW~ߘ0䑓}γAqЄg3GsTl|2哯p#g"]qs}^7k ?RL $2GQxIs3snҼ<'&\&1e̔ YL\3=pv-?=s+K^)4/E:W4:* @2c" GA 3n659y5m`(NKᒽ7%x)9jѤ.=cY Zy\o\ e/v7%y1m֍knI^O z%~1ǃgom+3VRt\tVnДyb.G`)ffIJ]'ύΑ߾W2zΟUrӗllim6zۂ C>_P%@@M@>" GA ֫Jv-%OHY+0~Q9L&ءAM &Ĉ$*Q(cͻb-CN "O[ݵCg*oPF<\/Ɉ|dN3nҪtlʦ;(뵚V~|rB.?3 $zYoy\kbf29zonb̜7Xh]zT.{~N%M} Hc  vp8  q]q($niqI.7,#I~eHIT* ˾ml%=ͨ2h617trW%WӉ|7bhA}QgW,K)t}zY!ŏMPR+qYړfNܒp?;6zN#zuld}3cMS l @ n`i熣 @@igg'48E!@,<Ȉ 7nVOݘF!ią @@驩/bɰҝ*9t @ @@ ܆he땤y{I} eg@ PV|3ȵx=zNsT׮iVjJ`@@͙qŞھ @@m`YZWGUy>*wb3UH`[Pm/_H@4RMP @ @ T7 ݠ>`{b; -@>9!$U+Vzּ§W~!#vC>搠T/nYⅨzu;UO( :}w>6l٣K!MyxxW{tj6"  @nyl\r7%x?)@NӴ(U @@Mq#RC|OTZn"#-@Gw?GVRX%q8 @ h;s?n#,G`[}ҴnYēCN]% YЩ_7<.`^,x IˎCP앿ʱqԋ~yPcƽɲUݯ"xc:9 jfܘ]ݽ}㈹䔎I~=LC7n Z;É8n?ڽ5nW2/vUqn0t364~;WJ圛~9& xX`Ӧ2T$|d3ץϱ :[>Dٯ†26N CWou$L!ӠcZ=`AϚH~y$~qJݔKݿ{Ia~̵qmcSzmBէU ^Vz~\D9#oȟ8T,˾OZHQcV/jΡ;YE9v~Qv@T/YuخͧEw 8cI+w&cZ|u]IJE#݉Ju|r?'-u;yn^ >n2)S8*XmeA?'lͳmoVz<$x&nysG›Qe7vِz^=eKk{7(UX-1c6Ct%}܌:};@/`qy24#G2vyGHReFE7ڕ<;E^$y $ݲu QOa|MLBފvv֐L*;5kh/&Gd4]щ o㲳^L*sּsif:'ɥ 3hٳ?rϡIr9!|T(g0-9߼/Iǚi[t6iƒnDZԋL3;Kmj^ M ns98hV P @㑝'L@VB ][x$ˈk?X(Hf>1nfu>~Vv7w\{.%//ͱWz쌜mZޘG9IȢTy4UZn)i)yzF}|~@J! Xq3.Z\P\mXτVJ&|*16&YAH9Dr&Kqffl ^CyoLDIF bi7?굌\J )P#,ak35X+cvvTZg憌0uZԀ3gܼȀDVllMVf,ˤоEK&$asjma2 joJ'ϡߠLyL$_(BqIni;)뵚V~r n6wھ!ϋRгoc~hYA}_|}FZͽ*Crߊ5il$W2y\kb@chѪgFڝq}^@@=@}䠞V|&ehQ08s}&ۼE19aEr3EF6vtyR!7/%ɜiF|@FW3;[`ӤS_'5/eO[pr@$&d|i񚶓<1J @@7ͳȳWLZo?~@pgTHtzkOyWq =9|ϥCy;vcDۑ=y<c}Ʈ!"#=YE.0t뺛xun|\ăTY>"w4%Kaŗ翍YDel5 ͸rqj O*J|;):T|G&ܮ=XޡKl3Q%ʣۛdoY` +feٱ{V\*~uM7;L[ptTKŜFf-o1]Ld\2_u@跮;~c_j$#"c n=p8F<ƌ$Dz螹K./~Uبly DxG8218UStSϩ'7% '_J/|;5 呏a/ @` ȧ@ PQmْ+^WQcU?~܇jum˗/Z_@H =55E,\SE"GwM5a!@ @ P[UZAOވ_ o;G@\oekU޾W畭DsLLX({8~ @G͸bOmP}- @N ,m+sr(5a˗+S!@@-{3n`@@۶q޺}  TwǭPMiO_nv$nBBD_ѯZ2rx4I @''*{hð 4hp  >܌搠?p)Ӵ=!?ؔ">D?^:W.mҼbѦO+]#K6>8'^Y2RO- eʁa H՟w+G=/X!PQp@P/!C>VD>qߣ검3n 3ðS\gȍ vgFC޹׮WҞyME1w{XVԩQK&=dɠbx笚,3gbMvfLL L  fKcOu>}|QLPU,{u3_d8p$ e'qOXk~1|5Н7>EbsG(_k$Y۾~Eqw9u.Ϯz-#Wf5FNH DFBId,5'L(}۠1ހYJeS~kO9srNxEEpG-?cB-]wm>Q-CVG݄ j""ltDNxդhFe}7 zQI%~z~Lp @>9j P 7~Ӈ7$%NG8-!@`[Z韺TꐏUB P+j( rl)@jKֺtXJt  :j@ @ @ TŌ~olnPA!!"cb|Gէzԧ*PGuԧ@J ! BoГ‡{!@@U̸/nYEu٥KaV\T~ n ZA_W7rG@@74ͯ4-xT/ۏ# @Uq7"5DuGl|>">  z @\kvۢu>0`l RqOE{CG]~((2:hH;eZ^lʬ1G?˸벀'9zq8Gh֥9wڭ^seZ yxgo{eUgA @@T|8#^@@-RYqO\ӱ_^ u0ɑCyO ûϷߧM}sMͼӶ{tXܦVbJzΪɂ:hѦƶw' RR&zHUF7_~vqۢo-nBZG!`1SEJnc6Я|2DL"3e˥܄yօ(@zLf1:@..h{Xsؼ/MUѣt"T%]4SJvvc!yTl{;E4@H_2yoKǞ9E%oI8t$>c.}׌'ޜ3ɡr]EJlƢ48  x 3FxgA.@GURzgtK%'5pCѭ(7Aۻ{iO~tRx[ LimopwG.Jj*W\K3n_0.cy~.gć?wU|r>}v'I)}x(pncъ7" @M7323@IbYF=U]'RCwuwJxӋ3&JdLн 6"A:V^nJdlEtۅ5cigϝ:;)n,C8&6Oo/PZl:U޵3D<~@*gb,r}}=&ON0ȯA|O=6g\\m떼fOx=w"|(>sIYƉB.@  h/?fd {PPhaڨwq4k/B6{\Giz@Tիdqv|ӧ[$EZ]N@ @D@HY=Ǎ%8G Fו  $q8@ ^#NN6бM/z0Eh\<SFʷ۳禄H%oSu% *p-9UK08@ ^3kV @z2Ԭr+Z6A @uЉyKW4V$@cԄQ: McUi- @ @Z@UVi8uC+īP?ݻ}+l%ci^J,nvUn}Cˈe*eyb-T;ڔ_(Ӝ0ȗzѩȸhҋS IllUE-u(mی7hJz'W(|=T@*@c֑Lb%V5{AnEg]~©Jwֺ3V@:J_;6~+ѐۇ5g h-4b(ުr}4[jV|_Kpvq ;Y_¬ssQQ!.mNr6Nٌ Q[?XVZ=3`#~ z|q\-rܛk[ Vk@ `-Ǭ# ncn^`vgw^s)=7@9nDQ IEV|J ;JLeHr2"ÿnםKo)pyV ~?!@ZLڈjao==}ϭKf| " A# mcid/z'MA]Q.M/ [ۗYUrl>`N\RScrt?~" KV儇=4[V۷'zx-$wn}%ȐyC":BE_dR[?ksj/1rc &w܍kUak/E:#UAq$q\}P߰n|>I̪R+8O}VLϠ\V]h,`i S"Ef׵%L<)>LeQTGcÖC1k!p56|x/ȈkжK&sZ8!|2Z,Ǥ UZYϺio…ƀcV 7Y \5N¹+vT/Y@2c}N^M"ym_8$(I`&$!<>,>q`kTpsNYBupvy^2u9R@n6⦣逬kuxpHgr>iڡ -B޿aߐ8>c{+Kujcga4{m-I 3?yOd/Vz9ڔk?F^?G}K(Q"ܼw;~CQ}G7g*QKO7ltUFfB6JJ 4 TBu=֩N>b E1_^%?qћC/P/.Tyz9d\VBKwJE꼼bj ҟZj}xIVVsGYJd}M]S y]yֶ"e'B8 wőp2;-QBFQ!h>m}F"pݐMP~i4/4rU^}$ c֍ǬfZh꿂l53D2}vWȼɊ5 c5ԯ:5@渕Ⱦt1K)s ZVLdc">]Z"ι'(aapcFv^pgNN:DLbwLi[ ri]k65ɿ7J7 ˗EvT8̸x\8CϞo mPҬb\/FMw{o+{c#! yYZ58؁Qg& }?,~zsP"?-nMJ_˫++2 Bc-ŵAy]?џUz5)M;nn4E6#D{6ׁCmG<>Xz4F#d=훟Y5 @3Ydcw:_)h"0mӳ__gP G(ZdЀµPE8Vxw^mC7m"\x!L#S=B'Z0s[F}\QW4:rB-Z5z{=Gۑ&-F 8}ʠD_.n]>OP˓;m[ >L 't#my ӧ[$il µ@mj#st:nP  P lݔ@YHr[m'%@:9DZ1Ƶ&l}xڀX\nYzo{z k OwE;@.@ Ҕc74˘*,܌8@ `@e"n3x0հT-jK6OܘZ$ڶh @#PKރ -,-,\1U]9'c5@] @$`D":$AtH2Ncin-vs<̨4<@6=X7vI- m QqCpVDL2JC|f᮰M|٨~3N%k0޳Zhy1ͅ/B]tpw[Ym7.m:f7n3Ϩyk/x?:6&cx"Lrg*_2?`~hZ pع|_f>x9"aW čbۍ~%s?hxck7% 7.ma J7)ki #A:@i=H̶cuq j$" d|?[U(n={hWO;i-`^-8v7RẅTk0um;37"hږY-m8|cB]LޑV?aྟ)I^cE1$hZlxr%b @PN#Ooyg-vBu/oTve,RB8Nl}/r6a&EHսTqjyva9'#E\*k lViĬ}lZރY=+EW_)Cc@ `Gܘ[f;:55?[H5^-%|8H5eʑ/*; ͐$2g^Bh|~w_: /VZ G/0,ȩn Y;V ngMUѣՠ9kϗ_ D  T{2=SYWyey@xU)s{S0Q4aǢqhഡ̈́,[Ǔ%W2 ED9]6a(Q\Q.Y"h]XόP|jV^ (+N-&C}~_|33E9↝ nhvw&d2ȺI (CZރKϊL*ϳ"aC cLd  '`Uč0pXxx莱6] uzQP#$/zoϝʷ\Z@-Yӏ~9gOҩBӡZÍ%[[Ұ;סԌEcC(Gm8tH%v+V-Yޜҿ/A@U=!O=J+<?ƈ2@\P(4u8N wq 2QZ+sG ݪ[ll˫%B'zjgy#ӵ#>?Oug{bǎ2'/|vm ee|\\0_=Y4f^D'١Ж"i's9a@0/'H2S]=}븹fч|2/HV_Ǖe0* @ P ?X|0(X֭*%/ٚWuDucCCzq\OI̫_?\ nmt}F-cV2E CwL3k;g>3>kp[b\퓇;1zf\]:3k`pgxSz>6Go!&n\ߥsmG.U-{cK#vT5Rӥ,W."SlgQ'g%o`gn;7b͜]AsvQ7<:wF}p@3K8N]>ÕKNh4YG]1~EE-Y9~}J rMmIoi睺;!3/S?2 -vdwAϗԲeQ+LN_븲BF! .+3"bJ >l2 u7Ʀ491Ҽ$4%0O8z\oR" xqtq ITeʑ/*;z$23rfXJ(&-f9lL&y*jQMN}2֮Mbj.Z 52-BeU ĎlULIX6Iϓ*l~SzkR.ƶwATSԏәE2k K&_}߽~C6'[1$4݈|ںLvQmmcǨi@ PwxU)3)}x(pnc ̏8@4pfB-Ɂ +espi\"jI5g<{ .::ls~cP_ѭ(7mq.*(m}[T m??f!Ҁ@.* w8_.A,@6] W9?10E֓uPݱx/g5Z%9B[lq tv|?qiHPL6I{v`I^}4̹҇wM1S~Z&<غlI83{tZUƍEs[TK}~zvDQQQYIh2#M:v1;ˮW6vjIeJb6#|Fƕmah@ c/J?;G WB6{\B^c>g|i{%\@ @-"zjx~tDm;oa-b 1, IDP @]''$$&PVj78rUc@ @ UJk;)#yudsSw\ƃ+`,@X@y{ [Pf jRVVr 4 5JocoYVq@#`W'tUi@"@ P wP#s45*eN= +S(@ - p;'7hK Oڮ=%@UDQa/wF9FE9.U=h59`Uo/^z$sőS4yUDܨ;ѿj=vͧm?{WlϾvXz_n~@I i:8ȑ>3ˇL{|c x{צ zdR|寨3izwC=,>B*U{sm>^sǎTJ^[UW8u#j?D/ 9u(j_ +TUD걂M?GDC\mMY+Os뽶r(Yޭ z܀d~֗(~zv'7;|g:v=3_QџIc"'2ի\:aJ\k6c0cQym;s&mT0xA2@Hyx*UoClqƞ_G{Ts?\yyI% _p^Yr3p72E>r얳otuf)(_3T|WP kK6yoѫ*1FTɏ=zQ?)^žg)kڈnN"Kr⅟AtsAӂɸ+=)+nonU,ݥ=3>eV%uk"YIz*yhƈ F?#}Eo-ũMoa3%߅|QЖ!).1e ;~_f/):!=?gxH` J9X6|;IH9O($=\7S PDv޺&'o1 B=t1^q ٿ #6(b\\.kB#1eGvoЧjm6,nW_+nj+(+x";:K~4 XMDS}*Z<}蛭T܅Za."wnnzM3Ǖf;y @% \{`o^x:gA~{ߺ+]A|x޵gKG1g_Eya[{n!#6\bpmf^c&dl3k6x;Ym}5n~a<^k}!Z"ˡSti QSƯ5t?b;GD*<(pOu]5e$O:_6,֟n6"83Lu]1eLelIngisQ=sʘ@aTLJNGM2ED)s2ߝ6G6Kᩅ}?LaJf\v\;Q mub>m4O)ۧwXd5~hG&?<=sb,eГZQTӖNY?d/7FkXm!GC|.+ѹe9G\>3su连۠L;yF~M_\i}+d3ʼn8Sͳy& M>B)6_$$C`2T /X _s0.$~V!LXJG*}U1}}{D,2}hkD\S8\FK`xotćw8yUT&ۘDeUD̾RTi7)M6ɿFzWxHvY W"Osk-C=*ub5oXff 5Lb$&.ОJ>aJG; U\~֩55ƍ b;"9=t[|[ r";h`qaƤv-ͭ/%/"N,__'Jw_oV6F>q 0Aw[u,vW k[S?D$=89_x_-9!2 a':KtqU aK~Vyrm4>9\{ mv;pL>ʡOD Z(8|w<{+[>/NGl{d)7KZ"J.6Kz5PK˛MMR ҽM:*3kr%sk^V,î`-T/]'&~ğrh<>L(m sE= >k\AY8nh͋ֈo ^S(( ]6n~dפ(3č$Um!{l7$n7hǡAa_dۜkvAg}KS/"܆]>R"*hp*<9dči0˦M]yioKbE1[ 7*X nri7stjd))eiy&9^ gN?~?cAZz?[#:qF_4QtZrV/+Dئ!wF+d/cq{&wxބyw4J_A9}l.JF>A**SDWJSԞ\fk>߫Ԕ7E;!h:CY%̵fT74\(: /-rٿYrGR~LŠ@z`r}ڠW Mb1<7xuy4?Gj\1ltx;B^^&tDΒ.ùM*}5o+Ji-.{ܝׅߡ7f1EeӵŸasK*~ow!EG@u|)uKbꛢțx ظkS1*i|CIF>r{P;F qSw}wu"ruvxK<>Qlt8g}gYq?Rq[%}.]6Oӹz&5:9[&GCyg$uckקlFYER,qYy42"EMcNƲK@Ml> qIN(11--oB\jOp*=lQ?ĜmY/(۟9{\`ߧ;HJHҍyPa/Raғ,l㠦2g^yw)my9qUkJ7]A/y ]Fq&'?2؋ zV)`/#7ϓj6CܣυzM=|݃P]R:-\+|VxK-j 7vJ[Hn)Bu:ʋ0c2"ezz>kŔR%#ˉЮ)*0EY9n<A i([VoFu 1Wus85#_@RQB`@Jv!gޞE->_3ۚY[ X#G05Eq/۲ONP/TMA:āELS4~ʧd́+;K|RCF+H;vM&\ |/W.k[clhA}IhDQˏ׊=g"9wᅇhhܝ: $ Y%4@zA@mɼWG6 8*$Y9҆Ɍ !t.hAc1ĕ*\ .z*ֿɗ~ɓPF`}_E]B7(k!Y**iQ&=5ԇ"`6q mhi!\V¨L=Md! GsL_oZbJ0ci:& LS#Q.x~ߵ{|~ib;CZ}wRגsbr5L;3Ԟ8syj>XA "kqً__ "yQ{&dmbeHo/dԓf!,.PƥVRqT+Ԡ8,azJNYxf<#㰂aOA:-2e` tӻT=vQc7ST6m Xa(%[=jv`mj]R>ΰO:S*k"nB΀N(υ[R -P/{ 76E0s5O.jZxys&ӸҐ5v*G=\aXuh1~1>&b{ G ->US{H)z #[inhMWPSjfnr}vW[`ӝ#EQh;= (?]8 횭prn.V XMWd↭`~5(@OuO7Ƕ5jB @!@<˥jvWJ$- 쪏~پ9>o=DGr ]oO}č>j|;wlljYsp[֜-H9=o^iAT@z 5ObDF,xf} F29/T 8qjCj U@rc7H^y:ķ] gvLXΨ?sq\|NrK7f׌ޣ"eGYv3%2ciVؿgߛ&b<4,?jt_` aH{}zzceVtĽӘq>cl&=59Hk#\Zxm`/#gSF[: O8{0<G<.vz⌾>BqH=>ny"~F/ AOFD3=.!o'uOԢ$q0N/Ikvu. _X:PBzGS\tԻ Yrˑ{LN._ WR&?:%m!SyAv] `U͹;7E"1pnL1ּw0uZB~6GXz0pCpZ弮*c8KK:INWMbu@G[&ˌc"h,b?)>q #f3 -Bo]y~*U4|a{xh%=Eߏ]4L1krgquk=)=1k1$y}D>#^%.$1SdMHQQTED+.DSM95 P %|gDѲJb:+w]:mNTdK؏=cڠf3Y1,Q%KqG~A{6%nvZރ !wVVS"Ԋ;B$l$Aw\,ҕPwƒ5Lr]KA뙀^/Su8]tt3ufF[ wٸE}CX,] ٱ"jZHWVx܌q8=]› (S|'Vd3'O'{+z]VY>Xce$Ae(];jΔ"$2fYs'-i%Lzjb<2}DлvH?1Eo/37c֠>>B"SncƠ\هؐ 6YqM+j/Հuw@[CY3cjW+m?ql?XngWmw4{1cE@Nzdqv|lӧ[ⱽ9_, 慒>eG5P#T7:{{覄FG^um)*XlJZx$WNaޫVIi>/] @5@μ5-ctRUwdA}Ti~]Ae7>zY6AA @1ۿӘ_kmm~!lDc^ބ?]R唝 P'mbXU 4'(y^g6.TZRc8Rjۭͭ^|B1"s=;ǽ|x݁YU4D9WxZųBէ AZAa&P PpUﬢ@ UC :$ T'I@ @ P5?@ @~NNV3mƍ8Ӳc1*nnOclwunSϚC'L]\ 5n.VWTQ MX^ځg]6Ҝ}ƘoivzQNu_u}ծ`xqHq!;!Ĉ9fIU.6@ ~oפj ؠe?vi[!(%|kT+vg5`;[&';l ֮sUM;C][w&bMIGeh(4Cr=/j#̝OTf(r}EfT|鵄DLY [յL Sz[u`껌02niGn?GZ7E!F@[ƀ@ `Sdn\H֦Bm/ Co<,EHHzʣlO.]6yB+Q !=]Hgs/ OM)VP(9(]+b;*:;|54 "qkB3nGdys>Yd Pj*M @vplsG"z;3z+Dm1NowIQwx4gx'2d-I pe?{Lߞ7Ĉ3.x˿Y#kV|1YGEW>=Jc /sE֧CϩIe½O6%PS/{Շ.\*/{{ ͘f8%4D:xbhDU4"/_ ;[n86~nԶ<9h;#i[#%)8"to\#de 표%3[exj~z9孹}\aڮߤ&Qx`Fg AIB߾!mTyѪ 0 ~3@NQJY) y ~Aҩ%t~I1vF/֍ve.|wT|\Lϖ70]ӻ UDy|X%sgԇ]RaܚVqܖTt|茸^I-%C#M@ؘDl  @j<6Ӑ__iEH7 k8z$vukpʯe ;PP8rXy$T} ?_r R,wo4"<-yHhߟH]|NɱK/[(Et$o$z=~%zzt'7*ˠyI*sNhAtP卫[1R}*J0(_SX`G4򨃏gp@`5 h&f1v0HU^q`_YSNDM)yC0` i8ۿ7wWÏ"^϶ג f| ɨ: hyz}S) 2[&/se#TI@uU.@ @UIUNjXz\>2fb5%PܼoEP;wh;"55{)|穊3JW^}Bu/t^g^ Up27'NnRJU(G ,7'J>Us4t6HUQeh17NFK")&<.+SYh-&PkTۡtY)w l ٮ݋KҒbJqk̥-G+$U3IMSF7tV0NH z5L~<\DAh/&}kq&$c pa+7x8 IDAT 룿xNn0ྀ<9x0=^{GNh$IH]+Q,-+Ju$&8bC+4vD^>TЈ.'<&gBZ-XlKBvJV $I I8A8bVK@}PZ ˗KKDIgi5>E*M_H<7W fnYvgh#YqPv銐* '7Gs஛sɘv7ڴe0nMzuܢ^;&'$ʥ @*BZ*ַZVGE(ԫ B`# 9!d߆"$!gcffyf<<3 KžDM+b,*QRTʇ@艀7Q,\80_\s:?OaJh6,:EAcZXT/c5$aͩ[6CXV2I 'L-~Rx+}Uj}tJTnXV"lst j8`%tq.4oQYERi+DOe^6tؿb[T>k0ݾsTQղ.vfT|D%ixXT[UJ\?j& _5T~ E/&NɯVyҥVPknE|t}ia]ɢ/uv>WTߣV?>[&^ } B<8U%E8<W.@cplJP`rėqhBRK+](?1sY}BIg9L>ry֧fުBgfIW8NǍ>gVKzzf~ݾߍ)<.z+4,=%\AHI{ʏji]y.TYre4݇N+>wOc<הMiѾ;&*.9mPWiAny  4}u <MBԞH>cDL׾51MAE#n tV_N6h[i~P&ikUpt͘fzC4cT%ۨ K^,i]շ~yҰ7X:0j@j{{N)Bk苚#ws7L0 tR:!( @͘Lپ&J9on">=y x]5tͩk6ڃ{1o/b9p}E$$l==t'zԒ}Ϙ+jݑ{u7ct ő--}#n\w֜l1=[Hyܵp&~[s~O:շռhDܴpVQ4ӘW0m; VE\ۏM4xDOOl׏lp8z}G[޶LX\rꋭsU]}i9s6ϥG-ִ*IԇF-*/UX:n[[ů#oڰZd('W:|LޮԒJu'SVr]a|$8`MYvtzAoO!k0+yޟӔfICx~վU}[ev:zhCDg|@arH 41C{("tl[pf Un:tXw0|)?IClɧsƻj}΋2K }KȄe,t3kEԞ|0| liJ{ +lٞZ P 1þG{M^0LqC+n{M>ʻZ\2Q/(V ϟq0=9_$H+2nK9ڃArǸ ]N~,JWmpiS{X#>jUVWFU 8 E"HUCJtDԿOW3G7j*Ǚm)—OcYPP5\\[/ZQ[?}$tVr:q>|7B+8WKSDew2t*?y/XZ=?!/Koƞ}ɷ{CB&v=;e,y'a|}Sp9 oKZ>/Aj7KuJũm1: LK2T jVcj8&)L1@@a*wb=vbe2;HQ¢k4 ZEZWYSh,; Ju@ V_qeir +)tgH+ӋI]ٍseʍ ]"#Ju ?4:ȴjXëfPԪ ETP[8Z+~_F¦RgSϗNJfe~\5}yĝ]D.GEԭ8u16CitzècuE\fE'+|m4˂Mt-QaZ(B~=$CpT烙%(S#f[&P+ `L_jG3ش 1M60_9cБ07Өe7M]>T[uj̒bXt+j$i}E Ų"Je[_42d,`BmKBY]̉Y1HpZQy3YOH3꩘xSG7[WnŦg$q)+Tg0Bq ogx1DNf=kM;< a>PTKOjeT:{jf[)̫L_ҷ1\,?Ӊcm>pJ@o,El<}}[ﮤ"L]>. [޲c7$/" gnL*ݲ7R U)lw6gAVY1uU eY lP #]]4֕XO#*OgZ- {.vt*amIm9}ѧI-g5ױ_0(Z9CwU'3ڬ/Հ oqQ?EBt?,?Xhs(0yGp$8uC@Ogk"g Ò^d :&Pw~qC?o6=GM `314FfR7?fReuM#nu9_z-䙺|=E)4WYjmaqiJL1M`7?fՁ@!Ж>7,,Нi) ۫1.7x"Wb]~MO#\z7Ew?r,toGroʡ γⱚWW+߱ /Wp?SsRmԕcQ̪1WWnpm1) z$ᒈ6B=V9@ qCyiq׋%=׳dPivoM+ _ZS`NB{׻LҼC>Zv} Dwp0nv@ o0|Ct,: x] hqڎݕz#=bUe̴'3S]kJvnʞXbcɻvI8s mLBF>\qR㶅P A4Ŀ_XSn]2?#âSSS\KŖdy|qE6o؏9;IlE=sן툉qԗ rPhV|w*% SٴoD6M $E$dEFTA!2a{s@NRh;ٝv{Wr L"7]"k[Z*6?`58g߾I{d媀@6d:: h#Sg ?%h@@*V\pTJT᮰I[Kp>&o@G38{=n䠷޵~{Al5K:'t߯bQ#)Csǎ~(_$z={%x' ەCJs~`S~"O瀍wΉx/elf PYnʬ{hdx+n&)h[s -J:]3z߄e t?0[r% -8|/L؝14b1f$kOnΚOE-!9+ 5@ tI1ǔ2&(@ `EVO ,]ch鄜Zu}To6E+8WKSDewƖBܟ^V}}*y/XZ=?!/Koƞ}ɷ{CL*1{vw`EYN/o85ɧr@ߞW2*|xn6g 3yy8BeASbTzSz``Z{O^.4[s%ZzTM˻\=r5Xc EyS1F͗F\*^,qsa7Iet 7[LXCA0^P@p~?A Ft5d(CXERQ,$jaWe͠ U<9'pz%~_F¦R?SϗNM8Ffe~\5}yĝ]D.GEԭ*uXhtzècuE\fE'+, &$`~Tӆ2Ψ%]{p?xBnCwj!QԒv*8+ zӪn+l?²`>A}ieiԙ ph< @[ ! B?X[0 ztq#nՎN)Q(N.u< J2kW[_wgdT6↢d2 q?0Cз;g;k||}R'6H5sݛf&Nޛj,ly%|{O*#C/RR+u0;&2f"ZF8ۮlklhרIg/K*8-#n2T{^\\Z>S-G523 2{6 x*~+ HbTb\ IDAT3r:@ "@cR@"U!]]4֕XO#*OgZ- {.|Ta8z`ɠPQH֋-K1nJC1@cG x= Cay<5+imŦ칒V[2}c~kEQb1tDx E?Y،l"즏vd Ʉyvė׈ b>=(FoCIee[Dn 4oݖ!n^gZd'Z"n+ rSNlMi5a^j_Rը #72}+%Csrő@dAs.he)Z7EGeb{EGTc+]2Į]jŰ~@ 5Ё?F>#@ Gpׁ\2c=g&H%ӯn ]CNG%hgmU!P53/9%w۶ @!؁Ilշbϋ˗kc5}@; x]xJ"q9r^t0NU'VTt"5CA &K15(ӏÀjV ;83QC*@ `I% z0ޚW:jq 7fwE{6]* @<Q2 "nTvЈ\nvZI]!VHrrYqzrX£WS NNMMvre/,fowR0A/F~8F'axXs&c)Dܻ)q3`b?_.gpsGLv&=:݋_#&bJS_+[L;y"13;dt2^y"@F /B0iT6?`5ˁs후mGV 61}v"2ע^TA!2a{s@NRh;ٝv{WrɑL"7]"TGk4@H?@0yH@ kC@3Ǎ~Y_3nӓAl#ӔfICx~վU}EoѳG^rwraȰ]9L΃W_:/rNDZJs~u|z6 H>>6ikG K?el:Cc?7BU?k1ne4U2-bwto/1&1_~ʔus֜N~*j9OpuI?=\42<' MJS n!7(t~;- 5@ 0_00? څ67K=>}XV>H E&բQٝr8=ϯ2f/ie"TܞCK {|BF!_"ތ=o,7T"cع 2S*W ?OȩQo85DSe%|GKWk:Ѹfq慪㏍L܈,FX'clD7PRf aȤ2-K&,}r硠eNYaXZ|1*)Rj=0d0-W/t ׭-zr]m Y}c: L #D~#d?D1y@ c) [vU>eeEgkjUa>'pRպ-2+:)Xߠ, &p \)֬,ERduY?.<|O."VҺzEEe4:a!|l2yKD,QPFGDXOᆃn+ll , 3fC(Z q>iJ4T[F%H+oD_X#*V efQ%KbᤷXQ%=˫Bũ%RDKV_Q kAt| 1iJ7ٝTcMx#(P %MMΗ dNS薝̑ *(ˬ]m,G3bϨɨ~=&Qhx{.W<ώ ~3~DDhAבּgRqK~b#uGwo8yo"RH$MDrch\I M?ڋ>TgMB>힍me¼?#ʴ{k-}†H60;&2f"j?d(lQ;]6&ʓ|/ഌPyqq6=@ С?@Ōԗ?L4I{X\X!cDd L6J%EWt `4z[!EV~:"hq'p_ޛtaSlZyy;XT׀M-Jco`}m-DL3c&g2Pu %&*Hp仙ޞC0{aVXq},itoO}ڷo\fS?40PH z(KWN. +4Js~T. ٣tt(Ϝ?ƭT{zੰ–ilnooRװ٪݄E}*Dhڞc@5 ݾ3N?Qy/N = `Z\[/ZQ[?}$tVrjeؒNܠͦPm E&բQٝy\%?&Yy/%ߟQȗHť7c>۽!M&v=;e,y'a|}bSp9 oKZ>Ko sǫ w&ͥűH"Mi{ޡהa x3N?)y/N = `HWSj>6"/G"b5FG!^"qzY3(EgkjUa"ON*(-^r_䗑ԏSw'-YY,:}M_'qgу_}u<'IZW]F7 _>6\ [7[eVtR+ Ͳ`bAO-Q9WB% ٔ@kQ!aH36bϵ]}3-V4'Ԙ8,˓ qm~|- ڋz/?f~2c}N1Aig_  `ݶR&P\,x|1e֮ J)D3bϨɨnm&}d:hAבּgRqI~b#uGwo8yo~* H"^qœNjZDNU]($v!'*-:BM䫝F"N_U`_帚V jZ-/ @x/SKpСL?Fq1"SB9&M@ǫJY ]]4֕XO#*OgZ- {.<#Pk*a-9)23k=nc& aReb^ "yCdt]6ǎN2 8gduviFn/,m_Zn#ɏ6gV) VMY,-mq0u'o Z|{kU@@gM%^ts~K8O5Fhf"""n@+r[bb F| F`X4@@k<^#ߒHGN7u@G"cW?UoD.e3TM=^V{{'ꂂEUKl>HĿyҡ%@ׇc&okLބ0 ~č(ăzҔy*Sӕ֊uSWr59[䴷:_Wvѕ :|04t8T#KqNW纒cDu3]ԕ݌J{)+Ji;;|h+d L@ kDiUi!}Ui3@ @*5蹉m @ @ L@#n77h۫_CSڋO{-܇ԻǞqtȶ{ۋs{Oͥ4%gWY@hB;9!-Y]ni۫_MHg^kڃNL8AD7uG3-evDg OT-LR@:3pi^3VDv$*Lɷ|Qcrȍ G @ }x:~D;ʸu0tE?E7 ځ1veՙ9t+苚#ws5KDټolޱG/ m Xϭ-@ tK@#4"!-yRWFNè2\nVjܶy£WS NNMMvre/pQrU9ߝJݾ @ay1ӻib?_.gpsGLv&=:݋_#&bJS_+[L;y"13;d(dy<|qGrNa`Kk->l8SzWKH NnzzV=;Fm2#ʏnOcS8 N{A󒌃տgs cp`Ѿj0iZEܘ?n"Oq fT0@l5K:'t߯冈D?z*Ʌ#v`ADL΃W_:/rNDZJs~&o@Gp\PYnW)4]SN,N-Q9[)%e:~ x*e{Z4۹y95lDgpv@ !cd3W~2i!B:¾᳇R L67K=>}XV>H\ LȫEť;xXK]T*c6V&B]0tz_ Qr'd%Rqس:vorI%2{l(35%?OȩQo85DSe%|GKWk:ѸT#X5 ΫJ4]SM %RNʻZ5/uۃ}u5CTmsT ՇridxuTA pj  @ ~/id?FLw <g?J0q) Fl)|Zl՗=V"UJujVnnˬ`E$ƲB,4~[3)pK &O[XXqek=;\ꋨ[U9IҺzE Ee4:!_>6~/G"(XJ#Tqa;4ۅlJ0±:E`_]?wELZќRc.O2+ĵGձ@t^8d: 0$mslp'sEFd4PA)_fjˠ`8y{FMF1B[պ\\>;2tWR9}s&￳ƞH^7/{bcT31ݽifH!4rʍqaU:CQQ(*-:BM䫝F"N*q5մZr_԰ 4@x/N8?Z~7R4^%/z%ͪRIѕsB&-;VHUδZɡ1%]xXר?/vxŷB-JTUglsŦz  %䄴gu::W0, M@ >qSWoНi)['*o?3x>73}_Sf?H6{ލ{s3 Q#3;r(xŕU?%:,uxvN4䋒C]CntfP2w(@ `4.rQ\g?!12:P@0\ĭAkP B=J"hvoM+ 8BZS`NB{׻e -;MWJ"[cZV_N=^E͑;9̚FټolޱGN €@#&op v7*GhDBZ.7;-~󤮌f*è\,nVjܶy£WS NNMMvre/,fowR0A/F~8F'afA=sן툉qԗD.XJnJ\LE2NHN9v)ٹ){6JOCf+O$_heE$dE*͠Kv09 ')L]4NCފ+xD&.rM ͆3'zDY+`2#z4WM7dgkGݰʀd !@? #@ : "nL7e}اϸMO m!NS%iWVrDg|@arD+r &gΉx/el'LS~tXw0|)?IClPJs~XZӉiWkƙʱ,P @EeK'j? @tH`$|N4J,;# A6TPʗY2(X0fŞQQ5id2 oq_rqœNj^ތɠ[ahAבּgRqxz5%G~ cb*c /QBelzζ6v:@'^2Viq:Ht&fS[8yC}jf[)̫iZr_5Z &K6N zbB 6J%EWt `4z[!EV~:"hq'p_ޛtaSLZyy;XL@T-JaX >~!f6z{5\睩1y`(d/JCJ+kOGF fLe~˒,KL"}FU`3XG %@  I/L]+?!P10P @P/+6匏?_Mnb)-:ɪb3r]~Ml>#g+ΧgNwn8hQ܊}u^ͽ{غ (,1_<IТ?L9G|܉D$*"}wQvvh|VʻuKoDX ƾ{1Τ1amZ[+N:\m=S-vvVfZMVqſ֩ 0D~cZO  Օtaxp F_(Xv ۮc\4Bv 0 04NhENc\˗/H4eD3"c*@ D$9^ȑQ_bO6h$'b[@ `P7t@~č(Ci4%&o^GIj  z!@e;8 ̠3 @~ĭ>ԏߛiP / ]; :)a @ b[|b@ @ @ ӈwIiiܸ.jIw[xM묮7uhק"m$9)6`V=zM嫖N-w3Ɯk' 5 Ը ڛvrBZ:T_)Ղ?fJ]FH@8Z !Sի&-u*3tgZʦluд=\ pVwg9? kK .7xSÐ,FLgި~,{ލ{s3 Kց\C9yVp$f.r~HHzd{87KB7M;>Rm'߭=~k`AWA]DBZ /}on ܛrE4<ػKjd*l8SzW)wWzUsxsc7<4N9ӔfICx~վU}rs ~:Mc;5ܣg۾^"i~}n9}oHx(pDg|@ar RT᮰I[Kp>&o@G\%*B*?k1ny]7)٬0.ʌn&)h[shQS&Lw;.[#P"3;MtD948^Sa-e۹y95lDgCbv@ kLNS &K@%'1/գֽ ၐ9 E&բQٝ%!"06*i=*ȍwM7G,W=?!/Koƞ}ɷVYn2Dưs݁-efUx ,VO ,]U(Œ~^^3μPw'67Glrx~R *(<$*{"%߶3iIک"i?)onȐ?{Eݽ~IBwQ:HA(*_A X)HA:HoPR ]]!w{K~||7w3WvKV1޿a)^UC֓ݚTu7l}q-&ψ?w*rU^d)d ~J๽Qw]]͓V 2#bYOwB]s KjI Nxh*wؿs?8lib4 v(m kv̌+H@ Nj*V:B O,+!ϕkD['i0Ti fI)JbNʶ Yϔ>TדbZ8&tKb@ _?'2aǧ;kݍl M2'3(# !4U\@&͊цly:!aʧhMNQ`b&FeVQVWn]8QHue+>h$vyi{TY8Β̈́:3dݏtS{>~(˒CZ])YIPp#͝_ Mef.2ҖL> 4cNlVr@<̹ XsH@T(*9ϳ,V)֕aL%FRC{zX<)o煅0Is&H$OOQˇoDC1*J\wڑ^s4sw n_o'c1-FO>49z%Ԥ+&2S0xx*}4#"d.S0A4<.,:S|ҋ9- ~rcV;M;ka ZTo?oV4[dm${d .D.+ۯk y$:7a2#n4J{J8*A'rxGdQ2L/n{R,#e!uWiP  /ǜ۶ K9w4 @"R'cC1UFP42`܊̌V~e`yso[֖"&4L;y4:/"2{D7xUA * >r|tt߱ "5*nd3Ge%1 P pn9̼v.R7Z pYH^QT'ZVyä;u\E ݛ \3;bB^l3Tֵ%cF <76)Y,E(nT0j-w1FCZ^tp]5_-G̮5k /.%/.Je>ZdC =?ܽM2j/.hU_ӂp &+L{XhN @Bp(`xo/5^|j/PpuꏋT6AԙoGI{g|Cۑc{*M"nK53S|_cuؾW H* lABQg݋z~ǖW+AR+< IDATn[zfحkf4R<. hڰE߼*?\3rUxfy{V?,ٷnP=ӹ]TK }gMot/ 3&Ee콖l<Y5%w=I!A3L[w4YxpGg+s*."/ᄌ,ANnU#{lЊ^ vj_g @"XA  2@CCCry(:rfaڄ^@h_*kOsM83D[ѐv=ɿ1|6.ܽ¯'i4?,H?b;hQ%gCѨJzlq%OțqM2e /4og0c6Y $ @'tºq#7pץcMjoEIRf دc݈MEZn% ;=ȎpD!$ue9ƨI_gU^  ?3;c;1ی@T,;(=ZKuM ?]p%Hj pp [\6Z.wC Ӕ!%K+*##"@ ?$H"?VH>?V4~<,( .K]WY沠\X!!!ŪbuC @ tՊU]muZ$ zr66_]XY:pZA)tQ~/͡V @ @8; C_͑~ Az܀3Yevڟ_L~[53m=S~M4屩Q>|1O@/RXnt>6IJ@@qߜPJ 7@"؛ʠb^n|SoyTqo<+UkJ^4 j]45??9jwT) d/~|}^Yr#jϺ1@ E/nV1\||ˣ-pESf&TM,l1$O3r )) @3$I bP%*SR%J飯|Ζ/,`BHSf#,7v!REsKmE5T^V@'\[إGYC.~KE%Kvy[1KesE<2 Q}k- UM.0 @W-3q8.l|>mWB7?2p>H٥1f/x ?Z6Oe<6l^{Pϝ aF5ݴOZUk;[h _ZaOWXM<>Fe d?脇UjJ4PP/'Ȉ'}1"iAkҘZǾm,#/sX=uR>@yD7%<vjopx^g= \ܼg;4`8|7V2edѿ kWK+'l j3}2\|Ҷyl_^*o^~qN%{c˺|i/NꇭhbނU9sFX%6Lv߸T:1`K@[եV-P)@4 ZOoD=k)4>Eiʽ> :9.]S >\,^p7OB GzOhʷFkTnDCG`ÔfSs61x0@$^rۻVdμᨾtk(n.m^ڭ#aI%%֔lR~ײ,3ߪ~ށ0ꂆ*G^xuf.~IBOɴfXU+7}IqfC, ( *uo-'I;9qf-xźI =٪-}M;"xl Cgmf??tR5qD5$gd}Dw=JRN{޴ڳX={zɼ'4|7 cHH3" SlK!sdx|6̝0CUS"B$]CB O;6.j۫j`{lUFNA쿽d/Z׋Wz{٘.%1-ic¢!b~z|K;3xOv}_P HX7ZK"ضk4_,W{"eu5 cEc͕;@C4W2 ˨A&@& n(H߮+ $nTrI[oFE/YGUp}C,lvueKGD(tY,Ou>W>(7413¿."q Y±7r1Z--+\~Fra{B K ӗ W1o'c%M T-o!n|oꅵ*IpZvS"~"r:%&[g$jԮ0+ e#k#E}fze;F7 oZM:0[bs\5]{tcXv%XV Lozpo}5h){㤯{P#9DlVB,%;^>jG8}.MkvrO2nY痬.?ŚEO ҴaɊ?,!d._~˞U(ݥ wn@Ϊ]odm!ĖMgno {C=s釚[TFk(x|/'>_d6U1w:$wQP8BkvTLj^i t9 GL_(˗M{m@ yUV(P\F#!}Kקh^>iDAufVi ~%'6Lab xL(֖%mn,d{yZ['xh_7G*!8ML]Wy^nAѪ|?c4JNn0?̕l"0ē͚Bך~¢]7-k$D8L*BSry6^{,y5/;"~.,)W^fV'`8a2dag{WFߐvi)l8|@W @M2]{\ya͈adqa{vO7TDP21?xCr:Ǻ~/4_4 2j' ~Q<5:D9 ~.By!ƃT0| [#xh&=ߌ5.OxLLg'v ii?v%<''r7^.K|tS-2.PX|UL`N5* S;Q8>ttqPF*e;(6cu8m81g3 Mx1wu(\d"7Ih[-ˏ&R\b%AiIw[^ vc ,'[ w^>|cJi% pfs6-v{qcfʾ|Œ R6@ PF 8q#4ӃB輇m#ͯrk.]ĄۘZcܷ vQFtyc&xk8J$}e>3K?y0@ʤ jKU^,hShq, m$J)06&^U;.'$<#`3`Hܲƍ0]6-xm_ IM13\^L&f RƋ,}B}ex"rrT\*9foiqzee$X v?EAJfYTb%[4ͬۋuHh9w-|Td$Ysrs0ޢ{(i\fxx,.5z2%sjn L h -?s֣s.>#ߝkZ>JF%KUǰ;kԛc/ŭ/~2)wy5fW t$*&7I~r(]x]ӯTR!4pZ;"@ Pa-7į?m|Fۊt OX.B|bTY^l'Xa&@pL^B.aS0!5 $U!OHw b8Z2-c*C&󪎓 M/"TRSw:8kk"*_Rtp[7-?js1Yޘ$X٧rܷBQCq ۶)J\'ኺu \q֤I=)y!OI^}5f9aTxR?š H[߬f(^ȯ}՟Oti^3'T|~X)v|E؋&9@ }oY?I%n v{J*c͆dy 8 ~6ke=vLh),̷Oվ$4f-h,&I'Pr(VLށXq|O9uRE)טE{w?g^Xܿ4 f9n/Ua+yCN2|!cGKveVJm(wrӃ\ p?__,1ŴW 'x~ (`14n Z&:\<#@mH)#]<75TL2lؓVOۣ싈ujId*=g*ix]Nn7\c&YHP ?n탥y#Z(]/i4Cw*kg>F> 9ih%he?6'n7oC3_?a <^:'tѧv䣱ÖgB̕r|R]Ԩ>1/a,K,=omωLa{Ndiw,ߜ,BSSS-uub#( @'96oxh EA>ϙy("Ϳ+=J ĘgQ*V[lgn'?nr7jh Vv-=>rc tF6.?=ۨsΘO}%?=nLm9"}PB 0V(lkO6m==iMK^xo):< 3xV؈a*.>^B\Cްs( by#΢yf{A (5xhh\ʯ`6uʼ.!0$$O;ޯtt#6p߾311mee%6/IjlzGq8 Jc~3bqZVZ@.Hg>[@Ҝ\8*Ö$g6p`$uiyGgOК)}ԎbL3[`D5@H B{Nv ?yqQRim[~,@se/o,j%i?y%*,SJ0=nx=/L0=#I=ASJB@2GIev!sxSYFNs?a2n4@` mٴ-Yߥs.`~M+KӒ: SԺ;EdE&SUdN`;@̲NJ]g&( } *у @"J>T @d%R+TE@υ92@AqG}dK NysµDgI1@T@q[~_V+oyZc9UZL'֗nٸG}կO W=3g~g}ki%l!  @1`~񯐯{8'|Y]c  Pq ^ĭX@ @ ;MR{…c:7 vmμ*K ~ۇhmc?} ȑNx4}η4bO=kݍ,ܷ3]?佷)d ޟ֟馣 ;&~s Uqrĝ=*NͿo)RϫW`_+${wƙ,_ qʔNjy c;;V?c~Iw'(9/g3M@:}NҤ@]#fp7>Z^3}U՗lq*K=%ط_5͓5œj_^ѾwbEy| pc@-c/_, @ip,/?s/Iq5+?&k4yH[lz7nꭱJo&]7ʃ~ؼj7N\Aǣ_Ϥݫc=Oʉ^11":'?{?%h&Dq_jݻDuqݚk, #6_KH)4n&c>/=}xRZ]oH'7ў} Y$Nt9;/( j8gғJZ`Ppap%+ EOV(} kv$ګ({˗U{@E@\@s?W~Q2gb ("vjl[vB2\y(ѷEuhBSFZSNuJ n^J>k?IMTi":/DPqMkx^(}b Q 91Q99OTs׭;` ȴg.==hL\9 K"3)ZR[BkRމVYj>~'?}N[Gn$Ik)-MDazrfB/van;|֠-|@N- ׿[٥moa}3@TdIlD|Av <%!~2O8eO%EU!#֟h#2M- 1EQ^/MT4HEM%?t\. OMha'!=z=v w4כ~03f"V yg[bF;`<9;蝵{İ -뷟j竨ytl߼cpOq3 b?-T=5댣X-ΓMk'ON 1ש©T1fV4{%@?4[{ᷛ)s8ЕjVa=˻Yr I]]02(i3|`eQ^*w%iFHJo񰧓I']4ȣJy:y?N.Gdyii;/Q+BP๱I̩wQAqPQPכpԫ4ɬ+c׳BB7߆u”&M#VÑkA|vj<§uO&woi /]^n3  \c4cf.㟀?3(p$B&ksFFBQg{h}Z_J4^CI? =sR.n_xih[͑뵱[ )\4QDzgIӆP.2'NpML6!I" u! !m̌[3OD:rr\i[Hrbo_]f>Ȗfli=cюyC2H 0^3UO+s "rg9@ H>;Oj/ݻ,zI2Y7ٖ E.q]"'k{E;ΐ H@R"dsdf8&MCUSLopAb%X@ Pf d{yK~qʔ܍|JK/]8Xu[iS2n_}k.%:O5c df䵰D-de\\Jso*_ysO3΢d-/7W֖r-usjwJ+//v,mnv)]n<~J݆AU-̼֘p4cgݎ7sfȢ8sɷi&"]_|˳ʑQk_g#壪[/z[և|ys(Գ)yi/*942L}ib9J}si+$8Ѭ0 |ō}ܡ`.c|/' sa o()/! ʄN^w=Qc'Y^8ԇ1 Jxw:=oqu3c\ˣW?|SPc# ??w2cgvc?hX 57ijntԠ9azG~#U^ǎx &é_>~[Oϝݾ^U36}3^h<'$,]PCALh~ f7t\7mznt9փmf>2qASQ% k l{ UL_3~Ymt݆I#B ;vE1zi틯2;(5uc7!V]ӆ/BT(J.TvҢy %¸$g}OonuhcCAcz/lpmƻ&$B7XT@q$[p5- !LP4;ר}%v}M#1_V~qÞ8qDl '7q`Oeiay` 깃PC~Y=Bp|~qىGYzZ}|0rhj~nU'? ~z2lGǯ+̓\|yU+|Mcqǝs1 ._2g;>,^Z}@.hIw. w֪.ϵgc*yJΎM*3R57KTʙ$fu|x˽{Y_vnU$Ot'oy Y⸩Y~VU]DRKsxacFfw壟Dվ6Ko?Ǣly珡S( 9ƍxz9Werw9ȵDh]yJͯ)6G1?H WaYn*4H&Đr8V`.P%FQ4.4IgH-}hCnraHرukYG.avrvqWT¹.a Zn@?cC4c'-e2HYڗ/DB3ZX:!QIRSPXĀGywʄBC!˵9em/}ѽZU9hɁ[JKpGF&w.i*gC?Y;NDlf5b\&eOG=Ko}ϫ(_O/f/qS# \L*y%ʵ9[}9yOXi?`A/{:oEx'ևcz珡S(A8qtٙ"Co4WBir5ǝҙ.uhjdM"H!rBO/^1rau!,E ST9Z r@%&leV&\Y(^|WjW[Ôf]~ڊOҩQ WJTPhh&8ɜ ٩/rU Ht n(6#MBE丳~_XwzV{7y%88: gV9x80U哃"zĽMϧha~4:TŁ>g8xiEtYDڜ$?Fi㥬>GaY3.~;Y'(Q.WX XGrC t'?fb?ڗ5c"LOc9%/1U}rM72MBwつfR\]ʫR8O_cz@!!nNM*v-Ԥ$qfvV?#/25*,ɧkMczm˄m q eм܈Ju`o:_*,/˯XQRWUtcɑI H**{OsmDlR))zz_4cZzp\ r" \rܱZFk^0vhtxE884qc"|ؕg~'|0 A)7]OyˤLfQ1Q]g)վe}عW<#s4K ىRyoyf8Aɷgχ. !$~VǍR?a13j_tK81>sG~MUe>ي*MM! w2rP{s iG7ܔd]ay;p"݇sz,Dz-!H(pgm2Rw7<k덫V]VN5 Ur#r݃RnsJ~rϨX4<ǵ2ҍqF6GrY\ 4rn@C{t5Lu6~0-'d8/|"|T7|( "zLw{͡sժRDd+Y^8J!ylFdq~z?fCv(K9Y3C@ 0pj@cJVg-ovhW/23hWL}.vi_JU ,+ Q` ͍{|x*e{^-F vu?$H",c]Ki쨩'v(QU pt 1U E)y.֎*9H@ @ϚwWiЛY@"@ @)*-P @ @ 7@ (y̛%j^]JA%@Ps䧦Wpܣnӵ?vĹC61Ԥ ;^WQOQk֐pMoȋ {_>|;Yݢ36}|G4y3_4xp7勀<t k~hDl|ˣV> + ŌA֎ݣvusi$?WDpWg 4{͊/ҩ.֦C0_Z7,ڽ ^k#dqK{Sюnyc~mC&]-'|-^Jڅ(/X/i RH(v%@ IST$,v=mkMߟF3Kq'0)*HȺ mRtQJfܿU?':kʎ^ .Lm;քsգ )TvT"M΄KVC?/5z 0=Nn6$d 7"/.x: @Q]GH}_aD^`ۣZIcZ&ĸM!MϪwv ]+E>|NwFU o76v[5r`"Z{YR}VjgˤRš:J:vLqGƊSFvʘߣ煢Dg3觹u}[HA-g1B~-=UGG`*2AE.m^w &eJaqxz:[+_v%Sä>~@&J+B'XreDPb/71qq=5~T̍i>g:Ǽ]P{pjc|.g{I+jB>c9ӎ zLkiXU4)˕~_Q/"xh>[[D^cl$So\mVS? 7W+yoK"摌?qLa d6y?4%.堉OnӿT!1GȠeIp<{?~'Pp ( pyqs&@I@@f΅Xֽҧ_to;3~våLy(TKg Iv+sQu*X(*s ߝn0r0׎?[9zps>fqi_,%#]O|wف(ĸ_QXjy\п&{jIT>mȜ\a6M7zt'D-y~&ޖw1i3B~mOF6>ipŎS;(}M'i/רڴaZ_T6K|#QĴi㨜!3Pm#WA}Υx|j]84]VEt&~j0(9m 2\APۺ.|U/-B韈y$; 13SYД;/5tGZ~<#-s.䈏uw[j )i6x@#0w=k@c ‹ IDAT@TsG$mzҷݖ(ZQ+H& bGZg2B:U*A~:>99rCfQ}ַ|ޚYҰnį8u%= Y/9 ٙIj]l.5!WRi [>u-fpiWG͉q{ )~պR/>Wψ2Ќ_[?]p'hڻ8H1ʹ": )b^B'&H*y+tǏĪj +^6<.aGJ;T-y.hP(%UhiEaj=$ZgeZ鄴2ΖG:Yɍa%ā2[o(k^&n(nhT?&!8`y58!$4ޯFӂ/T,CGdԁK&&\E܉Xl-ѩw i?$|5QMEO4ih0B@\ޔZX:e~ Gִj|<;1%ڌ=''LE +QÝtʸ&Sf>=ϮKG'7"jl @h~2AF^ZKHq̴ws Je!υvٳ\.*O}\u]iؚ[(W] "Zb^pLIUd RFkmt[TR@W%_] @#nS%p-ڬZ nj:YJfh x۶_ΞM"ʔ9krr w9 ^s}}FkڮR+zy"ˋ|>z𾉡\lu^8}[[yYlN| & 9zUur=$)i$Glϼ1){DySxy}[O':Rћ>'+a,%~}J_ dh/cz)n[{Jum>C -֪N8гî] Ɋ!n\ z_ 5VRD'}z^C<>kO-\Op gDU~∆5@%`qﺶ@ ('}7}`lRsJ`WbdnmD]1˥0؇U5GQ{bmˉ1f3~$U^?qMzW_ |OdScdpIb}Vvyo?Y-BLԠC%Y2H<:ѧ|9C{i5,qfyPpR3:^y!7:f_ ubӫvyo~%;{6xbW?0Ҕv;6Oɸѻِ^ͿewGRN45<:Va+o^-i]DJq&ѐk)4B$˰·Vdv 17<6&\ T(>N}+l9. @&Ә'1U,q+߭ @ܽf!w:+b>A0e0xwˆ*@t @ĭtC@ @$C$yj׸YoN4GW@ pK,aURV @ HKUjn@ @ @Q"nf]KEa`gi/?x֡^%UYR [o*+!Vsv_G=m0T*\ѐV3D &ӾܼeK~a= 99)hqCCˋ sd&7ѼF*r.y3W(#Vj.uI ty'9ZX c}~Zsғ~X5Ѿـ 圀u~ GVI_'̓ԭz:Kv˯]U|9oyFR˱~l*4'  4}ȗ]o+Prkv͇.]Ț=ZOվi7KƧ~b!o7OdCqg8P'jrV׏~PPJ[6Qj+e`_qT̚ewywwyV%9ѾFu:7O0S 17gy?~b#*qs&rO(72;y?+sydf̩  `yBjH[Z !DGgzX\[s hҗK_6WM7_}?ΐk?累AI 1Wn2;_9K3ǜE8?V͈9@p,{w+7.T3m֙ɿtJ~Qw.[2 Tq]:g1Z_aajΦQW*Dk>i_z {4r͜MQpW)m̺g%o5bs^7/({#cޡ{fʉjvwƪ'&<=*ތw70ޯa2%T6.¯{>~ї.NMoͫIAVp<) 7bCU6G/  \sDoB)\a(=< 5y135ؘ! VȧZ2Zv)Ա@DzkG 0~!YwBTЇg? W뵢m=^VkUZQy[gցZ( R,Z Xd%f{ssyN/g)o'Z{:'|Cܢחv i0E/oY bѪb#Uсj6&E}*c@n{}#-?XCZ1MߡZ*rcfv>j;e<40j!N 俽Gk6!Y y`:9ٽ1G\8VsYmx&>6-+XMh0XB6SR۰ (jU5:ԃ@c&tppy`szğO\/IՔ /n{9uwQM*(ZJ|1s{!>0jp~j8/w3@@3e9IqOzji(;C͍A7ZX@]H!"_'B ftRNM]D!VA   M2nM.0@#%@qhW)-RN}3̨Xb$?4L#;=VT}ƭ$5藟@@@@uK:#=Vgű          @@7ܳۑ j뱻W:a| =t׶iUn+wFmSRn{rs~qu*4o^*{*sJ;WRCmqo JP)۲Eމdl-,Dqi8QrnO'Y6U*5"^P  $ZDWP[SUeM*HObDK/1jƨht[";6tCg>9̧mÊ6հoA>'5c=7m=y-uc@@ _f1;V e0ح杍?M1^ bSRRZ7ZirRr8,^sE%Hܾ= ~?Xq򝤔ĻD^עx1yʽTSN'FXq4*19g}]OD\1BKŸwtekضCw\2² pe!!Ǘ-o*/Ӭ۪}GrRrnLLqxKH 95񕌛[O>e i?M5Se~2j1ʽ̤O(Je`ɟB<}kgtp) 5< j0=6j *&$]"im1ĩGTc  ׸=Lb`ϋyXϑi?v/#Jw`tկs/'[78'%\~+5fMyh"q'nޜۥ7;/<;G}^ECQf6";E]$ߔc+ _i|s_ (Iǘ֭0L%ZceT$/az\{^OQ6)Z;wqK7.!M%x.J3)e=br6*ňi[N~ͷ'G2n ҸO޳O=|%k؏r?U(@U0.Uen8^7: ʦ ; *QB־K&T =S)r=e8Q\ǤLJ?+G 'jg # jƱ|Nw= iWt;&,Tϊ9B#2u)bۏ|PnYy3'40#Vm:1dG'%U¬SN~<\UǠN}D藅 $ldn6jIx^͋gVq돘7%'k`ͥZŠϟ '_(G^VnTǪsQf<.SC0 &x_H V i)9,?.UU*m, E>.UّWnM.^8@LzD$ 2"T(y "mgP uO@UIGěo\VbVox9}~M-.kK)!&"@ekKvY~dXfD O$[VB-.}deΕKRH Oxy(ݷ.ͅ_wbDQѻ"ǢR7lc;3V_^΍g"z̗F@!Oݑju'9`W(}>ybbvQ-v@@@ ¤F MT}@tO@YTyŕ;,A]IJWգœg%S&PTQ޽X4taoޔeN^A ?b~^7iұSт( IDATuXZ!7d[EDSb')o'ρ".Z)I28<d8" Aҩ <_,Zt@{D ;ZUKFtf@@) 1Jl&cҬޝ`gEq&Rϸf7{@-nN xZl?%23qZ[z! *ɪDۮ12% N bD wrqԁV@izL3n;\uA-蚀&kodtL{.߰lΩ7F*wנ1Y<jl u~eW#o8،1}ޫm$Pe%GEeqZrłsV2XsCׅƭ? 7}{r'+J˶2$;|iqY<7_.&6'>q1͸#cCƺ?-{%ɞ)lǤAř7W'2bK$ɝ⩸)P Ҹ_Γsu\s++[FIbA2? ⼶Fz铄%e)->JC:Ar[sĥ9}neJvED @izLCi6}T(1}v0|v Mf~G캖/#_^Xq.M+h]Z-1˝7}'hcXh<==I$=5٫ 777Z~ Az7@SR%z+rq;Py;[{“+~#@}SE Od >3'y̨"'o?@]`ٴ5V122(Nƭ$5藟>hX-mH\0@=11}&PQ )))wM O}棎oL[<C=0Q][gǥũ]_cs* xneƩ1mċÛCLxijv} kD@rsBlbM/D=&C=V7豺^N#9j/1)Z>ɶz^3=;u3TQ;G~?pgl>j]'wo= EO&G3eՄi>DTԐW n~O?T~E =t׶i+ܡϟCi]n(tAR@fGys~mGOy*Ǎ y-~%;x8fkaa 'Wɽx~VJ>5j[nSi^T*|p|?麍 Д@ɢ =F9ϒ}AIAk'Y[w>ǨЫF1GkZƱlc)|R̋vC+,S{WYjgp \"cOzB;a1WVg}Ahj/Iiz@|#^Z s Pg4Zƶ?"9&^W|vm-?/hԎ|fHƝvg"G}is> 8xNRJr` kWǘ[OtyʽRSN'FXq4*19g}y]OD\1ܢG WlF=v8 {8s2l~w3$dˑSFUr0qNݑ{]jɊekζ/z/zB+lۆ'rؖkhe0N/$Fx8r6~[V$1q)wj*/0JfV8zwl/y+qgyUT gi|O2N3o'`;={/h]$3ʽ̤V>^ #W4x3kz΂' +Gt퐘,F((1Y*Z'd'1GȨ(D BIfI*4Ajh@k/nw6v{*iJOL}{t߾Sl[T^kD撹.rĦ(քu_ywRߣ|,'Y}uE.w*J>^SW;nQ0 [۷a(TF2IJ,?j_(򡅗hhSJ&6 ǥ.Z׳rm`*-Odh׊#N> 睇.rq6i]z`]nw͞Z;SyIҍlg+4p9/{+?9Fs]%\oU9z"9q^ɹ!{'z׾MɎ=,޽`Hx $WEo}YZ3 IJu19Wx'Fa\,37U%-FL۲vGo%=QɠHqo')+:J+ D8PuB@ZʴxﳾC?TK}[9DO8$I,*stlkc$.ȈN>Df%$5$GʟSΥZ) &.AR =ȤD/ԁC@UZJm&͙osdkD&fUKȄoR;8 >a;[]~o2b`HS*I/Bîf9:Vl22agR⢼RfUManf?Er%\֖얳'Ȑ ̈ϥ/.\y`%Ke5'eWԏ kEf~HP,[h &[Q'>}ʟЭ> {mlgj>}G<c>GAT< qkƤ}k&|{`beEYÎW]B X@" =R?koCi%mK "T}@@mf܈<%Dlb澻_}uH_EyN_xb=agߛZ[P,fWƉN$ô1!]b42$VX]J<-I2fÿ2,% ~ٶo{XchaHw5kiRWU҇H/1$K.j5^gyBY6J$oO6uXꭤ_+S(x_zV)^eYM2k..zx!xÅ`&jV-ŽV|Ւ/-1hda~7 =@&\NyicԷ$kAKP  @@߅SZ Ή#d ,/vqEG#$V# q1¢QT Qy/ :u}Ċa姯{~ŅWpncrL{Otn6!*zA5#w]WOna2fB8N7Yzd*g;NmmWQIuJƯvīJ($)awq䔄?k_T.+ypl9޲и۱+QTfdCs|Vq)Pu ?o \Mg/hx$1/=)y}œ^MHNy1y 1Өۢkx Q5c6 J;9\s#Zo}o]bc#C1+f 4p6 2GYEz!6_JrΚWxc[Yٚ#,q^[#6^>{rGZ(3<`}eڠ~?HrGM:;NdzU[/O!kVsڎ\50M,cJ'cYS(1}J>P @E󩚠:->3bFHv6t `53;b׵xbB2MSÝS%8y濾qu#$YԬg2hF W7:"=VGiu=F NMK4/V"2vOh K@o.OTxr@@@qǸBcTS'P7Ͼ̩lV03* @@@@`ٴ5ޑ\/A@@3*m@@@@ŮRyT~&@Ǧ d`gsl3Mxz o   $ 9!6EuCô =Iܠ4g@@@64ϸǨ6k,~鶧ɬRۼ_{Z/㴞ENT8xNRJr` YcOO:hTbrdirX]OD\1BKXk`s[|e߹15#G<nݖ'{i>l}>>#5ڻyr>l^Lv24sW(ƅv{^tt^qQf3-]£cSTUJG,^sE%ܾ= MRQ  )zkdoy @@$#x7{dwx)5էKnxO=)epیsO䰌/<;G}^ECN$c+ _i|s_ (Lm&jƳe VI{a&LVQJ ЎElQ t06K@=>s`&@@@)YR@cJ@@4 MjVͳΈWY:aIc^ˢL'!qd.z\bBr?BAE,'$ "XUO٣reA2ћij&G\s.%G/uю4p-[[[ ^ 5=.@@ 1PC)= JA@@>ڤ3bKyZK$/qOј\uVrXa{mFޯm܊ ף+{F2Fby>!X0gEdsY*s$nGX3'BdzJw+5kjrh  )(ǨHsc 19ZPv- > ;۲?OS-˸xc7'$\_Vr*~I3yV[M鈄Yt(U C3W?G*%8͋n\L/&oU!gť kkgO_]ؠ{`Tllo3s566}ʇ$.DFಅ'z|?wcZ @@@Sb1J< 1I zz@@$tppjU3_׃j>N?^l%N|5@@@ꔀgYDNRSZΠpss准 z25ԂT#ovvjZ[Soϣ~eG}PmG@CӸIvO*V@@@@z"5Ԃ P'7^%ˌ8}gN ;4Q7ni=u9B7ۤF^פ MK[Kt%5U1j>Iw A@@@U*?:U*-~АZ?x @@@@@@@@3dܴ]ɍ ;_{nL} Acco'Ni!?V=OO\0݃k!˃&K1nQ   HnNQK#yLwm'CFzH_X+z̨۱{bF  Y{vY6:Kh;Y?y\3ߠŵo;c61E7uyˆ|n{ Cwm;&&b"hRn:9i@@ К^"a-diBfH4aq]暾=@.²$Я> k>ٱ"D;@S"@X6* IDAT=s1XS vMӦt2lZ0Z@ƭYk^y¿3w25g[PTBJJދ޳g >?Xre1 []sR\RJJa~}L0J0N/$Fx8r6~[J~/}{TS].-EoF?ttDdi@]˼d;={/h]3+;:ʬ!+^x7:s}_Z:\3G++t\LK蘸;vRq1s3K>T&̼Vcf1S  2%)˲ϘNӔ~BAUok2n˳e ?i׃|)Tur=_ff,(/fAۮELn %1zlu~}R.{3Bzm1~̨Owbd6xĒз٧ N"(H&GʨP (RhRo\azg]LME;OD6=Z0j,/c5172s$zO|<7^vmjl7=fوw/NB0HHkKG+#KҞ׬Iqv^FʃU_Yt%TX6cY.R DNC!$rx,CS?Xz577t\6%~ Ulّ(*+eȲOr XS/JD|, ȻՎ}E%QTԿ-j m=wb_GʨP v5T+I005 c_[\e]C3{+=!2Žqt]=䚵?v\o i>8iOcV/߼f=ߓw8e7F6I3܎qڗ.lnS$ NXD,4F5o yZ8_2 Mٹ $;^ޟ1mjjn,˼}Z7ɂ JDDQ@Tkm7оjqsr?rR27#DGٯ^J^L?_foru   @vyZd=rO_]hl۰˂u< ScԞ}6wϭGdeۖϜhcFN;}*G6n/NXhD<==FC$=5٫er~777Z+=|xڳOvvܢo/։@SXjpEWC|>SR%vK9)X$?:8RfW?M J@@bbw*P   6)D3( E{fNGP[qߺ$JkWkNO8}gU;,*fFͪB] A@@`ٴ5Zmе^ҵ}mqЍ1pUT&]6uW@@@@@FzWi-`ȸ) R./v ?Mo0|?B<2Czp=v`ÛCLxijv}(kM'x@@ 9!6E1.QMX6DG_뚼jPӊk9eϙk1=ɤ3   >q$wWmv [W$umᘭ57g{*sJ@~{u{v:s;c6+K_?&?ŏ  MKXگsMNQsjpӊ{quok*64|sBSƩ";6PɅ=V    &=Vk0  d&i;o <3grWئ,Oqٲ|]; :\3 l?Xq򝤔Ļ2lǹgM+AWe&7+<:&.9N] E_cn=/":::{nYfl JHII}{{e\ '@WGAIXBO(Ԁ4uXV3sѳG_nW%1m/dv#]80lTPT~U =ƞWHbWƨs}$eYD:Բ9.sC.&x7{dWxTaMyh"q'nޜۥ7ع @%[T(ELcR&c3%   #6#0D݉ºO~2Ķ4}3 E+׊ۍHuX,sLZ4e>@LReG_2*I 0a5 I{%݈EbUmm 9VG}>(7`,Qϙ{hjρ@&kkd-t1E&U%cTtP  47kA/u]Wu/ -bLDɦM_Ga?c͘ö́L,ӷnWB-.}Z[Ƶlmn9/|B9O3"'I.k m=[K.X: z-ԁ4 q ;3b.Ե}ugQ*4/+Ӵaz6Ss1 <_,Zt@{D ;SDyN_xb=agߛ*dÓI245PoX§rœg%S&ҹ>@@@@Z/ھ@U(1 TB5@$^N~-:nkXֵ}ޫjܘOl}2146w'ӊӅZ_ }k6\ D@(YGmG]oT㶛zh9j!Nqk2e7`ŖqIޓ;W(-lǤAř7W'H6ur{Kc4q׭Lj.j;Z5"Y28cm-bAv¹MQ kk͡]>I]bYAWcy#c:潾[Bњcj̱lΖ3sv'B 4٩inJ9qUDoVWaW3“+Y<   /мnf-G>qCt@@@@X&*~kִϟƭx@@@@@[M[$a@@@EehV[`@@@@@{= } 8uCO͛)&Nxx\<ڦ*2>=0ƞ\?`!GU8Y5zp=v`x!&KY>j2mpt @; /qNͲ(&:ʟQOJA4 ƵZNs&Zt̟z@M q]6l:V AɎ/ZXX-~8ˏe3 LY5aϥ,Q3wB@gl5ږ9{g5Mҧtݞc AzmQM1(|p0bhttm_~3nwj^TJOʧ+ Mf]O;1@@I nIVXƥҳ2kDNZ ٱ@@@ @)2I N(^5nzJΰlF=v8 {8s3idfV8zwl/y+q8Z Ym?,+^x7:s}lǹgM+AWe&7+<:&.9N] E_cn=/":::{Xfl JHII}{{xq @@1Mc =)9<  h;qiex%Oo?[]u Vn Z)r8/sQ?ukߦdǞ O^0${,> G.97~*kG~Iv^nG՞ĝ.rq6i]z @ 40 zzFz *@@8t rNֵ}2D藅!+K߾*37Ii\iIL`4L-4XAFj$q^Q1Ui&&akoAWBD,*stlkc$.ȈN!Ҵm?Af } DSsx@@$]%]' )@!hy嵠:uC$(ۤ/`e5u_͚/P60iRI<8v\㗒뺊~qq[eVkr-[[[ 320#LDօN6Z/ھ6ڀ#h9Ƶ6wf$]ku=C(7p"1͇{wX$f88er-9^-錄(މ Og:\{㌰{S T';ehj8he%|<-I2ds-^   D Z/~] z zW"{Em 5k3df2Q_Tyж_[ *U^.~dqoqͤpn}^8YbaQA(*HoSSud1X}&mU3ЬSWe/"#GS[qLYcç*A@@е^ҵ==Vs+}^㦯/Ӭߏi2A@Enٳ/9{zox^NAqzbZкZGzL:4]yskpr8Qg.f\s++[a-,=6֒+d'۴e ⼶Fz铄%e#0~w#gnf[Bd_2y"ieɃc; ]RP$` DFಅF}zqQVrԉ-QH>/h c*@@`:88|a>y#"K7tk]Re䋙 ˲: jђ_'>XvTjpjI'q^'/! '>!IR?ZFBӳl$DNRSZ/wss5ºoK n?:si[.99mْwuD1}FHԴTJ9qUEoVWuniz$g#ݦv'T@@@@/GszWiF)AMP   H@3nI~tFunMsZOs1yέMaf}nOEx uNidրj5 ]%]:=c:  J R@@@0]C]~g]8A@@@@@@@@ 㦀DkL[<Cg$wWmv [Wڃ:=VG @"Ų9M,wͤfV8zwl/y+qZ Ym? xu!.ͻ)>ӢuK# VnDھ ɯrATLvUN$ɿn0[y$J\6 2rm?Af } Ӥ0il3$+W2@c#-DE[dHʡ$(f@@@}^&|y-%mk %6KD0lvYbce#wK6T Lx/xHEo&;,aFT_EQ]6.NumOG_[yʵlmn9/|$H0-ͷ0HVK   zB@zIia5g@@H sƍk7l\̰I)Ъе}Z(i4|Gkŧm>ܳCfb(f >u@x{\YXz577U J%aysXVֽX§@aγܒD)K6*y1["?ʕ@4:K_ۀ@AvyJ@Ea[tPmkyAފ56f?x-9͌eDtmV"TQ^.~dqoqͤN_m7оjqsqC,xLDDVmjjn,˼-*<#^ujS=EdzJw+5k=ty{%qqMd5['httma  M>qkt18Zf\!c݁D^=*09b"'boX// )(NOLZWkQ|XI3ov N.UY8jt8sͭlEHⲌ;c[KXpn_F+seקOngXl,G̈s5:deW%<8uq+OMߞPLd.[hw{1e%GU|d[?Ȍ*/Zq!+    AjPٺnvY^;"n3_kk%N|S-x$`muܮ@@@@CeO9IqOzjY͍źoKO CQ1&]dTP  u@ԴTIGJָA q잟9tx6#%dJ@@@( @Qa.rjkz&$uI:k:tiNi;f6Ϲ)_ݬZ0lZptv^Z/ھ8X4,qkX$ҧ'wM:5hzX-mްǚn1r&J7Qb6PEͨcw6귬8콠vl-UN HX㗟1ZAֹ㥶}@6`sl3Lm/ԶO=sˌ~&SNy* Mfk}jiu X]i1!HCwm;VRs;c6QgptmO{Nf AM_3?_kdbYj˵ҚgF=?SSo^⠘rYCT'ɸTLuS3  : P?ct~/@IYj?idǴz|%Ш:tqxM-z9LƬx> Je۳iR$u_kOywn'UT,Ŷd(qY3w>e[u2t sz@QR-@@i' _f1;V_n5lOmXLK蘸;v/}{TS] *k5aSPlJJA[X(ƶ`wRF{f :=u",>1jQQ>8=2~"y lW}-vKFX2fV8zvr[|e߹15#G<nݖWpe!!Ǘ-oڰE{>z /z/zB:^8RGeؑvKXJN[bf+ߺ~>e_6%~>3j~,ύ :r(3iŝPNr2R*:^S{Jp#RT)z62%`t{"qN_Vs]o#>`?TȠǭ"}O\7CY%7t)};w1x!PgےG&8|op[6E{iLmMT$+yzc\Dn׮yPQ6)E׿@AkYxF~?Ιq*Z0҆.Y8u]5U>Es>&<>ls}٥Y UGy,׊ǭʺzE9FL*Ѱ-: owt2Q-bdy6|*Bb[.P &Pz&D1I51S3+ {c;&( (B*ei~8bgmL(N2*EZhujbJQJ H|ܥ$%wd/0۷owew.+Ϝ$>\Wa ? vVQ4tC$"u鉉jwոط PJnhnx, f\ytoV55ICkE׉vET&=$T.~ ?QO;K KjL(tw)~d ؁LCnPsF{Q FآɌ 4~\zo(Rf΂Ev<ByA,"ę  =Ǟfd] ?ǹwhs @ w'Z<4Ot8}N|6Uܩ 'շì cq8{dz?pr[#MmjeXѾ[m,f@}%IKBMu5/%&<#96-FpSz׉aHB̂14j+/bG/W!*ق45DcS־A5WJy8-z٠RdQ7(ՇxܒMMe ?;U8^)?eu 1jis 41Opa"@' al,g ;$!' ؇뻝je wa[G6K?%Ҭ*:4@`j52?{5Pv2DZU{>}'[#?n}BgfmK~g.Z!J4 Xxr$SsK5,E',蓳Jnmy!tw#< ^<~\w>p' U}wyFʙ?cq3{ʓj?>@<{t*QV5G/4^zi4nw2P]A8)|ȱHM፛pV\i5#z#"zTV_>/'5r-Twkی!$06NH'Jh?oEV/WZK]Lœ&+`aJ9uN(oq=b^j(gVd'gu6k4n{ KJO2&C@y^CyҵC%IN5Օ?c3cυoǭ=hE\yZ#ՄaI_\[{%o_9qG;ʲVUܐݬ=6OXA˪o+_2Zc}T3ybIDLnK6cCGcMڤl'nYށM fiS5Ot\jzRQ*.]{hmoǓJx@W}APܾX< j@w°` S3'yqوb>XK8!;T*iMUqV;ut[Q%wzA  ׺XWw]>Xp;h?{IIL@ D P@B]e|ƙܳ}|!s[uEL =bM^[k`u1  IpTpph~yyyF (c>CP! th4{-p9O6` \ܳ$Em;Ū) @  HPK/@xܞZIENDB`baron-0.10.1/docs/grammar-python-2.7-3.6-diff-2.png000066400000000000000000005771121415427440200211720ustar00rootroot00000000000000PNG  IHDRsBITO IDATx^\gf{tDbCwcoDKo_tӌ/1$QT {ga [gDvfvD^`PbC@sK=X!6z}OF<;ؚBԚp"~6k_[*ڌ:FrϫSOyb_JZL7k*)GvP h"->HG>Xy77XuUNkک_κ@@ ~kgn#{8?v;|;,ykր7e~!h䄝TB_¼^ dlk s'j/<7d\swKͬOUX㬼sִ@ } ѡ9vhUv/.CmPlqM@8K1g]p炳z 1 'K:)2@8J8qς"GNNdS݃6BDٗ~ggJ4KmiΑ\{[I%-Hq8d]zFeVL]x{@'X"0xvjS  6&g\K:ǀΪl;8(;m?^j3IHT]9;p~ w3T(갥d]~ɾu@"ǘ+= k< ;:?EȪ5ݽi]F! b yGU~݄w֕**~ƋCr`?43!jjǮXb1O}#g~{->}KV&;1^Wd nV9[OS;vGKHZqdF=nF+2>촤[woPؔ:&{h9pIw@L4'MٚfMEq|gnan?c>Y]m]]Fζ-%(7h sdm =w &ȥ[' SV#EX vFGGc:r`6%5?\v2KaI\P:~`|0ga =L-C9I1[#ڎx̊s..act:; }9xaPK#^ sAE}k h/\xާ$ ZikP3{tgd3AxF [ }+y<\;x_?4|qpZhMWJzuU'wZ멿F}*{OZIH^4xuygM$uVD $9wrm`㉧)y_ü M_xz7dFD^?~KmdI阆*eS1"̦[ltV_6~(Hq;l=`ӑ'7Q>bPw:sW7qn3rs[߷W|yǛMݖO|EI^ ~~4DA/ 2KwKOVg^>saLz,,hS']:,edx.bà~ &;=r Zch~2|1c(BL3 L15L| MP@+pOS;y.!,AQΒ3CTֽ;<|:yt ?c|-R:dLx!H2%5jB"ܭ&g>'/؝*>ͲWTkkK\@Y'IHԾjMT dXIReeo7g~Ȇ n- 5[Z^UcIQ_0IA$1.F~9jYyc!) j Y51 Ƥ<߼R-s\g]l|59WAӮ~a>Bq}W-c&aӔz~u]\gH]Es.KEΎ/ij)bU4@cVοo?X:18*MvYb5]/AE~~_y:qmU){KjK(RҠ5u %(ܹǺ2!G5 ȗd4mR drRL%507bc W! -gԳmf1zT"6R7^}c;MJg6ڟ:m$0#o:YǾw7) \r:O#߻3% OCP2Bđn[c%GޡzKC:mtLO1;)5 Q""rԚsr\1/6ٕb^O%cf]<2Fnsh00?-I\0:i+ia_ldz&~92ҹ>;WlYӏVSzmky?~YwOz7/_~g8[@@9ǬLo!czv1YǁO1c1d_F~rע%D]A7Kͷg~|3Z%Ug?9g25ȲSeX/L/1z~7J\d-zBqʭe~==i_#ՇYDNشJ'MG?/X//##M 3PNクmON)* 첔bܯ(K3aٱLvbYWQ 3Xc>=wu |˗|6wreIJyz%~;mM5FHaq=ֆw/c5H_ASmXfYv<[kQns Zt!7s8=ډ>w/& υa;~'=P @kx ;7)E sz;.{s\AⱆߧA/ ,Kch&M`_5h{/ @ @ 8%=@ M Nnc@ @G"թ{/HP @KݴPxo |c޽5Z@%Ń-:4A<ӡ-8Dෘu:op @ @=թ=#dX my?ۆ+^XST'Sb׾n=?DI Vij<-e䞟/|V| B6m!u?w!Ա _*1~8z8a/gO 3twG= Ю 4?]A<Ty?cNvC~u^EIF-]8ԇ&뼝Fz~sgk-cTtϡpY╃|G߻ݥ/'rWaz O+o*D6E>Kdjr>g1T,/䙤l!,/~sOr]%),r @'ВfH 1cI :Z㖚ꞰNzb;b-TzVWh=}\%W !O̵ID-I俫𤖛 iA-@ФO;/` ЦȇBc۾#ڱӐȃL} X@&X8mn}U6)~vl(/LB|2Xº@sP5; t e8T8YGK]Q뜯t>˦C&T*Sy8wp?YWזԼZ=ӄW ͻQY&cELzÑyjC/Wm%lenIՅOrD8yy%߲+zT-`ze~|Ҩɻqpޤ RNU䏗FVۛu-{ Sk RǦI=cGciJ>Vrc[J!s#v0z#s_ HOY? "~ts۵5P({L^u.M2iI'=@J1fQj-1$2qOl}i<>ϷSltM5huֺd'44n@@tx.qCs=!W1hӏTT:/|h\گ.sAE}g<2$u\2zKsI_~/-8C^[ϖ=Y2}sG c~\|-5&y7's^m+R/'i`ÅLI=XQmԤÕJ/IШ~rPv@% ɏ99_=P zw`Rw+qQ13 ;X_rxg b(qͳ16v6?LLȓ?̸S C=rݦb|}1䟐ba1c k"u *MD&oyKwHJ)22 8==p.QԦ#TYo>U߿3O<-hT=' xmXI-Ff>z 8>!xigUݽ݇ЅK6Ćv{+SUeeq0Y)%Y tmEnً ?ZmId&9Nv  KEa޽G|D*w%smC=g^xSRj󈄡P'I\Y|l!XbC}JN.f[DzZ1}h,9tSũv9158ɑ{Hy^q+Вb{o}U8BS06c_}Z|j)e6Z/얩:tćGeϫO}{w$$))-:7@gCʮR[^y6s5,x}5;qEDG}P"\q16}ٿްm:&p4 f["01Ov#5zzNcZ`;C>rW_L,fqmvyhz{9ǾRO,njͱanT b^O*>ʟPLHh$bLWPl)uA[#:C@h> aN'=k8OMavM^=V$/|ɞs^ҏCukdtae[pPswKnc\Đy{Aq^%߹! l@G s domѹ6q[q5,hR ~9ə=rj"pjj^ruc^թt e@O,(Pru+l& a^Owӄ3-7Nk$PΥ6+mQLL+ *J.0Kԡڵ@5-d 7m"BOrrU _QHIz%Ku9OInW_M|zN>tfZ* 2,H#ӻȍZsî9HMd3LH-%Jx&o$i7tNV ~H;r=w=VI*ceNtuY&RR5bxQ`Ynp¼—zI#Fi ?'Ɲ7;@gi x,TW 8RCn׹q[]&owD73 WmΤ&^r7TB/EK3"A @܏ޚ92|'9(v?:Hl`Qd\~~ޘC5"z_cQxʷ?;A~NzmC܈ 47?1ȋ$(oLs C_ʝlylį9Ir@!@qliy~Ȋ+WBI.SN C<42Xx̥t2gy@-fݵ7lU }d-L>9q@ pYkNԚ[߾E@ t5/K=Ⱥi8Al izظ6[8?qP@1:2g ;b&i|5+bgmp&HM! z6GJK틁@8Au pFFk6e V?KmTA<*XA)@ pp8@{D`͚5-;:-\;3U;[- @IvOd) @ @ m&Ns?Lݵ=a_OJMO{Agj٘p.q}#`6@<ⓋZp$.+?]A!CuC}pߑfK ?šum1h;A'I Rl~.2Ջ|<458zbϒ~}S?5fq8n36x)9}?|agS@l5 ֧dաerX9C^RZ\o.g98+Os`0vB;ⱖtFz6 cV2#p6rVⱖ͉x~'LzaY,'v?b2%kN+P?p)f&SOo>{ܼn:}…+{Y䑏};6Xt7\{Ǿacv2#krǓSc}?cSoƮHy?|ǾO;i;kQ&Z;0$O`KC8(Q`N-.Nշr:?4O<(_ve!a zIY۵1iIhʹXoC7 F-0em n .n8)"nt,  Б `g}xYհWƸ ߾5<o"-SQ鈧>ܹ~du*7dʭjs[>|'?h v[YWﯚ&o{A<7B<$ k21A@DU8Q>{L={>}Yچ =-Rqb~RCG O>|?49W_?6ѫvT_j'fNz{P<뇅3?/Ǿ1h ǿGWgM4[ͣ??i,ivK3ȇNy6[X{gu;%]|^}+Buyy3ıZxj+܊bg[z-hRA?nYvܲ;bvP%Lb @%tXgw!Φs:U >PmbSމчIu~^; BUǐ^sK_]9g_'kA<,@[A#@$`7{ 0<.C;HMqE+ q'kX͖O_aYD8 K{a=zwVޞ>zm-5[Y!% $,-)5& 9LNStKS8i!]ljV`0otgʭ!9}/8CɐϷ3;L^WմXtEwύn@tH:uע<߾WWo+< Y0'u0yFhx  -\_6\gnܤO k.JqlL1Pˌ #Mv /K/J9b6-M\|!`M|C'TF#lhsQyv^Ss!9L/Fִx9Ӓ*nPYR^k`C,g-ז @#{I(] v|=IP9M,nH_=5nY>h|Ic, @xcXFT :q$seL}ʔȒ$ĕ\\h^u >ߍZL8UIdzp]'&E3w̪NR[q3v籍7lf/ d2W-r;_$vU15^}zçgR&.ꊖ~VHQФVNj%*n;9DWrv򅿜Q4 7vv2D_6A84YsKn4 Ё Dmig7.iT޵h-yϩEiJ?pw/re">ǻxu;-ܘ{c|kU}u~n"j#:Cu̓oB<+NR;^Yߩ(B @"@}3hX,-x]_8wU:Il`ڀNj||Θ=HIg=zřiX ))QaR.+˧,bRz9 どnWݙƏZGcTO*Y* @ @k2q܀-M^WNlK+&%*SsP&ՒR .pb%^pԘݟ$~]Pa'T1wLPuZ_Z `5 [D[e ~ "$+B="8q1sO[ q߾v2YZjD!FNT |.;|D3]p0SASqx" fȦzuԠa\T'B% x5iՔM Z4ن DRXM}H!+QN/:5DZB '1%(V?0j꓍As!3zVHUo% 4/Ͼ; +PIFJwKdgE"'vc`'as IDATH<ٍʝ\WQ`waL,tFKv0rO .S Y/*MH"%1\+̍ק r/kYU1}Os&ךD9j(:x9,X/>y:$550Q# NQYdiƃr4HY1 h3֠ 80l?0เ.l54-qTml܆]gUCן-RU$mܾwI4*aԻWS j*):w-mX=kJEtQ3POV8+9'mN.Tk{MfyY:BOec"E5Ґnt4Ld7q`"JDI|GyMD%"8(3t/]C}j?IMm72e+OjkU&o% * ^CDUn6" @ Bs8~Һ=W"ܴ?qF7r(c( T;yٍS{2Lpc.'E1Ar|߅|C 3%^]0vg*~mH"N-#h >LYz# 0o= daG*;C%j_-)b 'FA 2u[}d1G7f y,;KEPeSfO:ؾ|=cs}G/e7D!zH<.GS<}|75v*,da(л.G}ē~5p=y)֦+qK`t38gzF PuJ/ PŽ @ MuM&:BL Lgƞ`yPCtyrҨǩj>hT @ p d̶==Ee&A?ʥi8&#l,*Т Ng%4@̻!ZlE&]`E#']CɎki))jT,EjHDkAeo$ࢨ@C5Bk ]7Ҍ1TIbjE\6)_sw;d=k5Mz˳`?c5c~=f*ŕYW1m},Ú20is45r@t`~8gOݤn8sx{hP8ш.s9BA1_(TW;vVBѾ ,Iu8ev[aHP)+a;&8n+ґ*FwWh܀JBwӟ8~Dbn#fT˨Ck&pq$uFyJPJ'vk~G\iΟ!RdN5UMi[fbsZIaLdtw:~E֕ Hl9ߣ!;ٙ @ @ Z9q\P ιM>c{ΕPSRb:O9"g"4yID_1Ck._8x\h|W7 i/^j>1 e74wTNVʜ䋾VkzeU𰫊Pg,X0TPg^:au A2mCF^][aݷ!DZXT:7zS}5U%Z\diwg R}jeGBq%HIvtv8v_jwhdTf:{fB ;g[Lv/8(b\ʕ&_ՙ۫[Tz%@ @ \MEmbBXjPILJzm3'+\SPޡ Pj3CLG_i^d W$IBMO9v!DqNvMIΙЫ:9ѵt@LiK "-1O/2@hrkŊN\^K1a @w޾vㆭpG«G/hNm#s?8 "@ Ԙ H9>%490)b:{lA @ ]p!B@@E|۹`@ ]L][@ 2;e@@ @#@"H0 @ @t0'ҋ4!O]gf_8rX oԲQ"_XIW^Vvʙ)iG@< > @A#9q9)s: L.J!C_w|EJ~ajIrv @ =E]:'#Q)aOo<58@ Wu'tK@ @?\xIj\yXsSɞCazbFuVJJ8ygOk=9M^v㿧 HZyҰ[ /__7r/X}ƆZT2hnivS%{A /773_$@3Oj\JNFy|@ArkדNe T1%*,XEp}E޵qzTy)Q!R.S]Mۥa)idW6FӲ:9]OŇg(S౷s=z|P+3&ۡ @ mHD\ \lY:ye?_fL:-M}{Ig0q؍Ǫ MVs@_",HR &S[1ɛUr,lYem"&ei/P4B$*%'!M۹'Ixb}湣}͚O&;r:|T.;,sK96]ľ^E5&6*̔tzmZw#jdY;d ӷƙ`I׏n3v.=1P,%\DP @ 퇀N5awBt=_Sfq- i8*$ d:V!HcmA\)8ܓ 2?E/@H%Wx]¹W,fw߁Qgf{M%"J("ґj@=UO=<;O=Q@=NQz%@${Bfo6 ;ٰ!!%l^XC8O,߽ǹ:o(kpk /3"nԼ[,vmTbl]onbMcМQNmڕ{k/OV:d8 @ToMU4Շ%5 > .~ק @ _o:s5t{Sێy7zӡ%R7ovҟ-7 au1 A2jbS'c(oe@]~eējVjɁ yɸl5Û̚:*<S܆EU{AM#e)/Wϰ` 9V1jg)m@)oJ{sڻ_~rfKUD0,<pܲf| @ @@Ta@8b /<ͷ{EPi`̐r4էҫ\̈́ۺr״d֢)2B+jmfcyBHǿ=A7.>b!1fh"GVsNVW6rwO!wumzG‡Nћlƺ2tI6) y7z3zHc(rP19y¡Ґs @ @ p;6cu*AGc5Dg~3nS7pw- QSo^G!@Xթ]m[TXc (&S0\ @ :rqZ%@{$9J)"XL8Z @Wu P3@ p$FQv,!@EFwʠ @!buj{"& @ @.9qGFDbq% lˇRȴ{ϘC5R~xƪXRTGWsRcЈiB唽kNAιCbTĹ A @ p &2 IDATp/!H0j &=?Y)ص*GʑBiߒYYe1v wdWRݓ2@u`ܡ& uJKj!Wʤa뷯/P}f 8ee>9=\ƚNo=; CyOypxBiBIZ2Jqi X2Z.’wp[=q-4C늄!Is+v?\܇6˲$<ꚧ1f]M"$ILDX Z++uBŝrsoӐ_egҺ"ǰ!A5i#G [U G|?%SJ(E{Rb3) IwRp@5OJ0%ݘ}rc5qEJ?{ɑ_m~S @]I@_4L,[]e8=|{<[ѮYrk"oleK"BE0v HMNXi ;d#qbٵ3lF{f|:nܔv,PLݻ >6ܼ1Gfmqȱ(vԔ%/Mx4?[\D3g so[y{z7K)CTeqk=L%0Ιwfl]m$ι:֋si^թߵG.磂vjӮF֥gː' Q \GC@#TESeiMNzzPR .~ק @ _o:s5t{SҚ^vӡ%R7ovҟ-y+5iuvUxJ"ʪ)Oي#8(vh$Q\Lcyi2OXգe)ŀۆT|lrDh ?8kh7@n~RDpӠ"MN5<3o|9.X]i~*qLBO(n/}C-s_7gXl ֦). ;qXc2l@(pù@ @ %թ€ql&> D_x/@VW6rwO!w쮥 37,ue&ȫ7Ϸ={N=1Eko<:6Eq#@>>FYJ#KSt?cXݏʛ( zۇ2ܛdž22to\|EIBb?V GVquT+f!*6C5hOW__Ƶq7OFn?~nKH "F|U*A  @ @XJX ѹ @ `ujg  &pVV+ @ @(թ7" @(@ʺEs{1$BA t2uAu @A(ihT v4 (؛F@;!@ @ Ў=G)92Q:Y<~֌6qHP} 6Lxr%MtIc_*  WZQ]e@_+(MWٔ 8|Ӎ)qTŇrM38bS"+e;tEs)ߥ=gl_-x.KrGߑ(9u]jrDjo?ŷ72=2$.s{0 @ @p Ή)44"putGoloZt_$qXij6LaeEOHrpൣ/cld_J~f%$R9?aé}kxՔOUq^K48&䑊~bBƬLߓ z[o RHڤ9wĞ+E$7uHk  z$GmD$ N.Iȼݛ7V9*IixCNl?x!%ᓦU{EP)29=eN[_25 {vo}816Ll>w좧4>}M=iAƈO+TT:uB ,r7Ւͪ9>PiiWg@ @ UH0j v_ܬ[NZai)"y:a${/%S[3-޿4Ue=m uߴ0t{U;eˆI;6Z!_Y O|qU 9(ZA4Պb:+_-:|sFJn?et @ToMU4Շ%E5VpByw}ʏ @PƩ3g\cJWLܖ2!5ӡ%R7ovҟ-y/H"z*I%*CcQXuZ-7$.[ɚ vi`0^+GsMI8nJ~Sr%> "ʪ&ݑNnO)6$7d%r9cb!1fhn#+i,`%1;@3xcUw n#3CB6hOW_ʟg-" f6'ꊚ6.n܄h}Ͼ_W?C @  p#\XJm] A)fM~8i!ߚ@]^@tdAꞽ5xWa@!@:렓PE@ SOmKӜV}PBǐ 656hy8 @ @Gĵs \'[Tk@ .+.۵h @ו% jB $*(d @ @ ,@;3jJu W ]5iU|Rgg VSƼ>˫bZuZ3yqlJW6R~>q[tqJJ<8 N[_Ľi"@9XzeWOw3Qbu-qh5\QFtC$@ @:J:Q |,jpYISVlh`'u)!F'겚)NjB @CٱAdRbQe*[^ EQ9'MJ2>\}"|jnD5ş+oG*%S.YnpՏ7݉Q!"n9vU\k3l8P)lO,.ax-xyck`n2ڜ< #]SEm1GOmP6bǪ{:-Ǻ3k'Ą0bALgR;ѝzm9 @ ~zO2׳ՈVꩋ('=-~fy>{qzV8mҬG+"zZCPqאqpf hfW|qt/2̪^{ja6B^׿ղסΤ0"y_eIɧ=1j܅y%̆9k/{e ==49=.~$?iC?zV`A ҵfhe7)%=U%ڳ__Up2 @ @ ۾{ Bbk]s -X۷&q,ð":!\&emU9~~šsgmhP>MKC%aɋM#a{wl*̷8q&؞"J5!Lj;?,>NSbl]M1\OimlƂtz5+l @ F?S+T*)S:-Q5]q F z왔E-VB|q4=~pc"P* A @ @+bPʹ_sӥv6|Gzߐ,*"Z驎r<2GG*)n:vCvn8`ju}qr9+k͢^7%eĘMӴ蕏eZMKy.K)S&d?xPY+1lZz0zn/J˹c/~v >vO|bڑ6Q_nk'7ij8x`19H+|P3HaBdi}^#Oo]YLĚ\ZK:_?@@ @@ ]+%:1w] > P=ޗWg! a)) "38}q_^ؤ$1SgQmUy]Ąޚh8I/VJ+,\Ч]xc>!3 @7N9T=guG9'ε$@.vG3f4\Rna8&vwiSgJw=K+~[>֗ @ N/85m{tyӛ][ުZqWGWoB.tŒ3qg!t^R-*\ҪvFf @0GMOzTZovTQ. UF_G!@Z%ϽS[U 2A @ @h8iŃǖL|+pCv?&aⳀhssVOV}bUqZ<_>RnF$-cKZBǠ@< p;6ere( @@ 肹ݷl}({O _\m=ZW}LJvLJ"+%tobޭ#\1oyU]0@@ @&<線"@CŔ׼d@ @@ީs倫VY̵RU IDATPm>&'Oэㆿ;1*1DDM9N*Pe(_\ asɯp"|1װlGeiKw3l8P)lO,.8@ @D_vYhJ>Qm'.+/|e?g6Y]k+_CsW{qO_|c{Y5}ބk&N4둅 !p og=Iah7E !Ub Gēuwℼ7o6k/u9u9˲̃E*W|:޵04~Cq/<|`8*`uӑ$\?z6~n(忌qKYX\8@ @ Ngu*˾cSa5TMzKlO/04jBvVnY4!19焖a,[}ɸ,ð":!\&emU9V`ɋ^V"BcxGܷ vto2 Y[:q]OӇR+vi5FKQL7MHbf+ff o|- @ @*HNdrbM&WrSxq\ߔtvN*b)S%S5]qC5 F z왔E-Vy2UyXG[{<_ˍw4RX༬Voe ΒQeF[ou. a 1W~gocW?C:8ilӿZv}˳ҝ8=|BNͦFV4)#A2FM k,J)ѨcKI1UTD̞^_]1ƺ+]IHB{ʨ7G>q<zs{}IRg]P<ٻ3S,{剗Rb!aFBE n|כmh$B:5z,M-D.=p=z /ppYVͅ%( E-^N[dS[vq^WrFr= Wk`T t]|sUIRna6o9,\"& `6sS?qYDxz!w9Z?˥D_<_5DovUu5\ɿbQG (iЌ)lvA}B~@ @ ]?sưi˿*e,Ҏ%5Z]wyܷ}Z]7#vMo-zyEgt~0 7Vs@zce!){JΦ)z8΂HAP,z߱s{_M}.& 8u6RTIol-<3aWf~*&%Ezylv+TIZǖE- tJ]Çk5\oB/Ϟi9.+OG88+k,@ p;6e@ HGUᄉOخ_qWM'ݛw'W[^U_&HJyQ/bv72_yYc^YYROA=cκn&9;U/]q,˃Yݟ$<7\Qz~.c{=8n# @ Оdgڱ=.*vv[w>]"!@ @6'\07~JmI`U^4"Ft)cf@qߝ"즜c?Z{L(2Ok /`0ѹW8^kXY}62hCCܟ<798X`+pyIW1㙉Ɖ"jAv+k.86QЂGO;6oYySl?~dVV~USl'aHd*QS~zmMS{A #꪿Ϩ8eqI {sH5elj85/~{&I쭿{w4Rnɯ\P%= mW[>e}oǿ>=DڈC32w>57yNRҚϿNZi"bͣH@<{JSmqD^HI_,LŁ} k\?zO}('=-~fy>{qzưuE!/e|ԏ_ʺ|-) !D6ҧLYQZPK1̨8`J Ox!Ypɚ.:>i{k}n3?J&فW5l-15/Z"W]}kegs)7>n{SW;O(E|]/^O$@ @S$I_T˾cSa5TMzKlO C&~^^mg疝֊ݟ%_OӇR+'i5FKQL7MHl}54clZO|<׺Zho)2MukG/H^TTVu5uǸ66bd Y$u`kl ]lJ[> lMiq#MlHH), u \XWo:z޸n\WHSnnۏrY+r-ܼ=Ƥq#qD_}eVT'ˤ*Ǘ׶]HqkNJH}g2Q/um<] @ @hg̉d5&L䦄lWr}S~ҞvN`@u4ЄRX,U!Xfvnyԑ[M!mA-HLGTRϧLuzcfjCdHXCCBHK KKYk/˰4ՍYGzӇ՛hg6T8H/X`&;˔/0*(kQT;J't|2 r5ahM>ߨA=q ]ȹW u_׷_:A U@_4L,[Őp_{sVfS#+itX9(L5WqC Ł0GhQvc T-=5~93RgX<  #7#R(vs嫏]xۯ_n8 9N'%O pKf3KaI%R2Hfސ&$ 8)poks|,A3odO8cvޏΡĖHO`( 1ƺ+]IHB{ʨ7G>K桩pgOq\u]{vޞF Be=妥Hwp=zp  W_F,?SY}BiqR⢖u"޲u;.(g$H}1!8Hy%zn&>kEdC4hƔH6 LՇ+]zbNBV򪻅ML?Z :5o7m5WҒ?7G 2^U$Hv>DNQBںn$Τ=b>iY6o#q~M<;{޹はk~W&$1 ?*%b[l܎ f37zmPS8v@>A%P9ks:_# @ hHNkJ` ˡRr.؋_]e?zlj}第5۵?}ssYA .@\z_Z\=|Pލt5hS3#bD`y)'eQї @׫[SMU59AIQ; Ԥ oy'0d @~PƩ3g\JWL<Ĺ^.(s0tJ0,>%˷դ-5/B @ Q?v8z^=]fVwwʽN!=^b$kvgm^_-j0z tR-*\Ҫv6! @ ;HqƓ7VHA9z{z@鮴έ]>XkROl>=ae7w0RC_PֹsNy^r@*ZQn# <]FQ0  $W]Kgڡ v1 8˗_iKNxY[!̟szEKn~i)-Q\<O?mqpWqZ^˩~Z^bwWi.)r_!q/Ne:amw=ҖA74sP>nr@'p{ݟ%#wV?yQJa'`H`s;^~ɜsg3Hǘ8X~w?bS1A/~++6ڿιIr2S;߼o{p%.P j՗No~8#P>o1!mIn~?~'?/~~Nn}%_5}1Ak}6sDIGfo:lCk?yq?|;3};?>{h:@?losg-yTә%d}si>CtH %{_hr̿vq_L{u5f= tkx;cB<|}dwKV.Y_6f} {O7^,fwx/-\ 8H.niv؝Sx?=;E2:_vyIk=\i% A6NW񼲽w%6oXwFgce7x} XaʨnAt$3rv:z󵾮V-Y.TrK\Ӭ8VsTS}Рp]fR m8숻(a)+ '}q R ܈ߓxj~o)q<"籶]xk΂ ̉㫗((6Hв])ߘ)R/@pn۽\z\w aLckc)L\K:]|U=56o6_b%/g Q IDATrCD|ּzj[io_6Ƿ7QاDŽV2@%wnưmc(!wk+y[C^tKTlCi蜵Ԕ7j}[!7 N&=NUP4}ex} @g{>?t5U={6o dLID$K[VXm9q|z5o 8OJT9eZ^AR.jWG={h@wւ;Ck{žE1 #=4B+7:@:X <Ǽ_xn:N#q+Iܖi^xk}YgϞ>򭩱⦕⦻Yge57q@<wl+~բ'ל9̿mr/h`{oŏ/-HkkJWd.ZZۄmݢ_j?VOwcZ=ɺ36L<~]~_ꗿ_.8[q|T7-ҧ~׽:wv 9ֽeڶnϟWnGd[{~L>foo=7՚sɹs~ry-蹢8 @k #xp<|K1>7x샣:N۱v\.wMD5B7䓦&'X=()J\ÿpBO\̌VB!x Y!\gΜqt{S8ײvN;oL m__횎@ y̝ ҮNcW燳!\,8zrV|K? V8R{>WfNzNmXsPw@Nu 8?x~oӿ c kujKB@n0ݻmSç,r @Fhs^Wsdžk*@ @ Q#qc t=ndžrcy|||hoMD#zg|4{[2yfU,}#eh}>IK>{ؒ1WOh}_6"B-o @V@ݟ$Rjq/7qgz5w~x`%QI&:WtXEP0 @0ˆ@ xHzbc. tػ@#@ z!1N&UK/E[X5%s`$#' Uȧ&ITXZS^ש[qRޙ~o}4}?mss倫VYbCn~=Wr5vysSuM~҈7-ҕokgpg-EA ^=ؼeMuq_ɯ\P%= mW[>̵}֦-qߝ"즜c?Z{L(2Ok /`0ѹW8 |1װlGeib3*EԂV\pŅ5|~l-8nPݠfC OͭjŷRO]\Dɧ>9iQol0ϛcֳif=\]3$FK[i}M{e|~o+%Ĩٶs23欮5Oy-ډF"x2ܘǞpeSt*nB$Tc Gēuw|Cnk#[A@7,`x1Nw!4~Cq/<|`8*`uӑ$\?zO90_( y/~\RVkͺZ\oF&@CSq@ , yu9' cnRdO5eVT'ˤ*Sx<7%n۷f~nhı;x[K#JQﳠ]=p>s>s>>1e V1#I$s,*hڀv>w:+*J;nI,K侒e5xiyuqGTL.Q0P)['JdJa6(ȕ*b1ޚP<\Uχz1ߴXM@ 0'ߍՂPp(z|A  x/{FT*/+hɥ ]K<( <xkhIe_|rQX8c¥!).eߚǒdTeU7_>E۟f`t" U)"0gap/YWG&A$(Knjs,Uu]yUjif2(?̔\9IPhciX曱vA hx`uj)X@4^"qU˷1T-ۙZ; iW|u02uƒTJ>\reJ.&7&5E?*cnws>Vzښ# GV漼F0ӒCpٸeVla\,K}$cծ =[O Eaާ-@DԒaq\/j% qסrG w& :s3X#@-@*n@  ݑKVN_ܸ߹2B|vumYӎŐw+jE wnnTJ" W/-reD瑝=,1q %7p1EHEwC"Q,8 Q(饢™fmkJ2`ڵ)i­ԓ!}۩m%#ƕdz9ןuZḧHT,w-B峴>lKϣ_h9Ű~f  EqqqFʢ%B @@/S}T]R-U>[F  \rYX!#ٰk@q) >~$ u;:U @ @S au< @T³oĩYUC,>l᮱s tث\#4 kFh倧݉ ȑ5W]53` hLOM @#W,5uzQ7W=OcQg9d6 Y 1Bթ@ @ hlezo *ZL5AZ+nGcF+jXxlbbbW8}?L!:dş1q6yڨ7fi3]x4܌[ѕ3*i7gBLm mwI7.}7@d"c^JUVhPǴxL1h@ PLH vp>c7?%ӈܦMONgU֍ (ʓ=7u#iul* =Z,m EEz{֩z<ⶍ ^[#WwTy:B#v[1qi_L% fzyt:ё)kx@n]Pްte1 "o1b=Q /kn9͈FXM<FM[M,O>O7zj9l@ P hx ⱊc^sqc= D1TZH} suTc,0x8Y?'NS.f2~;ܿaPs( :-#<-3ۛ2%oǿoIk霾sƏfgoeQ_=zL4(8'݄ȡcXoy8YntVw_; ^~6%e:];ħ{۶LX$ѽypp/OQTPSł3iPAIǟmmglH{Z=? 7Z9@x ⱷc:{8 1&@hHhvyi}B%xs'K͋tan )BbsKu OB"{h`6zL9ȮeݬSQgnP+`SECתLvOًq*mTZJAN]$I+ɂ*Ej{EEX;KqmWEͤzP:Kgj+*+òj"5C(VP/3;ZuTe++DN0?p٬t rVz3Vp%L__ qI2Ĕߜ'!$_:(ӯNZ0qpW> LjTw3?FoUV+=̕>3p0f}@>37.قK қ9lR6LaYzJoCz mDYffHaJkj73Ԭݝg:+؎: 443Ͽ{;iPj4}nuJiAkv"]=X3֏W ;:uF'jgf{U; Ê XFqdJy"UN9"6B/JwX-c|bzT\CO_V <"hr&A<񘖗1-P  $;S[犨];~ ۷F&2+%A+w^8tLVV0޽ ^QkFnuF3#,%,*?;`˦?MO̰`&Xi!%Y 'ׅUa۸84U H>:z.rO"t^P,/lOH_扥qϳvzGPfĉ5ߙHnbAwbL:U*TzsUnP`z7<`@4nϾYj܎jC䗀~ĪJf P{z4T{d`d @+x! IDATW?0lMt.NhgvW7<{E%ݪEg-Xpe2nٮ^Jwd/۳Nu^w-3m|3bo\p1MEFэo\zfc^c@!w6 @2̜HOemaFGy@6 @&6@ ~^?iΖ*%w=4Qtx "쬓|ORJ!DТ㎏ZoN_{jnKgv*|zY2d%|_s;αlE,\[)%"Γ3(>Yi['ʦH/POgإv ´7seޮ60"=ET+T*%$!129brߴJ!40sώse؍sU(qr#lsh;Sђs>s>>5D;w\G7Uafb?P/8AJ%!$,--Q+W+L{k6xRRT\E99rT@`,3B]bx@92 UnR&QPJ 5%"ɢ<P,GK4QQYUzkծʪg֡ɔVm( L$)C'U)P`TR!  *bI6Q@,9SED-Y']oXTV*}%XOf\Ϸ`2J!_2 pcY֫WIkW^Gnѿ&W@Zp" @ @}0'ߍPp(z|A  x/{FTT%qj*!۪Z CՎGiWסa3ETƄeffIt" U"0ga)EEu2l~\-wpDHrT+<$K*R. Zd^fUZiBM%f8qQTJ"tXeW8"6+dyB3p!0Ty0ǡv| TN;wWW[:X* &|P%P++6V~('xXqǮ٢%E8@a9ST٥GUIOiK>ֳ Pְ:,@  Eaާ׭-@D*Hq\/AIɔ.(s0k=j3/e(s^^}#iɡ@6.>m܏s^J21e;sAP {=,Mc YCF6 ,KO?ɍIMQWʺݜ00ՀU6F_tvf|øY.}L~s(ezLJm>)ǀߐ#͜(A KFvN2+k¥Vb\!BBꪒ|h[7 >v;W}ⁱ28ف][No[}'a(e D*,4 Z(EfVmL8+}tJ@!w4O^F_C`A @0u@ H@SۦKF+gKs?bјQ0XW6#g-u|cy/psW!*%T2ٽ׹e}O;CZ߭;UXJ!>GvȻgT5P0]?l! G>]fmkJ2 >A eŝ:NM>V,~j1N}e"41W(^"_?x\W;H %_8ti(B\}t*^:r~4njW(<U qRɆ;%{+U%{@{go%>#dw)7}wnZ ׄY$l-zҾl/Xq7@&P0C\\\4JYDS @%pѾjѹKSj?gwpިN5Oݾ -~kY;u&ǫ'?;mꌘ1*cqSo~,K<%ΐS}@H \cM'V݁8M>@ [Dnu"pqg˔3\?nCWPW7Ȉk|X #2qq3@  Nuʂar+`!aFm~)E\9AaZC߆a `Sݷlua @4@~~F\N`wx=ZscH &cĎiY=0 z$P:O7@ @ @nL\u}̪ow|={wM.pF;~q~Lv́'@Nly)uv&u$Nic:s1chA_  TW3q^[#Ww+SyW==o*= Ǣ\'ΛʷGo1}o*91~hL#?zf*>u:%Rh@Lh$cF>`*= 1#}N*G@ L\M3h㡬 ?S}t-:>1!ADhgi:dq/<vefRe8m}7z!lGWV}?JxS!>~ qAkF58|zFZ[7*47c=~_p𺣛}k뀽M}GWm&. 3?.gR=e) 7qg=_K @KbbA< j*oe kyzn)w7#=(M:]z#_O|74wkӍ(v`jT͢YG%-([5`Rc>>j8w4|&;wb-QmB+G=0±ssvg X}c=ʐ_?pc\q ۽tG OOq_V3w'LiWlUiZ{iT`;?_knG#Kg|AG*}Kn~Z>,e޹'Ғ,#g?&LEsrh4"YBgo%`<.)3ĬUn٦oRo(p 09 xx-  LK45q{㺋/ ~Z+D0l(?QOs `&ʲ١Jw3V'\YdѦՏxFfta"s䨮V;Q}=e.])Dn߀ۡ=XcO9y#7.قZl2pJo!|544 <{cɢi~yW- b J2Ҍ]pFNKA@- SCxL0 1 A N1$Sd0xƙߜb}&go'Ƿg/s?2hqvsxF{܈MHxt# U!jz^JwUYyoZMB;qcgN!Y[jp R-:wiU1|(\u3c&sc&C @jr>~, uݠ;z&j>- }Ѐ =SǻG02@ P_ @>@ T5RYQU$[5QĦw{k=K|>R~z ߜ gse^>aNľZYbL*Y4k{L5xl_!x箝?|N]%MWhC8vn a/Eyzn)w7#=Oc4ft39*65/'=)OL#3? J{1Yrvm)ќ3\~`:sݕ|z"FG!Y[ K16? z-bۯ/.\@ x8΄x 11- LJT5qӅJBNݛnEH /"W#s:6 M?p3S?_ybC>Pd$]}VkBg%$$ƽus{)ΈD/ݦͤs9e>؅X7®EMqFx]|_=Ll/`) 8]L009AqB븑-&.,hxFfta"s䨮V4Q}=e.])/o@2/L`Ĝ1(˾ϗ3;d^JFfK3._t ߓ7M̐”TQjNvŅMާ+_Kz: #|gp*@ @ LZ󺮸QAg ht"c^J Fa0cO%@}PJk*9 '~эdX;ŷ~ۖ45[`lSK'/n\V4M@0t$M%1:ºM_8u.cu @eFq`="gGAa*@ @<\  -aͦ{te[G'/B1̾И؈_'cqf]#,&uza;CSB2mUE]OL{7Ys!G5“aWxYU2i_}dO[0ӼTS{/8x>Cت1X-;͇ѣmڜ]0WpG]OLr`^7bojD>~p?wOpf c帰[xzZ3մaQqt{7Y\AlG|lҼφݎwu'@o/*!1TNO5@ @4^ZEuxLEa{U  5x jeT=;loϏ[2JXۧ|]T_~әZ*v`j>X}zW>}>=^=:Ծ>]k۪luvOm;"8ItVY`jSY?'f ]|wκoNCguS:E>~$ycǯ>kV\CeU~PYfD;bkih׶opʕCJ0'm8jݛMr>:f=x99I8y!cn_BsCPEEczuhqݗu 2u7rx~}zyPd$]}VkBg%$$ƽus{)Έ)^޻MIr *~I\R#YN2.vT&&u-,UN(1A7;kecJ:jOgGOg=> ]JJA*b}($tCEVB07Esz6|x>UJO N* ś;_vo^VGͺ;jDa%E h|_~1(AM0# 3D #2uN IT" ,,&m|/7lh@!{ظrt;xL@ 'N K2/L`Ĝ1(˾ϗ3;d^J*-X…Em_9lR6LaYzJUsv4!%byYDSNC ZȢi~yW- bK$[s0}VgLsaԑ?-GEu@tCX&09$>]L0043tVCE@ *Bp z_1݅x L  'պ8S`-1!eOo=^p1*~dz\0stž nqx jzUA8@6gԉ:}6&xf N V0iii* u#@ թeDg @m:n@ @ hL>q+nGc֘xJS*a@N0]&ẍըĸ{!u3/% ILLubk|'Cb.]gx\B .9,9¶o9|Wi^Oi5ms@XT%QxeQ',4a#"]]g0C#JH:`k q"F;UOlGWV}?Jx+~ɰ+[44/nݥ;C6._9Dz TJ KVoϞ8U?[gُyVB۾嗯_tu~A?IيV|ͻ  9VNM$Ge,Z3/tyϟ~V{,n q^1Ԣ˴R+fgP^=;[uu7RaSd8ӭ}G"O>qԺ7|t̀%O{LrR'06i'1dsV"آ1:8h]u7rx~}zy<,g0ȼЅx}y򍢂_x箝?ӽmN}&NoB'v!ca#|~J/c,пf󧹣pEL%)zgC[N𬒄j<;׵7|ܶ9LŴ>I˖NBOۙ?z]~ۙWVɩ!ь?u!c51]  @#,g5[2/هBX7®EMqFx/Sd% s_NH _<X3E$mJIO N* ś;_vo^n+}?QOstdHBIl[7⌘XC4M *G~d]&o3۴t.GʨC[_$ʺv+gLzpau 8F90(Et*QH?{"IDTWRg7񔄸WA|`0]Kq Ze0vWW_sY̾ES\:Hn ^1yg̒㒤 ϊ{M\6Is?#蛕eS5DËj'ca2@ |W 0A{VލWҊ0%R"!~8Y8uzn eb"([c.\-巳V0XM0UUXrb9%)0ENra{Icw[Ŝ?swVGk~Y^AJqBZ(S$dV `KOa(๷͘exu".͕p(*\o}VS?O0Yf]]Ү -gU4rj'x$W<;?bE!ǒk@ j@xef5r tLI<Ʊclj?n-98&urcBËj'caC @ &,ZZv7BŚH*P3G;(PO Ӻ Ea6Hj?b?O|>YL^ S1!FE\9J2c;VO'YY= T6^-_ =Q_O}%8Yb̜1ǴʄrEm$ ¾#",}EF|wZ95œµΗ<UR}u!: @m)eq|&F1[O`gN?:OjF4xxB_z)R\e˰f5؅ :L[/a Ks,I|``6='iv4!%b9 o@yp3}\-1-{ t7S>6ckM1SJHnN,߬xTdn83Ori*:9k;`r >3ޒN[h@ PScxFfta"s䨮Vf7Rߵ?=7QOt{c51  @=$`L)X[Ϳ=s?>Q3Ue[xƙߜb}&gow֤yHwNM-c[Ռ;S^ ~ ucd]9)"Y@R+C<ޝ<+  cF 1@ P @&i8+aKW 7۔%y @@gԉSSuI{c`5@}$iթ)}cAC @AjeTʁF @!@3:f,Q@ @ @}%S@o @a|bC}i3ht_~ĥsMuvfw幨{vӌj:)z_wM%_M OTrGn1g?,*}Ma_Q"f{loG/~Vk:;@zC2qU(@ @[Od~| mPiıGڤ/J|)$iN闯ݭ TO @ VBvj=Mߚ7L .V`k\*iO[{l!I pI˨gZ`g<ࣨ=^HO P7" > (FE TRBzo֙fw3[3{wwfϞ;7Ly"= <^QD=gmTS0̾ 4T24mt?NyGM?ߨ43mgN qpl䅙/(L欑aƼ2L6 :ĵx @`y 4?Pݎk꾚Ι906p.@8.}w Wd'dr]=JH)zi}P8{?TCXÆ/"wg>݆ QUN7 fEXU\tTYxYҵIfNBs ςÇ.^dؾc;*U<°o<#W@mf.S(V)/J]XYF{W?^n λ_}{Yr:Vpܡ<̽4JC6Rg ic|&?vʈ"8-۹3Clߛ:dI/wیtn 5k.- sBm -Lf2 g=&PNJBoO*j}jt!{4ss|Jgr{ i% x>vA'bN&>g k8Qi7icCfj͛?F曞z\u"<_l"NΪ1ye[ճ@k wjk@ 4=8~?OVtR K!aKMYߧ &O$pIiW=:E, t>Mɪ)s UMaQEZuRYjWZ;UJGݳ9FKj ص 7 ?rNK0k!&Q c;rlʰ_\f4Y5zک1܌L+Gc_LKnb0wel¨-0cDkOmG}% >Zi"[jL>(F3uM<1Bq4fvRk16 opsm+5⯩C? `m)щB p o0`>a}Eg/3[CB  ,a$jH{qC~MyLNPS@W_~MFz͋dhKW2.%_>}/7^s6W5)Nﮈ8}cڏ1O{!IqYG|2@XrIVe2_@gY)L ǭef)5gz)9}:<9;Q%&GgvZi1?-qg:7Oc 4K0i)E  @X>]3LgI#HKsCP&_<kNʌp|=cs(L]<ܖ {>?AL&zس!&tf9]!Ό>xL_LIqZ_ԙ3؄RRs **ѭآ&GRY^V(9kN+捜4{TF̓ /jiW=ɕwxYlp-Q5VZ1q4~i|ߪ'L7%XRHLx5B}WA Eer"V͛h:Uu,;%v qCͼũnՐ*etˆMc_ynz5gxݨLh_(DQ='sp wm7I30q_)a0N"O3t<șZ,e?! ,F& dY8@ @G.SXErL]~7ʕ+.lwe;4iMݳGܢ[3ۦoPN $orb6eq:b. @k:aBf {'M-@ @4R؜5p30FV#@ ;ׄO-a >ԡS{; _͂z8 /{z !8@ h </˅ڂ5` `N?eR$AmNm& @ @t . cCT|~[~ =jܬ/s ΢k\(0Uua0ښ=4aΌdL[icKCMzh": MyF2) \҄t yc57Xܵw6\tV3ĘySZr䱮aE4`>7&@ Ў l/L,}kW ѽq߫liSU+SqXMʃVK|Mf Ӧ˳ Q~ƍǙ2vY+q ep-Ϲ7)pAlLZ}+_׷]܅l FEkm}+Uּr$cIY(ӡׄ%~Hkov{26Q.Vh@L\Dp u8n6 ӅY[&Y pi1W Gvss`3%w)5N3#dn]YNr?5&Z{uCjӭI-:~xLV d1i}{:ۡLA65Ƈ~Ʀ?X}G<79rR#$II!cz R8,LO/dڴ)"(,b x},ɨI@ξA&vOptJ/?78%5Oz@-`_<.&tf0{_-s)TbP=5R`5zSc#ϰ{S}l~˔O*8쮋* ML=k{c @|, ?u'뜙c#'K~i~ N}c ܝZ^~AaxY0v0[1>DHL[{/)mN>Y|t.WMM{4 ׽#FVF\qi։,sM8y;'7- v^f :{h%]ۛdK&89y>Oڢ}CLu-8wT9y# rkgc;I t|HnGo͜u\&Q˓g+j ) @SlE&T6(~1qĠJiJ?2WEڭˆ (WQՆώ<0\d lXj9Yd|iIU-Ltєh"l dLs:2%|vcbrlI2<&'ct09 F ɒK괐TY5ERm,g{з_ZwnԊ9NƗWV+y[b2 =] -!}u%7`ڸuRg+ߣgvR]a6.:>[u]NR< 7l",߂ GS!xvF%YLդqCc-.ϭٓ|j g,6 ݖDx=x=3!6}tx23*~w[DYhJQHxl{Na$' 硽]Ls@ܲy5W$FE(yKgp=m>|Td*& ԡ28:U[x|t,8(O+BVUu?Aĉ3?W"S)eyRܱ6B^L型͔f#FP\{ NM:m%iG)@@]HIdz-Yk?4 @PHɶϋqrJMS? g@S v=_~5In Tp!:ggɵ[͈MݳGܢYsݡG?޻|7u(E ت >o5; 5q| @ Z.;agV[ЌzTnu3;a'"@Y 2qhU @ @^^mvl/^K Op{0- ߎԡS{; _ pm=,E,:R @t6[ntթ]R)4 @4@Hdtu*dp!@ @ 0d̀1{]毷0قkX[>e gn_^`qh-fUš' -@ wlχ[{ĭbmt|@/˶έXvAA&NA5S"t׶A'8Ǽ^<:-.yp|{ӷOg^罞lCko-#hrnH @:,|o-;ActJnej58z'-7zV+j'@XVq)Bۡé& :֊ ZCgk@w X.b~B:^C\5@]Ǭj|겄S}v_>WyΌEkY<$`3 Rwwu@3\ 0Qg ^ +d]`3Ԯkq R_r´n ̻z7fVIڴ ,?^qywiq|I] c&|2wM>֯mU_GW[nuzE ޚÝUy2"[I,-'CUަ.f\gt[b;h·vJqѭsըvzܸ +x 1#S 1]c։K![)7@T&>k 0 EȭYobW菟~?eڗH,}ǂsı~sq'(&ϠA9|Hpܐ Ts%"EݠR70c):Nwi7.\qf7`Sk/:ԫk`ZXoMyy_#!Nv"^>iDؾkM*o?btUb>ҷ~J֊O?8YoQ?gxTAYziCe{}lqK/:[1Ko|L(2qB,c hnsRgr.Mĕj1c$ٗN3%42-?3}TIX>Z@/69F @Ǭ1}M 9d\ 5f3EPovZZK/69|򗘅2qTe6|&-ގlFciŅ-6b98P.o3I;#d”p+7k,+{tw,Itº]yN pY=R/g3^w.ínl9X_:2UǷ,GUQn)ƻpEafbȇ·s`)7f }g8YG8NCx]}%nbX@q∂O1LvL,[%."^w < CP&Q9Şֶl0hhNԹG⊘/ylF,XepYĿ?P[kkN1|^/x?M/0KMޱP'#CL1I,pU~6_?>#34_!&ۺ2QV#R[ot~c)B㵃>a;xҐs=,\ZъW5Is?lnYcU%ϫ2`J.k4A4۽pҸDQ5QBj8e4݄)]:0 3:!*u['.x2KT&꺵t"v .ɽGȟzxjѸ|"̦wǓ5[Cn2#E,w높e|xz9d]&0y+D$_D9*Xu߬Mo̩EfV Xil߆ JL|]?'V /|ko}]..Έ߻|JW KԊ_|Nm-tz}[V{ٰuEz%L^Ɲh-J1njN8jvnjtheq)^Z&̬)@ooo}%@%ZO=~IQZcac^wԼ{5upX[>ɠeہeyim˸@nݪU$dӭ_rYj,Y*(l窵yzX8[g{ƽ "raBetwOD @ @ ! Xju5p5'XVXͫ͡:'Y~|:ݠeہeyim˸@;P$=_SgFu6ͣe噂D y  ˬNZa @JySݧ~E)@ Z@ֱUFVթ-3 @ @u)@6Aܱ!*>_Nn>@ @$ # ^ @!A.mڗyBՍ6qEA׿ !Ѓk@  3O<>`0Y= m N|3@vK=n@ hI; ]K'~O^]<;cW /~J0~瓼z9jYr-SSZ{z;3s<ʮsSt0. ^ WʉO[R` ?lTKV\+%69',ݙ˰{fwws/$Hr e;eѯ˯j ^By71sG]VKLAנp h ~,@ @C^Ӈ-%2%SwvPhRV¤>N"W~C{O/Aʿ=%zhy @ ?DNU|ۮ,5S0Ik]۾o-)S{--ǰ !%ݜKf4'UI*el޾qm~F/rqee؍9eruq^xXץniC3@ >`?@ t'B@w>Pf% h`ϥK1BUYt2JΆ\Y{a eմ8ʣGcp\Qu\VM|ynҺWO޳잨kOو;OȂ4\vZ+8 h*K|UVqDYiY4[CמG<-= ^n-/vh@ ; q9i79Ze:8}xs{ԆM{|̾Kߛ +*Qz.}C־0MShq8h3H֠~V K(t`_=s.YDr! Ixal9㧕j` .VarhGƤ+EMKk B-"k$YJB.u5n5@ ZA0ooo}@@K S@ t=U$dե\v_շs]|~8j3/8JN=>ˮ12`{}֌z%ULi׶?/*NM#֟[\tNyQN]ݯ_X~Jmcibᕤ-}Ɯy7s5':V @t(YV=LHwwx:U @=`z BE kJ5 ʴI `v3L`ce۾ -Avnh0FW=7NbMnwM@FqA@=uGF|ҊN]q;-^{̴d[ ?=Ac?^vIWvlso\طbcRQ3j8fEzmO~/~]`݄b`g7}ss Q7IY#H@ `e-@<DMo!C @'`L8?p{p`3/ھ< x_/z%4-JkHLǮkeקd_g}NLԹL۵O-}%.p]<=Fw~`wozL߲ut"Fob|C;f?߷A w,ץG6nٯJ#|ψ5c?ڏ[&:3z5PϠm^6iv+;֏*uz9Lb(o9R 6*݅\PIE%{y0@ Z@'i1-ķ# @ `Lӭ߸?\N+W򢘰hŀ~n)#իDmay}/ʓd'O 2dg/?] iiaedqtL?GSwն{mcH#q+qb!7t:jZ·&zsQawn'7uktL(2iT=jg<x^Mq)uT  @[&B cI-cm! @L&\z翻#>΋nv@/6@8'-'V⪌{+_IT]|f;N#|`ghqv"0c~{'>k7]-)V]0wɮ(+8:pߔ* IDATVplղ~>!իKUfD°褘?_eF*j[f~+?Oҍ hKZ&>xL7i8B<֖` @[_@ o4k,)V){>97QiДcC[?K~:|NLZj=d[`i;d,)\Sf<@ alݺU Vm׷Oʕ+єS,jc-/cfǷ@K(&$Kޠks~ .p7ZLS]vɗw ;3@ `1@ @&~LsޚTUr+,ȄR4z-|FUj˔5óB  |W/w.KWg_:q:o@T:@ `@ƽ:B @ ,NЎ Ͳ.@ @ dZ~7܈9¦5|񷁻'mSt վ_t-Fx2C 8ok,3  ;6D˛z'D H` : h@6F2qml@چ9v\sƬw|&='dܰs7l措p VOrﭟc7#t @@$@ ,1@ ĵ4vɞԶtQcQ+? -=y^TgRw$?`/B=^ؼ}nB9Kۗo h@ =ǚ45 \-J28ݰ/"!g:ZoOP1kGƧ$>=uC##>}iܸuPיvl;~+{Ƿ;h,X~>ʎ<} V q2{+sЯjjl;z%&4ѭc[-JD}~to p+sE󷞌zy%1 RtkFx^M9+JI/Jʻ0:O{tYa?.~]oy.!?^7= 2#T4@& x̤9I@ D&qݯW`[[􃿲Ud1v,;dܿc~}q|gB~]:qԈak"|ψ5c?ڏ[&:3z5WA98mWvi4Fy{ Mx9T\;sXp b^u /fO;k>5INeo>}&oWn'-~5{|{̙ 0e\co~AO M$@V簚x)e \p-uTfTUqKE*Ӓ3UYFwrsD`1vXC)jթ%";&. 5U/Mlq?yoV%&rb'\^йaPu%*s+-BQ/eX &cm,85 ;Ax_p 𵛮a}.cdW?oKNMMl7Њ[g&>~Ϧq^UfD°褘?_eF Og5|#͔/lB2MSpS%%Kb WEVm?á{KҬcDWqTn~n$ "t!38 3N [_@ olO-Ȥ7*[-/ʞV\T25'3dVNႝ2ќo @lݺU+Hɶϋ{ʕ+ⷦ|qlq!3;x`@(&$;AxxL-@7Z0LutM6l`3 O؝1 cfcf# @ L7`[sVDJnuҬ毵g76a%]ܹ][lߧ_k-im  ?: x@tuSW6v> @0euEvl= @ @ |m!F6%>KO?<t2퇬9x+1%%%O[9Co6pdV+ޑ3C 8ok 8#@/o袔*Wwx P I,Ad :=<;ݶFାAA^xaF4 r}]F ~xgR 7z2߷e?E:߮Orﭟc7#;B*ۢ €@PhGcsY#H@trmidž?(ņ,GGUNba ]{dO\j[u:qPo͵3 Go{EѾcetb.w2nn/lǍ/9KOlw @+h-0hXc jݗ+1IGm][N:х~=,­{3E~z2qJRT>ϖFQ Ӯߒmǵ+8c/`La_DF|՟8kѿ-#Oc'O|¾CM"3<?rv[B yWra8#=P8/z>ir|gn>EzwD޾8%:\s+S8</vA7^}i. ]!ަ| Y=k*5M̈́R.E T")n?=eX?³׆Lxݨ@z@+@sx 1Ǭ{0/V%`LT\;sXp be 7Ot\>7 i4pegĚ}z- \|+{;c?lNmы&.}evOkٳ_N5bظef(k5#\?OO /;ㇼe{3bކpOa)|?:DE#ƽq:J[F}BɕUG1~bLʘ=W%qd;  x 2_kȾPJet.ɍ-x!T՘iT2:)i‘]Xu>z\T 9'߄42Uh@N1 NR8y='j\Ur|]^-J?\C0TEQ.!dAkTC*~4\zNzmxeQJL~v)y}YU=! X ^Lt]s{?}Q}c/dW:;K~xPKcEjߣ+NꬿDT])qkи PRTa'WncP{k'>y_0a7aQH6wR!LlثƕI߳v,-0 @x 18xY ' Y*Pۙ1n' D.Z[˫\ Llfٺ (cvQ"g2vL(iD:/??3{ˡ94D$u$"%RC%flѝ'~⿬vG|Evi_UMZ[tI`J\qyѺ|LbJ^;p<ՙ!n~'P>W`ba KN|R&#`( @ xtx 3:ɠ@&`<}bzY봯]$|3RܱɩEb"نДlmgm6֩ȩT$8E뻠>rLJ9U^t_j,G'\zqE*pEx ٸF=ᓃ;7-x N0B !uZ& w.&D|c?mkoF*WC/9VR%@a;`< cA< P  Ђ,:ۢOb0iȢF`P\=;gz7x8߰XAq>+qb!7t׹|~Ոlwwl[B}5ћ 3\u+<莒5GoD`Ž  3F8pB%*pL&5 c kz΢W֜x eKʳb-Ѕ5/a;EǨi <*?ϫ)Nk^='Oh@@1 :|@20S 7~5ǎ|7SvH2MSpS%%Fȝ V-Y>匿?~i~OMW0yʾ_ݱqnUfD°褘?_eF=ͧ6=^\)Wto_LBA{[QQ]f?eըguWM'=Yu.&>6*`2kI{ :*jݍJ?ec^;{љ u_Qy]'x@;@tRA</@LutMQvh> M  :T+@ թթ@ Nu,2;6tp@ @ h6+gPɃfsL~ 7vi~ȚSRR-𤹸E3=Wp  =xl. &81{]߲Ky[#V\Ԯ3݀36VӲ   wlϗ[~c#qc17F8ogM$`Lyv4SѨ>mݿ4 'mԭMFv|:A﹋hU:5ͲgQ0û6?%\SW&AŭU;\U[km?uWjU[ujVku((*DDN{ C0K%'~~{=OpSLgP84Qs ?dC\zXM'K>~  /J b|l0.bl mϤʠǘp!3 Hn3q8 ,v ]p1i*cO.8Hg1GGsdsoq[駚, ?w^݆X7B9c+MЈ2r P#}X))>zⱒx̨B0㮬U("_V|ɇ8/'-7 ]fxhT 3܍c` Ayc  CR8~+' vڶߘe'/9zI;_Mj͂!T^;h>~~>ٓ! 7hکz~+<1X~\stdJ ! oS0knVxR p6kǏ:d:Gg[8MFOkJMFM݅XS'Ы}dD}`S08] S{ 拡dVʔk'䓯(ą=F\+%YLrA= Vj:܄Wr߲_lg)&KLRT#3}Z#3y%IܶM~]%,V>};M0<@n 3 ʰ@38UF ɚ<ϵTg}q!Έlz[OgLGᅐBD}Ge:6X\v B<9~2^Fdm)+MmmZrƐeO= 1h .]tq{ = V= eLy\E! P>QѼF?6VQ":uFFwv>KR\Ihh,׶ IDAT 3ҍ ʱ@r9xM?8'<( IRq[Ǝ9՗jp߮꟰쵟ܘ#eeBEtB\Xz՝ 4t<6s{uo.&3떏*]L: _٠Je'n3)2^4Iml_qؓ/I.SDY-} >+KAA OL3əQԣ5GJu7tl#%:<64 'nj{>52,`y1  N,uN}fQjTIrBُ2QZ5pl{EMz V[lzo~7]h_n]ýߓ ۏxG=qP5(>.{2=ofs`QK|'e{uwU"vwg~)MNB̡MLvy1˿hInNSmp^$\6 -2,7n- ^Ǧ ρcֺ~2 x c R1)@ ,;j=rʟٱ)8̊Gq/FG^PgY~hKh3};J~e<aqeg?~pu 巟i׉ϿCP9;y|; iv˸}|Jd{Og/B`r?%~bo;8 ;*oeO%80 R;|F'fϵmu4{7Hf ެw;s/!8e3dxqcg4z)f&)vop|3T_&t?=sS9@xؚ7SF"xE 3 DEPOOO@_:Kͧ>1`'zyy|p_<敌-V٥sm@;aW= \| tK,5UӚd$7y5@1Xzu4QNYfUj >~E5cS b,+^?vGw~k ԇ>>T}S;5Lh s&5c5`a5 Z!(@m_z>C \v@K@NڸeRkq8"c Ȁ Nm+  @TY4ݩ=@ ӻSޱݩ @ @ j@fEl29ik{>p3yKIM}"[b]8k ; &g4- ;ۣ%Z*0|bOel@ P/76DC]7mLjN+A3&j?(ױ8Vt™0<@ P AUCMБ7iR=pO} ?w^ _n-rlW0 l ,H1 dV3 >x̂0A@Ke⸭&z8$*.!!ܤ:8xfn>qA7ߌz]aw*W/oj8nGHxxx9^^iX=c t4Q:M\{z,NЖm3DqS]UW#wfYDžl\.ӮLa3`HкRAFeNrCZ+&1qZd׷4U [W#պONVYfˤ@o6$ĕ$L\͵ğ"_V|iq_nOZIOoݻlyu @0xV^K <@ PX*bꄽzoa;]l^A#&ѿ'5pOTBY 0Tw|osC1`&_~76~q_clY!d5v fmm"?Rj&uCZ'h>\GoB)y1Y6-Dq#Ve?J6a] S{ 拡d:/eʵmI]9jOQi([l_Lgo%| mӻ_WgIf8զO|Si[& @ `cZ<`j?c=@ PX*H8dtZTg:|Cf#TQئ]yE)9Y$*W;H!>VV[OI{Xo6g5?`1mTɋxrdB7Yo)F`82oBbbUg?L+},gO֞6&pאR}|[D#^(? ϠYB|P8BAQe k\X>kc͛=Igw#~kJ 0c撪A# 3Z?cLA$VN[4#GmKhÍtOi.G$giqEH2R[Ķ=&()¸""Vȡӎ{]_rLQdF"4'$b ke 4j'AߺC&鬡&mE9m|厚b.Vlٚ,G|8.AQ!;fTalJ=ޞsOa)GRͳF(9%7M4gpy8"enE#LԘ<ŽO̱  ǪA# 3Z?cLA~z*aNC׬/^:)i3QWC;SH/5S2v́t 0Usv$e|Xv^,$ޫq*ąV~&teW.K&|]ЋTQIA7V}ġt;f BRjAȜMAL Qԣ5GJͬޫqO]6ϞN 0L1\^x<`c%`j?c b ?,#O,-9' n 9z=""6ooq]eS>ڿ g;'U~t?c o?u"~C(vYo9T?Xȸ?횳<4d {:{L,y 6څT.aJ2R{ne|ZTFU ձD U2LMwV90k_m@xLK%i1z <@zC7F  _g 'l4,g{3/Uxᮜ~a͑]ʱڄ_:bLd"=| tK,ɡӚd$7wl=0L@@`fyQ)~x Jy" MbGXV"vE ys֟ #DAlL@4|ɰ4@ 7j|} q0@T@Cq|ts]P}XTɧK= + 0E;yroJC]^aE=.jΈ1u6!mU֗ԣDs;g2~!~ɩgFOgpOw?`& @cj!n16=o_Acz|w,s ̔fEzf t(zB_́ muFlBYXqITCGmtʯٽP:fvS֍BMߛݼmI8ڮ׀5tfݬ2 Ufc/;}CܤG++6~&T$ѳ~^ R,Xg]?'.K|xc=83 @*g߃3h,e:bҢө"sǁx\Rie8 @@-ay.+߶v ǁ : =L9̎={ӢbԪO J<{y_%FO.Rd1.+ȳxT~^-^%< je2qgaLSDr)ܦO|[ܮۜɓfd:NRGvA~ڹ:VF \Aɬo9?oD~o;/wmlk7['D[cE^m͟9luWKPȼb|bʦ尕Oln:c}1;vnh|`tFؼSقCW|ل_J+K^˨,'ʾp#dhȋ#/ Fyv|L)Wa⢴8F Bۣ&][JeZ3 j{JV[yDnbMc-ب݉J(UO#GYٴ/JhJ_j-u i%t0AmY+RsܺɣG/ύamA uGXg}x .m1ͩTp $ڙig(QI9BW?w@ @1 ,cWvc' #1C~%PD_ ilL!+/drvk/ĐL22 f\q>4eӈ^N\4CCȉ>\M߿jL*lڽ2L(yOTμ˿ q č4Ib(Ih1snXԵ^nMq}[_:vL홆mO$]?bּ]K^' TmϤLԞ~&9U)0Ҟigfcr!U(i j--9`Cͻe6^gj9@ęףcP"%<[Vo|NL9}"Au(j<@&@!5EV]󻖤U0L_/IZOI B $k, ~<:l|VK{,Ƶä L=`k"-*̑|^fed#єrr}]"aUsY|i~ӪKPG6SU>1v|0"ʮ]Iyaʒ#1$g8\RU6 *>Y$(c`y|@40`=j*&[z" ı0oO#B\d^ {s{fz&4@29qevkKl*͈\*[od\ Zڃ˨ +zmshbM=SRYGZyX CHy[Rġy=rb eYXۓ*Ȭ[[>k^B4._V?{+pޝzg༢t5|6){zfޗgU~qIv9ѐ].WLRcJV5Syk @wV&ΨjѠV]!%v'O6%Mu5P}n3$7NkY![7sj+1QQVkuSfゆ@ P)L3)˔IV |!(2=5s[T%.2Wwy;j* P{POOOЈ$g4Lcvύ{n^9ìӧ:{[fz"bpLlb+˩AַO]|Z f7 ` 3$78ZU0:X&^圲15|/ic!AՏiA?N7 IDAT@ԽxD^|Tc'^ɗY*Eb|Iju xlq?ȨSGx)Yu+egv_]rZN>p5˪S!+s t? $+t XV!h%k4  @r"7@o/] JފKTvM4:Lr4'aE~m~ ;CD|Ro%$Qa\Q5f"3uF3&Fmx(x#kؽ lɓHiUgW@:P+UUձ 4s8Z66*unt"Ww+jaU_gI^[@KTKX:@  ^+;@ U&+ܝZlt@ @ X6zlBBBqUZg]r[]SؖՏulU%4Qnu04@4, 1&wUCecl cD@4 e3qЅ: ئMWXA¯nN3\ yvA>kٞ?bXOSq aH $!+v$cx@w uO5q,v eϫJ`lI5 Tifw"r$eO|3KC3 ̀@+ 1Q< @'`ݩ{B¯.18<<֑.V=GoX>/77b7v>.dN>w9,h̞vo?]\˪nɧcrLic;mݶ,'nğ4 @%P?!CB<e=  @-@ YF|Q^w7YEl"(N;o}t}yw)Tkɾ5݃7bgp_EANdhy-׍?r8Y{?2a誻e9MF'GQ-8n(۽)"43Sq4T{^ϢLmQ>iyvVB.v{٣W:%ޞZϤx797K=~-#^>~\>xݻewg])06n<@ P?!+LŇѿx @KS `P$v2:PCn>ܡk8nX,#)M^lЩ{̉.Զҳ[N&uV_ڼ|$UiWd}YSV&^һMN !* yjh=.4vm駃ز0[qʨ0O(9+24N=UO}_;x(>҇!ϜzXcD|ۑmڧt}'"IgQ @~B~ܐ~j0sx{ږ jܱ(dN-6$/ u y8"f$u'ڐAXR4&$b aOq̍otU=Uv#' vo;cŽEWD 9tZe~ @#$А!3!c& @}%@Yjw*1k֏/扔䴙{_q9!V5w"e^@U,"YIE#[]T~S6}*]L: g;g>dw̚?AH F9Ax)wDG0>a<|yǕ4aXv^,$pq*ąj?c%pm/ojʐ~JqE:/5_eL [Ÿ1@4: 1 }L 4@zKfw\kٟpwb]{Og/)Rfm+wz~{ɧEcC=z ?sXa2dtY^,z_d\ԿvYO-s9In^ےRiLDSTJÇC;ԛ4DnAk ku EbYԫ@@"z(?@ 6 g^Tj ouĘM5QXiMWs2mK_ͧ>1`'ō$Z^ *@@իED^|Tc'^fmjA<Ƹ!c@ <зw`Y0Hɍ_k >m_z~SմdUcڤ c ʥW_pP9pC04@A-;5glY]GZp[WuV] 0JoRw+;u|I46a]c/56O '+tݩaGbj}@b jmYz :@ @ P (ݩC8㷈̠/ GD߶)L\-ayV?wW๷Ǫz\c]j*?qmqe_]sMOWdH _abz@Ǵ ꆀ ucZ3 ^2%ct@f‚r}_+Л[Ckg G:XzIlB?oYU mjmMñ=AWt$gңDtܖţ[i8"v,| |Vφ YȀ ^GzIqۜ4)>>/z:tT(LZ͞z8Z~ov&0k^::h2U8|MպC/ @!I^5S!^7@,;4xì7R主X ȣ$jZ5{9iZCۣ2)[>mu}es{_[8ʳ䑃 Y#>-*&BijwʚS_Hlf?[?L}f2G,apbjIڵGG>S,E`%#NCA{8Ar دx&}%?CKw})uQLˁfۀlFE#7NLŒ*p7COn!? >荻Z! R.AO'_ Uܝ4,-G&}"2|o qls7:[#~[xAi%{r+ڣM^>nwieLʎv_4yh+.TIkգl>>ҍKrOw(UY9(쟕@ P5f'4dNS̷> uDLi V=ld\S,JqP8($j˦׋).b)0!x x @f X(5g*+?f#9fmx?-h1tGM/ç/JPkg4)~osv}-YnmI3Y')ͯ ?\+.쒊0m2 QbDuU6-xgkwgh19 hr'R^fqѳEɬo9?oD~o;h- <^?ygETRGV,j;cb߈kLj푘#'[)#k4j%oV/LU[+9G{tvu{/'3.kҼQkoyČ 6!"(ә)*Y\VD`cp8+~3-~9OuAbwXtP?*X 1cS\t>+!ϔh Hıx}ake{g ୟygF^n:qTS?a%a0%0 @ P;H^kNgHɣ$s. vo9 ǡ2{:ss}窥f;R'+}n$OC*cĨ|{ -PD_ ѵv,',L=:黯-KXq><9A=ͷnĥS/ /\4 9G!͖s0"TOc dY dtjM+wU3hӪ2O;,}^u(e⎤|i[u>jR8˩0ELqT* :  đ|eIrI D[T"9ō$-]5EbOgg7/3wuz/ߵ<6*+I⭕U~F߹+0f^ k[S$A_=K$Dqm5UU_/@+yb-`(8ꢵiz͗]l1;zˊt-XL7峞="s mP32HD'E.xMN4i5úc\;LzL26T?͘ 4@ `cLѸk%C?|尓(2K +D:qu3I^FBd<@ `!aVt}v!Ɩ5)/#|{k:Eׯ\!.OU&q2lA&};tf=|.reK_o]`|e8XP;YuϡJ6aN{h7eV ߘ7> S:eG`0aGf}y| B]m˨E8G/$%l1 ]%۝T RSX}eܗC5+>(YJbhZ)㺓ʂk^B4._V蚔V-V۵yOW%݅ /W [!߷ԫ%kdGG) N޾JyV.*:q޽J|w]B6 - @dA|jt΄Yڽ46d\uN[ǧлgK^ @mxXuFl}@W^^wk"XU ejHu7˯k`>x.  o@Pzo/qk^F8k3Yfy6}A^[ _zɃh2?=3D:*!@f&u/"ɃWR=k֬Jt| Y,s ]ӿ=ᷧKrWCTuv ][=0pCCX&~M5T_LcWkԯέMo/ @ @d8K3 x>!Z(L hP+e;1\Ng MV4|9mc&@4Zٝ?^r!}9mv;I^^p+en{zaQ6+_G+{?6]w9JBxx-OmP5OG]Xn̥f9wegm=S. @WpcC}]  @P-:r}!w>#4. pt8э'(( zi%?`.X0brJ؃9 Ot`͖ӍGEHOC6쩤+SO"}=> E?xX}(m>x3r$`q=N];.ZJamq)hB3q&mJ|>[:|.6|.j(I\7SFsh=)ϊ܊noD~yAw𢜮}w"xg*RagsW3&;=[R H " mIԥ6PۅАE'=*u4' B7zF_zLm' p :.-]39$ps G WL@ @uDwÒ k &s4O7qvba<2 IDATUtT묯6# z/fڇ.L\]_'``烦. QXIc>˕en#~7?y|[e~XUӆG7+ũ i|Θ酥qߺK[},G'& yD *+M%_5:!2N+ׇ;6KY)ϕtPj ov:YGF?)5[]Pv"H~LX` }N f̙tk+rXK7ߧE7yQx hƆL`$@ L ƞK:?dġȊd|:4™IJm=z7-O@].S&iE$Eqb q&U>$Aem[ߒxb윷MqJ]uFo\doކrv$Dm"%eT+srn52.-`iYM:ѓ"sӊ6.OOK:8X5rڛ\7u4eTN&F޸uS$dد "V4 ȁ@tX)I /Yms>;0;`sa]c, |T.-IuQ7&%_Dγ'kCQLVOq0>~߷{|[XMo+~}w1}PWMܓG&>1ӆym\ YՋ|߀uɅn:`%6ٚ, ?'OAc6΢-0/u%0Mz S/ Ym׊t @C&@ / @Ny)e%Dʹ|N珶F|L ʥώ*Ia[OL{\LA),Rz˼#Q E!&Wvq;?^, SU]e]?u(nXF5OWGV4dЎ2 yFQx ETTvw^ڬx&C.E/u0Ϩf @4ldeձCk @. @&.@ (#<\-NO+RSq($3j#  U%Z蜸~  x Qxj6u6fp f6f@ x7kNӁ @ @zKu[n}k0&o_žZ\ZNh~eaLUwua:lm&naNiZ{[M?d*OY`ё8{Z }v|\HF@O!"湢jφ?@{m΄-k~ē'if7GGmGO,JI1@Pb7m̉OIccXe)> ^.(YFRؠS IJ~nse'跄HE\?c @@e{Ps@ Glu[tP;xP&*{e3zx)<=J6BS6[:R?eƎDs^OmXË_)Ԗr?0f^N!12Iǀۢ@jӘ62&Rx67%i?*7~KC=̈.+8 S^OTL'xr{gc^>g^g[%|+hUtj1z}4mrҶ Eķ3A\  cv? Qn? lp{3A p{fbbO ERo c-x:%Z藕C&^"5d8jȺAJ(4JRwsA::chۜt0ȦxlV7_ؔa~݃= uϛv@R" #w+C-:cmM32F>bո Wa ,ZMۤf *|8S8pe9Tb9*vٺM5iYo-嘛#+IKӌ]*pD(kuQ_s0ٚ2LVAUع6õ (3e06~3A plGlKG흽iMAGko͵A[r#xWu=_MAy3Ιߚ3zIF PZh1mNUü]]k'ouw ͇C@RɇwQNu!8A]V|&ktԮ#Wk:}޽г[wDeMU]yJsO߽ {VtUSىXI~|Z~Mkﯛ(e;yOpհ;>Qo0ͬ>[{qfn=z?72_ff Zcn֒g.VcS.۳U~?.sq7Y5vL(@ Ps>cfJV(!W% 11x$@D``iL&,,%9J?y-3fS-s.lD˜ʜ^v'k QG>?׿DzqWvs߿wS^OB>Ee95y9B@dXp~A[7)LE̩lO/k[t1+ rH}%ɶY;o98qRH1) ;'Et\Y&غofqugpeajFl,,B `O#GЗc h `_LDu'(4%=Wh`s6L bO-yA凉կ\C-[.;"G|lJr&.-3?sEv_W5@~ˈE.^]J4J@?M> >N8 _M/zZ[~.]j+R2@ #VCYU٩ *]d^/  Ƴ+Nuώ kgoޘ(}  @Q2 o瘬zot)Oc}}N[N+qٶh=LWRIqZ@]tAEƲ-lZ%!/I.ɬ.d+t_Ju%6OSxŵgN~wկ d#@r`X#E-Z-ύ0A@WΈSy62Ӈ)O']ۿkW0p}!M UՂq^Z5OwC+Tݙrw+,LǙ.߭<95Lj];N>[Z|3 6 Sl(K9 {95 =@7@GSQ&^V3> Y9E@ ł{Ţ@I OJZX+i %vffXa{.o{Y'#`_E g%([{.{])Zs"!^+N^5 Q\(㑓.7ubY bXŮ G=Փɲdzj8h:{JBu @s~g?f[="E)] ő@ DŽW1g:]Epo O͹)ũ,]Ms>to[ͺ'd9GQ1qܫW9.'.@ `V։#˶׵x),3V^74{qF- b[HngB1ܴL}O5fU.0_$ΗٟJҳW^O'^2Fr.J !0Ἥb6cA+׼O~ľ՝ȵq+fcj'w~1}B[aT.c4)jA>. a8@#P1K?+*:&6=74T2dZ|i8#ic0=4zwW@쥿 1wU q`ԣ2 @U+窕E:=9_sWIޒT0Z2oZƆ~Y &^*h%ݚ93#q̉o,Pg"q,{'~Ackgf~|PykS4C%k IDATPqsXQs- LG-@ N)?v]00OE͔Dh4ύaAMg_'S}$b͜ -ӧl1{M}\G#(Ho|rkLf ^# eI1_ dVP R;;wiڽV=g1Û] kY.\x Љ!/o|zc}?߄A>@[}%$uF̝[5|oYWoӿaѳ>l nIT%s/x۪ ˖4œRsڵn1J?CY'VGݽ}>3g5=-ƒ@ $]X~Qak}?f  Ew:>VXWv:w vCT K @?~cŽA p@ʉs,W+b2L>0i w?,xܞ 1N˂.^~U$Opza׎CTxnםx&1O$NZrwXS~w}S._;69WN /Ž {KʆCpt_4GPvC~<$ogu!ޅxIC~yz'&®=r'az#|zLXm?!@eYu[d @ ?q ("H5['׈˪7'c,w #Wnyw٬7~14S÷rÔoܲ]/4S{wF\H:9ψZzwp~N+Q/34~&? Ub>ئڴzM" U\ʝ?۷fE$βs/*߾kg[םI76qIooq3EϺK.9TͰĻGNj֯I?{ ׯ ҭ$SI6W9g_b#K\M x?r ke8=ytp徴72wEJ牯=MIy$M#cK&U26lI3FsoR[* GmMw+_3YͲ!T_8@z?fKR! ܤ3@HܜY@ENCx&oDNP)lDS؉ŽL6 e1Z2OrO,E9I{oQfmHax8.vڻ+Q4nKK#Nỵגһ7Q~.VwF?F760yeo>+9-DrO]1_lN~[/y&ڵ1.֢ vݸ" yG5z@ Ǭcֹ8Z @oX1đel{hx`d(B^F7 n<)1)lsg"s2jhUtj1zhM.g_ՌNMa=I l}I}Ln`LGnI:N{A{zlHL҅1(@^V;3mAtqC՚thW,} gߙ [{E"jڕrLZ6@v%\ F1sӝX@ Plp5;Ѥ^I-LzN{uӊW&vRj{͇tfLRI#BYSʌkhV_M'Dkpүu?PGUسuU/ c 4Ck t?oVJ0TVl޽g#:v(abO ERo ꝵEw Ki:䏓N\117kvB'qVk$ (!;/,o񃫁@_U JMk } wY{=+Sāv]>ig/ rqΧߞ2eύ~TE=غ5{/GGjrΛw֜KB45{z>nzeQtԮ#Wk:}޽г[wDr'+w}6ٻk5ע,3+&l`.ٮ@#+p3O.H@ \"c.  @ X**, @Έ=-[rrShGj~]VKTd'T\;[&QYj"q OzX=z%sܕm~d}m=gQ孳mמܿZ~0@ $pBSM:13eǍss[JteJtq@ wX^(6\xkK[[r~Ӊ g~]\,Ḻqjr0F}jjڽOo,ho@ #cB-NJB/@ P`Xʉ+^tA7UQlb M @FNN.HQZTsۀ@Q&XQ  P ωꞜށa;w* j+ ?JLC ,ځZ@ P e򠢳~M?,1_hth="cӱPŔ@}*@A7Ƴ+Ž fDSsog17 WKO{@ @ ` V418ipO{k=^aaPy[E+EWgox@o{\3*R6Bzb7rxАwq?jaI5X7-?Rj!kNȪrwT3 wcv穆^QX*yo|3^5!!}Mer9'7^{[4t K<Ʒ;Ī+|ʄW\f7:7%iF+{+ͷBmMV%ujE_ s:gyޠ Y9x7m#hm#"._Q8 @aOj'ѵJ}*+jBdU y0Xn^]`i@шwkFj]$˖{.Ӆ|IcT;/QƁmѴL%=_yk|n]@hя CXC1ր&V5YyܵJJQj!K(kW_ Ԝi?߄P{F5K-v"]bˮ=b2u8NR);Hrj%5e|) v*Od1ʱņ$SP%~>_huJ"qy?<״3K-8S{N1Y+`HŜۮ}X!#Z`ݤ/Za9BrO˻k:Egƴ1`~Զ3BmA9@ LHvo!H^jLg6ϑtl #Ȏ ؈$zƴ<#$BlAݺK$o*#?v~Q&m8t#. E=mK0/"]]ggy3ًi ޚ&k-I{E%$sa'w5\PeXp9ѼEvL=Awޥon [u5I!Cw) 5,6ukU`Sn*6/c}Z|VEjQmŠ|'I[&4O&߻Ѕ-qtAF,J3^ŒiG|~^#ƗV#"eWfD!IMHi)EȀ(߳F BTҧ{~_ߕm/R\W3dktPXPH(@e3FItᘃ6glRO?w,yW^xR\/kk SJUJI3L§ h{䄉dlHsL]a>9[_j8@W5fObjtyKׯ$ve60&{}!$2[D2k)`ǰivq<)܀ = Q=p$Ɔi»QᬛqW7iϖ۹W lP3c +߂>ڭo2],q@$x |Xu tL;;,$طK4g._ykɛIYKud*ͧғIE uRizte\\7uWjeS'MaF߶BVow$݇yVf siWŴ^uF^maŹժ m۔/DBßPy!=Q0V˒).2Ԛ$tvpW$NzxNlW2fNt~l~O0{mnkj;)?gZM}ezY^6&nZW|YYAvUR y[B[>OJ?o#Y:'`cٿD~ꅲ4]5jivZD'o\vrnUL|wos}r_3cq } GHQs`w xtff6=nZU”E֮{^瘝**/ipZV:ώT.a¸k(h,5wg(ϯ&zQeΖ[`i^qjYL L?='WJ,%hֈG7VYۂIJ,sE,=%<.5"Em6)RpVA.HދJ&wkzlWjQW&Jh@W$Ѥ~X`IB">hX̭qp{}>-0*r1 u\EŋO/#b̴zXC;*#3Eɤ>5fU.0_$ΗٟJҳW^;''nj#ˉ yDRa2K/ 9 @c)WuA~&qqo)OcClIV dƧoMg@r؈cFuORESQBAtЪNz`ջGC^5nLuF‘*%ɡSɭ#4ť{xǠʝ(.Ryα\$&̻%sJ;5kod]J[C?ه(27;U+f}K՟{ϝ'6Ԝ-/8-[IԾ͇{qXF]gBIjE'BSg%iM5z$*XVlD R?*a= "qg@ q?̠$"ch2@K{z6%lϚDY!|ġlzr%VBqi۵ɭ1V~)6&Te&T׷? HM ?^p8nWsqv[bĦ2Wh׭sȮbFԷ2٣2{SFܸ>]J7]:=Q l}պ 5mlvoj19S_~iҙ"Y IDATnoV;IHxRY~{CAgC't;jbBE.NymRj$\iC5` ;SRK/ CD$'ˆ8*u.ً$},2"ݲX@"/!>mw2w$NRgČ-9g~lN@VKGJٷViZ@ PZ mfjN L٠ayyظqj}PNwr , g9%.!I7.\D.")L$Hץ}ٕraG:݃?舮g(^8nԹSazrvV^7LsW?"br.H뛿?D|ɕE"*}hS ܱT/}6>YsGTv)'q qM&EC(Ntc|k0£N%Q} rpA@ PPĸ܏Oެðgpޖo!\&Kk,g]v59oҨ7Oe8mVj6O:)7K=Su#?[/1`r=bۖ!hm#'W_Q TU6~vl9;_5igU+qGxEIN?,̓Z>fپbd5E+ݦ jUzg,%j{7/[>2/?-o엏{ iC=W[ٚTmdܿU%ƫ5C,cx*@?6ݭ߹Xc53{}ݑ,Ѷnb72)QYv_7`0Ɋ 5m,@7>>gaust=?E[_UŷT)^3l5iΆ$SpP%CVLS=χt[M*mY=}@G)A9 (`d^.,EuC9#Vq{;)+;Ȍuuس^ڻ. D~TlϏĽ2QoDZUyd'F<'8W48#!=wI^jL6 clgUtٱk56")GCsfgһV,'qPnv}B BG.7$`ӎJ7"_jfLTu}7u=dثk5y[x'$v ?e|Zcx5ofh&BO~eڠ.)w0n.'շ`$Fɥ@ ?BD iGƚ0bW醣̀`dYo5iNm#$u\xa9Bjwft|SnEyUyB(VtqޮCEJγ5e-sNٴ\Ή C} gVi^'H(L&5կb/k> '!E9 .P[~w\qC;p0OGtAh9%kaNa0ky'X|?1JozWb %˫}^]ݿJN}WSR]:B@>XAqU&:K:dxsfG[ gZ6؟adYAV ,gLBB^w)]o Wެ XPȮ'[?Vk#1Gu-Ib?wz,n@I^M/V2,[65ȩx&;9ބ8a6pHe[$TNzxN @'䓆پ\^ѩQ$~j?b^?~4ПEsfG6Kf}]OrLK._RO ꉽ3_qta͔M;t3?O:ަ)-ѸΨ?VxqaR/vڐT;W;%775%EĻQ~ C{g LN'a%$@ Pb{B|$.~kFX!?bOUĢ#l`+YT5_c${nߖ)rrٛG!9#q\v[SO#\;3}@4 #7i'Xrd&~?DDn?>”NoAMFan;YwE)}W:b^\Ԓa5ټ?niɆ ):D1gkq$[$.fSE 1cI1Y{#[h,:GZVEhָc{j.{Yybxޯ{Gj;(XJDzf[4C>Y&oj0El z;$ee٥.VI&w-$>OJ?o#Y:';XrS'4ei O5^k0Հ㧣vZ޾LoT/rlFthtsp@ PHi^_˙*x"Z%==Pߐ9nJ/3M`ȇ_iydiG{[.͝8||_,Ĩ8SέQnЃe)7Uq d,gq9io+Hs\Pav$l~](򬴑9@7K BVLQPf]e1t_Vp/i57U@o];cʰag G.0\h2&GObGw-@  w0=%뛶(n!fce5܃.ȷ&ԘpKrr9q\+!VnM;G3Uq.9{vr_721TϖdU|uָ$Pߴ!8fT$p[؜gMEEqŪwjݸ\uƛK3*%ɡSɭ#4a[{xǠʝ(O.wNs g.}SFJW_9؈7 ^n|H!CX{`t@3VW^ٽ* (44EV*Fz '׷R"wilMQ R5ZTQx:1"L%!#cM 10w!n1S$ʛLS`F\ E|$={᥿sSMC%SK6w։?6fMC~|Nwgq^Cy'i+[W Ȍx:qB=6Rl! Jָ5>}(/}#E ZV8e"m*~>I!VZ0)Q}J68G@X^0ZVXl YyXP}c[Fr7G^]^Ov)Ww-`ѝ#z7*cn* e^,⊗JQQ#|s08S4+FhAcʽ 0M45=@=tvZg  C${'Zi+d !]:nvL ccB[kB{i7G_nbF_,qu;#6E;g{dg1#ۏqQQݽ]#ېק>SK'PoXZ4kЅk:kή7Lm]XZK ChRmy?xzrA3d ;m 5x?1d5LT$ʓKp35sNgF9|ͱ_%{KfFJ֒y2r?p /\oHTLNԈfHܸ)R~5q2gM/ᖷYdWYO91,K߮j tGiY7/_Ul?IkDy&ٶր@qEfz GC,!]"2Hk^I^/%#֑zX+٪/Ē?J٥E=bxAAH儋DG?d #T'eВ(}*_BlƏ@' >? K}d&0 ?G j !3bFG˖3vlU]o8bTʗyO\Z8"GEG+Q$ Z mfN L٠ay9kܸqNI U(U8E'{@ی|ҿ#տy?1 e?[|."rIIDx; gGT]w5'o}Ȅ n=-nHs"hH;YBn[f*8mMQ G˶>۰ע&ߑ)c7հ3̎i-ՈfJ>dȒvYS>x^9H[KsB`ٕܱlJm076' j,$@ "E,mT2s4R_gHx>k곊KT Fdt}q)-~]0'IdhSٗN"L5O J-Xeホ/gSЄ옷[dm|^[Dh*/v2Vh 4ԯ| OőoVkR{dtdw\~W m2!/pqʸ2NX*9CUGVfCUĢWTskWAX{yǺ_<~ȧfo>tDxx2t/w kDa*m7՟ұtuMJ8!_RwC<ߏrTx:2)h @ &H>:l7a, _˺?2lҷGCwyhʀXQot'Fle/#lWRȹ>!:q~Ud6Z|wzݑ7Rx6 7>)-3vK$ fqgU/TRg|p:mH`eʧ~3|Aqd^_ba"_?;KQOs JWz詺v@~0,)WV/#1 b:u]FU\zEFU‰˯SYyfEFo'@ @ 8!" 0w7sp't{. '/VD9Y&8YO UXHH.*lN2)W 2?4c4,b,&Jv2i)OV74a`83zP 1n3$hqQ9R.`U b3"V6#./.Q<'ЍvEK(I qЃk(lT]a{lTeCgp{{{?=?9ǥex5TɆ ?"݋Q޵ԮH[amkC)2c6eYelƝsAU2UFFZIaŦd7.ɼ&Ne%)HO,B|ćRxx)yX,_9[`*'>c_OkE74 ?Ȍ푥LO-5|?kU]&EKe!傴dCbG`d㚕P*Bb}`"(G zOX70C`{ع @ B]jQ`epgH??} :&mꓒ-Y/ɉ^OedLҲg{f_J)"ܖo;^:(с[㵤ᤌv~_t%q)Foj4GVuk\)v`Ϛo?{BRpT{UUZ[;lmaֺ(EE !@ y isv_N'PT'E(F,}PkRQ3ߓ`ZiVIrοqc6b(Ia nTvjSK[\J9 pC^JZνTҳrͱ牍#-C3HSZU aX.j@ @ h@vQϟBMi`KgߕY{e3Ma%H%`Ă'W&\ØC>m5 ՚wt;&Z @ݩU2\#{ʷ]'7+Kd e/?ޞ*)´5&B>eM8/D<䏵^rO1lyKSO%M9iG2?Dݝ=1c駏<8*iU&JY&=Z1{Ok%8~J{GGUd}@Pހo|~ɩ WץO r3l{˸?u;F'SNTA!x?ЃzA`NB"a3dGrla Bm/p0sJq~B>&Ϟ /l?l7%rEӟzh7ݩ -|똴n ]dr5v&p` E m8~$as.4na{!yt𩜔ťyyEEڪۯ}Y1EAOG %FzTiUYN-j:r_rn3 h+2ApR0CJ?DFZ}rn-eX~(\'}$F>HСrJW=3c4vʗSo\ɑ!*mPj @ V%{Mc<.[n2s?8`3ZL;l=Q]'SA8BRB"2jhhp֮k,,^pS?:[K(g،^8l&]`L!Oz<3UJ0:AOw+gzѩ1|;T !ɒ*!5sBK 'VX~8(2V,,(뒖 %VM1VV‚o$S̀6@JIӔӲw RS֟C]8=PA"zyyi('?L=ʉ4SC8'X?׹ \MHN=7Mb} {3asiC$_x]7fٶMƁk+JFC561`69do԰oN%nXj #uy3ϞҶ__E pT01Q;oMU\)ܝzxw**ٹ g<'ϸC]?7$mS Ή3/ F,xre•\ZG ]y>?^jy(ٚhent庡2^M>A[2D.:88绑gfz[m?uK\/&˻4na}%A.`4n=.ʶslcfdK3Ti lWFw n{ZC|ЭA},OOloO9FB|fSPd*q(@ @ Pytv6W;հH7F7{<\nn(o-ݩd i Q$e@c:ћ_jFO Ӹ2!+xrA5!ɏki 9LʯYm\r&W`wj# tvZtM pٽVU\i=?uujeNÑC4Gd@L΀Lj%_ +6Xր$@ @JC\RJjc[4x@}' Mr,(5KWbg˩sWoY~ LA#5wt;q @L&.Ut`vy8XZs1BD@T( g=0g3ZCS @s P^tPBI͵ @ @OP93qVCbS!ο=MH89+L^k黖v4#XHF,knZMř&[Lh_܄p_[4[`Og!h㺳=mT3FF {'F3hf߭0h mЌV=Z;Tfcd  `YqaoeB s"cYpA< G|&ݷG޹ &n|۔13RBB4jȄ; DŽ3dM--6 `%M\ߔ>iCx<1cR|JlzAt!7P IՒ81NIQYNchb8v!/Ke/3 !]&5{yY~c6Gk ǎZҥ/f# cTXQC,[=W>j @YU}XYǙogD|~#Z D!N!JE28Nn@;1BCC-lR!4kߏ\PHh؃ړ[0 'm<N.H}rx?ͦDл %wR3cZNRÀg/~  ޼M>Km5T|ȥ.:y"#W O ;~;蜒3ӹ=#cY7CFu(7_.4Հrh'¬=S4KxGgz}c΅+u!μ_c_b~ώt[7KXP +Dܨ؃7^0rքxZ|D̦nw@hj }_k/@<߳A<gĨxTbvJ>"OE2ӒRB <7w]{-O&:h>Jm)x+7*+&/;Ož>Gq,֑n#,yz-_Xyʎ)*o<+Ѵk;=#BtدNq%+׺y:䱓Lώ?)|kG1(@Z^oЅ&x-g#yÉ\nt,UF (#`~!3 ~)3k{'F>̬eqe;x;0=' )xሱAiqi $6O`)Ojf-7*@9Vw1!3VG!Y3ί3qѡ2@$`L"^KrlOӱaDzjlZ''|߈nBQNACZ\kycu]âCi"!f,۠ LӍͰi:zF'^ɼ67j8uZϞJiǤ&}R[ + !<.ԁ0Z\3=ߋ˴i ;)c,/O3'l&}\|ƻv#,şW%aM1 A?Vc'!dC? WO=qr]K`0eGϼ{=̶ 4WMɇ?6_{#Q ,u67J FCscC{+x[ѕ_R[JodߨR}}pU?e<2Đ/T쟅?eSTz- øȅ~td_P+J^stt,oI6Cm|dW~ ?GǮg5ֻcʇ2zRBU{[k` ~C׶>ϖmR6g 8/;ڏY*-3;~ M`ݺu“D-Zzm?QcQ csU@&8:Z[wxX(BIg\5 3uPy:{PMc{ޗMωeJyģF5-,{ziUSJKP KKgc[<@TAK߄^n TxynlW)mS}JxqY/ +C>"G"C@+ `wj@ 0@hwjY1؝Z ݩ8LrS@ @ @e PA8Or-d6 {prt-Voa4Vd`[? 6@Uh6ޅ|>1]쏅4 htrř&[빆ޅ>V#@Vf%c`ǥaњ )TXcS/h] 9FYߡˈOu0[TAe[7UX)mc)=xh/Tg?V7M{:pDbq|<8R *_ٜ X!pxlz @&P3qXz!)ray//-90msg?ѝh*>p2>bOԌ>xEʱOZivʋ,@*@2_-o=WrX-k%`Lӹ=#cY7ԣVVf^jx$*!öAo[ݹpan=d==Wb\=fM4kߏ\PHh؃ HiC'Dܝʮ7Jl={!upPi0h}D0#m77 ҃:-;]Q%)vgdުN9g9 "+p y՝e}`(SM~_g'MNQ<Y$~+G>.K:JsV!P=Iv˦|5Z h(D 2};h*NL|vo()0ģYXyn jaǬCeO,,0@@T/>L{.cTd ʍl^P ,;k={J(r+Թ1,sG azxϘ^g{q6GA>O6Ѓ$qQoa|7h;/ YyL\ѩpXnDRv\Vg[WW!*WCK Ղ3 ϖ~ٞMc~6.KyX=8}x9r^GJɨ Ũ@ P T81&q/U/Q)(73czB%@z01ahCbnlh{oo v>ުK2T^o빣><>gA"7tgK.90.!*h,r[xvXX?]ovm σS7%{]G #YܔW]|oÚ 7b~nVC~.J(˵v-UwTg*w}yvCR.,ݒ!mQtV93R?.7 j@9@hT/1iN {zx̢!hP P///q P®7^?N;ku`qL }.wlAm{nجY˦pf42i\jTXJO7J ^8l_XkefO.h D$nݺmXV\xEKODKL28gt,S8C<% #^) 8Kwß(#)8lxZ]phhI۞*5ș:(~CR:(} @7,F1E@H2qUk`>U @]Tv*ExqYVJcޯTNU@4ٝ:otMs'YX;Ҵ  @"er;;u|:@!@ u ަw#:#^@ @ @U%PASN6o~v_;5^?wvYN^'eZN޹sg_λU7L˖ پTk"Y׽13sh`*:/xQ}_{$+ϲ;mDSNLQ"xT>P]eold9LF!PL„rO<M5yI^e\x-]Eϗcͥ'G9}p4y=tUY/ңƢ2%ʪK,կn=붊dF$5^cG6+ Un;uWxd֪__};i{F~L @ E}g!MTMccu/M>/A(@۽Y >0J}A7@L𞩙~Q @'ɚC>50R @Y1rHB}a͙itqA˛ g ^^cTm5}l.'7&d|֣g;wi\B܉^6,Cx[O(m:?@$@]Y;wIl'HYO[-LDE`N)\Lq넖in,kzu>OW!K|u=z5(y=VFm+!ewsW!:Q[0[+G*McSɷ@iX9e?Pğ:[P5@ ıƌ cwJC/ӹ귫/&y~M҃;fdlZ3Jld:nٳ.FBjC{GӜTƓ {_ixooz"}}zE$Cl[w{Kw7*aGd1h´kxJN/v:]8}ܴ bږ&Hoۏe((okc6USӆRY9h-)zPΰkh|?Hr `/UYQ@@ƾHD0:;he"1s@Cnr #"g7O!g=I|[Psmx浐w*\zy/ZBWB&G|S2 #!$$9E&MpDF֞:9o>DR2 Jj< g%wvzei'"?u[C󓟿RΪGBV|Y1]tL!HjЧ]cy䱈Te> >b۹+GӃ+A%՞i9=L MK{T??z@TZ|sf^/ 9E4%i92 E$z\;F\njMEv\-K<7hw%C)ra:tiq#,>S墘?cZ&LB}E5^VH34g1II`t=@0=V10UQhNrtQ2 @u$Z, Eݝ(V!+ǏyPYymJn|c\ Dv%bzn=<' w:/B%{Űqa"y=W!~H*A.dt%\֛ K)PWTu#+,7SHͶ;ie9?ej[ Gg8N &e+*H;ڒ(IȔ.󾲔_@Պ{fcU{GUN=Hp5 j :VҁrвLqTE~m"[C : uEMk|v4""ߨqЃ^Rvqg'.0nM{M̙1P+I}<2"T8,?GnPF] 9 s/VdΘdmUO50m鱷1Qt7V=ji]֭G˖k[Ig:4jt//۵MS8P#޿W84nb}Ew"/AVx(ӡA{Q N#ωz_i %@U}s/jBoC@Ԛ8[#]DLB)~rPCWdGO*Q1i,-L~\GlOWwo9~;z|vzr7S ߯³K7,'8:TURX@Ha.T_޻urWeSX*mp&/X8k7+I'Z=ڝC~+('76XJU@) yqiOԹK|Ed]޹ak%{FF; c㒷\@JW@ Ս{&cU{G2C@K!~7͡ PC ^^^C N M[BY.}mrb3Nְf4;}E[w$uj-}˩thLA1s"jo;$(\Tf2[Gŕ8^qgWUP1v]ݨ0etܮˊ OhӬŸ?QƷl| yUMS`VߧcQD|Q=0@o{wxʑ8KJ@"@onjq螵{_UP1v#gL]1փ,@| P1G{p;-|~@@jL\WT؆dҿ  KZto%L@MxqYK[UAP%F 0ٝZaC@ ֭[sN5tB!@ 2 NKL @ @ 9g 'Gbjo<$.6Z5b,IT@KyS9X [ l{޽5E Ɔȷ2˟ @!T==Wb\=mb QI0 -gdqL5c f_ }ӿg_/$`% >{ۧ5fnX`=yc p Qr_F@ P@5u [)d_& \HV}`(SM~_-Gq IDAT\Q(m*OP^>N"JgRӝ]g'M*Q<YDx D͟R]C@ Btx yvc@@ `"$z\E}uɑ1YIlN \)'TY1dR;g\',MI/n;Bo7Mſ>``IKu.פ:;?[aXRWGaSB$"%Qq@K7DP@TKs!c@@ `=Z9Wۮmxv}z̠>݅u#UVZ;pF%+by,ߥ+n"r: 58]&hb6}e _}@  Ø<".xL/6@  X*๏2/(ϫwX152Eg/(&NIS:s"O%|z-{'K-Cy"rf# EXYH)jJ'Hn%ϲ@Ir\=U @&'x62e(L% @5KN;k={J(r+WaYe{u wIkL"%_79P-~АVL ?)8{XCeڌ遗 1kߋ63xM:{_ol?q;ZrS$"_?k8F}@ #c&1A# @2q FCscC{+xaކ5A+o$Z}\oaawFX݋?QW+>[\wq QA[e?D f}FL||TzsӋGcè((<#gL)$w%Ձ. @%7x!ۉrlPP@ @ j2*_N6oskPƟs7g ~Sj3\ɰϚ#zq?瘡GwSW?f[^x@XycCX[Yel!M6 x ֌8 xWbf>-Hհ8ݍlgB mMG>YVlMԬu+o\v>^.#My?D@;U)&W)te\x-]R|ýpގ5vlgǔ?9~9?JgI(^.L-LSƷ4aJU7)=_^cG6ў1Ν͍mU⿓A@WP7au+DP/h^6Bm _?G,GB1Fv[)wu(͘|%CJWmϛ PNJTqy1"rJmŌCm}uFV1AQNԌijΘpy<ўb3  $ D6zǿ%Wu٪\kGBض:8yrw2 J l˻7ߛҹY<3Ey<@-jZzu>OW!K|y*7|ço}1] ϝ;e .}QV `rˍ\\ifItlЖǓEz"FZ8tDZgݽ+'ʋb7.-82?)š30VVK`##v6QXfS 9~2M֚:h=ڙr{R;G=yq:Hâ}2~ٱ3>ʚ՝ag礛4ֵ[}aCƝwSY7Btmv|q$h RMqӗRU8@'@ *5}6c-Җ0OAޏ\|4,U2<կX5myky-vn*oV/2Z5$;%i1IJb?2jc@@kaXZmFIE`OJlqP۬rL٥'箶p2y-_^E\ɥ/37xTIW";el?/| v=ok֪"Fv(OTOp?V⤽(ٹ)yBpǛ1>Q5r'_-ikxfMÙ8]~7NWO<{4X"DkZ|y.\@xB>HԎw{MqTzwiU ~h+OS- (5-@Dɰ'JІvEmw EqNi?ya?PEȻ(]JzKмGP?P2?6BԁMD$4SdzMSg.*e)Q.ȕ#.j1+ק#W"G_k 1PT}VD/"O{>D+`>yG+H~C S6ܢ t@@28Ɇm4z Ow2 ƲN6$g5$_s35ۢCg}z}h#.,[VlRګ>8̶qTPؐeC9`ˋ!ךPL&͔(RNOd &SG6Nȥ!;μ/J1llHz=W!GF$}{^@V7ʲ2Ef9uhSB LPR*ǀ.]D`(K':޹W};ˁPߙx/ni;ܦ4Y|ȟIcLщƅ%u,a?c*LvJEy޽$wS *Xkԭ{4Q4@ PjZcyF1kfnLSh1^Ou $UpͪݼCp}}TPg*E)mP|`6oD)E@T^u@PO0zjuT\nĆ75CEEE=qщ>ɗWOB{[ǡpn7cdWn{I~QkߥMj W4Wѕ]q4Gmx rg,}xöŧ vcI1.{ɞ3'C"ʯ7[gq*Sq˾uT\ixӄ!@ QLnW0^,+.Txm_Is)5dvlV`PӀwnںJݿkL/T%"1/ǫν޽4=ɝF?&!YڽO=E{YV$8@nާy-4@qt95[hMv'PR=%ڲe%0ꏫ%$w^krEҮU+-ȱ"#6xp\~E# GqȸD%:@JyRB7Sy)Ȗlo_,2o,Ŗ9i~)qô#tG0ޜl|6c-t Pi 7Tu~eNV~Z9nEjQÄonzS @HxqYNmSƁ5T؆d2oml#p3o# AE/W NZV5k>޿3Uy4x-{,/śK[~;Bw9:k)@=.sr*}c򠝞3NNjxh/Tg?hU7M{:pDRʑƍAtɫ| Cron$$$< {f;ӹ=#cY7C}=QC'Dޝj~#Azk*ݽ;yHa7+yx ,?]wQ!\\>RL(@ P XZet@x = @" Dg'MQ<YDq>|ޯxf.=z8UFL!hARMDVB@򜸫;K :{{ B;),e(S+ȓn?wr}ֶdC@;h6lSV!m>,;MhGpo!-O_ij.ʛ<ծKGrx !Qr3qdN ͷ8|Tb,)p|.zGA]'[S߶[-@>߯c֠̚i6@ $@#ı纷p'|z!M K1 b{gOm<8gK\.6}Ζoނ/ sJ>^B@i*<̹k?BoJtlVxjgUA# @VjT5h]@TOL|: IDAT+ *O)Pnzat7_9&|߭zjܖDmr UΩvhIk;WO˸5Gw/v76Y;}@{,?mBk MscM !GN%2vrSl/t`WkخnP/ٱ[0Z)R)הgę1$&cEHݿ.jPj6T`1 %2p^ߞ7kft^;#† /=w:|A9@$5c1q@ P ,6Su\}#{L-?&o9sޝjCD.ܥOv_s/>W="W}/b?G[& @# gۼǤE#UIwoHeyq[-ERvU˙a\C'ܳ?V?oן)s>+r k[;h2-{2d:ܽct#NL ̥ݧg@}1ܭwΣG9`s LQgGETLs1s; osAD_\#9'M.ke/ki*(`Ї3o9Zz0XW%SX݃8 eAjY5=`8ۋR+%j+Ũy+Y]c@ ?V:&ܿj4s}GJ#Kew?a$l,b؋YՐ?.*{Kd,kgxMoL\5D#d%Y0l܅-b6lJN gA [\`v~HCq;µǢ4'6N/[jԪW^/˞_Q"O_.N8@ԫO<ց.P##x~{c#{sfX^FeOڽk/;KO0̼֣ͩWO1%჋/5Ц19lzKk7oķ2q-ƸۉHOV_)>>X$xZJX^ c)fT^߿oR=-~{j_"QvN&ŻzcY1_]V9TSS W -?Vprilop$_փ˸എ"}C~^4`)78r,aWv+>/Y=PdLRȫDм_vd3 ʁ@NL c"qOW%h)tTc d\g^9JQ:`nf(zq Ka>;T7\QzI8M҄/@T0D<:0Lqe|&/z؊EqrVd^f\=Qdl%C'ڌ Ca|,CWrg]ی^>cכbJEkbhuX8䑄ڌ8!Ii4cùX\D]|Fth?QV[ Ę;yV}xWVG9 *EMj۳S+"!%RV KytC(U5k*$HDXiD@{>rH:dIfϟ?{r ]ǔk'ψžt,HL?V&uUs0 `>,zG6L\~_Yַv6q C84o9 :Cp`pvH._2KY)AS)h$Z$@cO9_?0Oq2Ѷ.s)ІF+S9,jNJG\ƼܴHuCV!Âhޯc?@ P"bZ\kY*Jl(+,F)K#Z+#L){\\UCYh$fyO}^wCTtA/XlI#(?H #{[gƾص>  99~nd᝺lkj?9)5!4 ,Jշ'0?_s TG7ܝ4˷p>Ý;HռVe^۶>Vqyw$2,Ǐd <'Q 2MznFO2(f2k #bi4)(g*v呸'4Kp* QV x^U-e*ت`f= k\(L az0M`kD9SO͖*oKf~%sdrN~vlf/8F|Gw4UyA@M18J*bn[>fRS.LVs *? Qb%zH>`Ud.ڐS -{|uWb\cWM}~d}dQBqf+fMeÊ~?Vi thK?˚ ~e25:~6u.9c]>! oE8QTGÇ;+5K񴖎c>$};ٰOΨy%C?q ?r_68S;'T=3.KEkeǫ&L4ksHNX ~?cxU`л=.Hʋb~͡dUgztzS`u iY0:gƥԭ^be~P{QQ'I[<343 4c*W6_jeWVn * l7Z& ܹOݧ?UV ̀@VAVD2^tGxS| b8C .~+R{]^+OOj&e)IٻKIFKQZ~({1}잁R_pקe6 pEfR>s. G4$Q,?s:}jsfiAf#h$2)ksd~Uc,$D>u.)a1wi,D0MǙS8A ?2ǜJje!3rXGjVʼghb3f쩕qn8b;Ml5PෟD W(4'}g&a^"v9fVY mBa5Bt). 3`}zʪBkd~|P&xv7DNUy?d?n.@j `X``i+9cކlh MGZ(Jo5D ODؖ0n;0zϧwW*k-Ltd Z ?xJ({F/;X-H 8fq^sOT;|o_{4o[+75&ٳdd~di.mԞ3mjEQg a5>oèd#J PG~|]S= Gw'8('T w^^5Uͬo-#}|qkئ؋ mG+"$WR! הAN/cUp GWxZkJa@CQЇ>`?. z 5 g %hjHFOj(!ȍf.[_mΑyQ~37MkWCiy(3 ZeunF(j0w44f?XcNl̴àz` e\Tv65 rjx9C-TȼgΦj$zG}Cx17 o3blϵ4zvMƕ7. gtjjTmҾ-fC{?h8`^e  @ @0͜FI"@K=dd'}vHoźƺE|B= ᱮԇ:zlMF9Ao~) ҭV } MƆ4sv71cy%D^ 5pΛ &_6p(Ay Hv2tj`oYP|) N'OsK\'ؓxg0!<ߣQ}x &|Z\p-m:/pف tmko<r#%gCme=F?GaoЃJMq;#;N!vxΚnyEY;rg)'EQ8+1Iʦ?;1uCV$n05V뮱(P/if(n?z\;U3>uzhP0ޣ\"c77HvA&ޡhtc?*٣`Zr"AᏭ"3SWPcA@4 ɒ7b(A:~V ([Ky/}y㕱Krۺ"2S}Z\夁Q@* Slh75t˓*6`[l-}gy% zNIW$6J"!Zcgo{5gANv9AFBDe[Y%*.vy V5!ޞ;%_HX}6ߍWݮ%Gil_" yM0-'QvfԒ)n__ݿv؝jNo unG ?VB鬨ȒP>N^٧kNOOB$hOx}|QȯjM8(FZ<{׺PRC`)F̅^@ @_T/'JӎX.Qz?Qzjkq(>ueNőW>K [.%0lfDX.bCfoǺ%KVp\qK##TZp}-P@ޚORAsM9|"R:bTK1w,I/_|ru7hs\~?=I[mYN'{bݞU%kS+(!R+>uxI7Tvvj|w o׹ŭxq}GAN|7>B?d~-%"%.|p3 t#W,i+ڌ=S-ߝ*2U.nvmȯVk҅GM[=<:{==Z@ץ&ҕC,Sg=hc2р@:VN/UBO OI&픦⴨?hVoA03`(@F@"{'sSwO_2bQ0w2I^w_):AKL IDATő~!Z. 'H// #X Η6lpng% ߙTB y cb̝K<>t 'Wܙ$2%RV{BYU%NA a}GghA!A\%юG=_ 2}%LZȋ)n)O= 5M"Q)L$.`8]rc{DV&_TR}ַgGac捱;Wg ~gVd!3\$#$4)Iy4[Fӌ< :ڰ )@d'%]l^*?ԕd d6q:hB|ewhCK# KXX5uc#.?c n*dXxay{c-Mf(@Êi3p"&%ȘؖTΫ6gJ ZN w -pE(?R5o*خ)"Q1pCJp@ 5w3,fQ>y>.H`D= f((b[<$f Ť~vrz(Z,5!'5-"*"' U8rabpok\ݔH6U \JRJe$6  &/1~k $q9_t&Ul0Zy[6B|M^2G&w/Vnh);fq2hޫP,<Q;wLVa9[n\S󟭜/h;pkӽ;X7)8t% -3§87=#.Mžܕh8s:'G\6QI4O- EcqJht71w;UJ BA~-Z(\d8@= Bz͂戾SY]dM0H ц/Rl^Sa;mDӘ>kfke=Xm ÇED`F](DY[.`>'2C@/t@8@>Aby:G:dsX+^;J V٧x?ԭ.?TrHP[GXrG e]?[;]3/4QXA˧ n{ܘ0I٠eaB)?G]RXL?޴SORu(&E+!wyM^C9\y<gFWeD>=f9JjZj[2'Cysz"eGxfėʕk8l78N2/>u y:ivFi}ycn=qPȋBBUs<X^eڻrmʂ@t Ȯdo]rX刵e~JܤҎ7ȩ*6>hr=Zz::r숉@n@$n -}}{R[1;6K?WVhGӉǔ3yhv jјPL/ߣSaŖ6%t[-jܑN9u=ߗZb/5H]TXB65I·E߲rʷ3^DsKb5$_ʷW@NÚvyS?@ @pqE~Z62s[Yn|CP i*=ܛ3tkKf )1ޔw95XHi)D.eA@بh9:xrq2ڝ{^ F~0ͤ=ێ g7_u(fYaYo[9Eƨwg~w?I_tĴ4_W!ȸ׻e%-襵nKG8^ARGhRh"qMja@ +TTy<`AE&#b]G^ӾqͬhCƾhd̫CY*aTlK|#J`3_Ι_a,O~8=JB8Ơ*fvKzpo;eX 0V_ }}کN/*=U2@,p @4);IM7  5$@ܿq7yohbyd8&&_ARkԄHdRn #./,? )'2N9ypzy׸bוZ5[⾝;-Ӳ.G%Me*_fa\vL܍ʸwyҐQY%VdEZ6RR-(̪q,2Ol&(@ `hZ.L -Q|:2ܙW)uHU5z>=5 Y<b)E%Ysf8 zs[hBLQt\c),A">݅4]>ߝoҿrF |S3q kܱ'1N8A\3঒: ωK?t@ M@#TuHCwddߑ{fn+vێV%k_ N>B֜ۨ ?|xoITS%9yeTZę%wy`}1^>1GsY7Wc"T 0܂@ uCRQfTS?giEN'@ӵ h 'O0  h 0wSvUZ8'ZɔȘr+e@]1#[$+lfqnz'@H؂d @XOxYZZ%@FƤ֪FsʴEG4Wa{OMv.z s;&b @ @I"qvn@ p(2?.*:MG;jC G~똴]_Mu%o)ڰa.uwbbyE-_u`~l$5ZGH7ۯm㯉E5WAҌ~wS;VaM=BF=)2.7\.t?F刬m&ʁpھs9p@ PZ<؛pj_JVܺtwh69hgOcנ2D6Z\pn:t-D^]׵X>mmx!;R9h.j?̗}:jzU8Jvԕ^[di͏tѺ蟝(zŃF<2Abnnc=wBۙwuiB#Qd yXZܻ>KOS U@8DD @{G=~q\xvI&vML00Qsc.sв6"i ~^\4bƀy=.Lt{ўOss0I‰$P[Mط@`eh3 0_?6$; @ @)cx6oeF4zpieq+KfhD6{svBBRykŞH6 7;WgoyI_tĴ4_W!ȸ׻)leao\'5*ƜIٔyz1`L~ܳ` _{vU´)dVRG e#Psy'Hn|CP i*=ܛ3!K\5^{yxڔUco;הb!M%ߦ9VeU-tX@O.S]zxU",\ねΜ|" ?cJϻ3ק4?/֛?4_^5#Mm`R,x&l񳾭3^w6jU0kwX:ʿ„AyZbeh:]h^7ב)!'=Ip PO @$N @ d <ܛcUvI×(Ҹx 7s1{>s0`9hK!#b‡W-0= (`XG;"X%?#\V>E1e,z˂DS-NOT)A Yz(uJk>n~a^MF2;}IhCƾhd̫CYӱe;8hZsk}53JYX|L4RssVVlkVVA/7F!E Oh:T (+ hmFbfD+U/y|2%y*Yv~9 UjT/,u֨fa}ꥵBy3O"5R6} _88˿ShՈj=8JË/ JS! {B @w$: .vVquˠ܀8.{{{n;j3pZK5jB$|u (Z!bt!E+ZH\ґ PNGӈWxJ^T5FT*FrbVT^yʑHM .]zZ#$Bn Ǐ2 NH<1yX"Xw9o72V캲]5β[⾝;-Ӳ~LT΁<*FICFe]ߗX9dՋqUh8#^!QVN>dse"3Lq,2V&@8NuT @FKpkӽ8az<4n6Jͭ3=u0Dܞ)]ǒFc\W#=򢓫{*0 /xL始ML={.[%47O~q}93g |l_#4[䝶v9O݅4]>ߝoҿrFsIjB(%N*t;ts].RypSy`. m+ \b?[Bg`h g'8@ G@3;%vS]3EEH}GWqCƪ;/%U_/=y{5}~%>ܯ?Ө̬^}ZnoܞcVnO% [Ml&_LN]RvĶ*(y_jL8~vq4FN+ m_R2d?TZę%>YjF0((m~{15RSFϟzkP [56ez .SnU#D-}cmp&P t7Yuq0B l' @FR<[Ħ[`;m%u l%[jjA @ @ PS4rPN!V/mx/fcT.ܠ^[i hF}4v`]+7z8*[kި< qX+Pei@zQ6$@,Mw=YڹKT9߮9m?V:~eMu5B=@prN޹Wϓzv_||҉>YZ07p苓:I<=GnN]QC zukz.6}Z KmܺoFp %Z4S„}'xp* [1F-?|upvsIlcmj6}xnq0'O_8uT*&0KnokdžhYnػ^,gsIޕ A!2jNޒ,sul?  jGu4sҫfﳙ`W庼G>e//bC*@hol D^R2a36;0# KALձK鴤ZZ+z:lQ>-E:A6(M+RU)U؊Zt T?8-&9-Us#1 V<ٯǽHkZ"$uB_&wݾz& 9E0W_ڟO+޷|ISƷ ZZZIv;cuvZyݣk'c=&-=J{@eΘ8qC7sQ6F$LWϏj#p} '6.4%ܫQBI8=[{xytRdBnI$ 6>w1ȳWVۼHD-mzBI4Ȭڎ].] {q~HNs^XPFm6`g m9.C(q? )Xos ɨ {˿f0cg>!~mUMKR$aW[Ui?ui>pg|E."!zmkMܱeOk{ͪ`#Ȯx\ݾrVf!c IO_8݉b< @#X){!$"X'z)! sR u\? T?{6CO4G+"Xy.k_*#!86gڛ,*i~G%SCZY̓DK{^| q^Ѓw_}bW1vq㲲ݩC"vii2m8ܘ8鷧\Qe]>Sl؅ad@ @Äac.laWrun#N0̼֣ͩWO1%Ld8eAwS>[ _,\KƵ߳vI7Ww&$\{7{ool}tpy_}+# [q?nV}Ǹ7oį~i,n(l5'%Δ"!.Du#?9g<q<;?ʍ9^{y lþtY">=)R#LҢg{:i}|LC:ziq# UMJJtQwd5%vkOH|0Y48dTm# R֩XoIz 瓫۾AKϞI%nDu:1aUM#4WRuKefGԿ=lwT+7mQJr,j3_"#W5`ioFynfʙfW 5@/c5Xg& ꈢ'>bEWU˷!v;kѷs99y%.1} gLd5X4g֏=ڵpaO(aF.%9quɧ}4;uG-3${eNoM« Xd݀"qqyQ/E<\mFxDI^RTDA0o>M҄/@T0Lr§}g+ wSJ^W_Lg*\ku2uVVPĒ?<`NjE:QՄ3d^|LT$>Q_EL$f>_. YiOrC=& +91 왐T^ ;hP[W4s's‹ߐ0\ 9tܕ#(CPBw8%ۏqafcI3(h"5}$.p)mgW)6_Q8Og"VBLsgՇwц vŬ5f9kk;+X:5 01*86g˾Kfd7Ӓ{\[>Yt@Ԝc5(..)R#sy *E2'7ȑ GN ӟ.*}Xwznn>͚Kŗ> DepWyļ1qw]S-\  AA8+ ?Ya>3Ů-9EHy)j1䙥yO.`vʘ r\$0[aK48KE$.S9B*]_f5¸."\0Mb鉻'1\K W.0XD^DV"r1 ^ $M.fb2 vq6J%\ֳO4%K?]n2ZPVs?i%\'ౘG`~K};7ܝ4˷p>Ý;Hռb9v_v qVUi:\nu}R',A) cac@OU۟G`ÛӨTq bDd֫׹C4\+"F [l/]{ݣ)@b鵟.}T#ُqf=Q|%PAOLϮ)&a '*ER0]uj?m.cenV~쪩Ϗ>2lf$$@z$TA"M)(`9E` ySyU'N8H/RHH#ғygw }$o?|3<>>;L?~1(f:W](it_ʘg+KqƕTM+N"d ]w.eĈX͑nʮ4&R/I;cH1xܝwt!O[<c8}^X#qɠn0* ڡr,[llu'84QwKwE%@w9,}] LވX>;VDpڹF`W@ x"G,cL>h4՛OfTS>zwYݜqWаq>k:=-Xˆ#|qo!\uu#w=@JgECcnݥ8f@M%'6s=Sf>uӳS/K捠ىߦ~a{e;<3myʪE)ƚkhȾS^Q) vl[n"üi sk/bOV'O)<0}wb }hOg13> uc#%AUrFk'_g'S[L ~FvU֨I6OX+<.~FFM."oYU6{l:S% @g ߳C 7 h ^i3Y'uRosU< #F^n*śDwPn2PwܖGL2cǼ[FgOkGUlvT-?޲݋!SĵӎG!@@_팝 0#+NFgڞ[8UȆCe7DxVpH9: h<ф(  QC޾;,>P5'ίXqQk[8eN| V'.0zw]#$Us~d8{N-Pm8-wD'Y_f#РY:t.M^6L5Oy03=-$8_Yէȯsg6ۄ'/M>7rILNgG^0sf@s nH 4fA &?t(Z҂L(~ps% ڕl:7ZQbG {xrB*ђ"+?{hY>q}[78~eɏͽmt י),LVE[J:DRgV_6uG2|I$7vN}ׇ3+}Wjj(2ָxeb ; dR栽Zi.rkJNfz%$ Ouq@O5XnG*זj!L4.8 q5?fl "թm'@ڻq 91SU­U+j^*9 + h28q``զ]W |UNw)lC,x% eL7d:s+}ъ~S&o,_)]RUr5PFH~ӆ؝Yܑ>(:)]%o}΋YB_Zm $8xr2Hk]}}t? ~! ;[p5?fl "k⤽}GG{Z6uQU{ [8 pyH -}n7kN 24WTR+PS4\t*$ϕ>Mv}&gR,8&S!M.a*Xhy7򴘡 ?3-dHɖ*$4eZ4FK2Qi3<9N7mēe\_kiVbw,*ԅy?DA 7 q&N?l#4[Po8p ec:uwnVi9v;[g% W6ŋKX鵔!Oo 8õ~UOہ١:닟MqfQ@D gK.\F~%q/WpMR @@{᡽آzq=_U}xZ8ߍ?peasNõBOq3kX.*j(u_X-koqt 6$թm3@<[%-FH/׫u4C\`V%4z9CtT􋻂G9 YA:@ fVZe-Nu"6+E" @@JNj׆!@ @ f6@O@xbWmc}h&@ 9…r"Y1WLv^;$B@ @{N-Pm8-wD'Y_f#РY:t.M^6L5Oy03=-$8_Yէ8ݳ&w9zwT$&3#{/9F3p}eGߑC @ Dl$ʩ`\;E‡v?ss9 za򳇦w'us' yX܋FIH@ijM_aUoO^]t\嬴8O$%qrCqgcMٛ W{_bSX$~x@Rό~Nj}'ξÙӾ+5"cW&3^0L-eܕZ劢2>`]<\[abzή:Rd?ICt&j~B1H @ @MZfHNTUpqU`7 ĚJN)CRʬāacUv])0U9ߥbȍ9(12PUr$}ъ~SD^jFb%Eku^M^CEYZS+RVj>(08 +8NW;1Gӳfy'}$']gXR60Jވ%E%'$߼3H1@Z[ս oݡNVǢ]U]}IDg'd@ @#@8s[MڿB3L*չ+-Խ.M$+)] HqLؒrR3S&y"慎Z]I0i2L%tYtpY%S[-c4z6!DwzO1q-~Vh}O:v%`}{%&rw{2dTS_{pmS'ϤtR9i;TO(j3TM @|mʙj*"_賳MWxlO>?S|`+6QC޾;,>P5'ίXqQkރ[8eN| V'.0zw]#$Us~d8K4`fzZHp\g_%OQ;TfSwP\¾2]ֵt<]ގgs.F @چfF?VpWr6k uֽ oD5V r95W{),LVEX$?39Iʫo>8gVN"O,.:SrlW[GZz9B~[7Ir!/-7f/QЮg{޾b=:gÓTV/$*|p+_pp˗Xm\idqw<̱g1eC*זj!z&<7>?x&[ZlD92 @ @- 'yY˦ƊiSLN 6:<¦1ʷU͇/)*9Qu\H?DrKٟei;K*ZmF>ߴ!t*v'bz;Kʘ`oo(*LU5"Rb\lƁL`i(/z\ͼū~ q*N66Xiו_]J.ڜb(WruEWTժ\4ԇ!{ {pGr҅tm`ܩ % ޅڷG'+cѮ>Nc{Zot~LJ !ŭ9~l @ vh5qUfw!ީ}k~z3 l)h:Q}VsjUת6~*V(i/Oo^)RDx_ilVRJBUgOoaB_L>̛ص'PX&ϕj>_]lgS=i|mѤ4;$z] ^App#/?צPߟ :صa/V (*<;e %d 4';QQ]wӒK^"xi2{MhnlĽ&X}Mʬ'[ot8obm{7Wen=Ϟ}2 `pj) sn{Y{~wIM6P3P@TmIDATh9E}̕er},??̝;ץմ1Af@ oq/$nݔXoJv7]?v-5&GtըV=–m}jzL/Cӌc{n 2ogu%,4 Zu9kwuU(:WZҿ{ԓJS٨HeZXyE%6K.>6Ǧ~!q2M+_F7ꩠҋ5 gf¶FmdkOr8o@ @K#@K详q4@زgjz*H @mKfdO-_0ۗmm>%tYtpY%StR95qw`pΧ@yK @ xgy)l1Z:w`pA#BKbګSlȭ1\f/A @ yc "n?|**.Cxɥr5:$RHCz~%>[Q&x.9[¼|IQɉ*;[H?DrKٟei;K%BH5͵*>VQ`#qMROWpbwb:.8^P{xCAVaʩps2Hl @ @huM&Dq[oH-&Ԫ=U2nNo+ϴ'\LjlB"\Ʀm;>g WYI) VH2J\q}G?@lZ>HXx_8<M)txxu\nh'E9m;[2s!]}wje]|}>_]4Y S=i|mѤթq?.޼x/īؼ">G+-_˹-~O>qҥ@ ,c-K=7Lf)fܹ.Ev 2C v(|s.X7\~%ן w葅$?gMt%7u˫MޛΑuhRs:Hn:!МlYWo쫕0k>m SJn Vxu~/n|6¾h3[end=E~_/AGv[uQ[ߌ{ + #߿˕}luW9F_rvW9-7zաON6.VGϞcM&ߞ 3u'Yf$|l?Ck8I\RKX@pқrKEyv#)Qh'7Bo~tO{֖G눐F `< BwUNюvri9z|>:tH5}?xnc&HiHZ9xJ2F:[o@G46:쓒le+1^>C{t+S{ꝏ 5F%mԟmo# `wWW[s___"_b![¾+/u|${D]>pPĕwLIAX %&7\k\y2&`D!6䏯6 IU HK8bhPhWCfE3M1'}@,^-ǘkKNuʰo7-!~ш#ڂh.{gVI'4ʶ)zIǃ8+ǏrH+!E<]v0fMِO&>?X ڸϚY#o8$/&v.i`RAagmj;gj1Q>=zS]1G%G.g/Zܵ3 D}1zoOW3!)t?|e<;B&<Y;'xoâ߅LI7Qԡ ވ'/ ѿQjӢef(H0x zl~V7α9%O砍XI8m|@1Kh_1ޤjT4\6u aMWo|d|*{j̿&~B7ypy=s_nƒۖE^9Ɍb?xg"\b=%$rM-tK\FM'ӊ!էi;>&"д~^⸕EG,am"䷪^zE,vr28H!8ڣ/rTOVe+N@п@rc3ʐ2ݵ紊T@t]y鈀yusg:p9&oqʍ,\slՠ[5moVM;4*0R :1,|7ҼMG=3vd1'H?Cai_}[X絙Y?o3y! ?2^[Va$-Uf=q\"<3~]:j?K,3 kvu[˴,W-) Pok0ag,~@me@Q8m(>˖&6OqfdH>?1 nFw.{5[]z"ϻOO({™iOIEhTKQ!9Pm`ukkĦUǕ/߶+3Cl8I#Bsq_R{ ShGGչ%sj0s6Riɽ㣂omƔ0D̓ڒ/e~ǾSX|ʚ\ %ŜwT"ncu$a$_6i0B..@?A;ݼêߵY b#:"E"*ӴTJS?É#\L+FfN'^{sצX;˱u9: [$φIۥdHq^b7b~ؼ-A5- s?=z]8t&7]}!^̋]~s&qH|9[Q~EKc98ߒB'se]tֻ*U`HCa< >]" 41IR.+ځ'i<@j/1L1 sܞ3$K~x$t4VJu^~?GN%NvΗp'UOZ4曥r)o,Kߵ2 W!]w[Y^u-9 H"{~o3U.?*6G(_^S Y/GTԍW;9ç92eExV|E|QTrnJS7L)xW} .zW1T髯j/]#@؉p}d cΝo.qyjf<7ڭciK]`x%-?cuu Hi4QRf m^4 mGF W2- ׳(Zmw{!xcOex6| 2IENDB`baron-0.10.1/docs/grammar-python-2.7-3.6-diff-3.png000066400000000000000000002445211415427440200211660ustar00rootroot00000000000000PNG  IHDR}x6sBITO IDATx^|w{Oj@ 4Hn#(HQ頔ЛzB*)\zknv{73.aϧǪ+Q4ڳL.ȧ0<{Y,kW hmZ.s],Y*#f͚e5yotkkpRGB_~4:x(L%(#ZIl*9 4F1T4M84@I&MIqVRes|-L[[!CE. |Fz⎾/t͘zouM!|r$)(j,[++iiJDZ;%[a:s$2-Hϸ߶:GyOQ̢,G~R()#:nvׯ GpO1@cxko~cfCNy7[oEfAeWSQi7 )+n/q\NTMJ} ޘ.m}%){XYkѹ}X%Q[o= Eqڈo΁+O_9Fl%Bf꾣,p@p[)*y0l]ھY(%OaöМ;?^Eh4[߱w/ܯGJ%sF/ y n8.훥Z"rԱѽ>":>T=zY|8lj1VDGEGQ]T3_-rP }?pOWFI_YbfUiBOLtkh_\+ ĵל2٩Q̶l]-yP٭bVAZjPs/Hj3xC)Ϊ9*GGW'} >y.Ĩ=Vgg*sIOoL! זORN%J>Ҳh?Ҫ@ x 1 Pƽ砮4(6=ikp@ #xޏZS'@<WJ@02ؕ+fcQƤwF^ŵ7+;w'LW;/~21WA3 (ˁU-"6l Db/3>Yfw#03 xOXʷhۙjS*t[I>R9VDd^מ4"ϳI?gĨjqzjh[Y̰dsŧ7>O] * fv0]ڭ}0~z S\Uu8 h4BJw=z,N|!#MG]#z~ek|W 5/^x CpCz@>&]5Os;uaШo`?QJThR9:yG~Q jL~ce@@?A< 4T\OqN=iu'cgd1 uCڽ G@M&?-#=܏-t"%ʴ IJ8Snc/rXiyBT_sZӼ=jAe|kf2Wy1$Qޤ|-%eU+X V4&'*ĪS鯐dBiteMSXIͳh>DݹScy'*:Ha-ѻ}m$^ViD6NENY"O~;RzAR\[JV=?Z|45_fk|W~#x6q'8Eً↪, ?Cq+A?䕑bV'mzy=LW& #ca7yY1ǖ8c'{k'O eJ ,K'VnB熚Qr7[p#S$vҙNO؊3\ ʅԖPkK+6J1 Ri:VoTy "[0%џԍ>BtK e>_N"H!{rl|5ݻNQQwr P qej3ӋoLéJQ/%xvx5]toݯjA2Zk(5KJbu 8=Gy0qUL\Rhz(aۻF-PQXW#} iZO)Q5@%r sۼ6sDEQ'KsO]лq~FPQRswm nˎKbԙ|WҞ{ Q)v>Ь>AH;͓٫YD3Z65DApF4NOD'ʿ({*"!<@d;YI2=~cݸOnMcwIHOg]j09LO6(aCd`DIq"0ʷAt̷(lclyōŏAГ@5 x~Aрj$" T|sO@@kp6PzH5ܐuh,qmQFhGDW_c(P^]w(8>m?>cp*8qORS~睯dѠ?9(ϫVB<ح!}W\)ʗ>'\UblfQ9lŊ)y/s,r r=UDWC{n&zjw, ZOE ˩Yuǿ3fԍhmOJL~.Y"^., /yPP>'VX>nP"Yy4P|hNB5h8#hӟF58xfCj +DŽ}byKUT 9 De"7T}ra~OetԇLA8&(-K&u5V\6ΨHJ}?f-Y5fҜؼDQv({QMF'K-p'J>ezzcA&(P h.LՉw @4nϴq@ @ hBm?qSigϬ7g9~~@} fzw7;YLe'k7u#F@ޫpaȈ7R6iw c4Q =4 h wczw5o3f%6Ӧ'u|Kk\ĥ9d`گ.5 .z9o>5Acɽ1ZmV2ol\ͪ$#'Nk=GU²wfcqkN=~?,1Hzs &l@h5_7 7^Nc>sn*g k*=h2*e>͖uah'O$5ꯨ25@v apk_ *d3nNQbST)vQyã?Jʓ2Bژ] м@;?75/zl[S]wZ7onk+diYǵ0' \*\ .tݹ79mv}zao;͉YxǍ5['. ؐkBr*(W!j$z9(?rB|ǥ8\'¿(}8"dqu +3rsĎ $?ۗt#̰q췈~##  Z8Nଦ1l;*۵6΃n뵢]VUJs/Hj3xC)"$D+(@ԕcL%(\ 15Ez}h̻:0v9:[Dm;G0wO& =};hfZDU'S,[5'Dg?Z>~^UY5T>)=myUi9UQ1W'z8|w|\fݧ}3NYr()31R,tuCn s<ixn|+sQzV5̰dsŧ7z=U(I*1+jtKg>g̚-mO䮋 4"U?ϸ\20D`/C<3)(@c5 x 10 1S O')Z sU3785oړnlRr"j=Y^T"c8!8a/$(% Y;|EMRN2[ٺ;ȊěZyф EޓB3_WQm) YB./J6oͮq7(EQE3Iyfi*J=ㅘ&$Jq~&=Ӏ6G.S+x?zdTSS"+t#WT}|:矺7A4-GcY}Ycb7(='1lBپhߕI7d8SYŃϞȻ6Ψcu]cc]S ]t~T{+#U֐?4H,Ax7p(@ 4qF"ẍ&#j91-p@FwS4vHOm.yLRQV~ nc/ZJ\"a`3o3fuB8ϛrU%-?dBrBPB)ۼ=jAe|kf2:i9 @rIe- $$F`{2I~,G Q-W#]8XqYWD$('_>JjwvN]k[4c坨|MmR˰0e0 %H:eMSXIfjd8Sg5Tm9g|h n4#2_*M/Ǚdad~G%5dE8z@G*n&L 8b @<!{s C "(@A hO!T3yyls88y➻~@GZRS(Y!=NBt Y8a8yP pPJ$1ͤ2I$`skm"fTJ騗"kk~ npdN:31Ԍ8Z30E aʖȋ4YBXX0R* 9X"\{nP\䄔~@ G]껼HtabOulJIՐ'-*aΉSI%l tQqlX#z9ӟ,/)9( 4cּ{lMYZJ WlJ̻rBS~EC8! c4dt}PlǨx^;xL LK|כ?c 7l^' o\C#~3:pΤpy.wfQ4K(q,{pa*drB&T.!JDT PyiJӣU˝bh*XsEYRí{4QroMrfm=<""mEf{ߜ`ȫ?J^{"Ȍkmt; Ϊ҈Gs@ z}48Ckooj;0ϫ_'*lB)m~Ր~DlX$sTi8IY[` IDATLd;Yѧ:X7[;G]|R9YׯLí>o֦!@h&}J^ԖnǪ "&c hA<uhtITFd7é=moDPϟdѠ?9(Jlfbc{?v1[XE޾mfiNl^ʨ{E9G3@U"}=7EwJL=;@Ghf iaO,/:}i< ;v@H}%婹 WDZ#-*mNџ#lC%J~n債DɧZW8\tZ;ROxNrhӇ]Rhٍz}ttBsyefΉ/ ZW{?=|톞1nD:.h Q~DAS F:Y(RK.ޞVүl)Z&M:Qۧ[}R&u~w& h @<Xxب/c5ct3 ctT  7Ã+e @GmaDG>2:sl_%әe@  u)5!ӭ;T?5͚5 !~3W Xw ͔@@Mx )J7+3݆t$}q;ԩ1NL.@ Z&Zj hVgڬ 14oњGQh*]ncAyf$v- N@ D f.\*4Q@x A@%`>(U@yX7y )u}1r @s")ɛϖW}ϭ`@ @% mV,tl@BfNw…k %j6˴c}QM\FlWu~'Ǘw.n@ PU0[q LϘ7vܙ`߰Geo9IT\ F^7~ةq[^x9| mFSgӗlmk-g5. A}sh!C@@A%8Y HȷgV|! u3$g;i6+CtSjYrQB+~[+]_%߇b\a. ' @} =ToAޓd%}reKg?㎇XU)|<9߾ny@׍iX}w-<4R9ư-$jk*7B&GC 3>mӥqZ9 Z}hA8Z4}^&C2_"Ϫ,p+7E`xY؜3xBU @@C0\@Ƅ%/fwRW5@Ac"@wӡKkD#yg<5 @4EFO'0]1L"=/^8Bc1R jc*x/Lg9W'O?`1/Β1,nnf({ke_Z!KwcydJ Y?@Tb޲^8V.po)f֕y,FrŌ/wM8c8Al-Lk6k1,cSMDYsfD1Fjh` t`a=+=``9=q8]bŜeyu53$\-/Nqb &PNDۮ2lh / a6xECfXڲ21T@F@@n#-ۻvW[m y[$haP(wεs0,gӄ줸uȝzJr[+Н!n7驭lIL͹̮i"`}IRxתӄx-{NOx',1i=CJ?$rcg01? 8S=ab7Fɷa1JN-xQ0@,zԩ>ZXCLؼc`SIxG"x9Lb-ۉsK7`YV'N&dڒvM*{S>gi7c۩GJGc2y"vg zܴ|yT$mNDB"% ǧr޺;v)_o3(9KqyeLt'tbѿb0D\0!߯hUH`͎ݘX}O%ؖ;bfWxQ?vth186tI˒YG_5N(v==Oϼz?lVkOt[tm+gsܿXጨ%n(:haqQDžuQWYhVP2[^`/l ko_1GV?Հ}h BؼY"3LR*8\<1UOFΊ?RˠT%FF~[E5=$Lr ̜pnqq+4턑++Eb=p| ӔQ f2[+yw$G2=)nwNKN>LB[lAľt9kiřa)SE߹Lp1o/c>]+34<-;-\S&< wU 5wLãny%Gϩ"=)ήpj .@p~MsaͶвE0^MaBG@!YCm.hq:hߍJ0K~/pl%b`<1.JYempY:o#$PKkDT[qe#2}??Ո:?[=};He/C9mL&r>@(Kr|xߍR $wzZ̨ZJTV&R78fH'f*4ũDIj1E֊SS"K6 [ʻKUHqת 6OL$Yl k'+30(Jlò:UT*M#_Ơ8fx<)KYC`-FeMՀIyީkO F*c QvK.NXjH v%rZYK^}9ZUMqʻoJ@S'`ܵC #]?.c|+E$jʿTƑ}eۖzJy}!_KP@C3W:R}3-Rqah>)oܝ|Up.PY僶вPy4]ZSy$Q#E%/28X^x6d1 ׸PPĒ 1cJj?Ӗܸ}Hz[\s/SkC抮vo;2WmzԘ9(F.'617OWI2EA?`B/w)dƊjõY%eFrHAG[`UnݦmKfC*VW18H}xD%PJm9rcdO]½~i If~*b~@q&A[:rҕ#^=G]ҥZk\|w>)k\6@0.FMʋuA"ccS-馡2BV{*EG䁓^"͗+~ ;1V{U"}~S8Gd9ڎՓ-tOkI/\nYXz)Ax7ߣݔayqZ|vK~Jtr M$Ԧ7x;3(t⋣,Vپ[{/jd x[I;r|)ސe 6ҝ*#x G87䌸lJds)f0z5x@'0g݊7"=^n4[ xIvݛz<߮t<־Ц_D?zG yˬXj!vʘT?8b"8K;sJ+.Es-;d۟(|u?tB/U^qVpagoOU/C+Gw#+d6v/"a5+/Uޟ,rV&R&NZ==6~#VzC8yf)vfʮSSa7|idBL5VB') ̸XS?J1W^LTrbop> 3e?S$+~=Kg^nұ;8#wx+ ȗ*hC߮^á//zT* x=^K@Y,sUdTS]8[+ r69E'po.ZEY8(t|ϒJB"CJP9_1ycXvdj(#hNӧa}:d st+W OEv]Ƕ~aiUU^$7_o(Lt~;|#P"Z p+S[ԲCO Y~AwMq]g.yXk{sFX/F#@dz->/n %]~LC͛XeX&ӵCFe}*K*'|[ umyu5EdT.*8[uVv#xJ⧮-p|y'Np?-y]uЭolK5@V?l(N S-5kAzXZdйPG@- O>5<ڭMTq|7Q|j^4n>I*<4w`иnuX+%K-cbcB: ܊i_l GeCc0 hHg=s*Z࿮[C۔}efE=dB$Chp"@@k˻Ō? ~*&.n^ *L{rE4=#k[_M,NFP@Ce@@i],#޴lm>y/?-{ۆj{ .dĉp @ tTip-Wc=))T Lf k#PTAgN @S @@"x֗ Hqaɞflz@"@ !an-a8eeF3gcӧ(/Fa3IcdAhN455' @4^{<5|5bwܖ/,}5㇝:y\}0i3:< @fLtxHSrxO-*PeCF]0ͅ$TJh{6m ۲Kgv^ۚb*9 hh2A@ h€2&,1#ҭI~&R,L .&R>4JQe"˜]euՇdgGgr[xojv_uҳ76}. P7w?8  D@nbe#.ۻvW[md:ɨP IDATyCc1⭒9ݷʹd2ӧ$z9MauȝzJr[+uCnS[ْs']ӨeM(K}a$rcE_ߴq|G%^) ڼkqsma9&d'Q_̏.:}s9*Ymc%uݰ (7Ϟwd_ O'!T7/?oګCB ILO9i^}GP}//ΞmWylaSgyR=#}mJ3vy'gk)nɰ=NޜUz`+>=e.9dF,3Vߤxu-ރ]v@~?O:Eȗ;}/m'rۃ20olw3 ^~Xʑڙg,(Kݯt)L4Gԡ5D~1B]wSpaa`_jQ+8)gPiwR˩aLerUIlrY'Vwyq+U0t!9ha j!??nk(O#Ȼ5GM@ @' Y0uz*>mKP %B Խ3z)7yR~*7a3~ٵ}S޸;9' jn%EeVF닝,;dw$emY ܥx""p[<*x6^n[ȣVdUJMAjE  q̡5e)Dz?i:B$zDw9e]!ReL)e*_=^{J}KEڇk]OkD_f1ǜaC:`{}3YUbP/jq֢?G!GݿJ]}S#]QgPҎ-m}(šݠ @ '0g݊7"= a=7aoiĮSbsbv;g􊝷(/KfSd2)AGG# I>,"ۨݿ(@ɭUNp 1̫`Ȍǜ$nQ ?CNVo=q*@VRα4u WRYn\kCNw2yYB 8:R蜔8%}W?bJ=!zYU}rIJZJ-ˋ ?0|}G;]ca1w[{u5A?y,}'sJ6"i`/uw-FJ: .T;ωv>Dc,Oy5NP1^_ye0 y7@ h^K@Y,s3eMFi_$cL,KмŐ-EL~ۯQ7Eɑ?>`S󟌎{==Ro?j}pU߿V>SAe G)t1 ]i7,qpL/YxΔz0ȭܝmΎ,M0M7Π-'WAsm2.ҪP":UK<졓uzj޷~2Χ0wQE*& Ϝ56«̱A5^jvOE.xu°VWD O.KV5#KL%G_.^fĖCTc;b< ab|! p 0=tTa@ 0@)!ӭ;Tf͚eK+ H&'J7O!\L6R98MKI*h۬ 1@;3x a&(@ @@Or*w8q^i ءQ ݴсc@ 7 kM  H@{^\>}vQlE=$M& 2F,ۈTF3b^]RAMn ^͟@>SuKa:͑ܗ5G\t3eniZ$oT4(9͡r @ : 0s[% e_'um_t3@0.1d|p&.Nc_㙾,O7vrgY\}׷;44=VWo}q|yP %@WllȣcD!iq;g]0fGn[=~bU#oApF۲}Y]Gk}2=cVصsgq}Y-qʿ]5;u8nߋ뵼uK#Dr*})XqS#uf*9k4֕!)Zr 9cl͆һA@ L@txHSrxOSyhF3˙}{KóAUxc&$w>rbTɯQN^LXgpmhԒGtW׷|hn ?K6d0Dh4|h; 0 0` K_t+y&1B,zEĒ)]ޡk(NܥP}y}u cJL~y\e0Ʋ~mDz9$Ύ嶞П>x&>},Olsqߙ?p6uq@4*ݴg|mՏA96_>ga22xw08k6k1,cSMrpko\N/O+_G7*k7gg}8ZXdʨJ2IL!@  i+F~j JHm޵8Lιul0wuK8b~\'w{˵S{vo*=0mnqʲ4cV>=[KvK |LlPUʼWNF^iь('A}3]r%HG^WtC_b'Kq7n!!$&᧜CǴ %"qWgLOmeKb2nΝgvM2!w>)ʭoBQDl]. ٲgA(zV^>3P+I3K % Z5s+jMUa>$!~~yqlJd3/ :je|N/rNw=ɾUYN(G0l_ !6,Fiש<~G_NiM'08~Tj=a,V]u_/Yb7Geҍ]}{!>8|)e]_nCjhl<@)hD041oI_eݮHfaue8O4r2RV.ZTEȇ^>Rewݿp{];co$6hRKWhޅ,:A'f*tUnnf~rQ>S~g=m'voH2Qg}OgB>jC= M+s۩}摫| }v,9WCV/,. }]-9jǝl"w<B7\ã $n[9tZ7ȶ9Ej3Qiq,Y_2-/rThVSlwfɀ?~mJ~b|֓v' _#EKCbUqYŮ^J0J~U&m3W1$J/Wvm5~Te4KhǗ>H Bkjʁ@ `n$/y%Gϩ?c䕅^"Gɓx}>dgWe/_=s|PZB9@&HE2 m+pA+AS7nDxU2&F >jk35{'& PD(!"(*{RPD=@B @TvI6wgMB%$$?j99w[I=[cm_텰|8ci>;@ڐ GV3'(~+O[[kuf4Ps8Z1\tcQr Cԑᔧ}ToɆmp*b7+a]<}En{/r^c }LAxcy1s8u/ /8mgZ%_@q+CyBrS\ܸmK[B>Hƛp=-$ٿ 9v[q}okf-#e,R# X"Y,4V t^! L|,ݳusQZ'y%ags۟zsԒ G^) Ej'c?IC?Wj: Iؿ,_A?~,u$O@xHtx M[˜%k9K6E[ UB}QčK2]0WqLUi9ݤh%s9;xb.l9hojUhr4 @$ Tj/L~vwf5rC > 1aλ#w;ko&h:yzmFu@ Y@14`[=3n⠔ YLN9EePnU^_'SeeK]ثtJP|RYѣgUHzęV?t-oҿ@-|'s`?vOVRHIj/;"j2'/lV>-՛= S&̯\ztbnjR#GLZ%qDȬHD+%|;w>HD^N"Qho!9>,]Qb. 9V}887 @$ <4ic>0 - ."oy2z[?M%d՗s(Ma}d:Ih+Iz6 ƥE'{|eݾ!uAnM}|̻Ҿ|ԝR:FJ|4Ǐ逇75攛I϶N76\ѭw7,ryQls2*YJ[?p~S (h5^e{n>ILfSor4vm_D3NXCƸ"J9KFkDs0ap=5m:5ꏃ0W`V&^+6*O^P)F>C$-1r&lP3e"5Sc]*;82*F;%n~-m*v Q̓^X t {ɻ[EPkDC1><:平EOrdJ̋*VEc^5B>CS '+${f KoNgу 0IۥO_-gQ>QsWl H { 3$lE Zx75N"ŝJ9ZŃ$ @EuϫHS~/igLɬ~p^ =&7W34%{[#6{sd-usgH pǤnuHGlG>n{ eUQV[s&4AT{*xrjs8|ђL˫e^4TVmJ r{"=Ԏf|Vm(Ғzԛau9޹șb[RXA+VU])Fx3Uw+& [Q_^˜4c І-o3c*InjzB\2qȲ *eqDToPvJR IDATu'_'\5@3@M"Ր߫pp5׽ʙãb“h^f[fq>ӯ.4x@LDyESWלԅɩc%yĨؕ){x#6 kJ=`K o>{>c>>==m*oX_+M8vQ[f9(Iz<'R9}kk *,\w#3_hN~ß:z>LH%\V6.K}~l(2'ނwK=_ybsލ8Q;soNM癞goʻ1Q$kO\]Ck%Ƥ]}+@ʩi_|lwbY@k--VCA$ @ݓ5BWd4봙~Mɬj R6F[wsг{zeFy}}Ed{1i7sd/I"D&G{G9#v\sȢ)t8>)*Q^6Bc&1të9rOn1 NH#=Qʒm#ѫǟ-g(I0R#uNXD/D'*LY>便9ӗ,KlV]vy7j]^@-/5$60c4-3n" U$L7Q6}xݜ A8RΤ?ȿt{Lrt1}͕Mi/ϼ!ז G_Y}qymIBz-9!.17I}uBA*0_Lzp!'^jc3:HUGʙeG>R]̩[n!cS\Lh~s0~}<:'2fIi!@² ݉7/Uś}!ם̸wOŠV$ @/ 7ًfI W.[!b3W&fS xƻe'{Dן|oܸWWlyj{t<eGD%k|l9 jA` bS79Iǜ'm#e(k [,u\hcLby', H H!T~l꒫j .3WU a:^D%+H#.6"nfkkWXjG 5*9')+=@̻'ReЬt{ìoKP{.7-n]Ρ H[@<}xl-z$KQa$@R$5 u603^sK<5@$ th喪Um7.ycD%z[uHL1!@'ErG)CfOB=%6;^H~MLי% Hw˘P˗<FwP$D֙baɤL6*v˥r@IdZ_)$ @ :YFnCˮ}G?*ΎΖrz*gњ-s4.`1ݝ3׻sVp&aR i5oΝY覭|+_5PGT=؟/GUj ]]yF1uҮЩ%onDkX @9\eZrJ=aFҏO''o7,̭79u>݃Jgiao<Ζ^z}#enqu5g ڗ ȋkjK*A=n_}G^i/h׭QqMzqr$jV磉,Gֽ(q<[jzK;;JTKe8ku`/0+Wd bmb;$ @6OX[-׵};tecsuC;d< R+ڋޔ߼?گf{ٱ m_?J@``*p_ilz] ʇ H UoF >^ C}cn; trtɓT^Jz;./CD 7 c)lTWsN:T` !HD&bLA+ߊD շͫtb$%+W.ޏi< y{voI8 A^pѓ+҆fMZ~@@u/5j۫ G}y7+%fL54UrcEO_uE#Y{MmX8\D- mZ*8f#Fd7L"hGq9~|ߌ Ӹےa;uɡ(Rq:EM_{xyl<Nk̩w׽4wv!*-RyOrGCHgeo=Wʆo:8E,D%q͚* H"cϫn~Wb/5Fc,)}v_nL Rq^{ګ$>6NoO>H`@:smpy@RqMW S8pF:(ɬ'X~)X0CŮ83] /;wG`uH$`ذ毽gMwٹu;\x E_/{m]12P/?7zw4m7Z{ji}s]ʅ-c ,:>@Ń޳5E!B HUgNa;nU Oєe7r1;~VCGPCM]|fzMqo2/. 03cGz[l3wmÖQlp'|Ċ].sAw5#Gx|2S'W1aɗ ww^qk@@W`I$JDZ=^% l,v7OA_o2 ,dh^\i -/B嗺W`4 Z)q:Ήb_jvΤ5h'J|>{dZ݆Sx^54ln44NRñlz6hނ 8cɿ`2F{,޻77l*zSAjOJ3s(U~,εx~."ZWt '5ΊΝW\iL x`Fmk({<^ bؗJ2Gc8R9A?ދ1a(M{4#0I"( @>]_ H]r d7ay'yHB]F0škG19;"Ŀh@^1< ;XTe#Nƅ:FO3@~*I `˯ks<{eF+)q٫q1C5:> ZRY^$AQ*~Hӆ)QpJ/i20|iÎgwCFO -s>~wtT k5^g{=]!>㝍j0VzFRe'gۛ,3G0Of@V5U<]k;zO?qռ:߳ E(hdj_d2K /k ;CNzѕח.þh.myv\.Z1J3GY*B]9ݡ]˪SqY/KԣC50h%}q:S4r!!?T$ @`b &$:}P^蛜Pfw͓! .nl\"ɯ\9i¾vދ\丰3nS<\o8qդO~ nb::ǟXTlb\BkO)xY/>3HI/^+RK 5McbS\{tyDxh߳5vth髪ͼED$10<Ϻ17eRFЯg+u$G8)GUhp2m> >S#gCV{!&f^hI"\4dW 8f9[`xh_ _y6y[e f{!+|ώo:6B}#mz+"촕36zmXs<ҁܶ|Ur.D?QAvVuk"GB-Z(=Y<w ^! L|,ݳu~$ǔ,SF3f=!5wxn/C@g@Y}nV/s,Aoi7j;Z"oDn)W芹[Ui9ݤ쨏"JVeJ(cSd$CnBY7=pQr JySG %=!V/H*G( )aءJc-=Js@;p3i0ζ8ϋQ()`Tu6a=J 0?2IZlC'*FTWK4`#CR>ܛظ\Ӹ{GϪ3٭2> aNCk-XnTxǧQ1w,cbC>)-՛= S&>9>hT$D(Cr|X;:EfN`"QBon|HT)^$Z܍Tj rYbRR#LZi i LDC_PI7j<:<ÒŤg?L+ '#- |auơ.ɨ2f(*^}ôuS+ځK8X7a/V!H 1~Ɔ G}۷ Xd5̲I(ߎiԖ'ɪ/"Q b<(quˉom$d+/1M-'x#oz c.J- B+ħmZ(= =5l*u>,pݦ]ݡ:(s?>}] O?y58fڒ\^Дlcj9oDNn"$.;79RR>]h+n@IoD?絏|Y:ϼHg؛{$So ;Cjp,`@S G;>q窛]K&YAM:~4Γu|paXܯs~ABOsɖEA^˜4c '@rHxw#3_hN~ß:z>LH%\V6).Zdžl(2'ނwL=_ybsލ8Q;soNM癞g "}=ܹyd6_u@>[yk3 웿HauEfʥ܅Ձc.B¦B 컅OyFk~WGf 7mWҝ+?_iF9;WM"p8dL%]YO9^kǗN-%%rK 5mt7sɔwsﶭ5 Hp2'K7XkZ} TB[SV疻+X LY>便9ӗ,Kl%\#^Hw1n ֆO?s3Qf遈T+-GЮi=NƉڀd XҮ+HO}}iۖ3J|46xY IDAT+MQ]@?v j}š̄>L9i♐$BR?!I?lܚ|Ѣ_3K.'rt>ڼ[f)TO1[xynާ#4>`;.,X @]H )r|K;\qz|l9͎J{huK]zAսj͹y; xz"}!=\n5TkҊ$+-[JbC227[ZJ:k.Lղ쏞h_v뺿I?<{Kڥ1Q(~JT],nƎ%np\<I~J[_c.nba $ @kULo 8 E-$ɲ H (pTTńeRD I.SF1ǨK#Wڠ\PF ַH`[$ @D[ēD)2hVa7pV)mQk9q⎭ %# $ < P'OŖ=TM{7^P!JZ ~l^%uʙ ESR6Go;o|~ HznbaԹm?:)Q$g8m=7$нtnʳ/AV2><7ȡ{E=hZgڶNO]gN7$ @?h4$В@W3P36" LJkO9Vyo򭊶z%bj3霋Ζ9T@RIt!*"gCS!HT.tֳ܆V:[~!nJ%$ tI2vƹdfIMӗݝ3׼ϸ]2rcI,#2Q/zէ0nW_Uudk|lq6"wcB/NCs[vA *E`661WtϠHz$\eN80#nL?G5@ZYO 9㘍>v:[>v]+s돫yM.i9>;9s[;WϤq~u $ @ڗw#ȋkj:Ve-;AeD;vemG^i/h׭QqhY\:3m"?0|4ռ˓rZ=9_ĎRNߣj4BXj  @$IHqdr %jί5T9v!mu򎲣wÕ?sJeMpjwu7=tm:$ @I;ēdAPX=0G%~t>N~`ɓ>R2֑c+[-4TOQìT8APE) A$ @V `Y22=6|+)XW>{/r'f/N.*&INYB2~UZ@Vqbgw@VU!o޻mmkгj<,}Adq7YZtwc_sA4<|h)@>.IRԿ3~o9n~qfC:<yH|gcH@Pgr^cNŅ[]sj>=(wh>ͨ.6{p,SfMsFѠi5˹QDIC濆 JWk=lo,q>mɁװhPҿ8Sm" @$ tCĆ6Lq$uM bdjXOnjkG,&wZk˳?|%Ʃ^)sS{=uz5'L6]H"zA>bRVZ9keiR6 :zҾ\MY^@#!H7o%[?SW{=-/MF8>7Y}nئf)PDP"ql̫OELGjrx}8 F[>Zth~w59>m-n|Q.(i+!$bUכXY¬'X>W1aɗ v`Ocl|MQsHytƨPR㙓nAq8/P|vO@ 0bXџ}0O){d'a2s`?[_~Oa~z,HԹYM @$Lt՟|cӋ>/>Tڠ܀ܟիhA/իV:E0tS%mVUqwי-%!>NG9'd89S^1mڿLv8o!c -&qZ]]좟'~fD-EtoWM唈[џɲ]v>S!2`yyKglb!{f2QٳTgZon#\nD='AqlKk9@vcyRӦ]- XJKL;Tҭi+?@q/ 9 @ X,8Ů>ArH3J'קs̵̳QB5PWy-AwhW㼳T}uVK"PUE|jDqh>=3%ONJJ}ږ M V&@5y^οz)fȅ\LP4ɉ#G?9+c8ht6 !O|Zy#xFㅐ k_$䀱Qa5y/f{vv8'iuϪjV ^ H:7{]U,4!y苄B䄀Zuzߢ\7}yqag >\4XV|cn>JNy7G3Ochr{P)őw1bb_텰|8ci>;@ڐ OY7f\,P F3~ p׉ 1\BS񾷃5ߑX聧ؽ;gz,B>K~$[Gi\7`.©"*R9ܬ!gwqDZο| ^! L|,ݳuܵeaOƊ@Q{\ݹ}"=c712yc} PAqg 'ڰ @}nV/s,hxK{Ps7)lh(ER:]+e aλa}UN HFލYYM'n\jႹ]4!JH H3 cSiL~vwudg5{xӓFlks. (֚ K8ȤEHr K{~(HOwp[\[=3n"Fq';;QR]P!CWmʻ(I`TZ$PLboJr*-,,40iPp)i% ?bλYku- _5,<i^bV>ftS w)wa y7y7yf|P\QV]4څ%(JO;bW0kxo;K%ZAzrFcZ >(nIcmVѦgοAVrH%Fz#Dx{kqf#ߢ^3|0^~avKNJG 9~3i#9AB{haRuѐ%gC+,:Sw uhk8)F^K~ȗ4Y _vY>Cj7&UIfVZ^ HФ76d(<'ؾ7\AG#1=3ڌ,q\FXi'oJVvYj}h& oPmԪGyx|3Y/nNQXJ0ʓTdPr8Di h#.Im\BKE zOj!I(7v5+H[qqg.ֻ|gO(GiL[zMۙ>vO-džuXӉV2'Uyħe+dݖۯ.H;\Svr(iG/xaB߸_u>a {ɻ[EDkDC1><:平EOrdJ̋*VEc^5b~h04%,pAgxt6 -//,%{0C*zA.stlgU?Dm`'j޿KjMdYD]NCyVŞYs;Lvs+pԷ{G1ɮGX ^ H =F#A\NվE$ 0~A9ϽZBo>1 7QQQ^T>U5'uapr0g WL8jy) ׂC)#ם|ysMzԤ3rsY3+Y& }Cu:'P~|8a}npͽ^|͝!5c̍In+Wj{3Uãb“h^fby5fڒ\^Дl ?p XOI5ʧ&M]R7b]`8 -e%@<@\ܺH'ҹ<2it9S,WkFx[ν4'.ƃ9L=a_LΔ}51i%A@P Ea9$ @Kލ |9 92!p[ٔ.K=>J6jo;\g%H߯<9Fި7YLfJnn(ؾ.?^jF8wT Q_Ӿ <Zz1a\~Pzp\ƿ3vpΊd͢ɕK qĘ^M/kdq55H H>F ,`6ӯi%ygsub!Cky7c/~si̜W / ;rer̪y/-͙E0e]b&ݛ(JnN%=]]?ח&/?m8D:Њ2ɧe>)#ڒRkC__9qq5Yu" H5IWN/߸[ї\ٔf[IxmI:ϨupAƨqnzbo`1$ @@[C78$V:SիTS{MC[\/G>s - HpkҊ$͓-[搬tqcI=ר9æ՟s: 4b!K0>-; 񼝠`5H!$S7oݲ4sw K *Km 8G5JZ $ˀ0"H H' *YGqѯAp3\D[{0>{+!$ <44F~yrk:Λ6H;u H#u+DT('U,FM^  r3; rx @CM`'3%X @$ @$p{\gJ 6v½?V 7 ,p$ @$ @$ @@$`u ~ H H7\e3|BE+n=ۇaϐ6S>a>97e=WPn Kyb9O ɂ:~XON|p9u[1qL/,qs-ᵇݽA CŮUAunYsc`$pyjH H)_f@I9ޣ;) Af6ʝ!1snJW 7.*ݖAC2nkZ2zZ VQr!PAkp@w#E to (P;H H X"uU- V-^fLk]8Ҽ۬^ȝKU(YI͎4͞v3> bE_ HBu31B-4/o_%m5)mK(#l∾}Av"Sfk=.*UQ5 " \'-y(XAXVn2$:˅^L(xRL,bڬig /0aȜG"}\':k,W^Mx)1170zRYwCX[xIxh*zJK.؍J.TѲItr={wUr%X~8481ljQ1uZBCׂw.tcg# IDATJ (d$lQO,?ؿqL1oB<%b vK#] TBsg+SCkQbPK+/(߫ej:&.ꜥ!V\`F_8gY>[j1ś)R/(~LX+ @$ @$ 0oTSypo/76: tl$*^6=Wȿ?A!5 !5U7+^ rT;P&K"HC}IJ1(܍ orx,`$[ O $7'bPWTZV1,v+WA%,%( $̽\,6n@}nNqꐺEASX6fod+ Geea'in|LO-UICenv961&ڐYH)}VW:w쵪'i*='EH`/W+/ MmR˲==9LxҔtJWKC2 NYNVI*e)Emv^Qz]. Qc9EJ4@rbOObK܍5*CZcVcŏc>~h[m^ &2ߍs>s>@qY;ʸn~ʲ*#/ԏ+Moʬ$Bʢ>t$QfRZ1BTIrҀj ÞlNa,!Q8nNa"YD|bulP9sFpE~浓׷2؊rV{׉ZUQ!xF~q&"k \ØSQQzEÅCE㲪X(\kГ|ML|~uHz&p Z<z zB2C9A(,7C __~0 ` fԫO , S("f^}m癢6mQ8es(Gs`t\PƸPٌ lД鱔Oh:MÜgO n |R#>4F6f`šm@?ZOTn#͖[Uw^&-> ٸ)H'Gqhn|`۴#gIF 7=(GHgMuoC+ G Ua5lܼ>?(ʨ VCr,>M/0~uΖWq(-%HIM$ @$ @&>RvAzu?xҍN5 75|pX( pj3j$i8|IT8(ϙrBGEuM, %tu^k`?IuUQ57DhSO|j]NQ+VIG\-ÇESP_?wz&VZ\ J? }pٚ@]J<׵l.W+ fw6bPaX(+O`Pqhi/؏u0њd9hoD5xRTP۴e &8Ih+$ AINי& l=os;:j/Vcw&izR~Hudco^#\БJ:644 `q_ Z/; @LeXS_}^F4և>5enq|#gXǾ2O,Ve".O)&vz[=QG萩cT:3ʕ[J+I' ?}lWV]RHUѱsi#&-"uuY/Qw z+sm:0<@&RqE)5TEZ>*5f,]UQQVHjZѲ&?Z,m2_2( Bgzi=󇩿0U9[Dj+ӏdMz:fpɱw=|E8cNY/msNhZYlɬm]n2Vhz#wz5-T<2V]Ph:N8nW[OZs_W`cαg H4 #=t+޳^^ H H`$TfI g,[>gKݫ% +:ZML#~'.d@V7n j]OJ9 g qfJ8q1j7 Cǿ2xЅt3{;ժn`- &"Xp@ᾷn޺ey5B;XJ%$ @$ @@w"@u g$ݺ6JO/zY3r $y9:]6o;H,L9I7j;9~}=3ZnhK'xw\`)$pu2l H K}N!@v`KG-"Z#n+bƈ8)ʪ+I7JGvP=Rpb$\?;}")AdOח~><:ӇnH H"ML6cי5 @$ @@!יGB3 H H H H,p_P[H H1sRuQDL$+^n=b=u]mjb>/,/\/͟O*j{6:yy Bx̍wjt\i:O8ͅW!H 0a$ @$ tWsY#0P²!|Eݽ~\z@:"ED AT||@^_l>"-HI JZ !@zr]!w{-9|`vv?ٻfvLߐz?Y*hrCiOսG~Y~Ԩm;{)OVۤ Oʆ PzS9΅ @80O]H;R׎`zzjd^= %熒D9 wn@ @=APB}L=R^uδyqXL |*a{ZNh\p#RX({㎘ 5gO}LO/F+NmSt*(@*%m;]^ҖM\uT(2mLHb$1XJTi);ҋ w.;_t۵T ZW}rSk؉fٹ>m9\G#{o2Ҍ)/W_y]| mo}z s!v@0=w |7m?+2T 8}OQ I*i@Qc.Sȼo)Wɔe&/Q]'߯R^965'-5bƌ;y.mɍl#$- "L?ӎbQ{s%D-{} F՚$s?9H ;."j~XjTլG€>9|}Xqpt*Q&Z\xFui34KPf)Y q#>J"\,(PU]>Ң 17W=vdt%c)BB{`|+˪=J bJDBЋd~b['%2n3je%Ak_~w!&:*n{Mt6+oF[eI88,6M/~vY#[*/"smd) ZkJe_nPb*խ}tEfSdi?~'*D@U>n44 Gp׃x_4;OO 9c2)1^;JcNHVtsn}0pܰVuNts=$PBuGOhjϴ/Q%˷_skjOR-)Rg /#;orp\Lp_#(̆,6֪qu[ #HeHKF?/KL7gln<թD\JUJAլ`wk]n'wn7^v\GFJL"L[ +4puѓz{_؉!ke*@i`iG f&ޟxʤ~ܗ[Yx징r8r˦ 'Bҗ_Sq HYD7B9!u6}"e5S$Vd i$イ絶M>X6.U_40S/?SSh1[ZGǶkQ{3_~HIvp|{Τ_W[P>DҚⱚJdr^n V)-or7o4ey_Up*m~BX `veRѦZux4qe0mhmcl*ƅ~$E-gBE;Xm^'_|Rzʷep0˿~88 @w 2@ Ќ-ڰy[*CTN}u\ڙioiUꮽ=z(פ-UJtCr0m&OOjӒv]b 5>RUWO\5ggMѽ]Əzյ܄ ˓.?v1tš[Vo+u2mEIBb\FjOٳgjߑ=3NJް7]kggE <>ݏqzUٱoUHIksS}7׏.΅m (ϴQt @ @hdwkdp!@h*sSsRyƧ;w'BOA*;/lŏ{}{vx]KAΙjlB6@hb}614 @Nw_nſݩc' kz)Ǩ&~:Ll)w"Lg# ڳmz;-0pt@hwk=A $@i +?&w[̕*Kg!3 @l@ 5Aa޽'&.DD5GN}Y9R: \JIm\kİ组%m_{ꎱ-D6G3CRL}g轛S3~k2밄.•O!3&(yzO,0\NMpi*0`3Q"J3}o9+ qmdRfAe>zHKGsn9똒_-9EntN'A@')d,]¤mŌr`uzXMe?RbM>3C2Zt.?؉s#eANJ{Q~㞻mā zV{E ζU뇯C 'y7>C _e>?J5!Sບ,Bۿ-?X!Cyob|ZQRLh'Nx]\U"gE/#U?vϦULZSb*Lв WǼ|wfR}~ӯs47?ix񭤓u\0H ֤ߪ2ygqcM=6%(uH4[s߱a{ _I;L4pl e_儲^NM2SGdw?5W7TmvfQKlܴR&e  2,"szq{ZISSTY¨*u%Ho3=[6?f6%39@إmGu#S:Oo@z7qqPNKg,5j~;Cp>990q*sǶnZ,&قZMe\IT)+)-әB IDATrupQ fF%X#K )BPR~?2E tBD-Nc$ A Ӏr0*y=~;损lJ6'X:|("*;j2Y˫RA&W;Ҧ\PjADž)Z[oc]R @p(Py7}HnAj=p=z`}ap9 h9![?Eu0ni\7/ "2ʏ"LSoT`XP=-rSee'ˌ*UYh.[edg%.^㭦?7.^us_*?3L`$|(Tn!!W?T$i U2E{/*0L"$Lb??Js\׏UH @ @ H.M潉/cqF Iy:[1:SpIP~cˡsVeϜ>Ο"IJ>OhAQ] hO7L,W3/F5O7_叟޺oDLF{V-~YL7џؕ~s=$!Op%=cڴFfg9xZ+3P% 0:Ҙ~)u^3 @[KFB!@ ŗl7wrJ]q|>n?&>BAYvtm[Nl0j,Uy(齗~G&y"v;>ʤAsQuC⩷n6 zr{\GܗQ)N @W`UDtiFJ[|2a5{lP"G-p)͙E}gMx|+\-X=lSul+'dRA@0" n*G;6<ͧC݈('_$*8gs^؆dCY Odsi뒥+Y) @I .t|0唎oOo} {!]1cğɍ1p @ݼ%z!@h,,&R";!-^|bPK U'~~PӴAq\@;]k;W)(j7XnyoB@u̻b @^1f^M`rr|22@=u B@ @ @hrwkr]A 8*$jӳqt0yH%v 8#y7g 4[i_&g˗wsv7zi7m*vH 4{̻5K @ @ qH@ o :B\T)%YcĽl,%P齃˩i.M?^e+58KsZSWh'F.`R@0ia@ }~ӯs(7?ix񭤓|EG?=YQH1i唰¸1J}Q:$Pg-A+Y9A뇝-jA>@8̻2 @#@?v6MN5e+w$d=Rβ,ð"},?G .-.,.q;In*or%:]˔Vp @9 gME?4i錥F8 |>s@1a߷~3P[.T()IϏmJD!MRݦ=7~~ }Duplq7;Q^jp мXN@.5e#3 @E`UD/tiFJ[|23{l"G-p)+o>E5x\k;wdTZu(=]Rn'/uD>SAX?Y%m6_s_3q ˱y""֪]n^~^#ܪvΙ8GWm4@@Z7MgIz7b@ zN;3 lFu/cuze]*۬ӖgQ0IG*{˘WuF{V\_f]lInuiFz7x. 0:ͅ @I@{nQrMٻkS)X'TDhK'$6<޿b3G;kl"#m45 1x].2 ; @y `ޭy7Z @]~LU_}.aσ <\~ʴX=kzq Kf0i[1c#Bv@&y7ѣb@  0Wri ̍HR$hFEh@2I5|3˱>?ҹ4VIn䣟(wjٴIrJXaܘ~Si>{(j3McZB gꋽ @e珝.<]>[\X| R28,_{!b͗^VCwүYqat;ԝwq Ê2)kȿX6\Ev@ g8~(w_ K*Cu#n>9|}T}=˷ 5eqlAjUժvyҭ p/APR~?ڲ(Lg6%~Ju jW΂ @wX.\RLYs_v)?2C XVEBfd+HͿcgv(r򻚹bSDQusGFeH9]W۬%rL7=i|'j :1ͺw-]& m1A=$ 4̻5F;!@1Jc1!/$4f !}M @ @ o @ХɩZ-k#w]$]ʮ5 !@MNnMK @ АҸ24LАe. {w_Nj?gC /t&}T9Z|yc xAn^@G @^ )q(a֭k/x-7+fTQ++YN @V Bu@ ?[*֊ yK5:׃Gu62RJ| V2y{Xf䡓=wpp95åǫLѳtinW 3vʱ+N;0r{q  / `͋ @̕uZC Bir#"4Cўu~ӟ~-IËo%,/J>aϊ_|}GM(ƍ7U쳗!:SخF(LQVfp7GX8@z B !@?vstlqaJ+HaHZ|K_ԆE7*$ip'FW#!Kݩ}gW 0Hl)z=T11H\B\lC @}ֻ㇚]KH>9|ssWs`.*t֐]DdZg*Nvo7R"& =Aeuκq]*δ*8a@7ԛqn@ x]@{nQrMٻkS)X'TDhK'$6<޿b3G;k`mSZ)Hk7B ]̻yC 4fjo[vSn_kv 3*W~_\wklR_DŽnסhj-un8 @_cژϵ}=`<֘C@4y7(yݚh~#/B:p9-yOqs=_|[׷n0ި6J $P}՘7~;%;oa_TncuOMnJKj;S;9XnO{v-I SΜ=^k?ܽpt@70Ww+bh3 {[xbqEEliouWSFl@ /cc~xdheM7_T=;f>`+j/P^z5 *0./!];wybGCn4Zri 7.꫋$%[G+OZ:oC ybYjϜ\=*m-O{kIWߺ>w @>)[߿a}i&!@MJG1s4xI@=V,M {!Pv>"ҔRANEi4åSIOYz%ٹ$''65p+: @|'ҥ)n1R˧5M IDAT]2fϞBkqQ\z[ 3 @ <}ںJyD׻Y@ @ @Z*xPo+[ځ< n&o;6-^W奈wh@>(@b"%ڏ(k ;`Sk@ @ @>qIζ]Ɔ>흐$2:G(õmrTmjY|(N)1NSQYsTi) 7{ QX'ZAі.{?jO^'}9igi~x3&Z}oD4>Uhl-x@ ZU@p)l}V}OޚxҞ3Ɠtp [ T@ ߜ;oI7Q)߮F􊓝IXe3S[][4+g}K_=A߹ug9t2oɄVV7㏐ρz|ӷ+8z{mN9:}n\l_'Z'+b@ xmWCjfU{9 ՚_/B B=sH\ a-}*D7x (NW !䢹 ZUh~I.L>D24faY h1މ̻ sYT4D`<NH>I 'P}(tj%a%7]2 mĜwv$\SJ1d zlMl2f>]/SG}7^E덙;Hձs.H-glkB!z|ʈ[_*՞4:.qԈ/g!: ;T,Ycaʖ=(YL;{wVmIJ FOQt42А{W]B$g7l W09qw*YRvgGlEFR禆bَk;emJ9yxɇR¸݂Ĭ*7+-;#~r8#KXÊ|[q#R k}˸qqgBuf⮣9wu^i7+S]g:q W>}m wdxmu炧<#T`e/u}iΣO]s3't?;*! ?_rfwO5$!C{IDj֥"0B?41Mت:/;qІ5C0RAqtQrOϲ7f Y{UNJV4ޗ+޿Y;9>IW.ngߟ24#Z3h17eg;<>6jgV.HܷaQwJzA>Ogs0s?/%6d;{78ˉk.[Q',2޻uky~qtrlKr*|6U@ާuK>@i xs1}JvWGӻJW*^=N{o;l{-1˖8-ѻ Dj뷒tpcbMVtwc1-767F&YO0kq3A`/}`:SK0umk[ .wՀwz6x=g>պNҬ@sW,Zt\撘K%"zU+ L8[׏T_ foO㳤dW5!4rwuIUҏȼL]=L}]w5 v>9gvyߖ"/kϯ՝?oE܎Tu!w<* $Ɠ;%'9';>E'>"w׻qwVYbO儦2U,@ja5 ͐ 9nDWf2M]eF\NiՕ `.ދńNU,֠2\ 7Xіs382OݗzZ(㶺r̦:p'zl=tM8pe՟Æ9`jܾW3Q:>e2,I$;>&򰛏Ozұ>jF: F.c>-QhH$wTF˯ѷ'{nڈ^$ra|#P5%?Џl}%Ge>!fpOqYbt奌_RHtg2FS!d&Rh.k0Q~JnȀ@^q_e}.a=!Q6rcH. Ecy%j}W*UD/nN=u\L8s2 )%pnM$rxN>/<\cʹ }m򬛏Ok)6OWzy!4QoS{- AQnыĽF F հWOR2qDg-KjL1][wjd.1_MڋkO=ц5S' XQ;I'ko'A&@SS>cF2(FFleѳI# ]GN]˚bLITD)yt1 ؍ܪ{BO_{8;kxZcI^;_(jۭMdQ]o\.;[݃LQgO@ٺ]-=iJ՟m]_j#;Kk3Sy>S|a Cw I cTANu~ANWݼ~xn/yͷާ0W|x @9i}cͲq㍿Vno^?\IcvP_-s{O/nK፫.!6 ߟQ I'k1vxҳ>(hPw׻1a< fre)_ =vΊ"FeWi7/Go?BH\yw_)fL@V]HLT{#}vۋGw+t}PtّOO)ۑp%mzlFWf3l?y=U庳R¯gf- p[@}HYXLDෙo\>960H3"Dqk0ϙ[s@yx{iPvJ˾ |6C7ᳲ @>Ӻm>Ӻ47XCuu %r @98gOhh# @ @ >S!ZΚrO3o)}/6PGou}6X}ϹƓƸξB4nt[w};@E7'ΛtrJ+RuoA􊓝IXejOuȰQHwA%/yUANĤ,׏yK&dZ|N|N! 4VߧD5αу Uq@@hݘʴcy.,;gVs5$@TW՝Z ^ܣ(͒l6ϩtȽ<׏{,@@3>mjfڻT덙;Hձs.H-$#[UHҖw!J]+3%: ;T,Ycaʖ=ܨlq}cHeF{bj;~o= /4.ZW%\x%Q`}}zl9R:q$b`DKcAɺΛėaA3\F<8%;"%g7l`B+LN\]J5D ۫T=5iVεs @}_>%xoP%o C{XvJW&ў_3i7> {C6c TH\0,{G-ߵ񤽫ԗCA-p{ލu;Vi_.P?s1w-3)+7wt :׃B(PJ&G9>u/ixgت ,E%MFHMO]/.M?rLsSˉk.[V^ BNާ&z{/oRΕޥd/ЦT 7[b/ 3~2T>-ʹ,xUFًx˱Wcus0s?􍹺%6d_|/yzq&gN{Ok'ڃOԬ<$B[6@o}|<;ι5%qA|oO ͽSNV7>RSSڃ(OunG|\hG6^}:ĸp LTؤm&N޺`e銼SpTuN ]r!q}btIAIUUUuyVVUR+,3q+չT1VP Bwyݴ_}ӏ;`.fxgl9폈cvk7>̙!ȁ"K%HQBxw%`H+$o~Y! vχE?~M2m'IR@pS 潨96SOvCvU}/maT}^-7ڥ=kgV~ 4@>nϏ9hD'iStwXw|(n-~AhsOV>7xm!u Iw׻qw4 VYE儦2U,@j>b5 ͐ 9n"HW HAyʣeDH4gm t>AD%To3 qnM S Ryz !𽙢YfDi9T[OSu\?e /\Pq[nZu[=@pG|4:Vt,7lF%)$Yai0pέYOsg'K̚u˧Or{W`\C*@9 ;KXZ!RCȂY ׿$D!\ڜ;LE Ja@Dxڳ,Q͠$;ĐY[EZT?e5܎Pjg` re+ӝ_iM^Y5Si7{#;G?'u!73uqڹ|u%]QzuѡBk YD)^ / 4Z_/LmkAp<&ԛ񤵎I%`\gUH /LS>cF2(FFleѳI# ]GN]㻉lu{wuR>cR|sPG_;9?UV{j> ~U׋-˄9'+ҩcP=&o?Al7F#$S&=MY/!Ȼ.U8QFaKɗ?ʟ\.Dn.`bQk5뇮*EFd=4|zX$j!wM:΀ Sހ}~KA.I>y?/@boPﯤ#KOw$3yt{kXR;#Ie]3w8ym=YcL\pj"";=sj惽ݬq> xw0wF Eۖ|,@tɱOtRJ H8%nV݉@/~RxK3#eϪ.ًK͢|:ĸfW!n*׺WQ<ɉ\Ndsqk?~׏@[%ꠟ?߬{ )itiFJ[|Բ".L5ͥ}7Vh㱆$u uR IDATU@MW`I⢓O[Ob%ne"_>Riq7%5vE @q.@+>9& @Oi]y !Se4HF^Y\9+64^%\?9 %@b"%B,Oj8=O\,@7*3M@ 5(:ji+@o5f 36c6!}255TAP o}R` y'@ [!ķBB4 x^'|z>6@\\-7>F @hwk@ @ ̻yB @ 4s̻5 ͇ @ @<ŠB!@ @ݚC @ xD@RQ( @w%M5i錥FR[ /|s~r;t@ ;o3K3Rcy3bvβ>tmǬU@nO>m]t @ @0fm@ @ Wn @ @LM@n) -U @ [,y[ @ED @ `i[  @ @{:&|Iy_>rYrJ͔z5ڑn8;ܱjtܺ( @|W.HNղ!">^tHB=@B * @ yTDQ|Dz' O%PҀB !smw߽4^.\}w&]@ ThFW=+Tb8ڄz78dy%'Hg|2&Wev5 |񭹾rqh~k/*D:n֝_rD 4_bKj4leѐ@ @lJBnW6N侐cJ.^x[0 >JH TL_Sz)AfG;nDipׯdiC @ P\goR:*}t,k54J:nի'1< Y%zifK5oV*EF$s~^A^?1焜fDEEصif2>34q颳r"jޔ:q!uEyӟR}Yy-g6 ?zڀv7p@M.o@ @lCnG~<8ǰ`E>)W. ]Q@a!_̘!&?s22&u -8:igswΡI5"di b%7!v}[k0ߨ)ZZ}s]쓚)0CmH'UYi\ʷgjRE@2 @ @GlWŪ&h~_aFpAokӆ@aXJE%e.$_bnOǁ,gvMIJI֞_y*A%.PMmg~2}Uk!@ @@% sP Δݤwƌȟ $t[D8j?1+ 2[W:INiٕ^_JW4}3MmP`$-)9"I;<5 Z' o#00 SKm1fM 8}|s&Wbgs|sU~}1.\|F>SߟK.b ׆߯Cӎd g(-QVTƲ.k3 -̼%BiU9Z@G0/~|dՔI| un{jpu,[Q @6!x]^9hMhh?UK4  @?+/OZ)cNvs+'A蔘LwHrts58ӱI$:)i'ptfC2ʳ>>Ie$HR&ȥԓj}8.2,b^uʝq?SSsZ8:^BVy}ICvi ׮ y" @ Z)Plz䷌t]e6]sKtjfjlO+KeхAy>aG.! -Y+sInL-Wﯼ|Cgu|߀w*2Z \LJ\\Uެx_P˨Nzmf))r`/t(k~R4۱%5)΅ @ @"P}R\*{S \tC|2޼m|uqBeל2?9B-}Å @,3z7j- cVygv[tj" 6l5Y @ @f0fMSN|#"" @ Un{@ P;9qjY@ @@U Xt@^MWR@ Z PZ  @ @w jC P&,(8NUwC @ PUw*Yą @ @w˭C @ TݪJq!@ @r @ @U%yE\@ @ ,y; @ @@U `ޭd @ @. `ޭ.>@ @ PUw*Yą @ @w˭C @ TݪJq!@ @검.Wu @'@ܼ=RJ!@TnUʋ @@HRz{D: @@>Ӛ߆ @ @ `MMTnao)~X Iv?5;hJf?RUA^/Jv-!Gj>t+n_=Z\իƠiڿe}I xZek|Ef>~`y㱧ڮmTo 㱊kBxe$P_%ۮ Z%i\ٛVe K3{ԆԜv5=6~V W<)!t,ig3U]7͗O:uqg}rʩ'~f#TU~_Nߤ!P& ާeIvVF?qQuzcȕ~xL@Ŧԭ܍3w_mtwlQq[@?(Q!#ӝsO-Ʈi7 WgKyExz!QY-O~ڡaYSx=ENV `\xg+*,)9 .PN+?$^-oAhO~p|1F>@铆})LX#C錻N6^ cJzTsׁ7)Q֬t N>c/ލ-87')&_~G8<@cܻ ݢ~Һ?WZ?䏏X~_xG0+߇͈TX)Pέ8&xiTuyp νlG[[kC=gufRQ-LJ!I7:O^F&>aZMT$ߓ}ʤ[˃GZhW'Ol :UȔ/ήvWR߶~IvmߠS%=9sCcD#¾mW?JlKH&ڢQA?}M>#qJjPDe=|&/|#YUv^t쾈62~E=t5~x{_wUW ŗ.sݿ!1.j;q?\sC|Y+>tW|΂@P9|.}aY1kl{犼IY y pK]wbcSR>7.0+>B(]؁7iS|n+_>|OJCX糐8 㱂߃=13}b<&lA2w887c,H@@9݌=x{&V iS cBTi6Ⱦk hi&=#1>² K95qvYSH=ۺ}Z/MYmd' }`S谽 .lˍ ꘯m0l,=ƍRXfp9њtK/zaR/9k*˛5Y٩ Y19UqJj@Ē6=LбwvfۏsUm1E?h'a5H:oXן丣N܈']c[M24C̿.#z ;+#x=?^}\_ܩ\KG=χwMk9@]x %pc0>Ww0=H㱧f?%cb |np (T 3Ui0:2GٹO: ˟~%%)5Ԅ̌G!%Qy-1S)ߺHo.m>ϭObHJߒמP "S]Ʀef-`u93X{kr+q.O}bvr"-33FVM*ATwJ]׻OiͶQj'=7j -QbYfi%)ʛOSXN|j n'33 J{HYZ4*5CХIS">F&+Z&7٨Wp=qx҅-mJz V% 37*9CUW/!OSu=?C l]Vna'ɏS<ό0#RNCbU}c#'DB|s~z._xV޷MN2"d]'3Loe\ǭ"Hab Jb1ls7{\gvFuO /9ED7$<Ӳ8َ,sJeo/!LS~r=-,Ϥˈ4}ש(+wy»7l1N|#ݜ("Ɠ,s+},uZ@oob/UHm@AZLONU!^BZ+qH<)zrơ\LlvcYœ 2Z,NeS`޽t5Οx wϚ؆qckD/fZuy@}*;xSϧ 6Q|M4>S+GNz 39,VHy xV/oVVR"]A8}žPM$a_D=+UrΥ+>əYGxX\8| 0xLpoLxLL􀀧A4`Ƀ7~zaIn։ә͓:n;n{GyY+䓁 a>.J;CzWtZe߰o7d/+F(_ ԫtJL*\{5/ۍtvn?w[&t?uXU?7kи^M;4[$8 @@pUat;5ԉ G mTtN<'mS$v^ )x]8B)q pa>&R8!r0-b %f)ԴRb&ӜLЖLbDj׮1ُ Bhn2hGWDŦէ&dWXVN`.n>xKm^G:vSz:?ʨgr/:07{v/i4gC `[Ǫ0 UĄ vrλ4t?M=yTB;'GIf ⮾):ȈeUu=& lvKI̶i8D//' a“xK3 !`} zf#KPR!ErCnMjxxĝF:tS%Q:ઑ|6V~M tZ w@]|ލ=*5))A `ckN*懫!@uQL&'%IcnϏ,43f^rD75VSıՐ)\l?1-Ԕ̭m4|s%79hz/U j <WQvm&PW~W5Qچtq/=l`.sccnk;"V^:uW]:R=劢|u]:ClR@x|"T\q cB^1+-!@ P޹:~s7j'|2$:tkaTr{CaO}Ɨ ʬ߷ XUM炂N>i؆AA ooqꓷo_{lA W^ɺOD~I1Iy= b+$t4[ph7Γ fŘ^o.,z:Сt $ 8>1!  >>>jZZqԮs-AQ @@X&&jcϟoU}j 1'C `7o6/rw3i)>͹G5ϽpxTl( @mնE} @(2ư^~z}SƞW7S.!֭K>(I TrP=0-A /P  8jSB86,(  @6$ 5@ Yy." ?/^mڽw/T2G u9aOr<?igoڞRhQΚ77^}—Tj944[8.m(v҇DkA?^u\R gB@5aAqZ]c%#(udiܕo0V$ʪ%bT  g 5eI7K]$sh=&/Y)iGz g9+afJ~t~+)SQs#?\_ՓHD9llfNR( |-.hN pkrl1NT|;Dp#վ bko[bnq8+Ž?(VCH:wtXw,Cf 6pyΆ+DqrT[ z)@| ~L7)yJG @6+XlScO/͕d R%Aiz$vTBdy?0%l3[yPOh҃*߳^{nr\ԁ`O}VXwb  `gͺ_pa]tZȷıĥ ;DIULRΉR;(ٜ5s!3Qo1Ok.x /D>K6(=TO0̢y/͉ ܵs W/>Y gT8(){!c}HIFT2Bͯg#;%GӟB~xΔ-Yټy}mmpyM˙RY,\@x:ϹǘTß^Cdc{#0GxF5"뙞)τśb> au قq'N%Y|8}.ƍ -$J, G!@5Mn~lC%ʮYAg`Å$91}K}3Z=3B(}SvE_6xȍ '(;; :9+YŲ`M*yB}[6'K/x sfu::5pEq&I[s􄻊GʸM ׋klR2ž^%5a=hg [HG`Rq Ʋ\I{u}OjP>@lF5E 孆! J^"4"qæDJ8MZgJt&]T]"+|,.6fT8ד$#Xn}k# [+⳹GG>-jVr!8JHRhұCuaLfbߡfdtRxp|}M[*%~ſK 4C_{YjZ7RJ}bs&B?Z/wL8,hֽwS":<bbB:uu5R87k(̝Ѧ ZɎ(J5l)PIdJKHPS)L?mUJ_(k'8AKCF6ߙ!֜̿GP8≓G")[MO!q(V0AnۥD7#Yo%61 [?[_&e (z7'_W8}$rfo^)'^>Ц]^E>g˛F;Y&N;EKro7Zj/1Cҩ7c`6[p7>)o.WΰgExtEmNO8Z~$)kPW`;Q:߶dxDr;I;P\J 2fr8ؘ}dݺ؃2j"+AC{RN}CA}z}Fcn4s;+==T8q.w"7vdOoeN2* N '˓EnE27_pObo9 PǴƝ{iRD> @xi8t߸+~gU|cu&Nٕ9R̕SL06I Y݊i3G1R;FA@@ }||8Ș֓Lɔs5mE4uoǓe~FB%1mѽ,'Vbև"fMKү7ܰM͉}06tV Ǜ72*r\6S5:( `{gv+ ؾwb[Uة]gx*kx{ÿI}1sǠ7pk긗f5dɲհfDq!@􆛷oS(/Oz7Rg`32)ݿKz #οgiyl<_ZŃ U㱲J<&ǜw/! ּI7&_`.2/He{9οCiθ lXnC־1'3??#[ Ok"{4Ĺ#:;\=V)J@S Un ܌W >#UgRDӚX} K?Ku7+kP#F4]9F_*{YY˄ @U$P}{  @v h[Akz _|Regg.֠}ݵ3FD@M Ӫp2 @@\8m-><Rz,[1iynي9]}Ń;߈.zK$9,ijjpOPq :)y:4 @_|?g2'[xi>_sQ51ߒ:n-)6չS*S _t__h/8\ʊ#aec'P@WuyB Z/܉WkiC&kj֞okO[& `  Hw>yμE\Rw?4gّ~~b 9Ԯ_6[z[Bg-Sz~4YfL ЉCI e17Fh.!}8Wo9NaFGvPtQsJ+sym3CS..VF"]ZMq8%d?2.-˫<޽MH=r$SI+WB72 *~|ܦPXAРj&'ȁH̸IDAT^z59R=[SQI_c'_ۯ$ kެnU,^ӥ)Ha +įr jq B0&l# @ Q{O7 HP 6Hd"'k:b#^,tGZ|=3c҆T#׻w<3jeI Ȯ[ioqAEz>ynӼRKӫqwuʡ!N_#ܘ1Y>m~,X|Rf׈7*X&AnT?}igZߺm]Rݻ>yFFXl$ 9A0VfsWv^NQF. L~_Nr(Qr"1,X|f`v?s22&ukm`/'%Z7@xY@l^70ջ_RN#zCɴSK7WصtѥyZUC3w=6i K軧BDfeҬ!-aPVvOcfzW~10bw~ -_bnN .8r˻t9IGS\yX.Vϒ2~.{)4kfqpʛ3r &Sm=2JdE:RnaXJE%er.+m9B@z7yyyC-ŘUx %8 |>s@<٤:@5n[nޙΘ'QG:4?#QY]\V,-<jо{#ur7-R*hIjLjBnUnqJK95ݰsʟ.R-Ǝ{Hyw{ Ӌ[4;"=3o_?)*''3Urn>5J*}:'4F~ߵ^z*qߵL[|.ŽCYw>OЯ9G$`a}.xhhR6|~Ov$#<`d}cӏq-(e/px.eo^6@Bo޾mY}I~"  Vdu#NL*6S~:%fG+}(܇vwu* ҙ [vCSII-^3O*Ƌ)Y}({xJ$0yT7WNnzo|<~k>N⹊faAVu&Mҳy}o !U8hN_pVE;٘cܪȝlʧc 9mt5paj>8|?<~Ӽ :K# 2 Tdi2I @U'N@vd˘d.>4ɍ*bu4olrJoWwwtW/>aG.! -YkL+^ ǐg_'E_}c{cFfd\w1} W{I}8T۸WRfe~h^e9G5hhٰFrmD6WvXHwgCK'ecN'U jhFk \V4 OKY[u'~Ӽ t 'C) @ *s)WLnG{aZUa$ǼߞMuU3 $ @ `i-lTT   fx}>N>=<܊6{)+5 @@PLip TrPXiXs>>3sBd#kmG&ZY y ^HApV;7G V/LYDVdS!@0\(mkIENDB`baron-0.10.1/docs/grammar.rst000066400000000000000000000272261415427440200160160ustar00rootroot00000000000000Grammar reference ================= This page is here to serve as a reference for the grammar implementation. Baron started as a python2.7 grammar implementation following `the official specification for that `_ and supporting both :file:`print statement` and :file:`print function`. The evolution path regarding python3* is the adopt the same strategy that lib2to3 and try to support a combination of both grammar as much as possible. This page describe the decisions taken regarding this dual support and it's progress. Hopefully there will be very few conflicting situations. Current goal is `python 3.6 specification `_. Python 2 and python 3.6 grammar differences =========================================== As a reference and an overview, here is screenshot of vimdiff showing the difference between python 2.7 and python 3.6 grammar differences. .. image:: grammar-python-2.7-3.6-diff-1.png .. image:: grammar-python-2.7-3.6-diff-2.png .. image:: grammar-python-2.7-3.6-diff-3.png List of differences =================== **Some of the diff have been edited to isolate the focused difference of the section** Python 3.3 is the based grammar I've started diffing with, some of the grammar differences marked as 3.3 are actually from older python version. Current status ============== Grammar diff has been done up to python 3.6.2. Still, some stuff for the lexer are probably missing in this list like: * fstrings * adding _ in numbers I need to got through all release notes to see that. Done ==== Print function -------------- Python 3.3 or earlier .. image:: ./grammar_diff/print_function.png Already done since the start. This is handle at the parser initialisation level, is activate or not the print_function rule. Ellipsis as atom (to replace 'pass') ------------------------------------ Python 3.3 or earlier RedBaron: probably nothing to do (to be confirmed) Baron: https://github.com/PyCQA/baron/pull/121 :: ADD '...' in atom rule Matrix operator --------------- Python 3.5 Baron: https://github.com/PyCQA/baron/pull/117 RedBaron: probably nothing to do (to be confirmed) :: ADD '@' and '@=' to the lexer ADD '@=' in augassign ADD '@' in term :: augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') term: factor (('*'|'@'|'/'|'%'|'//') factor)* f-strings --------- Python 3.6 Baron: https://github.com/PyCQA/baron/pull/110 RedBaron: TODO :: add f'' rf'' fr'' to the lexer Underscore in numeric literals ------------------------------ Python 3.6 Baron: https://github.com/PyCQA/baron/pull/111 RedBaron: probably nothing to do (to be confirmed) :: modify lexer to handle this Nonlocal statement ------------------ Python 3.3 or earlier Baron: https://github.com/PyCQA/baron/pull/112 RedBaron: TODO .. image:: ./grammar_diff/nonlocal_statement.png Action: :: ADD 'nonlocal' to lexer ADD 'nonlocal_stmt' to 'small_stmt' ADD new rule: nonlocal_stmt: 'nonlocal' NAME (',' NAME)* Kwargs only arguments --------------------- Python 3.0 PEP: https://www.python.org/dev/peps/pep-3102/ Baron: https://github.com/PyCQA/baron/pull/108 RedBaron: TODO Action: :: ADD new rule: parameter : STAR Yield From ---------- Python 3.3 or earlier PEP 380 Baron: https://github.com/PyCQA/baron/pull/113 and some after work (spliting in 2 nodes, fixing testlist → test, ...) RedBaron: TODO .. image:: ./grammar_diff/yield_from.png Action: :: ADD new node yield_from Implement grammar from the screenshot Await atom ---------- Python 3.5 PEP 492 Baron: https://github.com/PyCQA/baron/pull/114 RedBaron: TODO Before: :: power: atom trailer* ['**' factor] After: :: power: atom_expr ['**' factor] atom_expr: [AWAIT] atom trailer* **await is a NAME here, not a keyword** (because you can do `await = 42`.) Async Funcdef ------------- Python 3.5 PEP 492 Baron: https://github.com/PyCQA/baron/pull/114 RedBaron: TODO Before: :: decorated: decorators (classdef | funcdef) After: :: decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: ASYNC funcdef **async is a NAME here, not a keyword** (because you can do `async = 42`.) async for loop -------------- Python 3.6 Before: Baron: https://github.com/PyCQA/baron/pull/114 RedBaron: TODO :: comp_for: 'for' exprlist 'in' or_test [comp_iter] After: :: async: NAME [SPACE] # where NAME == "async" async_stmt: async for_stmt **async is a NAME here, not a keyword** (because you can do `async = 42`.) async with ---------- Python 3.6 Before: Baron: https://github.com/PyCQA/baron/pull/114 RedBaron: TODO :: with_stmt: 'with' with_item (',' with_item)* ':' suite After: :: async: NAME [SPACE] # where NAME == "async" async_stmt: async with_stmt **async is a NAME here, not a keyword** (because you can do `async = 42`.) Ellipsis in from import ----------------------- Python 3.3 or earlier .. image:: ./grammar_diff/ellipsis_in_from_import.png Function return type -------------------- Python 3.3 or earlier .. image:: ./grammar_diff/function_return_type.png Action: :: ADD '->' to the lexer ADD ['->' test] to funcdef rule funcdef: 'def' NAME parameters ['->' test] ':' suite Exec function ------------- Python 3.3 or earlier .. image:: ./grammar_diff/exec_function.png Like print_function but for 'exec'. No one seems to be using that. Typed arguments --------------- Python 3.3 or earlier Baron: https://github.com/PyCQA/baron/pull/140 RedBaron: Done .. image:: ./grammar_diff/typed_args.png Action: :: # parameters # this is mixed with the removal of def a((b, c)): style # which will probably need to continue supporting CHANGE parameters: '(' [varargslist] ')' ^ TO parameters: '(' [typedargslist] ')' ^ :: # CHANGE varargslist: ( (fpdef ['=' test] ',')* ( '*' NAME [',' '**' NAME] | '**' NAME ) | fpdef ['=' test] (',' fpdef ['=' test])* [','] ) fpdef: NAME | '(' fplist ')' fplist: fpdef (',' fpdef)* [','] # TO typedargslist: ( tfpdef ['=' test] (',' tfpdef ['=' test])* [ ',' [ '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [','] ] ] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [','] ) # after some analysis, this is just a refactoring of the previous form with # fpdef being changed to vfpdef varargslist: ( vfpdef ['=' test] (',' vfpdef ['=' test])* [ ',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [','] ] ] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [','] ) tfpdef: NAME [':' test] vfpdef: NAME *var generalisation ------------------- Python 3.3 or earlier .. image:: ./grammar_diff/testlist_start_expressiong.png . .. image:: ./grammar_diff/star_expr.png . .. image:: ./grammar_diff/star_expr_in_testlist_comp.png . .. image:: ./grammar_diff/star_expr_in_expr_list.png No more '.' '.' '.' in the grammar ---------------------------------- Python 3.3 or earlier .. image:: ./grammar_diff/ellipsis_is_first_class_now_not_needed_anymore.png Inheritance in class definition uses arglist now ------------------------------------------------ Python 3.3 or earlier I have no idea on why this is here but that's easy to change. .. image:: ./grammar_diff/class_inherit_is_arglist_now.png Raise from ---------- Python 3.3 or earlier .. image:: ./grammar_diff/raise_from.png Action: :: # 2.7 raise_stmt: 'raise' [test [',' test [',' test]]] # 3.3 raise_stmt: 'raise' [test ['from' test]] # merge raise_stmt: 'raise' [test [(',' test [',' test]] | 'from' test)] Variables annotations --------------------- Python 3.6 Before: :: expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) After: :: expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) annassign: ':' test ['=' test] TODO ==== New lambda grammar ------------------ Python 3.3 or earlier I have no idea on what to do with this one yet. .. image:: ./grammar_diff/new_lambda_grammar.png .. image:: ./grammar_diff/new_grammar_for_if_cond.png Remove old list comprehension syntax ------------------------------------ Python 3.3 or earlier I'm not sure on how to handle both situations (and it is needed? Old list comprehension syntax is like super edgy, I really wonder if anyonne has actually used that one that?) .. image:: ./grammar_diff/remove_old_list_comprehension_syntax.png .. image:: ./grammar_diff/no_more_list_for_rule.png False|True|None|... are now atoms in the grammar ------------------------------------------------ Python 3.3 or earlier Do I need to do anything about that? .. image:: ./grammar_diff/more_atoms.png Kwargs expressions ------------------ Python 3.5 Partially done with kwargs only arguments. Before: :: dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. argument: test [comp_for] | test '=' test After: :: dictorsetmaker: ( ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* [','])) | ((test | star_expr) (comp_for | (',' (test | star_expr))* [','])) ) # can be simplified apparently arglist: argument (',' argument)* [','] # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. # "test '=' test" is really "keyword '=' test", but we have no such token. # These need to be in a single rule to avoid grammar that is ambiguous # to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, # we explicitly match '*' here, too, to give it proper precedence. # Illegal combinations and orderings are blocked in ast.c: # multiple (test comp_for) arguments are blocked; keyword unpackings # that precede iterable unpackings are blocked; etc. argument: ( test [comp_for] | test '=' test | '**' test | '*' test ) Nothing to do ============= Those are things that have been removed from python3 grammar but we still need to support (and we already do) so we don't have to do anything. No more commat syntax in except close ------------------------------------- Python 3.3 or earlier .. image:: ./grammar_diff/no_more_commat_in_execption_close.png No more backquote syntax ------------------------ Python 3.3 or earlier .. image:: ./grammar_diff/no_more_backquote_syntax.png baron-0.10.1/docs/grammar_diff/000077500000000000000000000000001415427440200162435ustar00rootroot00000000000000baron-0.10.1/docs/grammar_diff/class_inherit_is_arglist_now.png000066400000000000000000000122341415427440200247050ustar00rootroot00000000000000PNG  IHDR8sBITOTIDATx^y\TU2*ȀoF2m|ղifby35+ԏZJY*,bŪ"˰ {wYQ~<{gsν2L$!p ݛ@lll<'D+@[^fMCܷ ( $@ @D ȁ@ @<&4 @Os75@JD}'kw/ J`sQ2G3` `&8c G}o̠% 0@ @t#쨳/taPXqdi$ ֿ 9+@c*zxƊ7&r59woIw_3\"e[w3Jʂs{KXkMgQЙ3o&-T͎r 1YQ mnMca[?c?.(kr¶%YE+Xʉjcy'!p`P-doZӘtI΁Y `#o}-אb%o^-sg&;I\ruQ]" 8tG]UpxU7~V1g'E[|/Y:W6cItkr©k?7ч M/_QZwlߴ5˂yNρy|+㟉9Kg3qՒNY:>:vyl*`ca_Fo}dہ>:"cb#7}m_GeL/yOP>چ&;]Vl11gdd@p3ӿ?;,ss!!$gْ-(݊CwԻUڜE^{v޽‚&eR *~8̟PhF.2RZѤ`SER6g>ۭ۰$aՆ-2͍N^%MYWcV(a֮8i{$m @obkw~;NDzM@>qȡKw8F-^0Է)n]Ϯn.܇~m^DGK:Նmh9~vX_]׵zQ. +O߅NKBs^CtXm Y!zEP)4T{.Y Da y\~"H?LOu _}mk=yʩ[Za% ="w ;go,_f[U3.83OX݁ q4<D#Z:#Jlݮi6t`:񗱂5xHT :n9Դe7E3Z1Nuw؛;(v' ؗZ7 k/k>'1(FT^לZW,.A:/(Hɔ*O(k'kYܾS7y/G)-pQo<7tbtԺϬ~?6[Aԧ|?;>pc^r]} |GMCȳ\Uu8ľ.m$x(B`?Қfg̜Cj~̨#gܬ\//hMntkIäE9PATQ\^V|ִ^WVwȉΩn,C(  K]fܑYU/ofLGcMHC6I_ܣ#G[)L^ďP}/F`akTsT3T하繾,铕IM5V/;55MXКU,vP\*vCfw }M"f'kMC q4}yqAHuF!wy¸}TÀVToMnDYqm&NDXʥ !^3} oYuKbft-ߣ [RPؗ }sr!h,BUI0%֏ G+B.u+j[0A!>1:M>G}kxd2yB9uUgɜ=Om\3eLS3[~d-6/ [a.NYbzI!wܮ63AeʪBP upT"TU &XlYDMɳzIQQ 9O<}d1jsYbv0U;fƜEy8.:GU]1r8Gb7ScIe/'j#+}Nd 9C ]#uA\9͉Cq{ì%UVn^C/ 蔹CΪoc,v՗-}M2;'6@"q8^{Tܧtj5ob&bvzk㈶q\&ŦO٭v{uou&Ś[S. yKF6Hb"!r)/ ҒGt,D}SKGIïSKo}#̘a!YnH?ڶmKJ(W,eJ_X<6tG;qyx-n8@А K ,Sx߃z `@Nᩒ&:em|dǹ2JYJ[UʦR~hsEiveҫ ̕|pԻawwArMͶO8] T&;v쫂rxD6߰\n~@XB@J ϗq_, xm]~XG}^E<ȼ2 V_H4!=V~NԜ,zwF, JIM$Y[1]J9ic5gڵ&&VJ)(_мO>>'{CrQQw+IGru#0`TɿPԨGui堭M=7]Ι4qH?ܾN S.7:Ei /< 24Xf'՜gtCNk^SN%Ƌ5LPmgV4@!ZB%R,0ntTNP?Tբ3oNѮ8IgYg;翙w۴/aiW)PȵN;fF$eߦO3zҙ0zB M@7}'LH}|K$ :=N(|q۸;@o|ߍPg >(G];}l{g"ߛ}ꢓ}t'E0tlȦ;wҠamPP)+&1&8nGksLC"Jj3SYNTf{OCo^A}i"k/Ig<.(wI~"=0Ld2)!G ps'0핺p'lsy.ش#W|*Z;z0JЗN61s>ܠ{ZvJx^RMi1"P{Sdfxz,՝:iHXΜM # @716 ;efD*^Ӣo)@|7Q (6kGTtſtϼ}7O)hkZYr_)tw;6ZەuL2wi\y3C)K ;Xs{h-o}K4^R@mzlaLxQ*F_:ύ^ҒU8ߖ1u|s}fz&›xӛғ?n( nϿSK #bu .Cgp[l(9 ^ߜw6 6jmR/"?!,?wxzt2r"*vzR>eVձ[ U" o#9%P_XӚ5])Azvܧߡo%pr?3mK_ As^B^2 zGn@/&z/\ ]{d}a6f)o;J C;`O= =*7oݏ,ǖ/(@79+ @ @oJIuIENDB`baron-0.10.1/docs/grammar_diff/ellipsis_in_from_import.png000066400000000000000000000347521415427440200237130ustar00rootroot00000000000000PNG  IHDRK0sBITO IDATx^]|Er %tAzH(6@Q" "6JoR&%%~{w.?f޼򟷻ofQQQgϦޞ<br Cq8Avrç-mL/mۥJqy{|u}L,pF[L,Y˖-c0L-7*8!e 8R+9,>VTU@ pSFs/d" жsI-1A`miL-@ B-OɝO6R.(|8q`#-(@ @Y8e}oEX$;KIg>hmwD}t'ΚO?PmqG u⹉< {ZBި%%Sߕԇ.0*mʎvXʺc{ #GpylxyaHϋ?|̀ pMes3jL(-pvE|>0B\V?% f^SH.;Qh[ +.BH! P`'6c(DuAC$Xk@"l."X;Ek #*u=7H>;m{}xw _ {>$ʡ48*x? 7ӿühZ DUkտO<5ݒCn$fxend .LNNQՓZ7uZL!- %Z@5"cɆG@J7%/bPr)4$>Z>.~{~/,@[9^>`ZTUB!qQl\WBMvE{ceR4 {Jụ_t\8SUt؍Z]Dm߽ͭpn@Cud"eqn>]WtNֈN.%FH d(}k0JZ-봐\!e8brFBaV\.ux 1[;eq=Tf pGY(D{K<U!y>gV8E??-{ ~8¿rXwƫ$"NQmD@GnS94rm؎]|]7pF;;CI:paa&7!n7-٣?{X¢guSb0Nl#|Z@;D} z]N@R[L3}0gz @d BbK'U #`]P4Co>qɘýVUHЫ48Yb;eYةV" [ȫO UW ?,h %ɤÙl!@8<4ҕ`%⁸"i +QR`ȵT|1 f1oj_Y0/2T+ e'l j lW,ʙܠZU" eOzl}/XN;.ag+.!\W`+D4@@ qB]8@P} Dt0-UubћE5O\ā6s!{Ɲ9nX H*Br"q=҃5r:onVUv+Zy~5ښZ2Ġ/Wrsd}Yϡ'uO;Qݜqgd:}* #z o 97.~Ku~ @[ikkg"Z.[n*~r\s3aOᱚ;=l\Up跭oȻr\VM+mÖbhbYB?'^oXHΩs&23!A2$&n~,} eJc93(^vlWxjUoSvu|U7_LyK`~h^S5>a:K]SZPMYs&ރ*۵Qkv2@Ɏ߲ 3ݏe3kYSt@s #GXʼ*a  @`ݺueWgS %m ,"]uQQ%Zm!1{ψ; r}ΎOknG}홊[0Nm{Qo[ L}DZe[!ެGlmaxGqA;L69pM}bWvs`(hAp9q#=,^}Yw'3%PRyt^?a #a Jjע:-'p]ܾrA$54I,~i%B r罧4t\uX$'mPچ(gҋޡ<1Z~l_QQqE̤?g>v/ ~91qtTW?;%&B﯈{<$^HrH){dΒ!OWھbN$)3,ǘ09/?$g⻵Q=͍ήlW!CҎtzs zGL72˷78”yn~Mrz7oRgZO]@sULQÖG:K=PL?S,wd^G;ONOB$zho2OᄈZɟceƭ\ġ!G3:c]Z;/lJm0H`n/J:mTߡ%Q@h9@Ng^_I&4sÏ]m~<0}+&./UA~~gpNRePX(@ .Xw,~D<'5cD?oAh8AՓv_:\o?/ m=Vuo(Ο?=:ďeg|)A<=֬a}8^Wg*P#o=DIj8 XaK4OlD>o?4?8S_[pPby.7`.BnI2Fm y'?Yɱ^l y߾59cD=rۓx%+W}`3ۿ(Up^@(KWyg2K56m0p@.-,„:xje5Cd.׫CoIoM.:j``=$'_sw}g40ͬ#~=FKcFšgGb9iz7n=ALOg'Wț[~iyĵu> :^pU)!tU, KŒ1l#?}X9m?mXzs)ZŏlwKNأ9\3XO̩O8]8NY۫MKFITL|%:0?IGol?4?Da:XoZ( RA#|P,K Nh'q}`}d_>w~1ݽ/$i_#O+g^1gj~rA_.y5?ދ`Xcc_}[A}Co$?\l#D E Vs2YΟ7J\aBۇ~|XY{+Otwst@ɟ +_qW*{ekekVߔC }qfv'G5|&R Gߺ?V~byMֆMYnJV]RTi~|Fb0t6>KŊΆ`AaStAvcߙlCҷϑs$OA?Z=-AIPp;Ct+?)󩧦 VSG.Tۣ?S[(.͕ r`7a,{T;c ڍUa ӗ_ܼ)wIƄܷpy^F;?O*p}yh: ۳CTG>,q1v >kI}+L9tq@>HͶ5^a()rLu+trrCmt"-=-~M`>A##pA'aL #8e=8@k{35 K N`vS8PUTP(jՊrKlW w\vP:?6∁ۮqn_!}mBS_=[A$ʊ'$W rjq'H8d_jZ)e(=qը&\aC8 FV&lϬ6mW} 3.9ي&N3qhGq9p``r%gP\OwyOw@к ̏ULS儋XAr v}Mrik V ly楓WUzҠp%QsZ8G 3`/'GzaEL^R#ƆP\[(5TʲJ_X}UvEҍ#_X┘Pɕ%r&s^lt~y̖5SCd5Jah_NN6APXC:X/#Bjf8bS(q0q;<1AXҡ?W8ԇm"N9*NhڇAGϳgp␸Οh?vz'Eːq:G|Q#B90K{ʈ VQ1Օj~pI'jn2$BByT=Y3 xL0Ez}j&!Hʓf:$@%u5驅ጨ瀹Cm΁ Z1R]Jó~1=X?B^,fKBc&v7vs "{vT+`:cAJ?@,DGt".hQ̦彸[hqWO $(aq{؞lD2hnxP+c0eŤR[O9\QS|51&0CYU89x=! &0V:2qkۿSoMP7QA`~:rTOԶ''4yF}R" ,%| ^YPC#Va'i5n<>O}+$n{zΗtsX=''WTe׮*"¨W}IG6L>[?Mcxˋ>\򜛻v` Omq~hƁ%bMSDoہ)A1@!!M8_:49ВM/mujW'Lzyox(ӯ٣EJpt?ӗʹ3xٕceEY-!u|?7޵d|=NX7rN_}6y=w{c4}3Cਨg`oOO &!=iy][X7_p`8aжDZEo_7[хs>uթfJ4|ә̘ɘޤ DZoh6}#6ҁ$cqu^/^emx`jc;].RCrT qJf}Hw\Xln:b+y-[Hz3R$nqWo'@vPZ"vufw\|6@y79_SqAR[ LpPSYtܩ,ց&KK[*@  ~~j=~gc$,qfF F8M5Luau.]Vy[q XoЛivV_~a۶KƣNqmmY|@GU>A\W-ڪ Tz =@m>]݃9~b𪴳},>iۦ9ŧhޤ,5@@ #ecWgK8xPW!&w/@ @  `n'("?q!:=9gtOӾ;Θ2+i ?uIY7‡ɶRiqqL؅W%BQ ngX!6d9,`:sw.7,zZCT@ ahqx4ޖ؇BGSWe%Ô^o~Ǜ2awXvFo.icZ9~ ? sW#ˆySzL?jЄ Ӕs@I:ztր?,>wn|<{!DBMey ):3#|gx@ @Wȓ.HuSt2R9, 9*s E[JWBQQؿox;ρ%4Y9T@@h~ئ'47O8[]!ṕkg"0;k㧫 8vo8~L5>ͧ4^ݧ˾P $)+˛> F@C.R[{eO? RhY0{2}cR/1Gum_b(v)L5ԛz6tZW1@u&ᢔ`wȘΝ=y^x,GCWO.W+I~ reiWiE.0_mIj6X'MrI*&AsS'''zBLDaڊ[.[Y⇴:=8ם i/]TA!>4娤~<$lSKn_Ϩ]^)J$Qy,x$My˒ģ'# Ib0;~X2}^=Mx8KE@d&y:ڊ;<( xu<2Bp4KaCz?6aHOi_pXxF]F_W>uy*jtnћ4C'8fpd\_'a9' ĭCBuMQbg/ *o4$R&Nj,f}u`oN b$0Ń^i}f(pe).=WRMa~L׿ל8SiJ9)"NJXNGɎ,MHxBĶot3zzZK +r5&6jQ>5S)Sz+(ZAZJ`cNIyh&&<N.M^\ >dR!]Cc?S|  C{t~H]95YGn*1A@Y#Xy<8ePat8B-QdgKww ΝDi6"8);DL;|-u=-^%sIBNC07z˧Os49C4c3Oaëo#;1lV$%4~N'65K5*" PWUĝFR_+/t62=#{Z*L@ & EfϵBuqKVqmV<%\'7SWjx, ˑ \Q~Uʋ /R]V|j's <Pq};sM WN-1,YOril.˫:7`c4 BH86dT'WD xQH*)ڞ6Cx C3)\]]ZEv==>tXbLSQUp%ܟ(4_ZLCF{ynтHE(o'bNw Xџ^5=-SK%%-ժWKmZ}~zrixON4Y{RM}`AP)ݰgoGtIP֪Ej+`/R |< i0s el [gf655aPՍq!+"b8 Bt!j.%@zv<9VɲR۵A݌W ]v#&Nr޽powc e(LnVMVZ>P^SN^/QP. ՟^R5j=&KV'WVPT!*ɩ#(xl~nC$A~O%՚?[VusKVGm3[ˠ?^ΙL<,%K!> NU=UA?ƔBuɺA/羰Dq>';<;L(*-IF0. `,I/'mϓH_lSGX fwpBkNv4 zDhll1xmEk\ 'WUQۄ>u:sо N^Mի8Ǔ7i OOCYNb&EjO8z@Ǎ k*̍÷ Er/-WpdOBxB!Փ\%[rGAEi/\Vvj{mkfy^=s¤u;<OIRZ`wNFLCNSoK0[H"A˘ ;BQOYgZEjf 0yynq>Vq/FLm+@f (@ hQ=r=H}ϻސ/>"yM;m4,Ֆ+ȵBޭQu*a< {D0#l@ -Yџ^NO2?@ B={<-,8Wg͖L9Bj{xX}BdN)'5p79 <<akܩRtqYQA(1UGZW?W{s$0]Fdc͔RF '7?*-W֨˰t@ <$; 2Sr H#ݽ9Ms;rʼ#bF-ښԫW*ӓZ8;)n:sÕ-#OWJn%=rBuQkgC.M3BU|(zd$). 3i:N*džw Vd+j*S)#zp7qXЈKpi*={#brƇ4岜ϜP뵲B%a*Ciz&"SfW,]3c%y'(%hW^^:ug{(jJ߬$86S.rR<>*ۇRGګ~d3#bؒФƟ8Vn/65đz֑"C'ڛKa^qqS]pt 2ksڗXDS^=wl\Ht*DBGDNa:y^CO|j>tkਨg`oOO6ٖ|& @eǬ4Jg ypl2F  N`DqcSm]TlS{=eF 5P@{U96Xu))hb]4gg>( 'oXSHnôaqzur.y,LF\0kc5 .3w1u z8t y_.!O%us;_x3;!O!C1fӎ:i)9@#;4Y_PoMUlYRXx˂^ `%Xrwi>[҃]>|2Bc<8_O,mWgX(wj ;#{\HygyGh{Z?lb/)(P!쨇V~4L@ ILtz`>F_*i ?hA# r?dRӮyĈo?mQ )SB˖T=fM/I|o~Q9P.\c=!o5/zvqЕ 'd~Zu.ޮ7#_q]tܑ_KKv\+9v+w& zL7M6m[ nسl-撨<LtC+=PJ}DYޗQ|c2{s; !O@ !q uߩ-~kƑ+.rEKxvsV[i\5y x;6uPMʉVWn*b'8}w M[Kf՛UK%f0G6߹yje MO4| t{6g.xMg"n''K6tn¬sVURoK5D~Rq;"~Dށ< wG>M҄GJzvZմܷOj:P7e?VPe 3_oÊLC@jyT"B@@܎fG;I 2GXRҚ-eol9 MI~aZӆr6;z)[KcP.1@F}0#JU#O Gf"C"^1{Sw4kVR%G@*"K}|<%x7(bޱu(O@䲕M*9gg~![l.Z#.WRa+|`CS)>G wkcXF4s$8UrHy_rs*e1<<%ȓ=S&/]i(D;_uq 镝Q$;dBhD9q~i׈I1ELcu"Ԋ wyF<ڇ*;Ud{ӐfFVL|{g/kz *1g.1P*MP?=OpN.rB"B@HC@yJ.3Xc3 !XK?:TM1E`A6~U (.)=E *p(X"5`@ }  @^^kP}gU @ @ic @ @&ԅa?(-=YQYcZ5 yFv%[$@0(9k"bwPm Y s\iYCW  y@&@ K\B_lIENDB`baron-0.10.1/docs/grammar_diff/exec_function.png000066400000000000000000000215301415427440200216030ustar00rootroot00000000000000PNG  IHDRH!#sBITO IDATx^Xwћ4^7L4&5h1%lD{{KĖ ,"Jovwܞܗ/}o̾ٝE"'bͭ>8*:?tjn`eoȧz^tHvP,໺9?1uQ23B^fS „ MΉ}Fk_wbZ + @UOľL3zdDH H2 ,m5$ @$ @$ @$ h Tު11Npek⚌O9fqup{97ѧd+k3mY k^  wq ;Ĕ˶ÌIIIGccʇ}O{ ί!H^=;mTv4 hv!J!-\|ji`YZ{ٽ;t}h QhED/m#4d4vm9Ou+|Uco3/S}>&:ɋ8{,a WnS~S}@;|LS}5`e-7n3h9f4ôL(Are?Liy RaeM}S/S;LAWJDd:Lど>cOaY5PiQ.fV${ ^tuqz #:5̱uO5eǪ,X $PC <ȉ=۩_uW0LF;*DQK?G:*x;vŊܭ٪mYpԔK)5g ŎVȮO&7&~fPd~/cɨYβ n]ݠ֔M,ܯG)Y66}/T,xl>P B~5Ȥi>Nb;# fo=Ga-K[ *]xDC>6,t"ƥ{&6~;kzCk[kږ_$)ezm=!2ջ(_O>9u{O]Z ,Ma4YM٣#QKǞZxv&ò/ ]uh Kg8]Tp5.J\."-CFaqU%z|@r:J}K ݇m;0ޚu9oUg2 =V-K}xfܥ]f37~>Oezb| ' 5'@پ0O( ; p<Er-h`Ϻ8[5.ѱtnS./VF`'e2d 0Oбt|``xnM&SkJޢdbGjO??wNKGY3G<Ȑ;ts`lu@ ?깋\redr!ۀC>a=5,E)n=SSLԗԧ#-H+g7.yÄD^Mcmqn IQ;0wؐvԤ\82$~\ X3_x)jCVTAvȾ\W-kkB{7wuqL|'n^96׈y ]i0`AqEُ@u$7*p9qbR·y/=%JRd8FjDc/;޷c~+#?wt|R2֍yyW§0hyB(sbȿzQT\*%;C;OǦipu֭cg_:gP?A:t.8lOL 'vFixKkРչcBXT?|9oaNN$Xε79݆4}YQim-z8Ine*R%|h|ϼN'‹}YjOB"OQR_YJh+zP#I+O#R#%P>K2ѧ E-yBɛdj#(H!/Bh,b +~@ɩ74A$*@E.g[آK3sn6l,7Fwnmz?WU+Jޏ_3Pմ&;oq ihιOtHDPME F.xdx^Db>O0E3Qs+<ʸKvˡ/0M(Y #yBpוjĞ|zCzn{fӖ<e9 Y1w:t MS#ONM9b1Sz2d/p^ w%S !#];04kI Zo{/ܖayoj PSCV%ϸ9veBlH+@HRmYHP9xx jMaŶ|߾En>4qb+=<8_]Bf7 J.H5-$cş:<^}~xԁ w|%;mq!X)WQM5YuOw&ڏ'<l]|rY[QKN5~E ~y6굧{LF>퇯_ 6|k$._J Z76.y$)y:8`n4`x\">pc0\\>SN:-.N{/|p-ϋXuR-]9s*nk'T̨x^^Do:DtLL.}]ynaw{Qdq B"`@CHa`*RB翘D خYl5u?ŏWbqiz} 랡W f?Soo{5?pefQ)8jCye܂N2C GL`>L '88Xb1)6-[yk$3@ ZXZ:3(<0}9Ҹ2-?,V>wWՈ"0OՈJ@$ @ <@9Hj/˙4~A&gh]zqf ׬}x+ttR=2Z0| Q߸}ͦ:bB׫D|Tu)lI4_>U^n|7,W8@{P&)4 !0/$dBC`E4G!H< tGXe/7yRh !Hj06ϫ@` H H H K"'UZ\)?/Ӡ[UyoYC @J|}KBN}рg;oZO UYUy^C- e5;k6Þ)Cjf$9ŽTTUC ?:Gu6ـiOUBфe{|.X~ԥsr跈7y}-F-;N`j *.O>А0U렙tGG'5{1|" "s-m,$`!``! ݬu7Vrv7_{Zu}}wYHRwݸ_ _I\)׮~ |7udC`ǔb W}4[kFyh%U?}rsG?_@xbkxQ DB仝i,¾^,`5;}`Mkr=_=;yGWJi A'j*x}b$.CGjg%=zܘGE?,"<|f+5Ro_8kϿWu\2h'ѳ9_~ۉ=U[ $B[-ml "5F9GEN};rVE٭Bԭ_"jR9iy;%6mRoLpT֞]'|qWwk2;&:: vhx QA!$ A 'L<>c^K'2^ľ -:l+ų.|e~NWM=zcbsI]ݼ}?KSYu,v3p'[Ԡ߲z7c6=2B4Q'DKT@Wo!nfy =Y&CJftcΠFO9Qc4N^ȩIc~x2^B,uKO T /zȴat7D[Oq{ky.jPu󃲅]˻ gc!iʙ!BwWrX[A T%r7@wG֨pW}ZJ#aCڕDeOR-F pnq77(Ryp~2>Q⁺} 'pv۷6a5 BX*B O J0Ob ƒA@@q0X{KDW 3ΓJ3e/rl9Z4xVD\4k;ZcyO#OwnRKegBڨ%Fm<2qrn?IzҤ{ո贈uEr.E=׷?FZg_(_D;Dی D2ٶ#4H!<&|BtBASmD}Aߌxi4b#ڛC֨=x\4C+6XVT:^;kcΩNRDD աWuAm8Z{}),[n,_+ǩZyyg)PU(nŧvL0,+ـ!Ӟ-㠸K|dF5Y'<:8x42iFث_]=I3#?l~i\YepT-prH,Byz1̕`B[M1Iz񇭍U91XfLIr牔R4B9i 䦝sl*8ux("cպ 2K$$sګ"xP7WmZos-F;=9D(,Gh@un&sXzs!ʹATOsONYƝ Sqoy Nq.ZgU?;m7>X!!gQ#XRe (Z ϝ7\e9-|hbD~jo}3 _gad #{u8Uss:҅Ē)!X})&KUrD &';Z婊RS'mfrڀ;6,`g g)]17qii`G.m("]X9YwaK-I9HCTcm+H$*oOZ$8uO%ĉmkE%<%DuJrVON[QO9k0&/@/;_X7g=F\$u*[j]# ܒ\: >RGiԾ}xNµ$ ?lΟ|o*:.u#Z_Od +SCeٽI;h~ju{'(߻Cm؄Z2ܑ{(.RȐӎ? w#{NԹ#lA-:^&7q Z xj 7>H9.ŧJ!Hr |/{~B8ތ[A9$`,/뜥//[wmhW*'UH"ЪdX $ 2/vڃ H H05@?, ׆IENDB`baron-0.10.1/docs/grammar_diff/function_return_type.png000066400000000000000000000111531415427440200232370ustar00rootroot00000000000000PNG  IHDR+qսsBITO#IDATx^\gl]ҤXPD4(V,gMbg&ŠK^v,v L=3+7iNH ,FQb/e:%Sz@@@^4m ^thgTy_dM*3Tc1+GR`a{E3wa@(" |g B|8]O)g@ܷE̍C|iH$ո{ԑx:{ժ9e籩j#I݀@9CO\qLZaL>x[T{a^ n6T?3c3XBvė~tR2ulMangD7Wm<Njfٔh}^iX]y;ϗ-H,ۖWs魕.N;{UMX?@v"nsvXg׈劋Ѻ n[<4uzXh _4EK[評(g)}8#,mb%AZb@!@<+n7E8N6ʑ>C#}s~fp\ _e() qKJK4f{̏ҥڍ[(8Nv Њ@g_ۅ [[pL6QAOۍ$NUn:huUSh'A/]";sa͋OoٖH@ c{zeNzoo7^ݍkOǬLᐘEzIy}zq.]Awo̪!eEr'ρDž Ґx}}@V޸?jĹ׸O&FHLVv;iC u 743)^yzt }DQv_{<8}yO Spx셢o7I/ {;ClWy7Ro9tDdç*4n -yG@K~9%-z +:P #xY~~_ל r)ouwCl(;HuOo}A9md,@ph/ԏYGXv\tџ?]wgN͜5LXn#C~ژ+'ynL*Eh)QI/.%F /u('?X.Q. b>1 ӈ^]eCZ^[" %{ 2n g8jy3ˣN F `ϝkzcN`1SoHHx61RPss@8py#;xM*% iKoκ}R(++*%U\_ԣOwՄ\-YCWtO!c9?iqݴx!4BVuT<`G|i~n 'U59p?}Ty V 4qOksS=tk΁Az |g+^- I )c] [iF|}tg߃a#j.h닐&#)e؃37 Tq~owvT}.-WNSPcTD卥uJiHvuD_O8 ^>LR%.,h҈.OJXň<]5"}fН ^@o!iE\q%h6S7bh`$sy.Ҹpkbg;HU ]/mR"Z5D,:HdT'$! ?wV^zLe!50ɢ ՟*ZFڴ`,`DJD5A ]_75c]<6%9Ԑ& rkQ?QꪥKTQ)!|RfrI+jU1(fJ>:ۓ곿omTwƽ&R+h?By0Q_x)3""ZGͰwjXTuUJ_`B.8^\%@ C1~=TQh^V4Jzy*5' ->8lm/+pff1Xb,[u?58o&!ŵgQ0ЩlD{LOÇ_,(婵3r@?DTqa@껪3g.X\Akʅ9M4X'Eb[ϊ8OA3B(&| jL9raHB(Ǚm^~p.nU>7 *_UC\4A0J/TM*>YǾ_i?_# 5Pey~,3miÂ\.&ey;Qpd/j3j3βȦ]?ħT${ƢEam$p0+X_-֡͜o1'g+抷O;+-`@qz8I"m¤sbp_&@qK[0-o=vP]Tu]6RņԘ7ȮLpUԕg՗7~aos9y`0[>ڞz:vX_Of]`ȫKԋD}Wke*..l+-2R0Lp6u0፷Fj۸Hk=X p ~^o~5#qֲJU !^+:sJmOZt֘>0YZP6=puqCtk_,%ĚmH5 jRAr|r_d4zZ4>g4m zj39-E&6AǾݑ,'IȄA@@y2AhG?)66*}<8۪q*ϟ0:[q8Nw44y?W&34  %@f?ӍĨm[**_]KSi*k"  \ @g!ub%,>?#S"_M%-Trx~?؄lUIENDB`baron-0.10.1/docs/grammar_diff/more_atoms.png000066400000000000000000000313521415427440200211220ustar00rootroot00000000000000PNG  IHDR3;(ljRsBITO IDATx^ XW׀gBaGłVUXq.~UmŵjjնZںQ\ TQ6AAP@H23B2 I.ޛ9sA]]]@&H`@@eD* ҁ@"@k] @ @$Ў"s:g2v,ݹ!k[6 $(ܥP5z¯&6%*!NjFFO'U6i,Z;&9nѸ~#| dس3=;־F.X_@&JcSY~5@w7A `*#!n`cfO ʎkggG~kڢ7>=Qys*-~O$l ˮR-&GrӶe6^QYV@_BN#|4\͆B~1Cix Z(y_`4j[L VO!@!~[yC@7QݫӘ)}aK1n !2G{:ĊîHu 4&epٶ^ohԻС @o9m%n&+( T!2g|-,:\fq?.<Яl,덹_=74:>>?z͘%{)?rdMMNhdrjkKM XڨϢ{kfΙ]%0EMYp]%-Y. P3Kps;3 p5;7-'RH@w.\}oJHHMՅE)641?^uωtBjtN9-jg\Q+"W}` /m!5RR e.'eލb/ j0[%g='{i}22RoG.lZ=Jj80LdBy/Ǵ ]C : ~_v ~_PR2BiKGo܊;CRB?Ηˊ>7(M6Mr}gi[X.;׏LYѿe! \*q~iɛGZn)O.(h[GX]ME֨nOڻ׀Þb(GqJTdDEQVi/'#G\ʫ@thu?}9Z}7 ~ y@ Ui^qdϩg|).)v6jHYs 5w>DxnL&)j;a(ܒ9|~nѬvҼ"iȞ=?y*d5_UB d R `ZvsncLSdҗ|ӡlqNHKR.ƹrbbAbc+|U׶a(@ ~_m'W~[j dO@=Xa]e ;M'#s!4kk=+z*dI%8JpC&H a U*3iWg>,ǫEjBLaVh<&`)\GQG S[S4:$&O~jK.yO6N@iyqyyETK>);Iu9te(%7'tngfIʆ4pn,.W鑤mCA  ;:>߂W7T cZT4Iw?c!|{p ZϘO9Z02tf' Ԅ:8_FU8GףFVu_׶(GND^A>4HblF2ƹZm됄YaVޯ<@5)ko@&jvmfJ/}L#t~ Ζ"^>6XēI_xphL9}}0F}]  pxCaL 4xn.2kNoB}" ȿ,XϒL^aתDtGj@&0t먡~tVwYpܾE}Mo&~)Vٻ.EA^/[xggP50N"[=D ~T6XcBbI"۴Wpftfmv1CcGF..aZv&\пMu~V J tyB@@V p8*_x/ ~_/}~A<5S$  h-$aK4/I%_EE*xCfsڿT[Ŕ@! -Xt*3/ +g;];Z@@vY._Xԣ0zܖ?f;O7Yi%0С^ YsN9flYE>f5OuU8ر:Ā i/o= ~_+@-@ @ JjW+6qW+@ 0Okö@ @  @iO`~u'DEN.B MFnJHIzA'nEXar\|-MSWS'O}οЂ?@ %$U6`fVă7~{t@ldn{5ojώ6^9EO}EVW]^/|˷߫#!nC[ΚtQsmGveKX6u.ʴ\4_c -/9pCD!|Y- *ed(2CʏWt  lSոXqB7.J Kv (ЎΙkgf1+'YF_gQolo'[Nĥdddܹs7t]NJHO8^DƢAQ73fד|A&w)1-##vd+6cJ&Jו#K579៣ɩq{W;.5=.x#i> A:uC XРFH@ `Xk k6@6v?g^$vaoҶbB?JFV皤Sw(&wM.č}NȌ!g9ZTū`g$jg%Xsh[ "{18mA~?X1ǻ((wY}Q_/{l9v'~A{>]8}* 7a5;&/m˫ @ `׶*5}> LDO{E0۾Q2V8I]SawTF%t&Em~1GҒq5w>DxnL&)j;aszgWsK^BSG3 Sid`űGo0FM|mK!B@ dF$k\ ò4旫4K'>3EyoU')z@uvaZ8YfFyˏ%yX E.hLٹFpNˡkW.8LW$l,y<ε5C˞HÅ/%\;^tbI%8Kp.WrXyq%YSOPו @C!~__=~__$A@E 0u:Rb+$kHPgOWf1^ #/ 6J !)yZZg|)qzQ#q+/r.*ȑ7${RT :ȧI,H^6&,fL$GJ.m7d,O( aŒrXVb~B@t ~C w0 L@8Tla9'eH?;VWFI /zy=Ge ~ e5\Zzٜ aUu#[J=2f"FAUNp:y4(I<̝ ƴq߷8G ]>Ȧs)HۍX> @!~_;p3lve&zHzxxYw"mQ97ɉ'L\9{?=#%fЛWϫr#׮֟6ƤdG~o:Ϣ𸄄kl&$$8v,C' ~W\䝴ѻ3]'->Ɯaw7ߞX-Ɏ|pVjⱏD.ZiPX I@ 4#@F~_aPWWW$`{m.jdeNڣ~?Fx4a9w1]*c7@UMִ3c;UOљa3 +U5.Ohf,\7IKcBbI"[@ [/IKx0СfYY@@VZq8ʷTa-E9 , VCY(N_Y"E"5- W~\*s}~Ae6d @#~! @0ȼ2-tuZa ϛV4_RwͱzA)C,9P~  Б8رm~_5" @0-F@ ԭfWеfo]* h>p\@ @ 'a#s~w[VSd;}tBA'n#S虜YkٕGhgÞ(%tbc~9g(Wm<9nDc,PG<.9ղk LF 4=Di&{^ݤ3#W~K_Ej%9_oM_ekx8gĎ oEkѫڥ6R/^A6*tGĚMu5Sz\}S @ 2n[]걢WB*K&LQqHxZ'OHҎ8G4aO:yv@D~{Mm1*(@09f'(oJHHMՅYk j#1=#vA&w)1-##vd(zcWvO2 Ϣt1KF%gddćʩFދ\]'ܾi쥵t]NJHO8žq 7-'RHAw.\6Tk:vor?G#SXw\jz\LG$'¢SI1(NH~݈ Tme ˿A dE@6D>߆0 @&#'{g(yc-Ti┺sȔU[DI"Ow9G % ġkmtی{ 8)FFЏƸz Jw-h3O?oczY]MEɷj'>Cz>sݩGՏ#H9;\bdl>|wo$7ܫl GA^?/_gaG@iKGo܊;C J}|[4@EHׂ}/]X+.ir&T@=Oi@4+̱;7at|AE^ak7L:T+׎?cӓáW X79t&Em~1GҒUAݦ}*SI NlT$!럷JHp̗R!p)Ƙ'ǧ2#KmܗP$* >-1sWgWsK^BSG328T3 ;g5{ݬ9ox5 H]oWYu*SwyʴS,ܳ:'5hY@ ԐSsQLU+@,ũCQTRpDAhS~  -.hgښ%a(QUxj͠s;0KbW-UIښeJEk{}㢆U\#?8rG'qеBnL ' ì(oSpYOL!r&i :,㋕_M֕KjSزd|\e҇OmwxIc*MKPrD=P ߧB>O FTb@>̙x *&P)6ƿWwb& xI0+"fZ.^Wl +/(X8۱L*MmѴ1a!0s`"9dK3d,Oԟ{G]9[y ~S~,)yZZg|u2UT3f~ @0ts!쌚.k|[s.=ibAUNp:yu0~׳M1rQx2; oi>ǿoqԿMzٜ aUe ȿ,XϒL^aν+63>L{&p?GޑULaW~Xzz΀*wjE4& 1ʇk$ ː)_Z7@ 46*-N] 8k iB.\<{rȪmIDAT)svEq ٚMIHqnm?~+u_~NZ]~sU$D,+N\s^XRڃ[0{r:v4)kOH:d)ʙǤ߿vIN,t2]M`wLu!"/gq͋}Mm*_2J#$ 0x PWWWߨ? |H^exSx@𹂦LZ]L ؍qY/}(љa3 +5FXXg38` ˓s?(oZgqDŽ|0;D. @  R7`CͲZpd/4 Iki~C@*gTٱ/; \3#/u*R4-u+Okkʖs_>:[ia-Cq h}[4:^)LKve)H5&LG( :9Rv';Ӛgeμc"Xf 8yf{m֫ٽ4eR(7wB"@!&7O٭LVeh& {NM!ЁOk 6 @ @@O 2HE1^kV/n]26]څ;\+b7QmAq  y\r^F4Uch.#u.BoA[_Uǀ]hNFn?a%=4P֦O5zF+a̒[E6hk9hVPB}z}y!OZ3?y~`GPK 5brܷ|={=l7iN|q[g|ު~(oU;#BϬݗ%]YxWB7EO\S4z̉}y2N?nX? &"?ɾ7ڠVl8.x˙_Rꃚ~ Y804Wӿ ^^'Ѫ^$E\uZeï:_v}"U hS߯i oO7+^f|OZ\>}QB|bf-0Հ|WzNKEF[5xqYvF].XMh^߈,ӲEH"t!p_2\wפ51S 57+V.;1*/&ou6Mg_*{}x/ݶ:&ГZj=-?qi/*\̯VXYYJ[˩,yΩ*ؼFꦵHe;LZ75/ N}{u7 WOM3q?7?cuWj}Au {>ڷ5$WcdN(F=z,6:1YXmdeqYS=*no`E@(L"}~VǪr`qy,#iW5/籓iW{؆GJbUOq[yɴ̃jٶ+IIszmP.gwn}){$Ir25׵0T"m*=U= 1ӻbH֮|jp\*){xwq0qEIS H JݼLn#*:md\BGH]7e5Iv2.MD,UeܽQ#u)z\NP"蹷83:sAhbA2@ PI՝Ggҭmv,G^o"a^>Q[3NeV5Ĭ,tve.?fre)JXOHԣ/"KV h'xb.J%4/ loni7=(5]U/NʹF;]4@F/+j mka|EvY?3&:lir-t) ߫buw $elVAi봒>Һ VKu;܈`^MDuw]]SG$pFFq cjE>+g̏dfuj/Wl v+ͼ󠰩┘1zX=$\qδcD/~<ϕ;S%~Mƛ<\5J>yS~P驺z˿$A,Zx ejPSӘL *"'|Q|G^<ʇܮȻ/>+^en4 *nJ+WSEb7ac͸o.ʔпzO\ew59&6*}Zs?}nC`#sf1^ #/ ZF`Ǡ2)%.nX4OLA6ɸ!9^!(-.k= IGi4yҘ(!&Sj{ZODZ^/@J vp%7B(_-e iwv-Yۊ~%$E7O?mW R.(p=&n |q534ȶyqTRmBk! :5iwm/F ۏx+ Y.m[F[V0zzk<@ˋ[G-t+.Tݤ(Tv<.f҃Zr(Qj![ֆm.9f/gz.Yi-`~ 8"!B av-G xe,o'jGL}ϓlH ː~vg/՝jYFC`睜7V_{>j6^T+@g0udO5(zns|/[iQNgd,O3ceEuPi x0r=,LtuS{0_O7>(`1(J>2^Pߐ2ʾ_x w1e2]-6ee*\Zί@T*Ew^4ӗ| @&~~}HKfVKmx0Mof5ՊH1I.+>׸!z/*1?r+:.S䜑!zN)"YBVJFH7q"quvsXioqsguwf G[1w^qVUH}`u5Qx.ul;o.y0Vv !xh׿W1)\'Rj`Y%|HUaB́L|ϲ(73Ex(Ok ݍ^=g7us\2&z{ϚKGʢC[nT`U=}(c̝/{}k4FTd-&V_,iѕ^*>oC`n|A@m~nR1[Y*K,ݎLb !`;;}jʜԼ.o~NA9 ͯ>᜿\5s\D?<9Yck۰= ^":7DF"&hZ>ރ~cS"x˴,I%]`$| le3hdxp_8F]][G4x*5Q﹫=H5wMv5ɷsrBjmHvi8/a?*o >@G&'jh-k}-^U'34Κ_FںzREƠInj#̙Njv g.;`%@ h6p_;Kx IENDB`baron-0.10.1/docs/grammar_diff/new_grammar_for_if_cond.png000066400000000000000000000073401415427440200236030ustar00rootroot00000000000000PNG  IHDR?_)sBITOIDATx^XRFc,+>5ĠƊ CT|b,> IkBg%3*$"(!6l`"3fβSss{v9sˢވ?X/}CϾ⎽5zc X@TTTJzk7/=$$"-e{m{c'~4ˋL@`ḶjkWJU~ϕg n\^"AMntybCج; ~Y8tPkͽt~9ݖ\gs:V88@ SB[x!~I@$5^A@ @4'6raV3e oTF%]NYп#r`VL/hF0Sںܻ9>8؍J>Q&%ȖvIf<]a.AvgJvWTF7yX2;꾧 o)^ir.fϼ[*mKry[k d 7M?knf~)VbZAL@4{f*I>~xވaݦ;ee˗n$)BrOyr+!"?L]a'o7g8j! Ա:SҥqB]~`@=@oq1P wb*FPm5\1T{+7i0gDIS/MAd?AwH%bdN:'o۝ϾBN.LKJ؜tچPiuТ_{{TeE$\ 6b~˟Z/S\HK[  mrŎ QSeqOS#׀xjVQ/Eo>XgѹܡWh`_́ %F6֞LN$~#Gk~Թ.?:wYm%#qqr p  `+Fls㗉Wwc%Ck>:Έ.R.q,xEFQƜ {Xp*e?p\@ ^n|itW"3EjNc]Ԯ_GuތMo$˷ےЋ¿e9ŪJyRlWdf;kOWf'ĺzʍdžʫ?}N~JU}&'[g6C6rW5mbFe̊S k|Ώm!ٝNXzs͘^(5$.duf?P4Wֳ餺T]sҒbi &"., : S9 Fs1^JB%h^਻~ G>#$@47+ > #HIj+1PL M9WWQ#8p@lw a㋚((8c:mei{'w"a}b]i' X:\@<KiuY - kG++ٞ%w2>Kq#ppi*9(=Z "gh{/ưsFf8b'|4#ػәQy҄b E͇ -s=b|U9l3ڲ`\IPr ͔C÷,zZ<_uXRr&D֔Bxm◹] ](=E67Jc#B`8TP4jxۇV`vS{ۻHwzy8Ԭ\G<9|MI<_g;:3#u[TJxXߋ:Ir-nLnM>[&r+0)?h j^{hrFs^p먎]N?\>k}](,1#{K#GЁӈ񎾂0vI(zd!MR-^}c9>UU{:=I]~2Eq{}$VY@4>>9QWknğ6_C49YҊ) /^~hݻg*n1-r>!F xz֛{G埇o3uΪ07%dJӣ;@H+'=6y'MNU^l Zz1)~uS =GL.H$^Gv(3M4>{5=4!9'Yx` ]Sd/DVcRYG3S ?\(+Oy˻K%@3x>z{草b3O_PNYĄ!&׃%ctX';ᯡ)Wzi{h?ܴjis㈙-#mIAvln7O(@s:^g9ϜBhٕrD6=7@ch?*(@ FH$N2Zna@wͨeFqs;%l9erfH*K9k+a QyQxY% ,0!f+Hj-pԠ w_Tɕ\Yn^dͪ߷+ۺ߷ZVr@3"`ŹfD 0e߄:>Fx#"Rz%7"@ l6:p6"aJ2y/^kRIENDB`baron-0.10.1/docs/grammar_diff/new_lambda_grammar.png000066400000000000000000001136531415427440200225610ustar00rootroot00000000000000PNG  IHDRI4jsBITO IDATx^wx׽0)ۛj$DƢ#@v}}nr\$Ͻ;v{ym6vLQD3E !$Ҫ^g7+ l |9=|JgΙA\ }S{f    pO3m6tD'6[(H l2BL&pߍ6>Lnq6(8wVsLKϬ-DqSd}G=DAnTgz-)"v B@@. Uf.ŀm[%yk>, E-~}eHi6]kz$KnHIغu /OoT_h}uo),4uՋJwfbSb[:|o=Z"v%0=/4RoUYX_m`?BB l G$_V{fAӅ2w=J0|4,b={-Rd:gYE]qC!›v\6/g0%L5% VdܹK#CEWybv"^ɦ+gOhf{t嶱xA_?1UHBں))q}F Hb'*N[pHQcCI+r5P9ˌD/ޯ2Y/lHh3|tȵ~v Oݔ* x{AMb)+VO hCznGQ$O#սLeV*"ssQ[:RWC0{"Su RAY䪑B5 VDW݆ VxB.p"z*OkY[.ڙk%^_F$YtOapbzqԖ8]٩C#E ]     S@ ='fњng8p~sӓ%@k%U{ (jsuQYM:|tȣP_zNAT䲸SL$͈cmãCFnRljR%'N |'Bzamܿ­-|כ^K}ƻFYe L,AA@@@@` ,={g?Գo7;j5 ߹w=a7FЎcmKo=-hz/bovSk4Y?86BE[V%/>F6M^D lY""m5'([KuC=E(Nk$1YLlDP^WsS_jYPJ #jŢX:YW/PfznLW{0eR׃~2vj膩[/w!qIa<(3N􅔐tЕvgm,#[IOg_+&B{ԎE7>)K}tW~[,+{A@@@@@a^;?1_ckЉ#l@0gަ ݮ* &IuLb|ދBPYoGCehlBx`eDId@KHepp]'#+2d} 'aX)ǾB+iy+Rd6XaYqa}|Ǐ^籐%+ο(@"aXM}Sv}YC_i|͊JyMWb o+"GAcrk1ڨ|8F(WL? `'i5Y)1!OPDYm?*9v|0n}_: lWDx :/M[̉E㱖}&X/ \pM~_JN]'ǁZ8p$"U):#px\̪LT8=)M2Z!`e+ }]FѳoKu̜G#'l^:׫B-X5H!z&yROs[77.'~D &V<%Z-m@!8ʓ'f+֦azc)z]:fܦTT<?L6='2itv"VYR@Uh,Χ!2Tœ!3^&Dr*P&ݕROփݿ89!Rw\9n@!et>8Ȕw}2ӟ۴vC]iv#uHua׽mOordݍ.(baQadh; dHkks+,RV}_Ņqs枚+fl[ xP׀ll7յ3Z̵%47WjB䋝!;_32cv۶m"?NhymCf zʍ53Bu<6 &?ܺpS-0g@v14 @@b   ` _U   @ kNj   p       ]]JRV(j18{xg=(/.cf,=eerW=DtȁSdryʏ]VEV;uN2P|z&3'xGLiMtmtmVZrߧ&Iޔ-OR:1^ A,PY#WIKV/|Vukf\I.M_9tkE<2X; k w,y>i _W֚^XX]ܠ)+ griڻA     0B#V5)Up6#/>=h(sy;q`ny-O,)>Ow E> Ŧl}Ũ+'v0 R})],y#*^cvT{d;lX8d`|8    &4â$a G{](2 ,>wEK|E^~Z7 z?1qB OE7nQDO}4*N[pHQcsUUޘCõu;\T ?%w&IΆ䮛pEXS606er, qQ¤QSY0lEI+r5P9ˌD/ޯ28Zrf/I.CMmG{))q}F a?҃NzT =۝?lL]GY*};XC_ӕB+fΔ 0^U[Q\7`j#)i;.0ן>GJpzuis},9瑱J?_h2]2z5VT);;f2     8,ZS"r>/%n*_ybw>sffuoYWY#.4|u -##T)s핧>hs?dс.NOB8aAR)Zu sG]!;opIjRe}U8[z' /*M*W{y,0oњ}m,tfAvd׹û:ŜƑ㏎90N]J~e:'ŃVryc-3>d?ۥ0pkK>%"E8ߙmC0(D2\h7{wf /IenZ    @c{G+y0}gu`T$ Pу6'5,zqo Iː}3 ",#]/e8륽0ivfNRDc^uMӃ6=( FIf(_E,ˇ0kU0K͓;J8B% =K{5<4P[ 1|l1pЪs0NkϗcIn Svy!8't^ 3Qî]p|?|{ (wѫ[DC/oF98,[+X~Y (nv2w-<Ui5Y)FA!ʑ1K7y=@02twbeǏ^),dIJOJo:^ L_a,F51x9w?ƍJށ|rlIo<Okq䂌{{(`SM'elΝ~T\gNQ0)i ]ʐ@ZVː ](<|_sФ\_JN]'d0&CМ1\bo$ҏĊGUk@K T5fA4:T+[jT8=)MCG9!8 SfG#Mj+Bj;ۇ%ʙ!8=&Ǎ^#On ~T$͔[Z=?cA@@@@Li NH\"uP)fk}+'2=gs4U?=oA9ڬ۲q2\_v۱ѣ~ׇeeR xdybwVwkK<:X]|mXXT7,9 EEdK' 47WǤ:YEpC wz1em۶J'_!3X|/ wztl Yw~wga|9A@@@@cJ*{XA}]PQ{" (ܓ¡PC   p0ADD'OObY@@@@@@@ =&Iem'.93?"\ U~\|x0ɎVWrxIwvW`scG^ظ Ge}i~IjXs=es+&Ɏ/l岥%?C`bHUM fE`}5ӔC<<nxX;lȔ"u=*H^5s\ڊ3G"6c;>}A^Qȵj7RZ䮛pEXSv˰q"潼{t6^T =}t ;HFh~JyB>xؚ|#Id͏,X&㢄I}aʚށf%K8ao͹NO[pHQ3Jx~ÙP.EޏxX "־V}8NXteuz4c;)؞hMQȹ?%n*_ybwB0Q霺Zuih 6f$*u9}-l!qIjRe}%"E8 S49E]2|jgL!XLz2#2`G>oE>n G& \xK@2C*#gygߞov\jNsN==ψJ $eӴS<!mЌ=\R8}սDZsԄq,Poi0&Jxf˺8Gnl38kN;T&qXOvAhkۺ6"=-h+ERH& qfQ@M_jqn3RO-zvf ԏ,&NW]0)[mw^W~[361OA/L=ǯ\ (pqp !QztlYIyZRbmr@ݐP.j|c}ț5C+X]qv;yE/gʆ4Qyr #r;0ͽV)Qqb-'W\),dIJ#Uf'hxH\iW(Ւe,~JCK8OO K`2ԇ\y^7O~$VԶ mMl}ygv  ;bgǿo۶m~;AZ|ۯ@@@`zYCϕ~ՙ*W~O 8]%M]&K͊n&]jɂΚ)uYŴæVBzUhb4[{|LL]uyjc<Y5}zz*&VH9F +`o$ҏĊGU~=C} 3l&/('2呸;ӟ۴vC,}3l      c%R]ubvIc吆%򅏾-nP^Kԫf/wߟ,15`3ͫCu-:!',}ʤ 8tE.*t- ^;ݱd͓OCN8vbaQadh; dm#(7"qnb)}=~kz؞4>'^r[6NY.|Az묕{}esfdBpdV 8?D(&{9`%К|Q 0Ȃ K.Lr <&Bh&К|BC._N;nSF g#@@@@@.@?\Jڻ'2ϕpʦ-?[ĻW'( @{T8-F{d PեtOʆBA@1y2Xwkޞz!W!xC7;ȆIya}lžSL!ަHI"DFLP`'j#WIKV/|Ve{{U/*ԇE1c558|sVaQ}.M_9t [d?OvᒸΜ5=DA,ڞʋΐ@@@@@Vyb}̊*wiya|%sJv_FC>/>ÃEu3IJŦ+u@ <aQcﰅ#S Y=y9 Ąɸ(aRߨ,i"ܤks؀eF"͗NWPn%9eHuBO?O9kkm7bU,s|*E!hIϖ^+AUsҞ^+;ut$섏U~JyB>xЁ+&N(\3[ 6</g3*H^5s\ڊ8:}mVr֫Kۜ cqrp:M7Kq3uWEkRD'8M+O8JWwQԜ ;wnySg~ҐbBڤ{0I2n&Yraޢ5C,X̂Ȯswu9K7'`#0g=5=6xsx„GxAXp鷯a/)JMՀӐ4;ؤ国-̭]hbVׯLԝx*U[8O{@nm7WۜYs[Mx!vr[!@@@@@@@c{nGtUY.ᙫ6 +v\ dpFhk5:{ZeDM_ jłh,AYyb8SCPrWIa>QLliNQߞpAD]훣]E#Ý~/yZogXC8wX.Ow JgYU; 4%(EkﶸeI(D2\h7{tGQ+^=S٪      8wa^;?1_ d`OGI3s"BkZD"H5EQ(62]NZu#S`ǧ9(railYc.d:/ME{[?\2O~Džѫ/+sg+5*qG1*TV[`8rPux ˘YXHBhUuW9.tmx^:/swa׏Nt?8|.{ _r@$(pqp !Q$L}W>+iy4!V?GFܗ[NSXȒkGvĕ8I'Os演:P'z䅂;:U{>QpWq" }:LJ;dq"߸4ȮFoc{w|G}{"{񐸌͹ӮTIQ^2;imR[R>,Q ilrzcُ.-?T^YýÑ?iX71riѡ!._HF,u.[4{[ J׮꒦.O s F nVoq г r>H$eXfQBoAsp@@@%R]ubvɭNw,YcubaQadh; dvz5h DcLhn(x5J`=&N|zT!, d> e.{٧|pK(>$)/>*#C4N y˧MZP* A@@ ﷿\ o#$ Ll@Iy~`9oMg5ZK]ysӤL/j+Gja5߸zGOz‰l:ۅ=g pdgaQ}~AEKSW-QHZ ԓ%v=ؼ=/4RSuXwɩ_}rV)`>"pܡjn1NKDൣעw6tHf̓w4(@@@@@(w‘)E^T4]i.1REv] ]zvo6lPV/j<䱂l'r7JYJ,I^PV5ِuS tǢT6+E)fu}uEIƆ`Gpټ bd\0oT4 [Y2-WcsH*Zbt6wEK|E^~Z7 z3 kf+x+iy\>ۗSd6XaYqu?=EP2"mn 3x_0(G",w.()>*Vfa9quBTtʍo jybf,#{~r - |h%;Ҥ؇wmx0}G|BӭFRp^ՆDB_@b^*5]J`MZk-e.p?p>/ \pCw'uO1+3U:]=ө

~Tx|(b.D*%QG?'Ԅ(^N/F;Sf]*ƽ)nn\N"Ŭ>=0NOJH+g?0Py:4giz 1Hvy:i]%M]&;ߟ7+y6zp/N nUlvfʭMwI     @@4'$.:5o]+eW ZOo&G:xm|eϓ9yߝ6[љ/mM0k9ڬ۲q2\_vہ6W]T,,*כl` c.K*',}ʤ 8.*ӄ,}s~]U?=]^w|G_p Zp\C|ʢn1C]6ݼ:T|vѯT\n`Mkk/Գ(HVNҵYxiɩ~v)N.B]_*Ȍnڶm_wB˛o2LP y% _mp8 g?C$p-4@@./ @@@ٯ*]@W`pQe       p Ly{77w+ o8s 6*W0cc?4Яm͋쩦4^53-G_;t~Lq!m$KrT      4D@&@kȮ_ۧ(b3Y[rVU+L֬ͩ!E;[#8lM /L+'ݶ&?XOZ51\n/yow 3Zq(*b[)sS>l'Y↽ֲ֩6KI絭YϤI7-l6tAT/_յb'=A(lQUt| gʎՑ ݝE9?,|jI '    S^ _k|wJMXcWW~[_W^^EQ9 j_v΍J8qᆫmrI~{`gC_\,zg~VpoOY;z ('b8z_[/Vu[cPqxwܚ~CKR+m9a·?K^aZfSBCԌhZ@vm`syPWFg!PϞ#BA@@@@a|<b&)YB(lM=A6X gj: 컬Okfwplڙeۤ=*ܐl?vYeqQu|eDĬ}Uk4Nx+9{|!!܏>pÜkF_] cc5 xLJ#b滦V1\F IHﰌ~XPnZ}P~+>[lz77$͋tLs<^+a֝aPZ .Mʨ6ل" ]0#%SOVB'3;{|)m3Du|&\@/Q$o7Qi:ǃ6vrAA 0 y+D~w p\|@0&:)B^ Gr&_:.۹gYscCqq\L#zXڂ3QX5R،;R=Mzp`,-0?ZLuT&>Ѩ(XJ\aIG<' k* ϫ=qKبKg`(]/79~{ʤGZk-e.p?p>/ \mL FqLz 6_ۜ*PMˎpb&,Rv~L:MM W ,8('mz#`r$Q%0D IDATer?M{_ t}jYG!ʇZ[F;I BܻCX 6o߯7 5&Q{`d8V3 Ec(U'bf [@Zn\.7=HǮzMoԫ:mL2֟,8XwR V\n5x('%:bݴQY,Gfunm%Z_E?mGp&z@xxr@mيu^3hy0iިEzr^q1\R]ԌT+MWggv&rLTK#@HR9q=>?g@ֵܰ;g^LI?:'J/~&NؕE]UCߵضm;;ͷA@@&(0y ?N=%3iF>̼-Uem4gv,z<}?P̏lϟycP*Y@@` ҫ4OQS=P;=|1={)ze&i3z+ V+U!+&{:5ԑ%\ƞ >@Q c .'%;Z _b      0_D540חVfwcSQ)|e^~,WzT!3D@&@kȮ_ۧ](b3Y[rVU+C>oڜ*R)=2Hz+7쵷 NuEk$|۩?~h>lc~&%_эI+s~&&5Me5naF$sV~` M^[\$~Cpz{K0;cQ"/T^+,R}S]{@@@@@@c{L{Eʭۄmo/Û0T ~aNTo{uߵҫc(ՕUf醗W%mчC'u}γhsC-kW=QN4q<٪=x$O<`D눐>mxॽnٿnJ/V}`F_?jz7Fj??)_6oaM_8g}:ٖw6mg9؜IÁb>fm0n)H     ApM>*ܐl?vYel=UGW1~Ց;{Fuo o̭㟛ey}$--Y)iB:3EW"KQ^C ڙe[^o;,&J:gn=[vsELa^G8Ϋ}26hiw}-vT׹iV?EJJ law"@@@@@#q0t\Xʨ6ل" =2IPN3?E ZϑHB1qя ]%cpq}a/DSuѵA o%zLI^ [{'g~sCҼHb k]}񆤯NQePȅ)R3dua3 ia<>ޮo1   U\>k&w#@>=٤ΉSz„\SvnEˑB:j\"tT"⣙GaIϮklCѯܦI׻N} GĽvYaإqqXJcM^a~NOv5s{տqo^1Z#X#McuB<bpb/ \pM>?]>1rC/U &}tpʁ}X +OOcfqv؍8tfȭJ_ۜ*PMˎpb&,Ry(bg4gdWٴo^s{}.s{տqP.OYF 7HkF/1AXhތoދ      0eGHOnAܸ\on{_t'/~>]y׀ٮzMoԫ:mϑyozD/sBDenώ"fيRzjT+%e7]\c8P<,BCq?Ks{^]~և!8+|Io^i0X#jwgVe}⭢߆#CMlR L]DŽu\.wb&wOqG\[a ;@@wŮ/22c۶mjϿZ|ۯ@@@`ɟ`p8@] kߜgtygϧF 2uE%ک~(  p (>=>jT@@@`Lmڃ<1uEֶ5p *T @@@ &?@@@@@@@o+:sef9Μ7|]}> gv,zl) ϖ}(<reH__QOS<ȿ_:ױ\6zg6,evGeJp&kw\/o r~ |ҿT~&sWИF@lFYzUfNje`x8:]o;;R %k4Ry4לS**[E;E;s=P3F_߭=^{L`vx`a      `;B'%;Z >AY, @@@@@@c{<$YϤI7-#J+c֣Z =2WkbRùT_VfD2gᗹ t^eHͥPI7$/ G{׿)[}0Qgf席uW  ~GP {J*ask[^[3v7,&AJbHH[swk[(rxMK_W ;+ BtpU]W-:$[.aFEW%{~&_Ou z+=uL1ZsG bԟ@W$⸺zBoڜ*R)=2iD}az^91E'B}c-ukAN1J&/n8@@@@L@hrl[5 ^_71T ~aN> '[Yϖ~_HGq>'?ˆw-57 L_yC'üЦ ,D>,2K7/i>l" >{ֿtߛwrr"5^kӘr4FWu]XgsR~bu__hΞEzsst}V~ނY?c|BEǧ~zAc NHGG=[lj:)Mp좉D8</i(sqt .NBē J(MN9!ϿhQ?"[ 'u}γhsC>._@d$$m4J7 -2?_mgT ('7xIC$}H76p\h@c{BS0L%ZTf[;I7* :)lwǽN\6KENJHkt=B!ӗ[hZDpzunЁs@NzuӋp^N^E4g#,Cdxj#xioE}&u,E{ƐkM'5*OׯIOCx:8pOJy(*iɲGtZnnmo\b!Vۥ;yߺ,<_m/,].6ьnÏh`sas9LΘ ]xgⳳ?,dXWA͗\}qX=8|"(UWQݽ=GO"IWh.w E%e$kXL7vڹboU󱯏W~:M! v|n0ɴ(W7cN(<`*fбZvM a|1ΨgvltӘ {QWL{Z{H2/76" |5f'ԧo<.µzz;Qumof2&Z҃*C7YL1ϗĖŘsˁjQ̠  @ͺB*O}wgV65&vom)v8_{UxC\v`M7FE+T|iYfn<ɒ2B%KSܬsu-X*NN^y fT76r4oݰ:]{1،WN-JZCݼk*&L**&'ha:J}:.-8sBi 3&S%EMcl[<_4K+TwYmphY uʓc{ӫ עE~B֒e6a @:nbH[_ x$JnnӺ7w{ ]##D?H%p;@ @9v {r.+5i@׹B}y,J>sե ,x~bD Z \=x즵zv hl=ΒuH*K nx~C d@!wh5ƀ!@ @hn\Mn (@ @ @b@[@1^zp ^+ @ 8 8u  @ @$}W  @ :;N]@ @ > @l>@ @CEϷ8S '7xbp[C$*n<~=`uqr U?Ǹ) @|0^d*>/ۮO7k-ZdMB YK٤@F9 @ ha۷p@@ @ IbFہ@ @0[x @ $7 @ z{ئڀ`"@ `#Kkm,ā@f'0~HG3/4(  `|h@ @ 6[Qa^'N/9¼n`Am'qׯ<7ǺB%So^+\ۉM_k__w~{u7 ?t>G4tIyeIeǿG_p^+1[UmI-j?h񁫉qz5.K@hk5T[3}Z=@?Oh,-b /DTzjmMeOC_6sfmd p|]-OQЉK"VOW Yͤw_C8lz^\6ջ\f2oy=iO| ސT4/Ӵ q݃y_9>ݺ{qzJ{muJO Lh*{ ̕f;z^C?'Xy@ Xk2Ac 3. x𢼒1]IH۱>'U}ph# 'Z8׌8n |迷w'*::tFgn>f{y\\B\rjJRBMy>+Xc/QgP}1M0 a=s/{ŅߞsBL-Ӕ~1oC:bsŮ?䣮Oׅ9L' IDAT{ms*DOL|OˎSzԴd7vx#?HǪ޶17[Hu周[dFnCdx%#˹{WjRS|>0~D%޹i3"t"&%5)N"? /%yVe~~c5@?_H!w'0 | 4@uTYЬjJi^"~G?&K.|?'ez.ѩzLi'<~i+cnXu=mStMƸ0n|7'$:=ueZ6$#>EWvoJxvs!ҿ4`e^ yS":yݖi?3vY)뜭kƽ=*"J{`zȹ"?w(l0DhR~~BU݁~B}tnV~~B]&I~B}( @tKƼ6}1%:Bǎ!S(8NwPʂzUǭڭۋKC*S+~"MEG.]FU^}H2;Mj& CQz7*Pe 뫧/0?NS'uy (bo?WG4|`vV+@K7[+Iy<9N8r*߹q䞥/Iɓed幙J #wsZB25^"{8C{.ꈊ_ә>o1k  к0?OhLM5w~B51'4B?a. `@홴r1{·(ώHs/ĭ ײq{|w7eM&vGdyzaT/{0ܯf4fmKqWuQU+&Ӆl:dlwn.t zNtl$ej77W-kty¢O ?XDte2?}E߉%n"1Җ ;2iWm@ԛ zClO'49B?a. `@#c{bחThGLԤ_e yjՁ-N? S,NwkbulBy_N8rXYt]8ʇg6ukR~q+OBYTguoJѳPsY(uڙkGN_bDYcs-fk=ru~4SJmaV`{c"8xuREr*Y sngf|eXxmf7 x [{]{Ǭ&a! @hZO Uvz>(8c\+#z9c2!}*lx.BJ-IUk鼺z\|oU~x7û Q,=g~5Ю滭$*1m@ lsо${ wz(JxxPNNO[ck=Fgh:VKy i6cDyڇ&{yG .;yBl9zPGF@x7'Hc2e knOh7 4@b{C;}1Ǘ4,[z{.͔SR|~\|gTs_Jj/Xh~Ͱ=&WRNB{-}0g;ItW5Ō=M뗭ՕgwhO_;Iýiɼܺr Mi<?ǎoX`v*:p.\ uFHO[hY'Z;$ɿG8 @-8j='l-2 -EQ{鵔P.@ @ PCb{h @ ?z/|;nwmzq=vW~=~qaKdc 015/^uT* {chĮ[/qiyGk,/0 @{!_W3@t: Zn[߅̓4ܦc<..S3"- NG|~>. @[ }[% @y`N2/[k @>[ 5@ @G!{z"Pz`o=EHOڲ?Eĝ\8$ls<.7@zL\>~\^LJb ẓ\F 4r>>'~莮۸E_ `U`6 oFoZt/GhMzC3 Ӵ@f8Y¤+_kQ$-^y6^#8/^G-' O|eQj&5gcՑF `Dů{d)5ϷyBr!RsUw:]2m'C3s|6ynڂ^.= sxA!Wi:^gN\gH[q^S?XXoW|Id ˞J9VcGIݳ]/9\'r 1Y,OE3 ~5;(@M9mx m<+IMѭ~CD EPW';.)KN͕1Ƌ#xEƿvO8r!]Ic $!Mpw7l 2} -fc{\5\O*/^W҃!ʬ #"_2ӵ3.:T]"1``Huez͈0gߗtG~I-#I,UP`?IR]O 3䖼KÉs6T[WP*\/7K\IXBPA]Yl*/)Yz3Lf^˺KU w5~BzzǏ\EPEمJYw3jp @{rCF߳"y? t 8Ix{[0{W1䆏R#$r\3qlrBէ\^7I6 B{!K)A1}QJB sP^Qk|Q0ޜ~b%n@`h &:\ŴUeE,g(U1;L̡)'/yuAz"#!ic\}z-إafc& GA8NQ, kjLKJEhbJ0 !.(SAP i2#qG+SLd1b7'Am@bD]lunL8_=@{x@󴇺%6[ }W_T;pǜ)E?[wx~קOLs)7?VHL9!H0e0)/#DV+ &*VD k11>i>QQ()jc7\?sR%<ysdY#r_:-H(dՄYoܮ&ݠǷѮwՇ;q,#pM"TJ݉ aZ`VS=bAW,;"T}t>z#=Tl⹈97ħTw#L ]X{y՛Qk҂ c,stxS/Ry+>Bo'1Hfruwwx-[3u!N^0XT76r4o0z7spuJ5WL0LiHo;篽*xvR4sIO*y\RfU?{nizgVqry_Λ^oWR?z'ߜC/8Cjo*͗yiH@0|tqrgr#[A h]M'd g'Ed~M۫pk5~qw8#o! |0 @ @9mL  pU-6nq+}Hi W[Oc7ـNȫ2U`IC CH<"ڸ_ Z"[/zB@t0'5x @͜Z?9v#`^kl0@,߲t @ %}c @ Z=K/>_Ssc7 [^$k'Y\v/Ƕ]_L=@J-e&-?2x?>jB3R֓ބ'XD곳ߺ:$P^}I%nmii+-L1Թ\_uw=NcV9@E  hc4E}puq = NG|~δ+w^LXO~^u>iaSJ*+(MzEn<% !>obAo _loy;W[  `/fG -Buyzx-b#Pһ^P hU oU h.|4ƻ3ɱ}sZ%=lNʡ'ظnڙ^`zm0)NIlo5arN>3r ]2+ '۟X(l\1~VGi2n#4qtXi=FMxޝ 0gM,YB[ +adUZbW蹼s/"/Wk+vgGka2Ҽr{N;>pȅ7RF%G֣|+&˼u|O4FyeŜ;q*s~y鯆,RXY!SQJ-Mp+bwaQ2cۻ|zÖ>Z,|qމ& _0D&^hPUY|gfAO삛ha۷p@@ :uO•,F{#7O(YN@I W _tyʴutu8l xJi nxl27_ [{{9qFpor<L#v䖑߷ӧ:$ѥUat~+R3qggg WEIz羖<,e^0i$zpLQ{׃Y$_?F;?<ֶ@ y4sP@ ЁiO+* J_Qt"F`'2nYڒJRzLJԔ ҝbx?Vyl~1NSs})Hw2ΞR/䳥C6fYkꉒHciWSt\XbޑoתJx /*BsA*-"I\})]F9;c,L`?X=)RhFFo''L2h+]<옋!|z4HL8J:MșB=UuIR]O 3mYM[U2BWk _[o<2@4F䆌2k#1'7s؈Yޓ{RJEZ2K?7 9fc]: )]5At|Rd:rL S|q"Ra%-;wǛQ̎(bzᏅ9s0H1 L)")mʐn(0ujDlGL^25NVmn^ӹKLk`(Z:dzFHM Xڂ%+FrhWw 26\\wM }Xar  4*O&qZF*8px5 4O{[b3P&D7UzܤrvL79q,+rD")QJUI;ѧmן L_ooRݠ9Zq'uIFC!\l@DL/ΧGO ׫le?u3IDAT^`V xD/ϤE]/rlW'n{U* UCQXT76r4oݰ:]{1،WN-JZCݼk*&L7xQEēm#3l]GO~Cq]0mO4DdR%@۷:@@.h;/.v KpLjK9  F2FC@ @ @ 1 hbؚZYą-/~vC#N$3׼b{ =-0b-xcwϸ<â#XRbTQ;-?2x?>j_"MxŪE{ߎ_/6v߯;įJ6 DqL1Թ\_uw=NlPګ Q: I @ ,#ϬhUۉ±S;F9|+9ݲ'm8 1l?rń.i9n][fV-6 h,>DAl+z( >Z4!>obAo _lopȅ7RF%GͶ7gWLya">jui8ϣˊ9&vTd. _ Y2Bv (3}З冺CzL\>~\^LJb zۅAh'|}\|xN?s)#pʜOv@m|Ȱ ŧ)?p 1/Ϩ *<$NY8! ؾ U @_$\Rj$o7r)%;7\7|I+}=117k㑷+-s0W~%l}suɠsGIZlF2q_*ؑ[F*zwOĒ,|ןN"$ӖOXTẕr*FhErߤK[ٮY~[9֢3џlLՎ]\E,΃9V[)5\|A\Vdz>$@CPLAӗFO  Xdtfo쀠Un=3G˴EU_] 6ic]AƟ{&Y'Wv3-\{ |{4-%iNmlξ1Ws N@v C_Ys<;;;?|X*L?a)ztIsW$s]6v" ^`auV2>KkWiv9 s03P Z%$TR\/EzS7?qF= |k/Eg]F|篥rߟ 9ou۳t,D7 6RhtQc|iO$x]qǒ@K@ "@]J<$(}Eщsȸ!^V^fjK*JE%2R+KRS~*Kw>[ѳ8%KOݓB"' ݑ_oHR+;{:KأײJqSZ?)wٰc?~*+.\ҡ%<}L~Uӕ|`Ƭ2+qbMk%XG]-T^,;M{ZU/PZ^[cU;Q%E7U$/(gg 3eRR?^JUͨhZdVv )/;bqU$&Ls Huez%&v~CqL^̺}R j$).CEɶ,ɦ*?w+f-7<+IMѭ~CD1aU6ߘ/X"g+a"j)/#DV3 <8RQbH0i81@ & @JY^2f$pŨ^J'n+Z E%e$kX4{z:-'"& !=.ycj`w A.M١%drLC8F섀<؃GEZ=םFCOK>N,UJȡ[Zv`ˆa}ȱg:J|lAOa`B;] $b#RkFaf>$ Si* mnM u!,Tg3˛O߹:xZ\{6ݻ| jǫ @4}=k /zT#x%ejJԹYK[ޙU@^9evzcTpBHW ʓOA.FV~ k.Ry+>Bo'13lG_qsH"\M:YެzFL"ӋsᕇeK{/4;eERf7opZJI-k,^TQ1>E[ S)\}5˓W!-n&*/-a+V5f<]_wzj;VGƯ!B/fNazGU8_>:S_,k%=;b'r/^q F%!ǍB. wsN䶯ꉲkkwpzaޡiz]Y~ʩc)tsȔ%3ٔ^uˌ[#oޔe'_䒊GoG_-_<1gnit2`< U`*p|< uP_)\2jov` p8؝ы^:j8. 4pNs:X @شiY#|B"@ 4rwgh@ @ EHgEIENDB`baron-0.10.1/docs/grammar_diff/no_more_backquote_syntax.png000066400000000000000000000326411415427440200240610ustar00rootroot00000000000000PNG  IHDR<;sBITO IDATx^ \T20)(b&/ q/+-3qMZZV)(B" (0 o7 y>w߹|9{}+RzCr*4(,Om۶Z5n@'vBD^Raޭyhg7W(~,\P @`KP)@ Pcc\6b4@4DhfE@&Nt>^B @:k @ @jhA;ΞwYP0wgZѷEp8,eZU﯉xYUzpNbJJ$g&Lf uvuC|,6gÅ\o/1|Z5 TkP7zM8.CN5o gs~xs7JFDFQa;7Z.U+W_l&*{~rWot6.нWc*Ϭ2Md馻=?)e fy%W /׸ƋUo,1dlȯ7fT.@]$eNz/ifJ?7NcGJ׏o P T@-Wwbۼ>k1p4U +6v"W|ZyYp;57<@ uT~_VOMq5 ڹ7S⣂NfɾtyJmD"56T.GOir'8_Gv/[gTbreռnD\ckZf/fۉrKeb0ZZr;5qvFKp:Ϳx7xj뒹M'g?wg#j7"0wڅoؕӢG}B#Eo_\3}^}h-p'6)%9萵c\49[H>ݒ<\IJII4Mq/5`XuNSwl 1TG<@ ~P;1ko5 0깡)SX7{×9\ hPasνkۓ4xAv4 ziQad?R=,n.\yzc)';WI4HWH_^ 壐#iצxnd<'#|>=]ivyB=m{Muՠ}z|7 `;Mm`OJn6FYQSs.O3q ,,:7!^}f{ DCAV=\3R.]zzM"Mk2a43b)p7Nڥ; (ͧ:gF.0[(k.n%s.n& ̳#dU`\!(,3Ϯ:Ω?fҘt07aTTr;ΌAW(gK AX}s{r(Jȿu%횷]~`Uxy$yq7) m{+6,xRqFՋ/0Cjݢ]VTaf\t oѼ՛.HJp!D p6p~K( [[X܊<̀} ~ o+pj7˿;f%q83D׸I~% _-AoVt"1FPuBF&[F*$ iDGL >W$Jmf "AC,8ɆW-S !4A {~ɚCqP-͕j'r~WQy Ы>s`Y_Z?|\ʑwr}88GE$ 4n(@!~pC7~[ \@ C[}0Q6On3 IN炽*F`?JjF8vv`Kc D*5zN)K#{:a"22o2 _FrxnRIH6iL=P4=Q^Z\B D47!7?M9xe?J- DYvmZ Ǿ@+XiVW?Ї=j֑U(u[QiUhaj|5FHrTv-HjŮS~nq 9tISˡn@}~DU5 p2A  (=lI IoJ[\,s7Y*/d`~|Vm^Ǯ7q#:2_v>>t 0 aZk$c~X>va"36sMтla}ؖE=|$o3ө.uimǏ@0`6udj3a^7-\9.On pgRE$鶐Igt>}rPJUT ]9u0U?n| GS;T[>=ϡ|^מa. FRD~~w  PNpgjk}ůvfFCp杋#Y]tD<()N/7ήG'2!)_k ՗R#V,-W>3/ i䮿/9=iH8_>j-ۄ, _9!pջZުastlUW §?0؋YwPd|rJ 7W/;Q{GZ]>L,jc%hKNIJmJ{=P~n1z,> gF>Ɋ&pfB) ~_KIQ vGE e*ojdfI܆O{^*o9ɚ7c&Y ߕDx{. #W.ko{~$Cr*,./OۥYq8Zqq=DHyDnǨ Y->TMhߚЃ{e]XDثwBU}:dc_0DG5@LL!olձ5}1hE-*L6.L &7N-b~%=pPg)dy깹s+@T[~8 L#DvӌR9CwȎX7Ӻu溏lUv_V+Bw7grYS ,}I< Pp+-jmnumo ~j#߯J>'D$@WW%@45ڈ`K@ @4<#kO =4[Wpe. =!Xԫ2$Or\ߪ[mQYlB\' g=ԩRӷ>;,)1?@ %25_lh7rt@ahA;K|J^AVn|O"|;3)L1Yn'⨀W#oxۘSqs?XE])S'K>~I2^_{oW.-@@?.zrL p @lK~ h7FhL{cmNǙD_6J09("::_js1aOD%ܹ% ;x?I)ɉFU1  j7"0P]z+$3ʩZag*/|pzMŝ-*|T8puMD)6|9j'=&;_Zx8yq=_}tÙO}Z}w>oxMgW3m/s3 @ ;onF3kv 0@vZ09 %:y;U32C #E;|"~Dtd{-oČ˸;3\G$Z8pb/}"EN̸.hλ}.p婊# _- &U$HkZ+ZHHs^]6p@4--E @=be^9&:p؈J @3!~_Iw3F ڍ L"hμs1qw!kxfOrBrrCߌr ̺Ә"S.oz񌲉j=rKon)m儔䈕v%_7I4reٕ4%_$:eW/9y')%>)Ytm ?;tʆg,W=+Ęd{篺R;X @F@_iJ *@]]]> u? c$պZڣ6>@𿓉F& T\- T%W>lʩ\݅z qaK-]EVow(^0t~4p ڵk%{n]oVajZ؀g_Sp?M )M2VEXWaqa" (Tq|5ռn@&H~ClTu. @IA&5 ^H ƻsZʎ:xznm[/~M]_-D3EQ @C$P_EN@ lDW_^ @ F@NBy.cYr=yW(pa ^2|M˺EtiF{e#g˅pNɢ]l=ptO=o nծQ,51@q7ː֧f}3] 5X %zK|5/2.:rL읿cŠeJ(_Lnkٹ_{lQůtӣo:Sw+uQ?-`EhN"u@ P;k֗z%Y Ze2Bmu"W|r@yTidok.=p3@4%Rkl }QAA F1^PHbvԪ㤵)վmإv#ão$VJפ껍^bLRJJ}mPq+ї9Lpqq))) ?M/6F} ùF\߾fwx{bRY;ƥdDT-΅mt zmwlj:{ي?OtHzLx,"&vJ7بǬ?n\Vlz5/hSMoY  z/FԇAU f+D=$\qpw ]zgt* 6ܿfxyy=90IT1p*4o>KcܱWyNqc}5g־G[ϭz|f:~]E#{-٭ϤmkFЋcjad?R=*"ݻN)\Z۳gS? `fP nUMWr  ꍀsL~uU `@ډ;|"~DtV,xnV7R"{nO]Rwo4y7]H:/B] =m n;*#Tѻw%:+Ӄ*e<.IK5PbhשU.pq(zxv{h:T8I~&yiދ4BWS<L&U7ɰ׾l定Bzu75v']ؗf5_qB5 $iϥY&?~*) @c!PuAʺr"V4S$bryM"6ϲ,'*i^qJ)r2$Р#;sReq},O;[OU Z S|Sy;yֹ?gm|Oʯw~MSWH$8E DG*ct9˿;ւ%q񸚊1ghWWӸZ>dJ ]gUmyS5r@ }}Tnx @٭TD,!Bgڳc r js 5C4,{kr6|պiVν%Iէ (̖P"W;6F[[P1a =j֑U(u[*/=_mÙ:[UϘu~7uęG$s^ŕ^?neƿc҃Ug:QV;W=l_5skn@> 4x֣_Z1"Ȓb6:ٴGw3YMde wAs.\y=,s7Dz*/d`~|;ݖRBIj2̰?"/MIDATb]6G mc[:c[/%+'=+$Swޣo%A^aI[ier16q U@l5t/}R׌ @0E֟fuZ3IoV c{$3''MLs$X|~(ItGˮ_rNRJ|oSڳavhμs1qw!k'/8Xlҽ+0{S\!pu1+E'$\ys 7k|fGN_S/CDfȪic|ۙ{ȏb˝F1ZN.H@O>IAA @յy+X;x]g~M{YDY?o?Uiw/djY=X$m*Պ!B fo'*/ٯZg'?]uOZ uyx.*8u@`ڵZOz.IF7v0P~=@*hpŚڦ|שkWLxpzꘗ\H*L6.umYNeo ^>7l|#:]?Qbjgc6 +  @ МW }cjT_urjz61xPpEq}<9y'~}> 'ވ..C{s4k{]. .';׹v6#gq8Al~n |W/qiH #+F}k}:PUC[_j{"&]ЕCR׷Ⱦ_c &ҕO3(.5틥xl@F~VD{[ٶk6ҡm w]y}*g4gncY#'6wַ-n&=Q>5&#(]y^+&=ўK5 >3i~y{7{עiwDjMͼ$D՛|I+OMpF{܎6h~z`&3\d ֹ|tD|'x"cb YW~wofKg/XZfڋY?ZuϫTӂ o +<=E=P>ⱺգ·[ }Fdc!k7tz) h\'ɂJ"H#ƝӶ(~U7.#u(RVxReiTz4P NCґ#y~[^euGHќ77f'+@&^߹mJ}r rRDSH@9m@Gq*_Br蓭>~ qnWV|Jml3dעIaA؎(B ݆'wKXHN1%58 q̸A%)vKE$KƈɼW:RgLBsnYpU&Z|Ć|eO%An6B&[%mPDJ^;RVU5^f;cPTXpڱ,N𭺰l׫'cmzR*S<16uI3u'I,j#]?ku9 eOE(Dn* w`e_ZOh:[OSƕJ%l>#I E;ꂔb&Y 3"^ p[o]@ttY'ヅgEfny"dGJku(e%;MBd  ) cww d?TΛHd#֚B^Yex¿7d&\4U8٠*ktmJo4橼KY! ˈϤ LJ/o%eOLzBZ){圧|4 /'МvuՙEjb1%[j@8Ytq=B*N#Yq G#Y(_hEY1sEr vG xTۓ`yߒ^=+0֦->  "X],ƀ(ODY(IF%s`X2>٠WGM`m@BPϞjo1aDi <M礬44팔zϊF6BIWvrvi6_#JRTXT aJj ۽`b0uCv-2.o,m\OvjMEO BBQQ;R6]m S5j/\KE.I=ÄCJ&?l f1uU6iՙ\]w]&Rd L u;#EN޹]v|N#<*^6|Xy2wT*C_jŠ}*blu s΢8BGP_9:Tx7tz堝^e5WLcnyE h,S+RÛֻŒ>E^t'RTS1Wgk\m[Jؑ5Oo*~_6ѣ9zod}yUdA%f0s0~ ]u}Ȧ-og_5q)h>v s qBT8DGi)zբgj9/­)EC!hr~ Y1Z!f<QVȅͷHIAKwQ$ sOq>WOvjסv˾ KGj_shq:h yE*šO>} zl)z,-shqNu( lq!pM/Fҫ~>-5gF Q>P|;kLwSIQ#t~ @ ꄀW܁Z; bGw<@0WG<](sEQA{۬4GYƶ pq K2Ū tfx7_Y>gφ”٧G9bԂ((^U5Os7 % 'MOUnT}uiH~hB4Ӌ&īDz+k"$7Vu!bZQZ&-;=_Un}&ﷲ)TKwLىBP^-2tkSvF=-yJXelj,J|bXLq؅gJBIlFfF"*z|xCBvPB7e^zS]Wێ(Y3@Cf2](v֣_$cUN<AbSfsڭWC9oU'֛lŴ-w7xul_HJ~try dYƒibڳ4 p߉|%u*<{?w,]g23'r &}-řbNFɣʳ[s8<#Cpͤb,Z@$irE+%zGsg@l;GѩȗӘiNIATֳ?^>4SHZ陈:9novbTEW9 ?c9<*9ZPS~senH-TcXWSnx4eNg "nnfX<@}[u7!m=Hfq_Y^gQ1W|uSw$2'~y,)1>Kh҆4ӧe7gt6r،BdLɽ{C[>Ts Wr9*NFR&AY>z wYӻ_I&$QEӗPp9SՃ$ƌ*"s.is%(rYЮGfoS_xViR"Ĥ`ޚoq,XI'F)'pjypa8C vuOH}/rʗOTH'#suB^r}ד0 GTv_j!hG*IwY6w+C0DN4˟x"%yx9RWGrٟɛOíҧ*L<yP̓5YOƍ/~k$wߩ_ݦWwXP);i+t3e)52 ͋L(mvoB}To*`/ F-Ws3d) A^5!V?G1q)d\Ybk㰋 o/,rdq QһȗGxoIA1ވ2E=J ߜV̐cߺjًv"0_Qٞ"E IENDB`baron-0.10.1/docs/grammar_diff/no_more_commat_in_execption_close.png000066400000000000000000000123151415427440200257020ustar00rootroot00000000000000PNG  IHDR:rsBITOIDATx^ \TϽ3sgeD6YL QAq,05|Vai嫞eeK(";203~}ga0:>{~s!f OEƵ cA6mo01zK GڞO۞9* `p}vW)4gw7W 9"I`Ȃ0v>׫E''J-Y3ً " " "8>$:W mx-HboK.I.\"}'UiP E%vzB-l_nfz y9& "w[..l_gZ{/:Ywdw5W%:׶v|ϼsڽUH*"`?Rq=G'ěٟÝ'8Vg[(]ZkZWn3lVe_+s#-tد{jMwO-PƦ9:io׋fco>V.~w4L緥0ʷ^v$葝y<>-IOMq-=S*9ǽCguĕ 1`Gv#Д=eЌ{&Y6 9=]#.>Y~0 4W`㋏\-"'!B $L#2fB& ʂ8 !hT@Z8d,e!PޘgWR@D! r?a.z @;uS||)/?1pDe:W}Bg 3RuL3tCؚ4&>m; 0*j{/#t:v/.w,p̢vCtx_]< dw|Az8g"kse S{zqq"C;R T4`u'7l:]E׼{\2].y~q!h]u_QJB2Jxܐ㛿l Ft \'>Kx)DCcI#\2Nΐg_d #,qtsh0[pnE9LԳ2W$\ޥE%=~\r$wϟ)5ei9MQD  .}Yx3̠ .lfQef4Ž111}춆"s=”.I)I-[1 *ij&] p|orz@>tnf{ 5 ) @F~-7XV[ Lj@b/|QoNإ X3W9 LBWbwcVMj fS"Ԅ,O$zkCKDIW(ΗFe;g.O5OZ~״ [v_);yf31%]+|t0O+ po}*/i$8]KhP.c> '/}{ƽJs5G}Oač3e 1 pmNJSn`Á F e{D'1|!Cr LA#Kcu@x 0=7\Itƀr"e$FJ,T8'E~ڣ![=k=S2̟Qmj<^@2o#4Xm`\ҿ;=#z+FEՅj|]\P\oSʩ_R>+1a>әQ>~9o:N}] rOtT(:M$՝nuz |4ʍ mA鹍'glwF cs=zg I]y oxnm;9ҩdYΞ"ffcv/Ђ+>uh.|PMz{j2Ӌ?u^nY󩪠'rc ^ϱRSsdP x\ 3ˁTg7*[{wj|%D}=9w OHjp-[T ֩Ji~FB˹D(% $EÙgorԏm(l|$js[QQ]P#GW-jQ_Ӄ .`D w^jH9vڏ#@;F~+| ;۬'W];b5w=C8\|P r!7߹@{ `ip_Í=q*1L'[u{@ڜ9bc],l>UFʥ/rf'W-ac64xJYy`(A,IXY}{Fpn§nn]elNdIra(@x+| uᢠ,*'X&<'#?tL,57 puެuF9VZ2wP:… ۬q2̿yM9Q%6M`{_V*AzQ O@mўQ1"H0PiX A|l U[_,,5uR'u$PHWD믬G[ li@_ە|!Ϛ){oN'TM= /`'/TshυcIŜ'VV\&[HtxQ)Pjήr#. Z4#0-1'gm;S*)%nufc(z Y@ӳ%\B8' R1:5@S`fՙ@K54kҥ!I<ƾ En8= vձ9Nuz7pn0ddUBt^I$310yO`zOѫs̿F֗o'mMNyxnb=ƨeၴSyrq \Oj̪xi`Gޠ)@!(35V`\bx䜗zUw[7p˃]r\{7r(Ӌ#z{qAS7(YNVWi]\{iY.t?zu r|,Ζ•e۠NKQΥO\- da -`c4(JgU:./}O>ҚvPGNt6N:w8iw1tWqRBj40y-!}B:p͕,D,өg'U4JNqg/3OM5$Mi)ô/F-6ŠD^5RYY5nE4Q.#JKەD̦Ig/Ί$b8؈Ĩ`O ~  `^wP{UsUΒv]roe" j)DmSpKtiqpc#-rIjFEW%OyFf֮й~A3"tvv؂EnQA7_y;Un"g> 0E,&YUnE`S j<)~g夆wLŰW>6 6 'xǎq%{yڦlQ:yӮE;@#o{΀b ߚ'}ck{Xc\^y=y-8&! ŒҌ9>!ަ)o ::.B6U59E2"?"TFz:LU E 4a7@t%d,')=' cUq*G*siC`ɂzT*/\">*C ~/]j @ @h-x/JS'lf({h^JͰw]?cr;9  (BBu21Ǫx @:\Rug]|&Pw9:@nyp2? @]Pk"%@ @׮OH<+}x%xg- {p?R;(zǻϦ:}ϪUO<;9{yu>_.*|Xԇj\;my'Ei ng|_y07%\('ϖ,1bO6X B@|wOn[iz֖Uf~(?Ψ()ZrS'pOW:vjQẗwˍC[;?5nWG|0h,\LyiɧF%y8,UEC0lq|Qb_V% on˧yS{Bk? @Z3WHvQTu)2)I_ fsH xy|9{'9޻|!ގb@ Ccsu>ZF^Heu}^4/&1R`l%E>8U-5d"+e͛7ɤCpJ5剋K*iq3c?`{A9M'͋yfZa3ZիƶIIAU2ˉ. HZ;"}%GH# F;oe+B$}ߓ2m-(-(va!~x2"Q?Bl;w.cŐ YgfەsVv|UfR6.ݜWLh篞:zIO@Lt3oK+.|'/[2Mohb,/|QJ&?2_ ՚~*x{ǹL~lo33Axۓ?z eMi'y mn󉰌Q @<6Wy:>~_6iZ7,2YyVI~A*͜skP5bF˯s?)K7M RȈo]&<=*|٠9_SAdƕBS|Pʸ_,Yq<Ө:»s0wDzG7z~s/k]-.0.zXO0xҪ9|Z6P}+-RWۿgd c?]o%aÖ~xh&/{ӎ ӅFMW^{):Pi>77zف=>spp&  @' ~u~a[j14HpBXnzNRc@G ˝* LMv֞<}&MW_nk/PwTWWڬNJl?^acƪ:]@V? ԕ~XM7-5ؼ6 .cqΊύ N1[厳`)C u#`=;|;Ȕr'm5%[ngܴsű}zƾ/ۏCgkjUDvpgKVV?^n@ .]WhSoSQs_ߖq6Ge"4:&L]eETMi}Y}J,QIh_BtU=7jJ8GƔHkӫ%9>-ڪ6( ǼB};-B;Ҵg.nvv5lhXT"KE"Kk#eE]ny/HƑhTP/7w5Ty$zokq %l od[;RʧƄOP-ɈOdl&_Mùa<9YQͥ 5uUj=\y.ŵ8K ]2\) @ #""Ʈ_5}/ -ԃ ~4ztzЃN+@i%cMz+g _iގ͜:IY?`65| S9=[;O%'' BQ*.MT!@hv劋.u]# EvXbW,( @@:\]:y`75%f5Dׅ5rR8t] PdbO?nu @:\Rut&U;W '؝S}8t磠[.uđ4 @ &|!@ @# p.׭]yVKgL[r'wl߽aQ>;UUzq}4&8é>߂6a46zo}_p4F^Ȼ|#c7y!.-`\f9"9@Ʋի?B>mY[NW&yG%?)大"N|5vطg(:fƁrw1%NC[;?5nWWޙ;NcE݉cn`ZwǍ㻓[:}Oh fA @ H3WԾE4Zk6cWt)I_ 5QKc|y}O%oԁ @ ж#}NOꚛ^4/&1R`l%E>8U-5d"+e7ɤC.&)մ'./WK͌1K뒀e*\bpj7k4R1Y|ȋ>РE|`60)~+C_)OҼg6c\jr5l^+^x .LR]\t"\VvL)(\^+BmC=5^r`>k|7|R>yy|RAFjPĴ~rrbk<+[N( @ ঀw2Og&M뮈#~V='rUҫ_aBhpy}-KVb=>]{d#eo=^&!>iM;}z}eKiV1:)=~^Y7I),`9?/u.9屿IwiŸws_s 7o9)e/Jr8iL?ݹU ۋ˹KǗXX q$! 3y&F/v & @ t[ vbh:/yX{(HΩ71uLNcu~|K; =??^r]g7* 3ky 4m2O->o>/OE&;kO ]_}suC @ ]Wçަ<}-?+gcZkݫXPZd(j2;Ռ>c0zXT NsL6Zb}g/3/{ҡub4rǘ8.p~yow )wI8ā,)VJj27s'ٌUNi4yA(' Z#ݵ.gkM߹NK:`uCq R1&@ ,I܁8>9;*],H P$IiCzL81^yqdGGwO @xL3ںƦf5&|KD2bIW]v T@tؼ][FiKrV?><{ZjjX<ř=oO#%P㩌3 =4^N9/P87Kİ @gȈWFn.@i%cMz+g 9nUfMۤx[tJhUq*GgQѡ>ɂT {IAQ hWx[8"to ѦEB @Lsuvo,n~vLyqpskA9 Ѕ!:t  @; t qڙ3ph玄C<8Tw/} @^{{;C @u7 ܃ge^܁ @]Zs.=H @AAC!@ @K `ޥA @=(=8h2 @ tiջ"9@ @:A>t Cя Ym5Qp\8dDD?2WFM@<"*Ncg[6*:T8w&W*.MT!@hv劋.?Kk 'h=AIENDB`baron-0.10.1/docs/grammar_diff/nonlocal_statement.png000066400000000000000000000320661415427440200226510ustar00rootroot00000000000000PNG  IHDRh2zsBITO IDATx^|Ew]zBo"R ȇ(MH((h@^CBMBJڥ\o/Fn6>37ofwv @i4LѠgM]H{Y+a9Eak1FkNeҘuxشi)qlXM|y1rV(2ҷe,Qk09V mp LR3pd2-Τ(E(3/Ȓ#4f 7wu^09V:q57k\3^T>pnկ{~SHbOyS3Eo4NG@c7靄h>)MmozZ_Ll|h[F @Ib^R7aP$ 7>B $ @$ @$ @$&N[=?1UH^K92O;fWx%ZL:[**&4^h=9P3&P]8S%5bl-;:>>>DϪi{6Pn/.xfw |%wǴVLəl5i% ՌCZ:ǔCXvZr:XŴuYTۡ^һKw56kY㧰vz1S}vm:;V- SLe_#*[%gj~s+MLS}1܆9q-ZtLPPCPKKޚs' Y y0m'L 88;X);3[3L79߱RBmbޗt;t8dI*0`ӬK~f∾o ya'LܚDP htYoNww,ƴmti)S4ab0ߙj0Ֆ @LwB_&%eI岒BqeaSh$4N[frkq1ѕ?#Îs/Ww{{^3SM[|7\1iw 9O~Y#^pƥL oKefaꖓa]1v$f㛫?jfM8B}b̍m[9롗vf_^]O|o>~R|Yd/j?x;GT]_ԥu˷8}v_ tr3RtN[7:Ke¦3aq1aM5̀OX`KqQ@r!Z}P;a*t9c|Ѝ;7N@ܹݪK-/j$ՍE9i}:KdEdGI\Y Ցop%;m= 滊Zg`+엨6|g]|Wʇa-cdFw>C̐겦r5}i/6QʥirCs'AO/A%h\M\%s8Oڗb~)w}xؖڤGG~?Jf^QNj~B'@sjX!l‘>= fx{̖;'3r~:ُ>sڞN!o7w˥jvć]%$a %P]yqsB%F.Ϗۦ(7Nt,Ū}E \zN;uݻi;vIxTm>0Eb#}NWנ~m;a3؉|g]|W aRݿ}D穴pR}fçO\(xPOHo@Sg)͌-.[ڧ΍K/.HJK).NKZ{R6E3Bs f}Oz\gohJYi%d 4&ǐz\.O<_i[ڎ5K]ivW+?':+#<{>c[WE'\(I}_V@ꅏAx&4KTiӥُ ں},M8lρ4I=f /|w]nphX1$ > /A#5@י2.PznǙ2\s]1.C7㛭wXRj~U2^!)f>G*SBp۹V(Tl0ݭC>`9\6|Լ[nuR, n5@>ԨW/N̠~-MĚbR(֎"ݏP; C{)AhDڕ~ T 9І/\.)&mu]>&ruH^o;'"Y7O MW;'_ PM\nv^R穻$noAVj>G0c1&!|WM2/T'3LAN1fзo_[_"zܫC">ڵxO\FnfEI\$pl(֚U,6r6ytԩ$w.վa8KfӢX(PfЫ2qsPvWNE\x"~9E96>]Gh̲oޗ ׯOg.b]>byO5؋Dzj3qNOӱojqpfrkH`\dAhdK7M)MPkh"]%P  3i°THSV?\q{}2M MGUjf@/IVٷkBQKΞXazԿ ܮx+*.>:x}<)cz??|eTHNC?g:˝a䣰Ӌ]G^.ޮBgc4iEQv+^^J?{GE\5 !QAٿ>|\{־\x Jɤ1| ۳`mHaMX ^^'n=vర{ 4.`8jAhGT 6v讋Ξ$NR[hh;Șh_;Hrǐ>vTc~{3O-gֱا79[#kr?+ /;R/[ڵf?9y0T!@Qp*3`02m'@}JK D4 w@4'`CӮA`H>'r~ `l^Pԗh2B5.4n=_m\yR_t^])[רMY׎f&shd>fM6,cRmwϛ7Q B/+02wZ&iĴI̓a 7C#mW&aXՖ1׀>0~%$ @D;K-+$ '`'^q5UZswj4\>dzi5IR<. GӍW},l5ZAmW J./jry\<.lKFj4*24 @ օ֚/3WޡC -=յ nP Ԇ^[KZvS*, H H  "'N 8>s]槷각\qN^W=nO9Y~Y3תּ--*ajߘ:>_ku_4Oxhp 29DdvVx@Ԟ?0l# Ó,l)QV^nTuן1>oL]\:V}1mhk0fK~2ԯ1HjwKmJӔ_}\zܕ<#[̙ZvӤ5vPSxxu/|e{:fϔS}ѽ S;},sQn.pD;OKW 6J1fu#c~z?wYfoiՉ lz:ysY.Qs8cӥ)OAAʩҚrCPA3&6w nz5^;b7qt Ogߺ~bWx& ,'0^Z퐮Prʫwb+sB\R͂'J{WzBgN?.;_~/XC 9OB:aQS6wFv`3C̐Ԑyx JRZ].HwD L#Y35ߋ>yJ\Z~EÝnm}[9EΧt0&KS-[1΋&R]u\>xJgNmBGW) }F(hr"9Su5C!p&ejHjP c[6: ~32 e˩;^9kg(gz%yNL۲Є྅D@O@NC{f;/16Hʦ>/RkI/T,7ttAX˖'NfK̊;,3m {𣾂E}T~yjF,9]6 JllV:!E]ݏIOEU:rN .~}¾Ƕzv=-{bʪԀRiKYQJBR+9XȹI=M"$.%b;y]Z*#Fd+ !duv.Beg5`G$ӊC*Ks8X.-;z9'VןA=$܈+O_jyvgH@/u:bȣ8%Zpn@ iSdwwJkEnHU.궔IX* 76cx}]wxaBĹkw?[6si߷ 7N5|Ta?8_|dMmNӎ<|QD(ͪAp}tB4Ged*,R/Qhwķ;˩7P{rByL:uZ HS:ORTjI;bڰ Kgp8WPiu=(PIKE4so?(qDr/UJ^[ƵvFI?`:I*h@I'80̕P*umI|7BD^P| .WnBKKޤx:ӬAV.‿ =I-*^@[`i#D6D&q 5<%ae2$dک&uh$E vEd]&ul榽c Dv @ ,G˾׋u@1sXLD8ĤP w2UՃc-ZPJw_рQH0/`6'$5Э?C1EIG'T©1=fG+->l;`:u2Q>Kn8 b7he'W%(^;3;W|>_YWU@ݚ'(HeCֳFzeHyYeҜ|YI{Qs\-"^->&r O%kWJAQKBQh.k %r\[na1?-/R'{N/!rώz4WL9*ېTG`*e !`[5D۽[Cr$}*=ѷO%4/=ˋ dkvͥPi)"_ޭwRy{ǵ!qGsЌo^֐E#a1 )$@'Ɠԓ&wz!a I9uXUG d̗S?+;Xu*@Ӹĝy r }b;H4g\l09E@쾼#姘`Rb) ۷/rN{EZv%*Ain _V&cn֍oX2U9ݯ+zt{ϏT"dIx^ ](޿8co"ޔ 2۱[B6J rMT-h#{L-52+{%99*+6 sWY2aZ*cd1fӴ= xAˉ[wa(K۱75+5|0i'3c}W=55<[w"+pDsƲE#Ef; ahz:BЁ/lFȻULn gIDAT&RbgK'rGvXЎZ >=zǻ>ߝ?I$YlGc Ⴉ)aE.Ԥ &M5?a) j;rDҀ"j.zuvŤ g=ç7#0e"ܧ!O.Z >{뿚>sm tiFsYF=+vZҤ] m>zjuޅ= 8PO1sajIF#*շ0R&kؒYMN3KƯ<Ɩ%D=:Wm} A? qs]]5ř|k%s"NvQD!M)ho>,XO// ߼ȏvkCm(~v3c v(`u)ݜ{{lհ 1aDk.'=8J2\S{|g82dq C uYbd"xd!~aw y{o.InR5S w``.!RN x/R}uRmpĉbz^ ڕw3 `E'̵7ЀL=9SUkw&Xum덲Eb*b쳩?ou߂4ѿ|2HgJ5_dbApjO͹8Qa鎒0N״.:%qlXMe͛g*BaD]Y7; ,&00ӉaVƟ0x-ÙsCq5/4L=EAf!}[6vn@9mW4 `'o=gM`$PN; &P}s.qy_2 ,ݾirkAZ5\xw3NwtWέGߙPǟ:׷ivm<%&pt5-磺vpjWկf ҌӃJFlt5hD/ ?n:?m^ʢ%u4 @$`Y::lKlMB$zHo4RxhWx=TTi]mB$ @$ @ xkpTׄ}H;jC4v֭ۚc/XBs/fk^l9}uDl;L6zZpG><1[Aî}u~|xlQAC@nQa$ @ k2|Ѻu_Mj+ 8wu^-CcCHj_زϵ-sMTlաkǍ~|S>86BwFS{oel}S⸵942f)j3 ]ea;1eɘϰASG}?4qCK6&Bk[*/jWPLY7U^en!r~c>Ct-!ĩV:  FLyW"A*69GyC?3&M,eσO5bX0Bk5=鏌j}.-.; q{VBQbӭ>lz;ZmcZs6"QF'\"C0O&360Bgtn lZ9!WΣNGd 15w~#4>0bH HC3ՕcvL̕fc>}F ig]&FWd4/"e] G;>`w"4IPNlǺEנ=N]8@UmXxz{nao ,٭F̏hށn@rJlD3k;RybSψut(s[9Mvb}m(Y1yv"G4us ..s q[֧c5MNYBTF_NrAvޫ۾u'I7cJ+#W"c?pzps{/& զu_WMCE.{%n]}+-. [2U\<_T]_]Jb_ +˭@R(([sQ0428qjdÅ Hz6 ArT$ܩKF8ƾb#<&id) 5駹|69QI ];6-AlqH~FRp^~6hc{%3aG?AUArl|R+1HH]$Δ)S%$UWr/>ucJ~Tl@ffRO|-W˟cE$GـFlբ7'hHW2[ i/oJQgl qq>i]uJf ˻ȈJq\ȍJ,m]ϊPAn|y^6N`\%h2K Dc-oY/q0EQoXLTƘL-5qp; ,M6 ]Jq d|smvf˩|.7E4qlO|;2W%rwtmm2WȋI^#j yu}`$I*SBsnʢ36Y7y+cSOcFmU G>oY7NDxNދ]?+6f(37)\-CX\)lFDԔsWVV."!aN'§2'Qw6Xݾao UxvL2dZk)hߡQ-,^,ǥ r(u/\xY?*pJ%_Ã5 ?Q vDEFM>z߸wP{4  H,M []ҨR7nlBW)u`{sjD-лu00A\$= HIdΐMPۇ "SSE{5TQ=@kA Kh75J-QZaIf:U\a`^}񨩇F6P(JeF&Zؚ:ls>[1lW;eR% -dsd!lf¢ Rd\Rj n<>ş#!*c&HIøoyޓַor@zeqNcVMq78u߀)M: 8,n?̈v.r.S_fv)'mlMb 4^Tݺ]aqw_(kPh Ch`$ @ zj_ )_=~<8ck9!=+kz׽ۻ e|XSywRHS 4`l8;.N_^'om͢ËYqsʥ "}@~Уҩ=XaF`fg;<8W_dL }(IITF&Y7ԇKjR3ӶK5y)9[];"yqˣ*iދ O \wQW}Onͬ"iZ N{0|d*) @$ @@#@~ƴv yDEŽ4tiA-H*8q Hn =x(u T7IHSuFv7L-5ҜrG0FIlK%=4$ @MhYR=ڠ H'`t?7  H H #4MIENDB`baron-0.10.1/docs/grammar_diff/print_function.png000066400000000000000000001110161415427440200220120ustar00rootroot00000000000000PNG  IHDR~OsBITO IDATx^]XGQAD4^ ػh4[Q{/Ak4 A@AED)(;G8gěofi;899Q;ʒPC3ҧt㒇"q]뮵 yx .ķ:0%IًmEԀ(Rhtmi8'=.t eB2Qc'+R{ҥ ef+$1?jLQ5?6 Pij}59d+˗mkg̛q||UJ=0J7%sF*V^"_%adkd/u ה4b:L?сYxA!Yu.~n.\WzM-/E ebeΤ/y _ ?6嵷J9M-/E# p\)_0:HIcW_M^aF5 ?+ @ ͛jdTDpth, d2 @ prځi1Ro=]yz(yoTaeچ8\zNOhqèo6O V੥_S#mf%O98npOz7vaafV&_Q~v!Vs0@Kc" hUl^s@q9QZdbƙ{=VN=g6~]Q~NE?jilßޖS>F'iX峤!J8^;z. W*]f-| STk}>HZͯ$4E] :ZgQRWGQiͥ)F~Kz١wν&lظE>WR{PX)ôy7r%n}m4pSԮ'Q GrT\DT4 q>\F!sgmʁ>6^Vc/CH9)=  zIx IRdRʇ^xK$}ӈj419 LXnWbV~J-2a%> F~kOy}ef6jqLTaQ^g’y얪K+B}h6ngfkQ~:UEz K?e nP?*yNS\máV7K H}#[Ki,w\r5hN|:V8Lq{7} -],WbQ%fHه$])nT'mM\9=mxJWGha֐ ]"sP8:ByKG ;K[^MTӰeu6d|yYO<=_.e]= h0׷$A6֑=b JIB.da{^ leMzHӵ٫_,`Uf.?u`ѨqJWJ jjg0##O.dpK+\+"x5+G{>/C1JGⴠ>1v~?kRAPs˵+K/N! _B׵0009kI3)6AA9նV8x~U$ Omm2 [rDU]r&=_79cSs[_21ڡٻxM`_ke?_%WInYHɏX!݁tEEzԮA88%?)q^ IN'KMW&+JM]{\낝geH ;TAvEX@q(P8|U.?\bǾ |x]9,tLvˑ;fΙϬ hU aw O]CDQyjqrv)/?]$vBw,/9Pc9?=Ra{n횬=f1$QV#8kn@„i7.us78qz7b 36ҡcʗb(qNZNqqfzIl~QN&i# S x OBt[0U[J O^7&H*)fQAոm%!g&$7^ :taK/_,r4&/%ҢdNw⩝XUh(0JI^L6 v%8I 2U̽;L'((-s!OR^,ŌP?(лVu-SiZNiwCGRWERR,dk})[qQR|ߑ#?@N1*0i rGRٺ,$0aa_R7F j]#P(D4]) `Eb-}*I9eڶ65-c&D5MVR<F[Fx?asn r"+$L8􏊲j\Qʫ=Wv톉 zUI.- $Z>"%=;}inf̎链>p# KA8gታdb4˖u"]U YeBO2>Q㭨b,pУi+_7P0_|T%}QJN):ilIeJgO#ajcW] NHH*h;%O+ ,ԗm Ciln8$MFB4uKkmҬʫ5*GPYȀ&0No8$ @ $~0d@I$IJ _ @ d2Q':o =쬭N:.:.g^ܝgv\)fr\*@{͍IVEz7t%_pg* ƄN~W ?e+Ecmo͜!QN\ee𶜪-Ue5ҨMd!MUfծ&rSIA h[BwѪR8JWCV< DJGQyxSKQE󫨼Zf@)UKQ$ZvP)֪{d)aZswܰbP'mM4RUAC*8*_i$[<HC"ͯBo XiZb!z)ӊSh&}gt.qb2nhG~) A @ .Fmĺrǯ[\$@a=tHhgJ L65dWYjBnVGնhbI9 /=!!9+WR[ @9z5%EF |YXR&a3o𳗱ju:Ax)(:6dk|LwhC/gT,&.+}rvOubW=#FcY7mɱ~/f8ν$S\[ %XuQx 76:"}t0'MYHVCcѡ79R6N ong"ܷV7.j^;A^*JSufPW/n mIz7]Bzva]ٺ84aٍZ{.7%]tIWG4= 9G>.Hޔ(VTQGG̰g"Iiƛuդt>qˊRj'vJ!Os],X4*E%GmiUh2|-9qzkWC]>a qDhꪖ|gdjϥt\liUF9UTQ.?Y}ԩ_#wE* #f tZ23] -1RV;gLz)NЉÓd.#{*Cw~oWr-j=ܕq _R7 n=崘y[ [P+E qآoF+QC9p~̂^ٌ{#>.xg9 Na_KcOwߕ$ " xC [jL-[P*^%H+jF2˭n>>g2_MhB4$?Ng)U/)AG9}q؋,QA3߱\ g>,jM&{mZ}~FؤϹ >(ֵ/?SQYO,_&% $"nhD +Ny%#{U8hO "=OB\*.:^z [Il0;F][(|C\h@̋{vquċ9lo3[%nG|wDr~S@V6@y+S|1rUPKFOѻ2B絋٥3bQS|9vjYq$*SOqߢĝ ʣ:&\4? ~;?q87)1eZ$lI ÖL>?GR9uC,$z?q&8IеX:gď/P@=@j m9B6:LͭuQnIqFk2sKt 13|͘+ 4!)?2g)LߚC| Tm3czQxau) !aFuޕzˇO{2|<)+E-QQAZ>>Jy`puВ/JgT(K)o4})P"BG]*s`z֦C$KWrŸ,>0S^i)NYD\rzܳ\g*|Qj`ΤVG#HpҐ˶fqx)zcw|jIT1N GVg70lF/fs#N(@HR`#nVNw7bi9:($ [ iE,:ۊ?EiRʈ{ 5hյ9Kт|ե4q?Ě괛0;Gr_ZgZt_ Du[y ``B^qD+T (J`;s9nʼck IDAT5LEqfZ5Aj=eg6 S..& ?59}Mudk6KLioHCmQc:HǮ4I{~w~fε/: | JlX9܎MzG&s?q87)V-GW> VӂY8D )T-3{+6KKߺIݰ7~42 #"6RBIts0vK֮mw.M~Jxv-[C|埨w-Ju~vWPhh_M }vws:.~)t~yuf[rꗫc>#b<;;e^~꽪ݗOj;42忯kn$W(#VT@P0~au-zo(nx~|T0Rhs-#Ž8/{Rc:B'2|S;ş|?*662sH;C-8{vl1{vI#Y &^p#MoA×>fp o`Gt yPKueJ@?Ӳſ[G dQ`i@Z>m+G_899)XMPrqC2e?D[{Aoe T ߞkqg)~ە5o;I ٬"!?J'ԩydj2dwwܘD*V.]JL͖ Q: #,)S# ?T6}['H}}osB !0 y{"a!]ʤ ߁ @`GȂ3 1O1g74`_?jOtqPRvxxS=O{ɳǰ-sxIg|Vq^,l@ ?%W}T8Z&VL58]aśM_ JG}+o+gWUY؛ /T<6֗|>d!mX\6pe 5 @ _-pW[0d2 @ @1^ugohh.kkZvn8 P'USx0cl$ ;7&=C zEw[v6YSR/γo̍a,t9EhtQf*~dxfF:)i~,U?(F#-IUD6_0bơ&_n6Ym9e(x2iPglW_1[@hCz6 Nq!='Aҽ{ QW =,6/8DԔ_~dD&@1d^3Aa=)}]h(έ7P_*^ۺo6z`%Q®! pb/OɠtQfnm6U} 0-zO]V0.Od5!_BB5 NclIá,cGQ(|ɊF}4T̔4-j`v^i=tiEGOe\1CDTzwyJB7\֨!uNα]iRrC`LH,/7ςFן{sŬGc=&yj´qٲRud=´Jbw:mj/:Hmr*P \.U3X`RNKOHH/P%~07~D,x.9)!orG^TN r_@"Uf߰3?8.]nGP7;=|pvIONb4uӖd t= FG{2s/? ~||Գ~זݧ;ס׮sKAѱA'&[Ӏ .`A]{@QAG8C?{ PEҔN'ajk1[K|$72}z[2P9͢PmV=~si^wyrCoYs*r{$4r@<+3{x? ~sO~ühB|Di=ǛJ+ o ?wh\ҎMFүl1o^wĖ5[r]C0+yh&㑾Vf30vxYVV=k}/_=~ͳѦRBCXq yv|"|i?V/NaUhvsnG]wdr~_c \Cn " >uWhTf\ Jx_ԧ3ғQί`Y0p"{/a҇,=qWp> lkxҪZlRfIfȢCr1] WZ>38۲C'O !;;,Gт!y\#@Dhꪖ|gdj%|kҞSg.ďD1%.}xڰ Kv Rz*^^y/2gWSE|7Dw~oWr-j=ܕq rmA8S(ptٲߔ B~?bI @ER%_D?Moq 15qu6"E:YQ M?W+s1 ߓ3'\|[#-lvssҷ#F{Ze /z/{u8vq?e#ii@sRY}wtIEQӌB6YiӁZ7ǰwA6".^2U0,]ƶN{*5*T 8!joS~ϹN4J.?s f W>4mճEv.ݑv)=FyG _:ŏaьIr{k#i4H4G9}q؋,AS6XLp|1iC<B3b^{O#EŜY7{O-޿lr?8[1xN3Z m|>&()L| IDީV:mؤϹ >(ֵ'Y/|c֭MJQXTTQ-FiT 3_lԵE2hO "=O+ pdIev(L{cޢ- ,d4tE׼0D<21մkcrD~K.}Zf^J NPH)kef;ɩB&3; 8Ŋ3SI2FL?>j+G/O65HLs*|3,oz/舨iѱ[6ƨ@Hk`Qj$`~*`?&ݿm3el |rD7|l+F%z}*罺p# >#8P,] x(A ,`r Ю`9dΩ 4<<;ǓbB1)o PB+l?lUcQVOju :i~'$m+i}!(Z.9lV+L.W7i}TTU'QCH&aЫLͭuQnIʹ{ouuJOw&j~ 岽?>_M( ?FNB6|`pe+[ൗo3dBF*oߵqHQBL1R>WRQb J5M3I(0Z\ηtKcHe2W]Ei>(EJ28:h450C\pBA FJnTS#,/c]/.MU,Hzdo`c>)@E-TKJ(-uJ>޿C XJ0>AOmhFLGΞ=|-ږ(J xՒpVtG+'$/ZB֯!PQzcwY9&Q :E(DಷiKs=[_TiO)ж0b"f`c@}$?G|@ngʋ GI'ʜ+Q;ܺQGyGVIX|q FTtMH%7p},cݒCZq]H~o8:T_m<7c~eU'6T)>mސ t=t6vi6l͊kI_ttEwʱj65i7uaawLY$ِb`B^qD+,.H-k֤o.av+\1 0?/΍O۸t+;,G|$wKzUS_{T,=UӎCPd\^d; 3纘ө*7 ?(XwPuEѻJ \7/'I2"D}VEmm=8I~jzQ}d5пtAΚ^<$v$âxF&a$-LLAOkd+fǂ˾m[Gc>Hg&IZd?m'j/M,EL~)Xri$Q CQ[-Xvo˧snBMc:ب(eN'􏊍 \?ҎAv ^?[]'eҡLʻ>na/,9|k<(gTm=Fru{c͍uw0{Uvu^h G֦6fl֙(8bB~L)}vGqc6[l+(44O>4B)|B1*?xo=q_y{]98"r=;=*:¸6wm6WOswq@A<epIr2[ga_ :}a=.;g_SpCl;S{l?0fÒO5YKmms~_fqհ=y#*O"L=w&FNKOKw?tk J/hsz1: n'D`tf+iNۼa@_,OCX闉MΗA;Snt?xkRXy'*շe{]ޒ-_Aܹec(-"]*Une,3C9IN{Aoej `J1ҧt㒇UYa]YoPv}E,PT.jؽ`y#ʶRUob߮Rӹ?[{},VӧOe?u\:yܪfǵ{e ݽ<ܘD*Vŗ.]6l6}$ A50M{SšVrN}(z@(Y_Q1cobPd@,"6Su۸t|_H$4ʮ.U+N:]Hߕތ!_ŧ}Y @G^;2A]4:􏊕&Ot9[zMr$v>k6lto6ʶSul^*f2GHOnq c5YiҭVk!*.V-+sg8Ÿ́Q3ˍPSI6lVnx/ogύ53ryP &@fbkڋ4Mo/d " D0d2,lhV&d2 @ d@C/.M5cl@c|Ͱ_}S:Ϻ[Ϻ~@lsw7ޮb>{}CC_Es^Sd%0v2vٵ/?=R;";˴c?furQ*L 2@ hݮ/'Qn ,$CHB ]SԠӄ+mن?=-&uܼ՛-kG( fծ+~⃹ƀA.sfOJJ@Kپ9 E ?:/9;gq,\ |;Uf>z=8!t{3RI8RF| / ~oSkD{yJ-[Ɏ4is׷ֈOs-;}k8´r۶ n#C[b?Ζc.Gd+j[>'gďG:r%wV~L|i0 TzaiWOpw2qߞ[^}o>oeιhDՏ1mf}}mUj27]jgaӐ B{jIvK)2=ۜ炷񭾌P;RE71kW 9E#&^lHR 20m\G,q%&ȉ~ڝbxkc1Q5vcѪ騆g5C/ /=!!9+WR[ @9zeC/mcIZxl~ef`hD ȀA'FዌL2u^/Ztw KE~ nшNߟ6_߽}57":.k~ukG60윿?~z׽G8MgxS o:wh\ҎMFүunC7/;b˚Wv{op28GO=pm7TN r_ݠ+= FG{FCT p ~2^s!>V^2㑾UԻ=釞C~[?oyU*bǥr!a=p{2>z9GofXU-ݜۑw8Imdr~+4c \CO7{]O.L;=|pvION F\ynڒcC_<x_#BEu HiA$&˂ulY3~Jv,aJHgNmMT]G'fۏEq\u.;ĢIdn+M|zړ+3,;SSҾ+iEe1jl!E ʅucwk,y187c1`Wv%|-lvszymG3[vӑVX;ﭏ~J3h0v IDATq2+YV9{mހ9T؉f<utukf+;;yТ{Y:;;z(F4Z?p~ϊvrZCmV;g/LڦM[n]J А\C]RkWrXɧ</ Kz~~ 5hg@WӢ Z;[!]jF@`Xmx/0EY Pr? |l5mDnv<$=>@ 3Z;O:mԽ/Gꓚ/%,=^zpA;]Q;[uMA-[;}ȡ%21gqpS;~T-yre(T6)*,M~+i7R{3HGX2մkŏrpa#ӎx R5o23psTPB/| RIi]+z2xS5!I M| bC7fE\}Y6RJ4a$j9>y΅f'n/8CL"N-Lc3R^|~>asW͉~a#ZQ7(.2☕R{Ol_nUx/!Tt8;ʗI.9,4Uaİe~ i1,ozTb)֚P@tTQ#trƶx=帉fo#_@raI@LyuxĂ$3vqs`[ ܊)WMh+ <|IFQB$>DdWЋ"OEKf=rc9ae ='Ϛ?Q _'7q]*?< {8Z7JE~UK9IIn)͚]ô%y! Jfj4`MşY `gCb‚t!_8z^1ekL/WG\R(ЪAQ為!cAfW_8JlQGl-w瀙 μWamWca<&,] xqV>3::WXs9 ( /έN3% ,`r Ю`9dΩ}wyx2i‡Ye ɩFQVOju :i~'/d2bhXܲ043@G)(9.qjQTUK\geW0;!SD`}_d$>r3ddC*0 6E]+Vy0)ypص Np9AL!qկoAb~H ֍jʠ9t[{x|IӋWz^;V:Qң9ÿKX^G9R_\~W@!*$=X700LQhnJK]|$E XQdTftR+T.J)iF^$0,; MaS&-݄YO uޕzˇO{2R8oJg(TZCnlo r׮bEKk!Nx xۚ,f47fcn̠SBDS6~oKs=[_TqOT *0}V]2Kb~?J^|y[ 5ȪmEiX#m*EzMH%(d].\{2- 4!"ݶ0g՘qpk$(dk# 7EUשNZ,m#G9aąIiN.(0Mu%JI@ ZumoRxR^e!>9S~"M_' w_`AY$7.Yy$ 2{s;|C$ۅζlKnqQHSKvЯ\߾J2jO&w.<`|Y3G茹c:T}D55砲m;_&Um#I(J\Z׺ɗYAqp%k7!]϶Ǩ1 c`B^qD+T91YĹ |ne(OAiUSzD舅I40 NN:5D̸ #VyvS3A"kފqE(xQ&>L/ON%a}۶|<^LRBʃl/Jv⨖*bЌ>ҝ$f3i֬عvEGWtq?Ě괛0;yJ$ID5>/Y~RG0ja.n'i3a;K~Jŋ;fU}T /M ~5+Td.~z%?_K@ OL Vqv]^u}QB֣,oAj1( s^Yr-cѤnz ;7cK>vm`9d6q("FGAYi+!> `~Ps}KպUMQŸGYVe[[[)(հ ^WM˟wSY_C';Q vɟx/ \G(v_RlHz LM:rcB:vtRaJ+iY59 6A,~O ~K~$ GrTXR2 Wi_g6A;.Ntҭ%ϙi}_4^OQ- p`d2h?R0)H~5cŏ9!)64?Kol ޞ9Zf@9aLI6-n"TPJiOSC-+sfPMзO' kd >C|r#lh~S#j -3,R EDOt^xE QA hUD @ ubja-Cu*% d2 I3rA@!d2 @ d2 gziuzYES8&G AuL3witŇz*<䓜EcU'ۜF4EU'ӹwS5m@=c6^'KڅOC2c9@;lHz*A+OrR?^A W۲ 2{x[NEaZiĆ:(F|Et뵯j,6/8DT{#Up@L _U8Zl[J LxSYeڅӻ}]]c0vyѓۿֵUzJYdәw]b.3®zk =k]{uICF '@v#WЭۙ~(ZO>ZOT qUٹp@Cb<6?UWlm>ū G|#`+MW,qZ9eZAbЙ#m=+52qԜ#_jwP >.J2[7/j &`F0>A9|pQ:_r~׶"uG8}O_pcW_N㚖3EԼIxƱ/m#V. 2jq'ӟu7\jȖE8l-5czjgK 4akڡC"Qdjh%'$$gJ r (R:8:jg=/IJ3D𬻷$]bu\.72}z[9|fonN(dYͥze,ZLˍgͩmxscc-+p3o𳗱ӕ`o=?ո4&+~Խ.!Հ=I$L(%K./o3e.$+H 5ǮEN N&Y}AZj*B(&Z?U}*ybDaœYŊ²f?>\|-E}NY]63zhe~1*arGiEEY&!fFr@_Qo HQ&GeX#$ 4SXhTrX| ,<^{4UȽ_d ϰ-vot)~㏇{roQ箌cp/9}fRKqeN^vp,w_|/ӆՔ07eBo}#؊=EGΡÒ݂*.QgaU*U G~=Q]9%y|ԾU6R^ʖDM׳"}w]D>g^եb 'vc a~; /W5Rf$E_eNgضgrOy4 K&od=1~ջTǞXKaylC)aXmxT k:!40u0fΝ!$S C`^`Uٹp@JCJ|B(gd2I& S(ZG(+,}],  ѫۇq|Î;QPd7inϯIvBhV>y,{ <pOE8;0IHyR! '&../S>UhΪLJЋOĐ(I :w~Yo Bz88֩MQX٥G?or⫟T֔-e񼎃L95a*9 S sA#{Lˉ xv"1sZ'jc1t̴5>=- W ֔^wNT-?}SXk"lN:28-)}׈ 0@#-k X?6?dm>d0)'Ћ"OEKf=r["H5~Mlq.7$쓠ktL|?]BܗR@/."H%YI ̻ç3MOI^D~eK(3͔*vz mZoFŠ^񉰬<ر(s7Nʝao/ `[1so<8,۸jzoB K IxT @h B !\zBm:qýrQ[YY+Kl~y3ggvE r~0RTO[l=hb {_丆1'y=Fi,h8H%AhI`]M%PYw@zN(۞@2!Ͼ{rݓl)\~µR/85Px=lJ=kѾ.*#<Tvr0$U`=^ ZO'I!HNّv) -TdKpRcjG^ozý|\|cbZ/Y/MGE0\{ٞ E畩i'ӫnŧW}akv7Gj 9l\M64>GBFpQ̞mΞI.HlW#lߛ ɵ6W9{͊}3f0jv/z1EVk0>V(Jf hU`|4db Iӎԩf4;/#!-T5,.Mx۴Rɘ.OE<=t{FLvF3B}X Z"b_sakĪȰOޝeASW4rf(SK 9V(* @r9ԮaZn祿nʒ˦HN'2faHRUM H DVJ J {dIo]VZRڨ^ԅN ,&P^NN\}-$p:EyoLb ŶﲴGOYfUvzȶc)m3/+ rd ΁(KGK.4 G4:Nȝ4ClG~G)~,/Y\SujF~j<`ˡKe)d+|&V<6E\^IܩR|lr9Wjl KOǙ.)=#.~[@-+η ѫHA;c=/X֖ʓ(=|>xOx!%64> qεg}0{wLy¢xGruTHsV',Q E\]O/8hJh %u iPG$P^Gԩ^xP9 ;ԢmLqZ>}Nn"Q+}d> =Ff7hk*4P,nѻuJj@.i P8fú_Z.m6Ȫ 8x*Sلc"*2ByDŽo~i|Vf`3G{ !$Q?!g~7$PC6O}JC0!0>yѲ eyfkd; O~C _uIGCVXC.; [1 0_bD_m\h$ 4(SN5T0>꓇"# ٖ͆A.n0R@ځM3b7Vs\Ećr&VkvOK^ČWn<#YDuYn\RϣpY L[Α#Gjkf veBΞ=k6])\@ߤƊSnwV^؀zlxh2v6Y7 @$ ԇ֭ kYh-|>VyX H8[[phqBH H HLlA Rb{X7@by#<;-&ز =ɲ-04n7 0>6 HPe6|1ݏx 6tP0s;߸b6sw93dò@AeܠN*OWnT?jGfH 9EEy#ݧz܋m{>_G k&~v~o&(V@AʍAqJ0>RjF3'3|Y+^(=ozޛxz:UQCM2t><2`8u\܆]d8 {SYgqZn+#ѬՐ$GB}ؾ I@ IDAT~_UtV?gpCm(6c!8jI`|r e{q۫O^eJYޣ+O>}:8ןCخss6k[$phƩ5#׷= o9q7gyo䖷RAC'{y>_Y[#HN]Ba0jJNeXh#.KI*WH%e%RɓP ҡʂC=C&Oߛ͝Q veWam ߉!ݼz!wU!p9Qz?v!W3)JF=_]NFƽ܊/QH^gs lG^m$m`/ ܸ oL8RHphET {hpT[ȼ!\&ͣ m R@q$7RtOhXe (7 (b{%t9&e*9!h׵Wϔjw=%I[k/L,YvǓ&˽/;xZP֜EmPo>!]s<őLLՐŪf9[_4ox~̾ۉ_S%)̾7rs>ݮ#|]Yř jyTvہsN?jZbNu+&A:>V*O>=|e ON~X=~Y;c="*U0>*Z?ԩ=/IHUnR$ W.x(+?(sS?Fk[[^()NKNJ})T] m]Ϭƞ %)Y~^~|\U+SM[/sr.JLP T@nQ^og8rt2x.6-@wO-㊊2?MY%aQk/k׃ 7~Ѻ 6Veꅲ݅m\W]vQ(<9hp1}U3ey=2Kbw|.#F Xg7\^ء֫`x}zYzPfNF~-$)?w&eJp2w3Z-T= W_i2ӫnŧKj{`(7~7שDTc# ZP 4+Yku!|wo{FC㗵3WUE@4-eEHXLdža)#ێ(ha%_wޝq1^ltN0{vn\+SOa *Jxr<ɉ=5j.,x뢄I%6fl[r3Ъ?VM! ж"[Oĕj>P͵e,xXhu#f4;/#!-T5,.M\IƵZ;~Y[?wqG R/27Xr8iJn0>Zn !O;3V KS;Posp]x䢄ȋqlf[KeubNQY= %ؖh/g?`fwolh:X>l !|v\^AMWM̋/t Gk҅M Pw%?n+M<7A7,bA}m܂MWEUo7[5` RoHnT$q祜㙔] Ő@"P3>%k^6 o@q$oT@q$oTcc8Gs:u^-h|aa1"$7kqfՄ H F! YFhSU>r;zHY[ $᳜XEOȲ mpA j#GEО ٳ(XBxX;~Y[ vY/6 MhnР Hغu++-|>t !H !P)i  @$ @$ @@$Svހ{W3 dFxx{ƀ6Pbnyjmc`)=t[tY:p̜3 ~3ͮ&Pb|nNMpyOO'~G{O*h0~o"DPn(1nyjmc`)=t[GX6(wci녠|_nœr8]?oՊI/- 3y =j[s%5QZwclYYQ~cv@duqKo߃VZ q맧d{sxOK̪.R6~'u@rj@0>6 AlkYS߮AF?` q맧d0>R!6zcʑ+ EqrT=wP飔{HRvgnڠ r?++=ย%<P@-}~*ђ [.o-Rz̙$*Ks}BHSG DG7@4Lo.7MiK2=IP~I7|fVW%2N`o1RVSLρ’" ϩG)ue^B( /;a mHu#i ׷\XoHErȁ/):uo2Dhy øl1}_o9Y8<8tUy{_ER3>|ԃ9 䫎ݼYL~59}GB'Μc[o+03`vyr ѐŧ'ȳ>޿EPA :3Y!{yz= ow7Ps=Gv~nKAPϔ M=RBZ@9%7@ A@=\|46\ޙ! $/sάz4,œ/g?zstr\%%8~EŇ=h܂F)?xcdO7F_o=Kf~2񻡱O˯z}s%fV'j)46ț{;(^u_ 'N7 1:IPȁ J 57<Nu<&3dBw?Nq]MN~^}s뙕KiD-aOzo;݄DWeql&f"?dud)v][>Pզy2H@œqޮ O;6y.PTI*A}xM[/ѽK 0RX 3˪^,;Q[CQg)h -`=9/+O Srr*uƁsPMaIpc^HUћ3Tjn`#`A!A_5ڦ iG'_Ԧo)~hS:;i$v~KuF9~ @,a?ᣕ}/uZ|^OB}NC9Cw*E8n䋐ےR1 jsS #C`||\GuQw'J0>Vߗ:>^ g{%ld%bL7b 36='Qޟaiy1d"E7c`ށ+Rxu`WF(x# 3IHl|^MYyXTϋyg@բbq"5MQQ*yLtv_r|BQײxڱy psh$*nRX0~^/N].W/FG|sE/:Sג}sE Br_U)z BPBH;}B~J\9@r~g+J>lu/iz8潍o)ɦJcҮV<CB_6jD$OrǬq.e'Nt#Xț,a+PTIAUz`z/}z?_{_քĠS#C t?鋍')oX[C> ___?N?< m!/3$rǬqz֋z$_)*w|,I%6ag"k+W`1jŕE8ϝj@,\]'0G?"ZMq!02bxQOSyiˁȊ\x[a%Qn ɔ$nsg#%eT9G/jexuXwɟ4<0Gfcf "zSH|7QRVZrI^_ VJ>kUi_9sMH5I/ h-n> {*EX{e9JfO.yg%YfCl֦V+*WA#ZC{Gct@@ISGȨ~Ba|ԔG e L_5+mjwدO8 {#F]ovΒIw,TH sjK,$|zX.sl0En)ء+fHwsZ`;1[9/ n!ʟ]eoAc.s"E3S6FT*d#l5eJ]DK"6zx̷'4} 70D'q!IB&fa9H~*u+Z uL?j `1~z"%ǝPԯLJ.O:qSx:Qg};jd:`&=X"\s$7c|5hT,t 2S2/S dQ;m$0>F:ы0>H5)/Z1*(%f~e?E\ W#P^Gw QX I\<;|4WڴMwg%VK:Dxzɉ 0ѭyݎ̜SGEAi\ s?wϖRHh!(ہR2}; /M+|;QBiX۾ߛގ d*\j))Ym:N cb,]͜ .t;Ł,{vC9͇(흝j~f̨ 77 zk0.p nx6C[ZǮ { 7iAy E*4C]BB6 J [ tLsߨz? &[0>h8./1+!Ў;FǕд0>Rz !M[9k2+}߯ir/Asu?c뙸ח~{b.zXH?ϝ? @Q2Iԃ_"G.:kQ1 z0V ~@N;(^xRV|@ȵ!=9. |}_ٯ2W"bzJ l]fā|6gۜMF_oS}t}H>쭔F ;ٯmsr6%H}q3ܔ_ {@”jRU07"@;IGS˧tF'l [[-E*O.\*0>h0/@|օQGϟM!>AAA>(v",87غP1+y/XBh0ߞx?$`֭Z{®ݼ\xѢE5PI&,r rz ]F|k < `v=2N.Ci/844 J"r_ξw8p B⨧e6޷Ya@% ?=3ZlC\9L?mhJ!c(h&$`5֌]p( Yk5*P1$ @@'fM}aڲ~A!$ @@3&6΅A$ @$ @ԋ.߉9L.]Uʛa'%Fuҍ925kUteb7%o+_-9?y&)\v9VXB$ @$`MFS/3|Y+03Ω?~Sq3fmE^_b$Mzjj*ĤÆeK61糬ӆqp+ּ N& jNoǽvd:o8gOdYfH H#kmP~I7|fV̺#sf)>3s׎2C+7ȯrG~7r8ȝT݇QA_'WOL0S=;w%`{tڹc;\cc_}t9}u(+}E8H;$cgv_cBܐgwI.t3.OC(?@W ix(s`1ѹq .ř7yCX<Ÿ}kul&QL$=Q~W + ` Wmd ȊJ(xbSļ[8ьPVox)H-h<42ipo8QŸK:@37HQ,P @$ @$`*p >=|o6w2 ϻQX:UjX%oĂq(r T04)IN15KJܘ|kv{fmU_nUO_9n{9תּ%Vor隨5(!Uh(טCa=j$taW'm\qS1LW6@<3-LY{l/q35giQ'Ɋ' }X39^ƅOw,_xwߊK!8o ng RUy+:SC9 4Bv¶ݱj?2kb>Df?~*;׿.1\FZKrDRDKdR,GpjٝyooS/x H 'Zp2KLGy(2|2]H('Ǥw2;1$'\Z\f\z'MG%N9S C#)$,0%9)q)8:R,ʖ eRZEO%acDQA2uMIDATDvfq:P>M/c:Hm$gU*yn6PVBdgUE*G (G0fI9'm8W#1#$:iV_#c6G祚Vˈ&UY_\#L'-y\s΄qogt[.C$ @$`gMQ|aO@(o̞_o5E>Ws2P̠4^+{JKU{5` pH-uǡ)ѱ[8@U* 3e֕yTєR9h%&R vui^Z|7&ua3j:¢1)8bvS? 1b׈g\Ab[~2Hԧ,/fqu2$G^d2ҵ0fϥJ!H؝݆W3:Z̐ xhnԋ\K.l3}3{͊}3f0jv/z1>0GWѤXl{;;3*!s 31\Rth䩣g!dQZƘG7uzU3pxVodhCDnFZSyWJS8⃛ϝ4X`*EK{GfCU<cyI6Dߍ4< @&Q܏ Z(P0(*ɳkGSpE̡M*.AИN~%]1ɃQ;5s 㶚8]h<E<$;UaJ$I-AG 1j H H T5 E\]Ogjm+& ͋Y}4ئ,V6c޿\057P x1Y HB-/~eIEeYl̡ݧxnz҆I1λzi~wu;Xg߽W{ Ew?ãտqRi/.u9vWۉ/@w(3eJzE- &IO~}|k!> H 'YJ;8weF45k6 Yl "tֵ6ʂH\n}oֻw|y[l}=* .fvN뽆D_rhn89=U,e=%gGs8̩=~+DL}C~'M`qx  H>ֿync~͖Vm[ݴAk!+FLsGu+bYxYTޤAB8UބWL_mBFCS!H HLZla"n j 楤hPQ)d E_%IPGK#[,0XQ 9m>lN;tl Ȏ-rϾ~3"-2>sjP|p 3GEYwE-mj /eIߦ1,ɇP?-6ǡbyl:˗$1FlwU\ʮ- j Hp >=|o6wFmn!xpξ~*><4!id߿"J o\u2(!JW[h"'UBS.]:c{CV}YSwg̎\byuvk1``rA%K oUei>qS[.hO/]>:BASZbѶIH Hԋ9db{D{=kUw~ ',Py&mC]y^w0]>DQAQQ *YDV| mqGkVe8yĦGb2H[i@'^M K pdHsRrs +[MqJB1L_]8\#Lra~[t[J-CTNlrbT"H H P^փ&('YB /$2?MY%P\ۚP\\!I^ =. T;@rV})8bvS? aBuEXYnvTDnZXz 9Ϸw(-c8Tez-g.2ɾ6oۘb,a(`U﫥+`wfw^9dêU$PZr?4U9dP~SԖEYsu!>ty'%K}zB,7_<W}TP?Vn)>(jy@Va~ᕗ ed> t\p<էkFW-8dv}]S_;Y lގ(Վ~C=urrsއP{VK:iC,ǡkǗ-Na(5kܔ "RDmpDÁ qtb֘XSuBB$Ĵ]3^Ԛvb®ݼڜuѢET.ive˭ @$`k(w8$$:6M16m#.>hȐnmx\;瀁c;2+Mc`.xl~Pum,@*\)󇙗 4y 7n JR!slj̫2%ϟCQLF_w9lQɕ2^6i B_ zJP';/P($_2wW'\_,++pD:.CXO XUv .)I5-O3Q+, @$ @Oԧ;'b2}d;JgaϥX+-e4`$7MEV{O[Rg\]]-W?[ں[{k-nֺ{]j] "yI{fv I?2w̏|p28 =;[#۽O*U=冯zvU8׼~ѣpΉto>xsN?oݿ$pr@`P233I6KKKK<q~.:;:T@ 1t0#uClYxerVMh<,S-:#屿.#Ö'@?;:m@@ @ Pާ7Տݴm(+}wƵ yk.}~IBOX2Ǩcj]شŦ(蒷Shk&~ڄYM7gʜbpH52Q WPۍE֧=O4&ܲGzME®<O=_->3n؟Qp$@H+JDBxyyKy|G磱$RȿAܕicv@} >!.;޵:g^g^y&=.XA&5Wnuqy'}4|$Ὕ~qb;_n~~iSN{{,e-%9}#}i΀A F4Wn.NB?{pOt>5} b'8nv ٱ{^9AYQ/߁($0,kZ(9.QꪡnL HC4RWF*#T= OpY<n0|FxȎ :@,kI;jыK'9/=q0z>qټGx5yYȭ6k3Bp0FO=%M0^KXqHɉ3Kdc,wo:?q_{Қ-#͋xbdjaTgrs.P3cCThb^S?ك*S7!\Ӳ}CnWim:Q׳ՙv%ol{Xo< g?µy=!-rMc("=E9,zd"^ҥO[zscNL<x[0/=h*Pǩoγm9YNSЦ?GGN>QNz/As3v?}7CQaacml:^mR@H'X Sy:M~{gSoEU.%S'N^H:D)6%VOʸg  - UKWzc /sH >~6LiX;V5$k2^S1}?m3(D~A!5riUX;kwp4t](,a monB[ mjުx_O}Ed׽;L?آ14\n,ފl, zE|ThmRXc#HSSެvVP(o>Flm%^6{ )=mSC_b #6S-tr PV/odAJNAm 1yb~Ns(e !l/d39'wp'XSyUlvLx5?o~I=*|R7g\=%BFo?_Ǫ;RPApPܕ}Ntm|xa%೫V<DZؼ9;!Z z+3w{ib{<>i+(C(Ʋ5+:m."՝ʾw0tbR#A"m `mFsE hܤ+ K(דYb"q6fM6[dqH)Р@ó2wYb6uF|&7oQ;Un8b6b1 l!y-@Пkj^D)?:š[ v'iO!4$l?Fټs  ЗSF[-*뗧תl<{'x`ҷ׭^\'+Mgw/lKe==w{{HU('aܡm7ro!GX3꿸!4r ^.fg9+rj\4Y4DP<\ Q'6 v,o:]$=Pa@`$<@7gB~@OֿE_q>YFh,gpU_|m RCoZƃ&1G;NժQظW0JhP踲0g/h>d_\u*k zOG.?Ot;r:o"lahm]RΥf=|JZZQ^y1,zY gs[.Ek2OuݺOM\$zWI+6ZhpP,a}qq'P!ugAݣ^wƳ/$dWWO3;"k%()s X od:`oAOV۷av2 !yc<99O=ڛ}Y*a8,:l~h I ܚuBep0rf]b] P~^u^LѨ#@DQ;g 3 7[ْ2OFښ2;on18bufʜbՑ@^or*ew)h![K D]R'񙅢IM\;Vpð%wVC!SҊ:ѤaZZ]V . =OpG cܠp;l庝`+ PhKVd~*c'P<ӎ\@Sɐ=2&CP!1#8EDw@` y0\>. 6du'۟^j&uNA|mۍw2v@'@!A\xHA@Fڥon|@ 0 dffZ4qw[ln CG^8"L-IENDB`baron-0.10.1/docs/grammar_diff/remove_old_list_comprehension_syntax.png000066400000000000000000000510661415427440200265060ustar00rootroot00000000000000PNG  IHDR*[,*sBITO IDATx^\G\8:"RػbŚ&h.cT`/{ w`ATB q}w\ᦼy{nnn0NpΞϥ eNWUVмE-mT<Ϩ`@B@@ P(׮{F@ *-|[;+X R9bZW1A] ʛƱP/OP@ 8 @ eMһ8kS}$0?YʺTo 8?a-Lf<9UC[ &wҤEp!_s[/UoCV>5䔶^ZwR߹84 p s\^M%{"MAB}_@=#2U r/ּBlUA6v3REJⵙpj+ʯhcӊ -veqiyvyy19n1lKIʪ}OS*R9C~Y<|Lci]IkT _-M(d DqVο&Q{˯PՆ@ |L>h_dpJEG vC@001f3/d0YŬ;jgf)!$*L&i$@f=0XƔ9~tJ=R)A݀Wf+;d v0 ʟ@n0n_`(*:S͔k[Y:r+-lG ƹ~ܮ}tSkF{ x} }wH'm4l,fFz(7ЭE͚e3OO7pp٥)uZ|?4:&sLbܺw#h@RHʭ{.$:&2 gZG|LqY#ckܘUշJ /es.wޙNQA'/vwC]_N5 ޳}ykWS(v?m1f>_۶ջƶS-!GKQ~֬m}&O$sorvٴurWwcMlmWV/X vy7l99c٫m] 3jۿegZon`ݵTWw0i{W^݂ /}]v?~~ 6'g};*{:hi+ɧ>uCbb"\s1b% _jTRcұI㦽>ntt-{=_L'OnD)C7lCjQl/˺ee51P{D\ovV$0kŷ$;0EWD|6=nf-v?XF#j0iN=52mg+"̺{?{&5pj*ܱaу1-K;;tePztt V`*[[Ǣc/Z{xܪ3??fA)ew=Ϛ[B>66jW(}˽mYtlTQnK9?7I޷nAY~/ArZ<+qcs?ɨ]s%?]TZ.7|w0iy1:)Ynf4R LRW\.-}J\@ToU#`5+jpX5wЫuFLaQ{fK랝0ϛ;[V-&߾L@\̾g˜{ %C>< wt(IZT̻L5]zsl $)-2]t5ױѐD1IFwKBDa$05Iı1V"?3Y_m;88-!˖"\؈ /@ղ}m !ֵq3|6p|6^"=Y$R?3Z8}cQBz Pi  ghv.ʩi߂i[-dΧ9A>(>&MBNҮJA%y!f0 >wfIqsiD|P/ F4ؽ1"dd7´rk0$٤>v4; s{s*]磻.tW|vձB s')^c+婱רnamY>Lâ]h޿ϊemNl]X)4|ce(vhƳ!9YMMIR 3K^M I]mBI8e\'/Y|6"Βj~ ) `uDl=iW7.[)GM$״c()Zout14*Q 1<̮MS~blj8)>3``?9IY=F̬-S-Y(kV2 PT,-բ%H)D ZMۻל3t$OϐFyg>u7$v iYkzO5pj֤$#w݌~vؒ]~5>7#bS?keT=W]m2e"VL%$1{gMey_\7V?#CO~/{:uݾo݆sLTiVvrlVnѺSU_SM>o|l\Jv rr<.VnGXN==ЂuʊӾkR5P"*Gm]e?gpMGjVbk_P| uܼoѵNB*z0~Au3W$@ &vߐKIc?PK?3sXг蘈26}1ƅ=v}.p]s!{{ EWr/Kc6Oj`\n`d_MIu4~.c QdKoȂ@*#VмE+ i3(9IDv$Tg!:8ݯ u%'`Pڜo+?åINnxz)Eb0A':0O\jy P$5Ũ+@_][K/š@06e`ggK \;Ҭ?-'=z 4g6I, W7 ª5nT'Scn6fU@(_&EV-D kWˁ(M!SjߏlW}Dyχ{iEj.rMU1M%RYpx@|i<~he/}Z_Q*@) >`¿jnZis)@"" rKZ->GyyuKnp)F+ m'cc4T (*0Uo82x gZ`{qrW7/6VNxIoMǰj!_nP3ԅcTj䖐}IB|փ׬%?t1M`@3rv剷N's+8+bNaNE$EK/$EFYQEN̹8Zc-eHaevPCs~tK̊n|S U͋+ @&Pv;[]XSgXcV"C|tEl=E/%t_ %jj;$LGJy1H -@*(݇̚ؼK5QP628MK.AoicXʪ=jU(kAѮKxߴүMN]Q45H4|,\eOo;':u{uĉ&Lh$+CF="`^xD,W.{ #m\STSXI!N%1. =*K#+"@k1:0?{0D @v_^GS,\솔]"Wv+ɟq~n{vJj3ālO_*?U_3}GBD;o<)>UMB@(gJ'ֈoY:]V9wnǚ^$NzW^LpeYS2iʛ7ycd*v$~{-m7EZ>0|tBU.q.t{$ +Z45ƛ^dS>Jj*ށ@ P15{MdiQv?PWHMN&d--"~ IY15G6A\Y'^y$h$7e|+eB9 @~SLa.OҷdJkR$Cnvwg#y!ӿ9k$_5NJc dBB+d[m}UYٲdKUyD]Ey!o4-Њ$tI|%}Kq1g\0yg.%BK.7ٻ 8C@@Y}u{Wvk\eׯЁHS잛x *E2B[V]AbEEA8Z LZߔ8 m3ƴz֋ _*%ww,} Hat @  #v0N J@j(g[רEҔ[Eʝq (׮gmCv"̼'zxwgܬZ=+&JKussʁb@ 7_ܭFk] _.G&ְ`x @DzTHIiN4j~Y7%& c1O> aEhjk/I'6Ja=!˛)r(vټBl՞lb*\͵Q$|#-HuZK{riEQnjcƷ@: 0}%U7$v_ݎLB*<~ IDAT6cRD9ͦk$"%䔟ā$Sflz00.'@*M~n*v Ng˼(J_Mr{ 93ș_Ԫ1aE#qhШG{g2GV oG Q{o3qkܮ}111֌rO6N<_<|ܶ7¢b#7 Z[wn-SZ*X[=s?<KߍsR ~gwOv7+>N:t h,WE|&?E4N7Id Bk`;  Emc1Ŗ-cm )PhiVIۖwX٬Yߕm;[2S{{xN<$/"t\ztm #4nԼxve~ݣ˙)mԖ(u [Ɛ{Z794/82l(z]=:zN:Km:c8A֍5b՘-gshk7UMZ˥cQV'uА{f1G ؤq^ ^}z0An-1~Rn>u`_8vG(qRԶmn ـ@4f`Mi@'rv,2Dʋkٍ[k=ajzz 3jy~[2"d6,?Z?Ҟl;uΥ^yR=(Iet^dۗ HŴVǎK$G(#ܱϏ2Iחv89_Webߥz&ɂb%1w { I.~i]`ߧ,Z"rץ8vM+v yUG~o[ȽҶM   v_3$f'*O[ˤ ii;Κ=oLKManoNeKW4C!Y _ӎ~DgHoofOϝA's>'Sc&6s{NM5dn]xϣLij7`HDEhu)BA rz>!'1Nfhv.|Z ߂VN|Knd\u bh*Vݮ's1^nږ7THD` ɀtf>el`)Y&Slal>YT;3 QN23mk͋EVuKM[;,Ɋ,fVÖ) .p١/K{:+CpA Y"ACw*=L8! xc&)W^:gԹ% )IsCa3z5f(Snj-QsHn?z,!#V;c;gw+zQrbp!$qt$ 0}%2u vWH8ȊӬ%ae^ퟵ2ߞ.0Z7v}nH-rҲ3Өcޮ㨘gGaC߹űMY.?9;r7pf~aQoodԍb]03K=~PzD©Yu3":cKrWӑRpv=ub9|2,j,WK! F1 N.H@JO>J@[94ׁl T?$Z ڵK 7WdA>-a3IڦFMʵHԝDѭZy_h}f5?G @9UBG4oQ+oQx;)+vIEivC@T&.{tߥ#^]XZ iae._([4V}RH,F-iO}}ϗ9, @_m`` %y:U},A?vNDh+~ՠ@TRߤ$%1](zm*Br"@_]ZjwZA @ Coښ>ѥIݚjY/gq{@Tzk!$pE%kjiiղ^`+ٷ@@rvP}x_DI#a:SD+mk:ye}gNSz_5vW-v2!Tꥱ*-{8Cէ^kKr5C&NwE$Uzj /<;oF-D KkT'q#8$`*   &.(Whg f'!}=  `*~.]ÇOh/VSԲvE޹yY߁u6]=+t;ɤ0?mzji ]zR >]Ǫґ'B$L)`Cۦ%^l*nתG_fH$ Gӷ< <D5"*(ez:g5oK&3߅]ص?EoCz)-\$zzZyϐEwKjzRY+D}AaMzRO~rKXgv#O>W#fڱmC[XwtmcTiJ7B.FyV\2gF/`c'!zZ6\x)Um?sp.ES׮. $zo6u%q݋^-HɩG` B7$@z9̚LVj\yh]0$5o9#筹&O=uQi~HGl U"rR>&&*+L(&1FK2X%J p-zʲOg:q,X(-Ӈw6.Igo(:ℐʉU X}qގ&vw7?)NMf DOL : sXe_ uQ@@ iz$Eٲ\VG` ꇀݯ?CP  `Q=E Z7u`4^ިZU[ <_PBf=k\_a z"9tYלŵo3lx}zr(ls_ס>Isv/{}| ˱ ȽMOm1m8&NV\&fo'xp+@`L6f(+[})r#>^F52j6{!R$&~L$埉I'7 zeu @"*M3v?vJ@2q9J"rɔ[{ty᝹n~;dL x:q>-xyDgXgхGsƲ;nM_e3LBn5Oe`CɴßBN̝u"^wa{4oͨ!OXT살ܨ{>Y~Ӗ965-$e0_ @aup4. q 5@@MOSFs[6&4nSO?'PS_-5Vۗ8jes7h'H }+hޢV1ooo x/k%vd @tNV8H|3v@E G~(1Ʀid%c`FED0VOFd}XڻVtHuWEs: G(06]rEgLf8GVg_w`uX @[|R&⫻^E@!ŋ.ϋ >  Tݣ׾V @ @#P^7Cl_a^(lr*.Tg_J`vluytiRm#N>k*ϝe:|~&z>O5/0YN_ ;gk:Y\3ӫ4#l2. $qdL)ܖ af: I3J.`k@((_EvD/d&&>m Gf=0RդR˜0ϼNEUaUJXYlw._!*B&j5YC|S}6WO9u̴m7g㴦&2!R0ǍjAB PS~w-Q_`v_3J v6 @õ5={Cm&ԋm=Fկ9Cl,f>QZٰMؙe~"tѢ+b$L$ӮǠQ?vjȡrRO:p䍘o2=ز]<10lGWN;v!oXq/ooRj9ww^{?q}`{y;OMonca %%ON%v0A.ҿ-#'_Kyvv$?/9!G ge0fF,7r\]6{d'W>|ò)>돥?tq*R߼h ecߝљnynߣu]8* l-ؓK 1̂;yt~ss++>% XLJ1zOrBmtZߍhnkOH,[dɷ%t)JH|NY /\~l0ka-"'!STS(( PޛVt®2+8'?]9/`5%*#7&#~+l.^Խbd׸WV1kXm'I6r]? ]TִѪ0%o]zo, '2|kYNBԬjŸ ]gN5a >;ti,b~ӻ[)t fU'eߌo-,05yl[W_}s[z^^z )x6x͡3ǷBXk$Ux{F>JslŠ9@rW#ˑWs JKm0oL2 ^]q&a [Hj_͉z˨qf'_p':wl?kgR~/nY۪Mpj)NW,=0/GSX.Æ02wҼASy5ah".V6hl0A鵶zl4Ipˆ~LK2v;T\IC/Zuy'N5#~ke_}W[Cv`54r&g9f³eJSGJ[urU (-,zV6*]Tij`*z#0p;IJ|~-L:6>>(&Nti]C]!U((x$&86n5?=̊o`m8li ZR7wc>Ces:lWr&Ӻ[;.cXysdAsml'")EzĵOHl;uΥ^yR=Uq'GJ}):.+ݛs'"̹(w"%}FaƯfQT6/o_TC} s-Eak"08{M_\Gӿ',#ܪq3ro+wϛ'Υc)΂0Ʀ/Χ3!!(fŅZAD#bTrZ%7,wP֦wb7.]3A @P?uHafY >#qXtVh޿ϊemNЋ&{L$XY93,xHNjVGEIR 3K^MJ$ v |B&@e\'xF`ZZ Ǚ- ",zpDm j^ػ^^ґBDL3C57?ȭ η@3ߧ$s>sS-'1()ZGf=9AYʹ^Z PPA7Rֿ3DXs6Sٻr_`u`uWGʋ@@wb cu2YiVvrlVnѺQ(v|6]߶ظzO=r5- '>w=buXt iվ}ZNYqwQ%%zu}]߶O]UU&[7 ߿T| uܼo<3Idַ{rp}޴7GF^u%)W)#_cmR]J1״UVD̏<&M>nR~Og\H[~_2>X&fDLtVʣ?O }`E7CB_ZZa*{W. 쾮 }]ttĕʋFR^%Vrc4=lc@ U>8kk+q3[as)e:zs!{k zp֚kE7RG=W/*gOxzeu19\憜ʁ<}xl2G^aad\n`d_MiXi}Y/M!/(3ӣB ]GmTy?}BL\"Po+ UJN|y53s|z{ӪJL9:_4f5"QhU:w0\H }G]\@ͪ5kً+Vy_ p}٘7:.xC.mDC_Bg\P ؽ~cn\A%0;u+[#0}{^YHH?RK'd+GY |r_];?Wz(@$@A*X3P #sm_?XF4D'dxQ:4/z&Y:ٱ.Xllx׾GWoF,bo(ޢ]?q g>Wҗ}5V[y4h\ZnWB칏\,qL #'SC_FFI-‡A#4@ UTg#DT0T1q <be^8ٜ|6.aJtA>"!3o\mf1iիê6rC kxM  @/彖-[ÒFn|( n8u|Q\HvWRIVM?48?psf=/O`Y6a%xyv ^gjl⨇V#)،% ;9lG}n|;kk\s02,z_/C l66nj-KCƴ2{ԇ~ԹO\8W1^RGvE^iHV=1A3̬ò3)C(IvI&Ôus Iԃ'+z%Uv1q#Ws3P]r=Hmd,2z4[ЫF}q.֥iX,-s:#M@ D@~gh8{ft͉FYRke^(|7^Yܭ3gLCqWXz*NdɝyY z2Tz/#+0^=1#..18vKsqNu^J)yFVakg0.B֦r㠩 >Sjf'3KIKkd΅mg/0mUySW/ޯihƨ)vZ*A23ޝ#`h{OR=@OЍZ89x 3$ib{fo%+t)i206֢E)V*J[R @jF굦HbJ1Jg'q)[1ь.xy+ka6A3> S-U= s?2ڸ|Hw"q&IJ3]5y-%xrNK_\-K^5h?t ^tl)2Y!J-ʔz GP3/y-U鶭]kޛ],BHp*59!n*=8J`lH;e>jS]R`l}M_OgRΒ +-UD @*C@췖oŚ0cjK"Id?HT(( PXM ^95Xo_Υ a=wR^)Ϸ̼fbH3i$O}k]8E1Ck4ő2J<$C4bJ=\ T*(],tC͎Ui"!R+1{¤"wSIIHkzA]rJ}| tI2ȐwIA `:&/:h\8~w~L;P(DrbƝ:x¶urVFN A Yc+&7H=?A t|7godɍ$Sm"DSQI8▥پ>5$n r%˿DEU@yV\8YXx:DYLB,0D\h(ks$' )z=ؔ T MĐ*S)PTA zCx. =}u EfZ8GsSXTN&ГyB#2lHCcWB`5wL>v`[`"?CQL`g߷r ?;°޾5 \NRԣ^ړ&_z3N]6ʴpuZ۸r;U+'D겵W<ers@ 0}(=s'(q#/Dw A2ߔU@ G' 7IymԱ j=0&Ez\Lq[9Y0+G~}x3GTnޘp:M[7w}ސb(+e̾xZzQtsy?2Ifۡn Eq+[n-aМ2}RR[qs67ɽyq03)ңg&s.4m94&3箩6u%E"_9 !o TQF}G WYQ3kU.%k">ڊ6;Ǫ @ ͍oբ:UXΐnu{ RW"xγzqu,C`8w͑'3{Qͯ.7&~(zޭr=+dLmr$*Wq|h6Gj2q";ր{m_׼fңB ]mgTy3*=$@ JOeΥ/$F4;wsT H@x5s>X}o*I&'MhJ^U#Zo R @B&r2IENDB`baron-0.10.1/docs/grammar_diff/star_expr.png000066400000000000000000000044551415427440200207700ustar00rootroot00000000000000PNG  IHDR8;sBITOIDATx^}P۽89P LhHmh2Jc:Ihh)F 4N$%N;NvDRjcU*^b88vܩ0*wg?G!^NhG?!@C0Q @V-z8.SP#%_qW\oy { V@2gϧf&Vkx##-;HS*4 +C:~&/])语|?꾤\j*Hx:V$N:Ο1%UgSO o\sP!Um;9U!|}6ki6Xz5*$\)˵*{+ ښX@ɻ Ś3Ǫgcmmz5W$@xL'=BH@|:EOlrHFZfvzv/_y3`Fbg?;e'8fQ<WYepgLIU[v]Wlo7-ltOE[ w=t{['Bݻ}'z{/.kq́o~ 62hH:r:_ZR!qj&%LO9Lb6d^3 }g?>G/G(  `F@%4#Uk Q^Ywd+s4A?ΘkNm在#f=h?k/hj*+5X>j8B}uYя5'*.3 Ml/ޭũ.3olnw'$BD5 kmʤ8#sMP&݊l,廮7]Y{aN n8x}^|:0)"_L}j}k :w(dTC9+5m`ZɚC֫鮎!HP2h+syRqvkr2߬:h s{IQ,L~̹ }ru4waPf*|AoDBBGrr= _pT٪5) *uvvGT*k֗kg.yJ{ѳ[K^ply +=z, 9o=Χ]׊GϞ03qd]qG##I~UExlKi`2.F˥ǺXNpJ'r9< wB$@H\FV;{8nXwX,A ~ 25ia0"28*cz>pt[7oʜL12*E.K?Ҽuv׃^2?M+&u}K_z#XVL|ch |)w_F!@mjqQf szbFWΖ36jl/Yn7[z٦y Wӊ}wi"tby%F5 S}bOzWƑCY <nb[m0k}͎F8Lf$cW変w, @[0 p?!l}_z|`{c.Rwy<A } @ p#Y@wBK&jO͉q]2Γ$ %> @AAvB@|*>E @ 2&6JIENDB`baron-0.10.1/docs/grammar_diff/star_expr_in_expr_list.png000066400000000000000000000113251415427440200235410ustar00rootroot00000000000000PNG  IHDR8&FsBITOIDATx^i@gI& Hk]UV}ZwۧpŽjZ֥j UAQTVYe gMA19;gν'9]A^܏ܓ7l[:z:SA-ꤤ$Vͭy3ffZBP!bK]MTS $IAN)Oo P@bdg,W%@|3j^j@ *x>qߠ~0PN@N27Ox:Nl3@!Tчw^Kw@$cZvYz;}ء+ zK`o6@ @ Գ[;W9vOsr&e$Q R㰜Dmg#5*3[9%S:w \}ѝ[omܜڬysA!vB=L.:&U،6?Ku#" 0>7vig5ƾgL7?ghepÖVu9.5Cg*7ӿe^JMXwdxXotLŤ(,}^?g*!YX6晸 0zO+k/+x;9yMaCpv#(@ zubr)!sα]L5t JzUUߊjEh#T?Ko8pk+/?IR1#>= o_OՋX %FRoX:}]@_fܩüCzIX9:r8OƮ[ `[Sܷ[|3`i 92P{GeEL2xRrl12Eo*o|kѐ~#P;r_ҫsK@ P,Tr;b_10IEiО۝v)kQps0$m+ґ[q9+j㊌ثn2=WRCBVMԹQtU4tõ< 3mmx_~ijg"7( S%3{HyiYCbB"箝7뿼FM?1z̹ٓ[2wR6mW};" bHWwSfʙQų;F5~TOid ^rQ!9bvڽs' oEŎm We~J41ӝ%3f˿zxH*q}/±Xi]ɐO# Mu7 ^gPm_E(29o iSmZsP3_Zj3dEE$R^ylʯ&H<:xgyD*7kR/\( oGsZ[J=m 6(X.Ԙ0T+.bK{+`B$?fTw 9i4P0٦TcqNye8= ِ<6,D}/b޾XsMYz> һٮț0-NW4Ujӛ:fM:9{+]-oq{}KpJ%Wcd]_3y#a-;:2 E颴<Ղ@'`oqø:OAqꀺkO|OjdF~fѧu'rJ+"džHwäk0$dxLͫRb5.܀ʈc+k;[177Tq3ElÁIrSӝJU2Ubn0\q]nFbQueQU +ǭf/JPiKi3WSzrj!M3M@ ` vKrcN׮)Z3[wsA ,M~1Nn^|t(h67eM=Yrx .VhNHuqJXiعJ^yEQ_6i|nphYv7YtInL]W^Ƈkm8ç?g PbKIٱw]Qy4л)iԁ7?nBG6>4_Z7{.bW7wۊVW3]saw,W*S]ڵ}OR2FiP6r&.5D`i[A\l/$C2/UN!oza3צĬӿǟ%At{|ɏ8¥->zӸ8ʺɮhލt:_/ܙt"&ͻƃ6L! t?|A%GvS^q "ڌ73{(ݣ"c| S}]pI=u)|19ȸp ñ5BlWE9"`4jxڤ%C#4^~\Ts!H{"p3xLģ"{Z؋) >Yy`FZrcy5J@ {* FMg$o-"7a^,B5o6Itw cF/t8?*kEV=]_>ϣyhp|KK=/2iB'ϻ>h؟nfIZlT>C.N7(KG/lg l{t nq HJ^"V ecT[k8#[5UB%մV|mKڻw4L1 EێkAfJMw"kc#!>N3p]G ˞6NCN{&cZ*7j%k!IR}! RDZz|iE-HAlM/u Ank{?mpt{6ko!oip C b]D]h5|$_Fx9JSe,X-]R;X>۩$tO,@v% eH40^S6Ry}is*ț-$LAͳ+]RAo'8 |Xa'¦{\PjS.JK  `uC"dNBuW=pp|]T!jD0ewϨ=cY5|n"tFn_uJȢ7Z/(C@w>mIۢ$%%YTPfP> x^BBBVmf+B!ɽZyޏVhsq{ZU}-'OR%~l{i~O))Eڃ3FVEl ~Nkid*³ȅC|Ūssxg+)&&T!Pf22݌7l-L'L`lDbU0}@G_=='k57eN=9e-~P~=Z틏7&?/}̪AǴ?Xy㬼\ӊ ^(WH sf B!},]eW(+n ޕ!ejiJ}2OWYo[%dSa[P-HZ v̓i/=v-؏ל?uaM8Jڜ'!VG:C,@*5} dԋ2m}≤!m9nCYHB!@ B!@ E[RgkןZTEꈊrl\" p-*F oyDSdSOͻL61eMW<;`z3%{lpSt'YюuosqC6yت1pN:eJXzqQ l4s̀o&=7$i\G#XWX 69 w܊Ą[QCY g\ՁD |N՗Uh(L {q'2{e,l@# l0xo}Y3md>8vqԿy ;4`hGd_糵ըlrF :]U2h`W.uEy ixM;6CǙW:,^`C-kWUuCG/^XNo_1b>ݱOz3/oN]' l,1N-=v',FK1i)K-Z]AM7kN k^Ve<=qxߡXw2gUs'ihQs'Wݪc302Ũt/nbtռo(sd}v[WHoI|LxJQjieWg U~*;%rXgߛ(FZkO[yGEۅӚ_NEyb.xv_K<7X뵼s~p-wl^0!r^󛇯~rm9kҷS-Pڋ-VSMjڤ*Zye+p,d+3#j4hn3WS$u3vT¢__+]q߾`:wq) ^k+F+kc~^g1ƗUurNjx)vr*d&\#)ثe-ĻW fQ_KדTMjuKrisLdT*8V(.<|M@=s=^ l{-l$ڹF"O28u)uV˨V !G y.?@Yo2D ƖEk&-2Y hjoRoOk%zQ3&wi<`6/OWS~O-ħT_YHI}7W:u?irjܳq_TzTr56+&̌uG tqL֖gMr=$ > x0ąm: =Ec1y߱Q]a}ڹ٤GO]>>k# ]7z^\G5>V|݀|%c=Npͦ ƵTc)Cu7 *ÓV0Fy}}skڶ޽N2L8ԉ|uT3jl~&">; Nw}KEG{kc{&Sn#|27ԝ0rў&#H %>oU?#G`3{A{b_l9ś9Bϛr##@p7/TOyͿ8DtH$h5{O Ӡ]{Iv'")@S"a`04%R~*N#٦a :_/ w3ͼ_. fD=E@ *F _BH\;xcHK$uƝ̽EP\n|C@`D~ؓ @)T8prcF%vw%/Y| %( Ael~B &R>=CpǤW R*2[mx@I5:;=ӠV|@; PDax!wϛ4yb*A7~ϙ2 |3,EWچMH>.ttso}3Zt%)v舆ToyFf3Q5@r"Oq N&ęm4ZBa賦?D?7='e$ { }DžT1^ r뙜d/ F:qXf߬'r޲q))|A~#[oA#o4?ׇ2Mc|W5gr4d5”B>C)Mf)sDU@"k )E2"`3 EH xsris3gυ0ݣI:8N.QcZO?Ny^}dF'Ѵ'6l[ahBӏ`x*k ܲ5-4dRY0Nx Q$HAS7=DUx_U"v#)WN%mi $z,0=q՝Ȼjk_5k~BK!C I-wW*"{="IDD)JUb y?'CKgƦkLA+o}}+k"N-} 9fhN ޷Z% 7Τ>pUraW F8XM tK=PyISB/Ub1*($V#U Ŀ|'Dh Z~a^SCj{qo}UQnwx<ܵG熞|\84 _!^ݖϜ5INQ4I'C tߧX/u:y~5[$Fvks rX,˦C%$\@~?o$S&"7N]":;,!^I k{I%8/@dsd&q-үb.*2yԾl%!I?וpq?9M\y%59"SbطGmUqZ=\pLzYk'*-z Ah qRJ=O;j#7سzvﻴlT[b}o~Q9f"%E OT9͋-{|=?lm}E'F{0¹V~^SJ#Jvzv{w xo?d_a9ҟEӮM |Vk禯_d`$ja  Y=va^b/^]}PȏE㈄gStUI@r(fqb- ֿ =u+)'6'3m?f`ez|*ĴUo1`pGωpxw rv`A̢3NYNs͸Uy+'j*M,X{3)ލ՞%%ݝxn }rzjwJO_78Η䪻Q@A/tyzgx*6gutE3s-Akг-[^²n;ukn{B͘xaJ 6fc˱Ҳjr|~I-+C..r˼ܴ`k "os; 17φz}6IГY|m!3e}_ Z|d>~Ջv>=~[Wnv]22ГG89{ Tf|)|ZNnYߥqA3?;y8#ts>|J*o{!gXLixp,+"tϖ?eb-c[ysέ+./QY!78%*Nc C~tUy@:,w]͟Ztc|< ȵYFKbn;_;Ed\Ng=4l<+V fb???k|7f?Bڛ8 9OB*o®2 6> T׾o}GrD'N}e)aYg&XGX-]-2N?8/<$Vy9mpQJ1qZ/?g_I'|ㅯT=j|M^ry7j@ @QW@4ʎa%Rz|IENDB`baron-0.10.1/docs/grammar_diff/testlist_start_expressiong.png000066400000000000000000000316121415427440200244720ustar00rootroot00000000000000PNG  IHDRH1[sBITO IDATx^|lfI$I@C H& HU@PA; Q4*I( %%$H|ݙng$w{9gnG$ fFqu&g-r(+9Y:їF-l;8|_qضGh *Z 7.'Xo M\|dE9x ;(q (5ъm :Pp#oG5o7i q,q<źzи;أA&$ b|PiɛfcEFTpL_N(FϺ^)`/r*r~[.Gtm=pyy=2fɄ=AuG.C}<8@!#f]q2(+,>6t *W } Z^|߷~v{uvi9|՟}(?c%2 z5uNvn ?umB̠o/P3l2Dx_|sQ?aAm'/}*PsŒ.} ֙eb_6n&an)8WR|y)e#H򂵾5"7v[ӹx?Ozk$>lP޿P~>S#DŽpDRQNXlY}w76 4}nס q'chْU]O[Ѧh_1|/*+ AnULJ%Q=DOވ֭XKQj>kXOAP$_xuim7Vr`@[Q{4+4GOnX%rJ#g:ͮ!m8+EX,E,y E\kN%x>K_#>oΛpӆd^_=cx]2#/^G\Y,~gǑvGͿ0!ϰԯj {#BssEPoڿ)Uxzq+\%$'WQQ;):_ٟe}A|#E :o}/jfvG횺򯳍>g҄v_mF+Kkx/||7$/\R]X?|Ω_<=,5l|= k^%F= @#ݗ؞l+(V; ѯ2*eXx*2MTNac"ECe(%RL;D"IPE'7 j^vzS$+ʱg_ ;7>—y|kP<%[ ϵCKźl]F#=WH<~DǮ1#柝VV j/}Ym3{e }HwqwJ0@>,TӐӏʁ+Ҧn'r5LNznSg16D 5=I9{"(\Fʧ?\~<ϠcUQWR3ʒBGj˺|+N; cBB@z0sf'Ed$Ĕyv םJYj 5Z6aӟ{tu3<;y~%ˁ(z<ɞr>CGȲ%s-?ߣuieR}?W&|w_ss:'k1peV(V8/9z8zvi|Iʷ4c G 7 ML]ȍZ !1Q~P-ޠ۷_핚Rl?B\޶WZm8E`DHrtǢ(ud1ViIP^;A!5ׇEio+-YvN>EV Mƺ+~|p,f'&sD|:ãܙ_ ;v.KWRW3W'*(P\2oGޏ|އO=D/̿)H?1LԺNqXw|Rq޲c+b؄:c1/DZ,uQU#aӟ{&= $I<;A1Qds/h-cB??0'SDKjnQ}#tR'S!IK4} q?oVn筚_AJ k̕Ra0)XmN-BʓS)U5Rq40 ,y!cga5ne):$d!MIVJ\MqZ>K ug} }I01q-,lG׾:T\!աV ĝC\T"F.l;EmG w ^yo'KҢQz_\'caɲ&g~/Zv%f77g p\Sc{O.7f%DvG ?ߺ+EHUuyx;y0aCU3܅ֿEcӎluspH.#Yzu2NgDo=\Y9t*2TUf$[OeS}3(''3Mi4og,xgS߾v1I%LRʁ]('ǓgCU~Nw+>Ig(z6vuRݬ} 7󉜽lN*qm;AaM]hOy׹"xK/lx @@ݗXY߯Mf]aXPH,|-A+vHS5=ybvZY]O$֩~"Dd=<*@e{o_dXm4ך Ø~&-{Dw1!H;1T .b2>ñUqD||Dʍ͌cwʊz"@ .lyPQH׶{:cÈME ]RuwP=۠ b?m9o85 @*A@\b/ i^bϗG<ۿj9v-\4tǛ!Zi,Xz_[1MGa3V~?6ccݜ+[fo*60w'sn'7 MѢnc,^TWݪKW$=z [Z2|Mّװt#;Hx5K(nh($chV~i5 fK3ƩzsKX夕FDϘux?]C"qeok/WU6 q }( =8@mF+K‰ 5D8m|Њ tZ3K<3x E :gRL'*^Nx>K_#>oΛpӆd֙|'vNeT}ᯭ큟gR[&_y q1<.O?j_z_ogiqὑpCMI|9dnKO{/R#Y51ӧ |1|A9Cg2Mk)f ղ`s"Z%F= rL)H`iV_uVV/Vy$ȽrV@ `ٞ'8; ѯ2*eXx*2D~Pp )*#Ei/)d4!I:t-?A18uQ3 ~N(Ǟ$}?~*/6l _A̗Dnǃ</y2Cu$Wx' 6/6]cT{ K^Jp@SN쉲[p\X,}sb#gH3IUΝמIyoqܢ>2* nD9c~"eIyu>,N)@aҁ'WG$Z7h]|.*@"7sutJuJ82b#oL; N&|\-Fvz^6Dƫ8f<ȡEP/$CQ^x:'k (_,Bz=b(_ouF}aϏwc^š2(!+7@ 3Xj Y@ q 3b7RԛO%3e WL}1R oWM$ 鏉$y?o$lN=P'ר?%:$_?Pc"z~ב(i` & k'0VO7hkIq2hʉ!!7 qsb!L9|bʨrn(p/Av 2^.&[eeMl-zޏXnd_.ZI{{wG {?y"?!$uWY9)Ac*I|o[\Vy~AT:Y@`yN % X? _[j).\MR+ 濵V4%٘uTyc]8`0oN¼NE]ȱ0z]*OQ$ 7RLZ'ei"VSM9~bBSjU¹b͍^++qaԾDT)roTgG(L[y JM&(ʡin.ˡw~Ǐw kf>36yjsZ1[š|l~@D[h |e9Y~&%$me)P@$r]_@>7Kf>'Qx.#'؊C/O~w[(Y>J0ȪSb5@2#Cl-ܸU_*=vEPEiT:ꔁJzzUdhÂi6IDAT%<釷He(]M){u ,GxOTMjGc:G_sjQYΏzsYJq<:qY_}AdQr\#e8^CJő7r *Qx3)'b_ fu{>#ygߦcvjgGx~v"sjV3R`/$T: ٥RVo IXcMk96|zEP?61e9*ǻ.sJGhWZYp&O92A>7J>'`c.C`;ak'PIec0Tggڃ@8cPNJS_8n34\D]Y_C_ ?#zE$}x6 Ƶ/WHfu!zB}d6qg)>ckknE@S5R%x6Tu:wttarE*~OV|Pl[$uspH.#Yzu2e6KNEOhwseߢJرiGPxz1F괪Ҽ,` :}q5{RI<,yiQx^eWbv}sKm} ݍY ѱ]&}810C @zN^8U.)~챽'j317i͇3QY_XoSuRh{GL1'bs(@'0@,b~.ClٕÆ4dX[VvHS5=ybvZY]O$֩~"Dd3:PqF3{&Wdc~F}1uB03gjks>&|:;}ڝXZ sĞc$KR2NkanOв6LlIYnT/~̐,*AB)>91(9y`uQ-sc3OVE rҤ_-yJD{G^_;YĐsOvILr Xa|~-VI{k/ŴaZ= UuMBAC:&"Px @f|2 uy!VPBنV悲xQ74]S+3GL)1c5WkiyUgտͻ>|_LqE'Yd|0UݺG61:XO 6!ξ*|y39_Di\[D阳@>by@!Meqs spnч;NP"MNfHWPy3cs nvw$6ʶ~=aym]?ts:_j$-YH[a[@ RTqZjC66,bt+ FKoTޓ1LdgO.$!pi))K"l?$cf^GAEG_;rc{؁T @ut DQ:̉9Rz M}}|pݤkv&'LKVA ^;TL|G1!ǺQsW!?%'ڞ*;6|Qr_nƾ3K}"N~u|-֔& \N'o=|q+]w [wy]kK]|awXI  .Q^-.5VcvI].{B ȟSʈ$+Q?zPTKbٰe#:k~u ]5:H@E@;^1A՚dܫ#^'nt鹣6ͩ-u?`ƋR3!^:Sf*VYR$z-u+JrplwWb3UZ֋ d|ѳM/8*xѭLĞxsٸ>ߞcn}^s;γMFڸdxg?]NEU.{CvN{jڋMٽEAEeŽ"*`RKu^fA,9X߫jZU7^¡g2+?A[$ViK4X2 vv+Ap>cP/ @8Gm7+TOrԕGTvnJ$ŗ:E!N^`Jr[oOW*Pw4A۩rZlՏR޸-AE5bh=ˎH8];NeHGOI͹yG;v쀥]}ڥ?,/:!Wj]#;ʓӬB "Fo]a U\X|E6҈l@)@[K? 'w~zڟq{8m # (-Ө$xT88?}{#h*< qleDO_c6b=,΋s%9zTs|G`=|co08O$duɒ<=;ss42r٩#\:pP'g#UUcVx6%moIP+%v(O6"WLqoӝ/LL6z鋙@h,&L' R:/{_M@M 롼 p0;puou 4?Xp%EJe<`5(L>yp7"kȞufAs("gGbIwB>#&`گ~KOOPSXvv1MؐOۧQGW/qƼBbzq 0h+߷]F5,*Q/2sjvz)}ӵv%vaD²rFZaҽ\|x" ļ[G UxO.33j{6.r@ @#`T^]@GgM7s7O E1t?XpBznQg7jɚZY(4x"cL@RLRM!gRG>9U>6~-Վ%}iCm3'pL3y\1N͹|7ޛzVvc9švUlay460q3{ #_"gwV9r$tZToNQ]Z~}A?aPB}&v< N2 @pOۖ1٧N=T#U~hFgQ|̥x|RTaK1ʨpqeZ]9V_es .,1M%12-Q WtNg蛃r3~ \9i\FH3]M ӥǾSP"?EY)˦Fo;F('nC,#ŧNtfaiurN{iv3B<~m5@Tbڴx5GoWֱCbHBFݜש^~bM*-c#HlUwՇ@ @ 77Z%ѳ<&h"8'Ȟ8!̣?w7n#k-gE)L5i顗/"voCZG]Pi^, YDȬȕ$!,)~GFF4 ?8'L1Ϭ_ %gxA:Lo PLF왹@)@ rՀcH=f2WkU޺i%I-SB}G?;'LHEEk3a.sC;b.  MX&P{%Mԍ/{zl}'J70X]"_s)uEUFAM? ]bRəNk.,@O - B!@ >+؂d @ n'В{q _ p;4p͝{#Y+.->cC* ӥfGg)3ٻ˴Ýp1^gMݾjk5հyT`&@Л%ڿf_ qلz=]{Ϧu_rXJMh4IENDB`baron-0.10.1/docs/grammar_diff/typed_args.png000066400000000000000000001101341415427440200211120ustar00rootroot00000000000000PNG  IHDR:KZsBITO IDATx^|Eg.JB轇A* ~}y_6l `Dl@@! ^$!$-]OgvٙEbbb@աT*  @~sv HE+Vh dt#gΜ)J3pAaHB} H O;m[Bg` H HnսlvߏVz.c;+  x@zq639@$P*G&#lU5a$;F s('}o+ xK @$ @$ @$ <\](; v̘㓅=,X;}K?L7jS<~;c<ȮCtTu\OC#("$l]Jԏ>Oyݯ }cX6u*+M% Q,"B5ܲZda틮CZH#A] s-b-G3ɞ{v\.sdD<ʟ/Q~,z[_ M۱(D1 =t},>k{'Xؓy>,ww͙ړͩ>3yBju=HsVfOߑQ^U5+/Y|-? %6;&n+mh԰V5 kרoTMCڡtb}W_Պ#fz ; ]̣0ـ;Z>HnXy%JBH,1(cP5Y^:ʃʂTYaEX]t@sLH@XRk 5f_ʳP9s]-{Е}%gkm Ur6@$PYo+~t&ꎳD#p%7$EezATΆ'ZiM{<@-C6_۳zR$'2xol烅zM}ĝ1) 4yDw[Eh][7iIOLfu\ V"!1}=HƁ1?9iWIiW4j&uߵ+:gN\ӪOV!cQFU3" m߫gf!̂Ҭ#GSi~dCR\ 73r&wI4~llҗ7kDbHӉ]c׭\kȼsݢhzN\Wa&=[Æ|6W*>Rb(zz-j%rbCC,$ >; >zbdŅWO%*Ξhy^~ —, sUHĎ/zSphÿ}ifD.}I6L6!3[g_,9x$Ip,9WO֟V픉7^5ʒ. K-o0Bzxn{1mʌWjc:"QEi€LzdqꩳzkjWePyѨ˨QͰ K:l5pH,שּ́ڧlAqCۯcz=1T}|S0˵_?"7V_ӮOH'*rj=W-yߋϘY'FF^I]wN8ڨ*Sgyɦ;)I*yiv?Wi 'K}`_MkNҖ2`q@$XB_?`\Ụ3O<EAH@8fׅs_Y|\SYt-`tkԨR%gVƗ[ֲ<S7 {vu;+zsFș ($XnJ&Z^Tr4q#*b.XUbD]4aLRڿ{YETѵ#{9sdVy6snIgٮAK S E <)ݔLOS#?cAR"b۷.yAgO !%N`^,gOye Ɓq$KP|0c|9G$yib5Lد]YXZLĨqPkoy*P\#E-!YV3|k YOLmصӈyB`}`,7EwR'Oܭ%Le.RT„'+ hhߤ2k딾Tsh@dxFfW;?N]oIfu4]C6WWkMyh~8D#SWnuu7t?򈼏^,7T  }a} '_ŻBݪx[e+|tD fIy [,I06W:^NcV/þB[P*giT􋍞*}ySk40w=] RmX0+qb^j%sѣz7bTG3A:ݐ~r,]RE<50oD66ΪHӞ)sUqfu :h@QxeyY)y L6T-\\vWEgw f,oJ> &];XqqU၆ 1G{>Ւ: R*fZ qܾb/YQj l|?O\:Z#4i0)ʬ|ςK4,þ%S;8Y x$ <DW ,ǮYaJuz$}Kк#>\!cu&ejg˞ A}f Jwu{HVU1YPKDi檙=V:ɐs<4n+ wo_jţXqS^\vglMgC=y87X=YrÍjfkk^sb"T!θmO?T+TQ\lg;ObFEB_}t6WN3/.—.P5``(VzCGfĐ$ @Un@; fq$uFa-!!ui(1Ŵ.s,is$ @ NFG6x)`>[akV#]֪P ۮyW=`i H H H ?"g1ÆHwS{Bٍ X/7wwOQ|f32"g봵U[We*>E֥;f=氖f~ttQ;޳vH췚L}ՠcˇqO8b$ x;?]u~zqM] M3';Yˢu8a,ۻ'3ѧ2}wM{oknwRz|eC8+?Ԗ9JA$ L{wY x'IM | %Ke  @O>2<9"ʦ]cӋ]*O9|Kк{ۇ)S!Hv1g |k}Ι2.6P)hmL/#F?9al0j9϶oNe[ lX*pi骭)ǔo*rMGaq#3;ZqH`Li?ҷq nONUҭroE( M%nZs3=)϶wyL͈7,w-q6*lF ߤV}zE'bֶo V!Ƭ /2|mg'/La*Ǝ1\DZ+E0դRϘV WJ4G= Av4Iƽ=*L.ewēH@gBV"'/Sv|)v,tA dyGTIK}+m#9Ζ1^;RMM_9y Ly/`xLOߎܟ~B N*"HpHpUjmzgK)۳{·^J%V@M%,7)AЉ?s=}}TI{@^2T!lv#ݪ+g#C>W|c.%hrx +!~?DxƗP3@?{ @XCN^TށwЎ^KLGuf_7M:{XO2ܷJTmd}sYeZW.v'r**JoEzYH vYw#7 ʐ~yS&J")oW@4kw%U1s۔sV#vfqc1-[=%LgIl!GR@H1ӥ7Fаӆզ\B5P1k-/.nXxn%\)6S'xʎxڗ?]zs` #$rI*w < @vΆ yɦ;)MJmھUq070ƣ-HP{%-أ|~_bBx>Yu_jZp-`4 8b3\x7kOpVD$ 8&:e,1ZnJWaG*X&~И3POg)6<IB0ԍg]K@%o__ځ=2hI! b{ѹcgi@*L󣊉WId^5ɢHZ""V_#GjrwwT]l P+*4QQ`.= fAB!HN>_"C%c{ѽcڒvU*ɦoR@ >R}Z !*o*.{mN U9/O |=C\р 3 ̤ ;=˿vyRƣ&͚յV iV\]MȲ")gܯsM[vh](}8(o"qHG;s"cDE"߁  QHjJ%'* %87[S_FA)1Vsv3;kr`OC{M:i&\Y,'{?' FO :HpD>Toƥdl׆|6֏Wt\avYCAp IDATn/HPɿs7J5'%cU_M~ɥmtpSsߙPuwjSPu=z͸=$邿 *=F NLw^{ALϔxK3.]^3gE}Q v?YagMI{[Uk]d PD( @>.,(I^kUSRwZ.XkY&;F,Sd <MJO~k\Mc@$ @0zA%Cgb݁X!C?!ü!H p[{ˌu30`wu;/_o$ @g HY`{&G 1)OA]}R7 $C\Z ;E|k}$Pr^ -q7$ @E֞nmq<( FU{:^ @$ @~J ~ڰZ$ x=!\I5ߥ*FH:tt4 6>|T/O顭8,{"IaGRAɋ3ag>X!nXq:3ݬCt/eQ+݅x6#Vs#=?bUp"W^1<1q%^V*cln=*+ ~(}__>ÃS/tZ?>b;ILx#`DHBLW)ݘ0kOpS?_w0ŋ=P1ÒEe;)oP5#/0J&%şGO>d4r+p#7vxau`%kO6Q$( @ Ӫ}ON)׿ߵ?-M%̖O{]$ @>'UI;Χ.9;M>HmDVf?ϯk9׎Kş Ȣ_ك$: _3wbGa4Lc&5QZ { ?,ϫ 5|ŗسǐgI=Z T8t%ߋA{wJ\N~,z1<j:WyN|a½30Cuwn[S :Z=NvhrBtywԠ/IPJv滩L}\Nkǩ-T'R5)_V|>B>Yv$ʲޛOrTCPw2S/Dž:~#h:xDC}ӟ)l2v^ N<'Ne_:Sٖ H>I=0@ x߸g`Aq^|yڅO?g/q"ѯ Db.1-^>ןg2Nӧx2"a;{&b;[ gn/Q|Nlv#ݪ+g#KcX !zKbC>W|c.%X]#صVjLC* `dE־J/EMlyxWj7D]/&d[z4mk"c@"FmkEdtXx ? :gb"ǰ8i/(kO{t$Kn%<yyk}Wg3L@$XB;`ܹ&$s{M"k|zMc1/znBE4̣ۼ4wcPjܣd* Nﭵ|~B <MGV;BWx>Yu_^Ce'-Sw\ T|bd MY\߄=l5V ?cgR2RT+Veo&OLH(9uOBG N,{\ed3YJckd=m-ί[??phmC??˯ޤnyOJS_Pps1Uxc\ שb",Cҽ1ٽrM{nQ,FqhBq G$LRݻJWkl# $E]b֒d9{xn;M2}d:' 3f΋6 9=>/𖢵L@!{5bJeޣWWH OI6,[T>8~OeqP46R}r O#<T <UXJ%%1;  ?{ADF@iKQNIx쑄~A?5i LϷ?'w_ ~=qJ:Ǝ4 y?ҙA/P>ѯAjd.lF5Ӡ1\H(JbLpZ9QOǾ o?:C9wAX^i=b P׹agujm11ȋu[ʓ<@cL.D,g5Ӑނk* b (-AO(И I@PtWH:8inczt[6wp+adBG\yʖz9ՎG^pr;<=ye> H8ҡr9Sf{8j/Tt[O`:?A_1E1,[>OBq\ (ǜίsKE.]._\M]tJI`Hr:0u_g"B;rB~Xa?Rŧ~ɆӯSg=Bp, v\:PDf14}dnG' uUPU+du@wKOLC䴞*PȞyKLK V2_ɇ7%0a" 8CRWF/=zYSS^zLA/ ,9 ):A xI1v{ WtLϺ<^Efs |:N,G{>K}YW0%ukAY=[ޞqߛR,yu]La?veݫ1C-<<ݚ6Ԝ/#:uIYuLtY_E[e$G:J@zCD+8oOMW2!DycnhQ҂WR i75҂K_'+@D_^/d^׆2J'G1!K}_?8RfWzݙiZZue] ].E_< ,FitwL H pG:bhɟ'C:OpO}\5Uḳ?9u"zg2{I{"_y6VÏ/-;*wԋ~,E &B@ibx[^ /ږ=m H?) Yl7$ @$ @$ @$`77ħ6zl1r038XYDyg}|ojWƋٲz凞 =r O'fٵ6+=/_/X&TMj&=L)T $L9޺8W/q3r6C% J%*z}q}^֟yY ys*WA}"\x0mCme7&kA'P0!G(۸Ji_}+o+<"qN)0ɚߤV(fցH=l5>8:mrCiUٳ}@-FImvyyyM-Ryxt}i?NV,܈H;o;`$ x[3{@H} |e/@ K&ʿ=_,q>-d7L5W_/IϚ; Zm(pw:_ԡؑ8Ei|EAo뺎A#=$ ߤU-$c,.^TvQ;R2T\vg,}uTgR 22@}=Uw+פwĹ;!$x7ho3zZC~|KPZ#XO#{.Ep5|j![>WirBF9ȇWo<'hvXs FmkEdݤ'Cծ{؟g#rgșOmH#ְd97^K6m?żȆɻM; DȿvP-Lw´}o6=` exl: 8bMzǫudI8,}}{}\Ou߾ΥtGp/ .Rhcf+OoG` }qfygsFXfzy fΆ9X<—.v|>qSvɗspݜs(!!ݫSr-?B*=E֋LE- 8lӊDK;.(9f̓g^N.Q;-…4ԥ|<ҝ+q×PS2Rj0VwUx.ەԽ㕝z'Jif򙇉h UT]6Ih`1\WOTgAgN.vn4Jj$jvrvîq$KP|0c-=atAu*,J |_zx |<^'uI1NL+qv9*D,g5ӐvٕM0Jw.d :޼`*M%V +)UI(2vr9ZOtW||ҽ^pr;<ޭրg x.]~&f&*`X;TT(˼`\@i И %hRI0tRʘ6i~p7_h1&?/þB[P*giձ#zbR8.X~;Kp9DiZuBZܫӁ:t(ݑ'{x)|ɳaqesv2x&[B^G4su*.?ͻiF}\?UҪc-b>[`(GbwT]}^ hx RCevfE.]._^@NV%2t셏'OZ3}fS@逩mDD{Iϝ!mڲ^7 MNS.F,9_`^hv8q#(-lzKgfjU܉?ӯ-[VW}"\D>}RĠHՃtmFlDuXs7e "@RWF/=}FVd72~9Y˟Fd ^Pk.b,;`d䶀bi+Ν/~sxQa{$dZױzvܖ}ҋjLT,N;5ZngΜ)~nEQ<+|)i)Ƅ􏯪#l9\Az7.8ĘȺt8&Y>%}pC Я ڟy+mJʉzSgnu=套d_"'7v%{SR%y.G`.'Ж%gX@n=D $/-h$0VQ!H/Uv/g%OM#hX|=aqYp`2PЋ hQ҂WR ejû'ACڷ <^ExޤZ n/Q05{p%+I/ #YD5(|pT18`dAM/(!",:Rvʦպ./^K?׈v۵GAx 8$|9Qv[bx[*^m  Hb*ƟT-,쾭^7$ @$Ic> @ݐ$ @$ @$ @$`OL: ޤIM$ kN5(0y+z8m}44:{ZJħ{"۫ٺag>"UVt3fܪٲz凞 #]ϣb_=A'fZzVd8ڛU?/Ѣ G 0vD ,l:}j џ|d ٩'ufsgv2/@ KQ'INooMͭSJ&%o'/f&2,o*NqA .$ "f x 5]cq@S%^_:Z[8yvQJQ=Ӑ^"Gn<"vPdI&?wnW|Q@}]Ʃ EVWVv;\8(6.nTx}t^58xypf]٩q^|xx#g\\3ox91^fiO0}swf ̹3TRYT&YyLWpIY m^ZOIZ8_Y& s&֖{4`xj:yh*ye|lSJUGo?RDwhV~%SbG,407߆0 ߝ?n)n(;WzIOwR?^eE;8p`_.'"nb@ O̮>-+<%U> JZ|Y ZvY|OяP9;نb^ɒg/yn+O2[ʙp=iZwm {AXt:qnż#t|WHɒp@X8 ({=!mNPضJk\D)낋TޑMXRV?dX̋l۴*[`:2Ks;7Ӥ =;84 j]L&^Vaiyބ4`Q4;^C ?1"}|pg䠳 Tug.4!T.OADv o?)O_ɋhߚYXX<wYGvoK;>G;A.c>s%"}DI6ͼ{Ji|&xDq$DԒJF9) ,:DF^4h05wH(:ݵL7&X2Ⓠ V )Je+^|50obPJ2-=aZ <UXJ%%HFF+0VDvٮ2pm~u[U;Oq _x7RѶmt=gɗ.>goƒ7KW:xשqvpӴ+ͽՍ#kV;I[Px4{>vZ%ucb?sY X]!c ;/< Ev=r^=q젯sL/}oH\}]|"\F~yEcf'c@Qûz`b$x2b/;AI={V}^pWR Y_UߋEȳ4ɟvz)y*|MfOy2-jBKk_sxPO~f2p3zE%ˁ_1NxҞw ۻ|'![WڵGg^IqQ xߔF!KBvixҫo)Yv&Cݥk:̜9ST9}K[wx#ܣMqs(I$o|<7th='~eysΌ>2hasv"ZUtt%~!x@(i+ֽ550Un):Zp))FFthKTdz78ijˑ)l)eݻ>kZxy2U#m֯Ysz}/ڂF.|ߟ;ZZ$a^$a#:>:{N"> OX87@x ;ėWҾ]n5~aT#{ny6qpF">:b818Obxw-J'.C$ !Ubxhmÿ@EA$ 34,Q#*vm;$ @$ @$ #wDZX&TMj&==U/ wN%Ԡak鼄u\%'Nζ)8xOGnFg?A-5+zSP$ @ @j.|[ /I=07Fu )YjN%2Zͤ\ND !Hx0#\xj8fXHl'yhEsRa 8Y[UOlDOpt.68VسgN[ת^X# twOv(]#v1<`^p2Z5)P} ݢ%Ƴn[Ld>ވX'@Ie5`{= H@\} ɪxX%N)(3L4i+~x HCԍ٧׷SkNr~ p!AبN&j!dP ڍǽG #nxFk)Q%kҷY-Y 銏jI(PwBBoٯsgT੗Qj|un3L bQ#RC$ #;/@\M9@qU"$ @Vͮ3O~Z{lsGU=3W"F.&)ǰCyFOƕfiߘI:LO椊ںL؍L(kj}<$9n.'~Sg}9_%Z@'_2NѧosWΈ]k4ˈ2) Lxva\@o/=6Hn~_w2Vƛ2s%Mo-'j4..}mnAtl5pV.OŁLaB}98 H#;#p_t%ӟ"3j.f㑷o5(7q"H Q\ "TfK90m[k1|n ~0Hy+#1@'έwny1}$>Nt>^OH[ӧ:/ƫ#u\̨#Y3Ҹ .>s~ff:l!Wa?hNö[n*OJ*0 &uny;LWM\ZXEKMɵufӡ@$XB;`ܹ.K6m?żȆɻM; y&sq`d(DǼNSJfF.m>oH axs銵_yڋf;,$ @@\ /ɦlJK3U #!T]6Ih` 1$21R}Z fkuqj%O+ޟ_ZU& dddkYDG;!{Y3n%k%jETghiK,m{_jna\4Œ4̘e8_{:QdLq$ @n!`k_? +SɎ+. HA&p=DH*e^`.]FnhLAHn/`餥3մw:ȩ>y]7~Ohz8 Ι;,`.xOWYdxg:B5lih&0'㍹$,:N(Brsu#H9/DN]2J۬TJQ*%n3S  [/At؊9sJ]/d]fh@'ٽ%PQ̔w|?*yGElK#ڙKes3תO۾&՗Wj<ӂrL,}GH)7ԑāTz'w#c#>8_Y6ayO@/#Ϥ&IߞIaҕ꾶YN8jJd'^1SԁY)IY,B_W'_%]bZ5V ؝(T3@4}n۾@#bwюDw=LRC开lof.;J kC2^fvaqtnɍ9U4P:E 3kpkCkM>p}ӑig}FH-‚ xs[ϖkj_؊plJѪ_XX#I;w EIZtt0MӹMh! @["uYFg% /Hkȁ6E `0 ꀇ #Cm$uFJ  xf1͆ @~-_`[ -.[ om  W2%ޮ؊cX/֪r  hj @F12 _߬Ꟛmsɺ$ck-% rbˑ%7Wɻ_)X&ceo;M ?m>v;$CQU7`;u!WVnEյW"2{ܻf\bXoˬ=2j7eK1k_ǖ TA+43a_[[>Z[?QGu?oϣy\}1狵;ʞVh7zEBJ9*,HdF)=YK%~LD(`Q[w 9qLs8 |yɥ d' Vӽ%#ls цt mN>|9ؕ/yj-B7Kn&BK;oYV߳/=Y!1~hnN l\G6 sf IDATev]ӿ~>6g=?A%'gcW[!rtD7l>ҏm˺@VHvHL4~]%ZMg&2ž/I[G2&cT1KoJx]-$Uvr)|6 W4K)IT=YGы#4mr) ]ln{`PMRTYf@ J:tQKow-8q.S=TdU5fMib8JbTa!#w;]_rʸ%I5Bv{xՈ}3>#Џ竵k۰i#~;_0io=̊/L6J( ?=UN~$sΣK~ I{V`ÿOiU)6a@\4TЯ0uHOIVد{ |X}S Du2lz d:(rndA'.(J) kkWG&Wi囹݈T   iso6)ҮL,5>ɻdxKV2I>{Eeԓk+NRh~?oiyl̎k؟ nHbv=\ PN}YpbP3OT{6h3GQC&A ͮEt}D6ovW!?|=D6^!в'zGs2RBQ`QgꥢVj%>`&5},?_$_IX;[*SOOly7&<*_O=vw-nWJl(yvϷ~I:o`&m>y=4f}Mi[n@SiF4L$耡沉n=$?0=w)NdҮ9X8OBG$#EWHy3lo2 L!Mw6n7NDĔdeDtºc^{LOo󗄾5?^Oe_K?} 7Lٶa6kyJM=~R5:^j݇\Z\OVĝ]"toEdZX'5Xj&}.Rf^t°3b?@hcFk$}>p#6pg X>mY\tʰ@i~OR΂/!;>, :qiͲ#tb宗-3Efq%1ɇNw٨Muȇ:̟JZA9U!Ȓ^0w@ӕ@ÔJ"$Ue3^CzbfMHX젫u,ca@$Pqp-lP}m4J>q$j(.m0\/敏;gxcL":yz~:?~!h:͞J3@)uf^=? [Wvj`;/RxM[yBR&IJ+C5PPM%@;ΡEۓbizwKTVJ'7!)&jА^~'Fu-4+PIV#lf \óa}gikaˎwKc"aQE:իawVN HޝFlEiW5G]Џu +OCzr̆Jmi-3 E[X#c_~*'_:F?j7u3e[5^^WF2jgY;L_ pQwI0UMmm\;ӘI|uh"=ú3~hʫ%>|fKJ z@: &=,~4d0C \T]TK>~Wdu,M6XWFeLEc5ڷx^:'.OgvٙN;Inmsrj;F !rhPN?y^&ʡnHV4w"DTحB1VtЏPk 'ґkŽ%-Սԕ,„sH[D)JY4~& 6 &>&0'㍹$,:N(bN1hkIH|KI:]vxjȩ>]w ~=]OCISңֿ?FF'n¡"Sg\;N" iҥ/k~m:4XJc󞄏<1U@Q hfeliK>yD`F)O&4cDYԝ10w<eǹ;W$zAk}{=~#ǕiZ?t]\V ~o$x/*3,NJ%-~%#iigLBGuo|^wEvgqoOBDu)*`t岺7D_̚rQm-U"<؏7Pwh?8X?\GJ=Ob:_~>"%Zjg.X`ZWCɼϥ_y> CLh\k90'劂y"inYYB캂1Mo'JUȦ,TKIBLVI93nв_vOh} Vt[}|as_$ɓ[Zt MͼhMA @-P>EB'2!OE>D:շh[ k7$7]BTo-1UgB9L%ߞR.pFo3[bZdcU.*[=}#mm3骡>$OVcLX ҋw<cFn1R9FM8w#@ 4,$"L"lk*gHf6U~pݱ4E9-i/M1n9rNiqeQp [m.DSn9LT*;B>N8 WzM&-Ȳ,kh@A@[CCZʑ]UU|f @ Z@3^e@ @T @Qswq?o.L\4pÅ/O-<67:C{O_57N>Nᄱ3ﱉ 4NfO?]>)e3U AR8NЕq) N/'h{ricWF/`S&G:vm%kFdcJ_4v#;^(l-ϮD^JzŒ-Y Y% CRR#\fC*12/#_mp @Q!,) ?g=Vou~,sm<%xw>i\&Xπas~1DZ:{ֶ1vc~eFL'Њ31|-9nXd] vA?t9cu'/1'C0w 7g_wc l6Z]V\/NkTL0w0s^q@S6lp6=otx`W+^2l|xi]^wyUY/qxۺuKD͖9,J} : ύtVu9e~~JuّĶȗWy8OF*獯-?y~y?ž3]k7 QxT6=NJ+ 9Q.Tau+teZ<:&$zuqUSU;Ot:qR2ki@M+T(qNrJL!b:g2SJr;U:.\V5A .mQȫ}5o*2bj˦ {JVĕPSIsR\rMMi r~-ࢦȰy̛b;o!p:G@``ssaKkBD#'++1m#NlxN}Pй=}S \,pu̥IFSMJ1d"iCՕƲW%l+` A7{#¦V  RuO iá)ߖ4j4wt[$â#ުۣXn@tbMՊ %nlpEFQƢlfhy:&߭]ʦTdftYnƛ//. Mǿ{f\/jhiNt:U˭K ciNu_9c^cř+) -@ ntO7".gSY L]%ϴםqGmfTkZET Kv`U8t'1#=y!70at7PmMIXl 0䦯;~{d(ӳ&oi{;*p^=u潣j ώS*w w 3t_qB^t^STHr(ο[sA @=ig}FND/XW|}wx+\92>_TlK/~^])cѕ w;_~\ypy͹ј8x]:-n]O\reN0]1!cr~3ʸz'שa$hŨH+kԲ&47v0E/ۻo<Ξe3]+\+>;2v#;8,qd(ʑkv= Wf$0t  =4~~Z\EH6f"0~@ x/إ6r_frK%)XU\cunVyNVLf/c˳q6?ѵ u!r Hy$q=#5 5{?d}KЖSNp)"@ : `0AOV>VҾ['ȶB5EsZ]`R&~GfLTt}MK=bxK( @%[[[˵Z@ {Z^ @ m r@ pW`;u!W#[+T戣i[R|a ~Hb}7~:Køv̈́3x))3G=}Zv?z+q3bR=5Ŋ9'𨠽r9ϰi~<(ckc1F}i'4fDM‚r6%ٕ@yro Έy(qk\ܥkZd@ ; 0'dT:ou~,sm<}}{dh=3 )~؜F~|[Bg8|m-AQq+BnXd] vA??L(?'/1'C4}=ofl*FQ?ƃ{'?/8 )~[8'v߬U8]cƇ'[8 8 XW({ ns2@ v&1C\#hي+tngX ݖc4"/`mmsTreilpuʖ;3a#+ jK l)OsƓ-f.RU=R.F6i R @p"%cQFU鍼ei|8GmI*M$n{I$W'%h]n̽&f$뫾rVmJ+ ~q*QuNVBӞ@1BʇRߕ |P%clK9)$**=M:w ڿi=2,웓= Fcڡյ_p(;W<dthv@K/4pl<-Ɠ-;8~ewJ Lw[`΍H ^B}+g}B J׵BIC `+!/3R7IDATZ T\?sFt_C#6(gZETHQ6G>^wyUY/qxۺuKD͖9,J} : ύtVu9e~~I!L*m|pnky@s7y#YזT<haG.Myz(<*_oqV=NTmL-*.2uLGDŽެ>^LzW|˳---ld Κ Eqg)fB*,wD@f'@V\?wsGѥť;LNdlȸuZ6|U jza]I'[o33ٔxrWb$ Ӯz[bn!AWf\jmAO0KڹJW&Ub1D̗gyʋDvЀsc[v))a2)m,H3/pgd>0 nKE-}r‘ ժ>MSϗCl8%_ld ΔQCDCuq/qQTGm"u_!\8sx{}6$oOޑߜƔfB;@ŬHWWU;[.#g2n?=" #>$zu.USU;Ot:qs @&S\y~&KK \xBL}uRe(29˄W ˘Y35/47sYx~l-Xov >1gּI̋-&812;\7N(84|<l x.\{.lIzM(|~E%UmÉ ]^IQϣ :/sY,1ꪘm b4))|E\7VW˾_̭s++*pĬo7pf|˧Yɔo\KF@iJoIھI;,Z<⭑9OHkp*dt? [8y?(~cQ6l<2jA :,Q @xąԋ~&9cɤe%"F,ƅD+RLnj􄁪=Ddi Ӣ{+Cڍ D"ԙwU*R^ͺ܌7^y__*\_0 zt:>W[=ֆ[J/nWNh/gjV3VT]p9s Ϯ7%@ @.|=UCp(0u0yUXajʛ[L{݉ןi?{aFFkUDAkW !]eCgO}֣å0t&&nF򲉴}n6%# c Ih7TMO9PX+M37T+mb`0JU/&@qZ, !54Ĭ,O;7v"z2+GK?_I=gڤbX._ѰW&0#YފPRWDQU_銡B"{w>sqi=6m4ft2.^@_IV^6!N-k@3pcmzQŅ;]蔳n|¬AO2_vgbPGt'$|^ZZ 3+6^k1K8ٽRav{e$@ PO tr\5G;M aÂN1сrj%9 DqWwګG}*FS&"@.!uc] @0eWM{n#ׯUǗƿq2}o^ca_so?Ę^28Ĺ?Ovy堜eotٱv[VF @LRՋnQi֢ @1R!,^`lʑ0ȧ.0_;?phʦ;EA0:bE)u8w.Vpؑ{fS>_vf.6o*2?i NUZ&'dw;?xs>5 >_f(Iu{*=6W't@vOɿmi  @s"@ IN.0vX20XĈ^#4Ѹ0"53݀}E0P5,ٚ;{ZtO_peHqCvUDsMntFnj Ye𜟘ު 4"IƘ?܉Cs  ]M_ oW- ^I.|=iTy%SW`)on3u'*\QۇuFn%hT Kv`U8tӅ XA 5g.WuI(p٭Gksy=Y=6[LXqFK.~uQ@ ,K @0\ ϫq}Bgu9/5 @$KzR @ @&[uq@  `0Iov1@ $,u:sIENDB`baron-0.10.1/docs/grammar_diff/yield_from.png000066400000000000000000000160531415427440200211070ustar00rootroot00000000000000PNG  IHDR7 H=psBITOIDATx^|mM6 5P ]Pz(ED#=ED@1 P4RHHf| );H%g~O{˹͜{nAP @%شiSzdIL=hPo.H @) `MY@ @ @( @E@.^Jp ZB԰JP Z @ܸ|A:m@#;E+?]3U7sO|~NlX,lq-=꜡zr܇L6g^|Fȶbi,aҒŻr.K Ʊ9'-"+h=p\7nq%kٰ%}r %@bq19j bK vVKXl[ݷ.L$CŷQFa<$ l#&:Yr͊QZvZI[cSYLޓf˻xSq%֔e> 'Q#-dVM ˡ۔aj-/"#ɽUv-glka} @_8Va5}r}*$x@ ͩBnĘKЪԻBLMEjD"^H]4F"  }ro]6gmO/tȥ;]C{SLh bnJةrttP:N\)[^5*N2Ԯ= 0`Y)B\Fl μS& c[/ꂠ^wKpN>_}{ k\Qk(mǗJwܡ䱞 KRcv&:}KF}.Cdj36`9I~*nW?y71©"G៨E/<y^:ծs~EF@ @q;b:OTֻ8 w+n$YT#T.LP1O++iŤ|ꕔW^ ;}5aTS,alys2m Y}:I\GxُWKDy>&9ɿs"a87# ZJsuw3LJH1 E|g:")V/~G/_SC[jA6 Gmm>Uw03k<I2>1a FoPG\\ no3ϛ$?9{<5Ǔ) oQхP)Y4S@i)Gj-. bGf/e^ҨЮ㩦#dYRW 4ex-5^Ty f1U/b&WO Ȍ2bݿr3=xT߾Sta7?{fvhj $j/ƒ9SY1Ya<)= 爽vh:f,M)B$!'L A4"b&^NqZo;Eq{ j%Շɂ\>6wqM#?oMBcݘϺгK~T|iـ,dB)^q,ķHfC_Y %;sc녾_[_t#MzH}[\N_?n|SQrq0[}9s_C821'sm_> ,"v"Lr=];bBeJ}NwI?s*\BȨCRi aj6tRDKYe^~փ @s}-Vs/:^{0wU&cy \"/*wũ uiǽ;.+ɻqnr2/^a ]r-ft7v\:w$/Sc(iT>|k%(Zviގ-m-Y:89Nhͨv3}+J$ 6 +&TQw zqxù\:cI)3Οח߻o/3N^Ur-d8Dq<@O\ _Ֆa)?[ЭdsB ʲQ)S*Pk̷hU]ҍ1#kQODa?ڸpF~tEm2Oe+j71$A#]>20d3fsU~Szoeґ>LyOԵTs6)T.(|>1{.u^=`93hR D ͔)fL]1iM |ҍh0[v\&T5쉸R3 XPz,Bƃ0bZP 6xq=O3ƹ~T@"0p^ %I3zA,4ԺKo~,7>*w'z:fyϋ/~MV [A] ?ģXc#ʓ0;C. ^:mGy˓~T&ǥ^#KRI5u|\s {U )(oQvH@@x`Y nv'X7C:_C5Suۣ%ۍP`Tf)̎Rm.7f ظ=cfEC @a vs1*w Yc\ OxzDuO$ l&`dfY @<Zc <@6K o+oܠ@ s{\L|,+L9U|o VKXZ3K"'#~Nlcs3 vͿd Fn   scoRYwYٳ֬>2z]\Zޣoύ~ C\2柹jaQO[σ3/}iP1,V%@<|2!7@ 袻4ͮJs2m랂hvMۦc % `ҭ@E\>8&H1ckGI{TCο+OY:O~|ºq,5ƛ#=[BF Z;'YK>1pɤzE),8=x4O.Iwzsl_IC o%!ΙAt:Ը]%?8wuk4KzͰ;+2]֟;jly68(Qc?Ti7G>pQ3^(̾7;cRt:M7/[{ _{0cR)7=klkѥH](RqV'}]Hg쭯DPʢc"@x햾ᐬgʪga-ֈFճ~3fr0D Ц6PY  Zs.!+ /rBܤOOeN1?P(f:}ՠ2tk1 (+ƴW0-&q_̩_!<ў*P:US~YmoTEXIkJ~N^8B eŹ&'&_X,W3X!؝5:9/eLd/aؕiNZA m9XPa m2nD4xâç`!W m+I2_{SS~r_}ϙe%D]vgo;ȃ }y1 BHU`7Y{҉cd*,^xGz1o43t}YwpxфŷǙ,˒HZ{)>ͭ>\ZeJ9smHFswgN?=u]Pgsc^s+I#rtr#V6'Ӕ 6Ef*,Zg2ߦ0Ae@\* Kgu7`_ (AST) which drops syntax information in the process of its creation (like empty lines, comments, formatting), a FST keeps everything and guarantees the operation :file:`fst_to_code(code_to_fst(source_code)) == source_code`. If you want to understand why this is important, read this: https://github.com/PyCQA/baron#why-is-this-important Github (code, bug tracker, etc.) -------------------------------- https://github.com/PyCQA/baron Installation ------------ :: pip install baron RedBaron -------- There is a good chance that you'll want to use `RedBaron `_ instead of using Baron directly. Think of Baron as the "bytecode of python source code" and RedBaron as some sort of usable layer on top of it, a bit like dom/jQuery or html/Beautifulsoup. Basic usage ----------- .. ipython:: python :suppress: import sys sys.path.append("..") .. ipython:: python from baron import parse, dumps source_code = "a = 1" fst = parse(source_code) fst generated_source_code = dumps(fst) generated_source_code source_code == generated_source_code Financial support ----------------- Baron and RedBaron are a very advanced piece of engineering that requires a lot of time of concentration to work on. Until the end of 2018, the development has been a full volunteer work mostly done by [Bram](https://github.com/psycojoker), but now, to reach the next level and bring those projects to the stability and quality you expect, we need your support. You can join our contributors and sponsors on our transparent [OpenCollective](https://opencollective.com/redbaron), every contribution will count and will be mainly used to work on the projects stability and quality but also on continuing, on the side, the R&D side of those projects. Our supporters ~~~~~~~~~~~~~~ .. image:: https://opencollective.com/redbaron/tiers/i-like-this,-keep-going!/badge.svg?label=I like this, keep going!&color=brightgreen .. image:: https://opencollective.com/redbaron/tiers/it-looks-cool!/badge.svg?label=It looks cool!&color=brightgreen .. image:: https://opencollective.com/redbaron/tiers/oh-god,-that-saved-me-so-much-time!/badge.svg?label=Oh god, that saved me so much time!&color=brightgreen \ .. image:: https://opencollective.com/redbaron/tiers/i-like-this,-keep-going!.svg?avatarHeight=36&width=600 Become our first sponsor! .. image:: https://opencollective.com/redbaron/tiers/long-term-sponsor.svg?avatarHeight=36&width=600 Table of content ---------------- .. toctree:: :maxdepth: 2 basics advanced technical Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` baron-0.10.1/docs/loop.sh000077500000000000000000000001331415427440200151320ustar00rootroot00000000000000#!/bin/bash while true; do clear; make html; sleep 0.1; inotifywait -e modify *.rst; done baron-0.10.1/docs/make.bat000066400000000000000000000117461415427440200152430ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Baron.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Baron.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end baron-0.10.1/docs/technical.rst000066400000000000000000000211061415427440200163110ustar00rootroot00000000000000Rendering the FST ================= This section is quite advanced and you will maybe never need to use what is in here. But if you want to process the whole rendered fst or part of it as a chunk, please read along since several helpers are provided. Understanding core rendering ---------------------------- Baron renders the FST back into source code by following the instructions given by the :file:`nodes_rendering_order` dictionary. It gives, for every FST node, the order in which the node components must be rendered and the nature of those components. .. ipython:: python from baron import nodes_rendering_order, parse from baron.helpers import show_node nodes_rendering_order["name"] show_node(parse("a_name")[0]) nodes_rendering_order["tuple"] show_node(parse("(a_name,another_name,yet_another_name)")[0]) nodes_rendering_order["comma"] For a "name" node, it is a list containing a unique component stored in a tuple but it can contain multiple ones like for a "tuple" node. To render a node, you just need to render each element of the list, one by one, in the given order. As you can see, they are all formatted as a 3-tuple. The first column is the type which is one of the following: .. ipython:: python from baron.render import node_types node_types With the exception of the "constant" node, the second column contains the key of the FST node which must be rendered. The first column explains how that key must be rendered. We'll see the third column later. * A :file:`node` node is one of the nodes in the :file:`nodes_rendering_order` we just introduced, it is rendered by following the rules mentionned here. This is indeed a recursive definition. * A :file:`key` node is a branch of the tree that contains another node (a python dictionary). * A :file:`string` node is a leaf of the tree that contains a variable value, like the name of a function. former case, it is rendered by rendering its content. * A :file:`list` node is like a :file:`key` node but can contain 0, 1 or several other nodes stored in a python list. For example, Baron root node is a :file:`list` node since a python program is a list of statements. It is rendered by rendering each of its elements in order. * A :file:`formatting` node is similar in behaviour to a :file:`list` node but contains only formatting nodes. This is basically where Baron distinguish itself from other ASTs. * A :file:`constant` node is a leaf of the FST tree. The second column always contain a string which is outputted directly. Compared to a :file:`string` node, the :file:`constant` node is identical for every instance of the nodes (e.g. the left parenthesis character :file:`(` in a function call node or the :file:`def` keyword of a function definition) while the :file:`string` node's value can change (e.g. the name of the function in a function definition node). * A :file:`bool` node is a node used exclusively for conditional rendering. It's exact use will be explained later on with the tuple's third column but the main point for now is to know that they are never rendered. Walkthrough ~~~~~~~~~~ Let's see all this is in action by rendering a "lambda" node. First, the root node is always a "list" node and since we are only parsing one statement, the root node contains our "lambda" node at index 0: .. ipython:: python fst = parse("lambda x, y = 1: x + y") fst[0]["type"] For reference, you can find the (long) FST produced by the lambda node at the end of this section. Now, let's see how to render a "lambda" node: .. ipython:: python nodes_rendering_order["lambda"] Okay, first the string constant "lambda", then a first_formatting node which represents the space between the string "lambda" and the variable "x". .. ipython:: python fst[0]["first_formatting"] The "first_formatting" contains a list whose unique element is a "space" node. .. ipython:: python fst[0]["first_formatting"][0] nodes_rendering_order["space"] Which in turn is rendered by printing the value of the string of the space node. .. ipython:: python fst[0]["first_formatting"][0]["value"] So far we have outputted "lambda ". Tedious but exhaustive. We have exhausted the "first_formatting" node so we go back up the tree. Next is the "list" node representing the arguments: .. ipython:: python fst[0]["arguments"] Rendering a "list" node is done one element at a time. First a "def_argument", then a "comma" and again a "def_argument". .. ipython:: python fst[0]["arguments"][0] nodes_rendering_order["def_argument"] The first "def_argument" is rendered by first outputting the content of a name "string" node: .. ipython:: python fst[0]["arguments"][0]["name"] Now, we have outputted "lambda x". At first glance we could say we should render the second element of the "def_argument" node but as we'll see in the next section, it is not the case because of the third column of the tuple. For reference, the FST of the lambda node: .. ipython:: python show_node(fst[0]) Dependent rendering ~~~~~~~~~~~~~~~~~~~ Sometimes, some node elements must not be outputted. In our "def_argument" example, all but the first are conditional. They are only rendered if the FST's "value" node exists and is not empty. Let's compare the two "def_arguments" FST nodes: .. ipython:: python fst[0]["arguments"][0] fst[0]["arguments"][2] nodes_rendering_order[fst[0]["arguments"][2]["type"]] The "value" is empty for the former "def_argument" but not for the latter because it has a default value of "= 1". .. ipython:: python from baron import dumps dumps(fst[0]["arguments"][0]) dumps(fst[0]["arguments"][2]) The rule here is that the third column of a node is one of: * True, it is always rendered; * False, it is never rendered; * A string, it is rendered conditionnally. It is not rendered if the key it references is either empty or False. It also must reference an existing key. In our example above, it references the existing "value" key which is empty in the first case and not empty in the second. This is how "bool" nodes are never outputted: their third column is always False. We will conclude here now that we have seen an example of every aspect of FST rendering. Understanding everything is not required to use Baron since several helpers like :file:`render`, :file:`RenderWalker` or :file:`dumps` handle all the complexity under the hood. Render Helper ------------- Baron provides a render function helper which walks recursively the :file:`nodes_rendering_order` dictionnary for you: .. autofunction:: baron.render.render RenderWalker Helper ------------------- But even easier, Baron provides a walker class whose job is to walk the fst while rendering it and to call user-provided callbacks at each step: .. autoclass:: baron.render.RenderWalker Internally, Baron uses the :file:`RenderWalker` for multiple tasks like for the :file:`dumps` function: :: from baron.render import RenderWalker def dumps(tree): return Dumper().dump(tree) class Dumper(RenderWalker): def before_constant(self, constant, key): self.dump += constant def before_string(self, string, key): self.dump += string def dump(self, tree): self.dump = '' self.walk(tree) return self.dump As you can see it is quite simple since it only needs the :file:`before_constant` and the :file:`before_string` methods with the same exact code. PathWalker Helper ----------------- If while walking you need to know the current path of the node, then you should subclass :file:`PathWalker` instead: .. autoclass:: baron.path.PathWalker Here is a succint example of what you should expect when using the :file:`PathWalker`: .. ipython:: python from baron.path import PathWalker fst = parse("a = 1") class PathWalkerPrinter(PathWalker): def before(self, key_type, item, render_key): super(PathWalkerPrinter, self).before(key_type, item, render_key) print(self.current_path) def after(self, key_type, item, render_key): print(self.current_path) super(PathWalkerPrinter, self).after(key_type, item, render_key) walker = PathWalkerPrinter() walker.walk(fst) Like in the example, don't forget to call the before and after methods of the parent class. Furthermore, you need to respect the order specified above, that is: * Calling :file:`super().before()` should be done before your code using the :file:`self.path` attribute. * Calling :file:`super().after()` should be done after your code using the :file:`self.path` attribute. baron-0.10.1/grammar/000077500000000000000000000000001415427440200143235ustar00rootroot00000000000000baron-0.10.1/grammar/baron_grammar000066400000000000000000000145021415427440200170570ustar00rootroot00000000000000# Grammar for Baron # this file is a REFERENCE on what grammar baron is supposed to be implementing # to be a mixed between python2 and python3 grammar # IT IS NOT USED BY BARON DIRECTLY # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: 'async' funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [ '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']) tfpdef: NAME [':' test] varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [','] ) vfpdef: NAME stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | exec_stmt | assert_stmt) expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) annassign: ':' test ['=' test] testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test [(',' test [',' test] | 'from' test)] import_stmt: import_name | import_from import_name: 'import' dotted_as_names # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt async_stmt: 'async' (funcdef | with_stmt | for_stmt) if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [('as' | ',') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: # [ x for x in lambda: True, lambda: False if x() ] # even while also allowing: # lambda x: 5 if x else 2 # (But not a mix of the two) testlist_safe: old_test [(',' old_test)+ [',']] old_test: or_test | old_lambdef old_lambdef: 'lambda' [varargslist] ':' old_test test: or_test ['if' or_test 'else' test] | lambdef lambdef: 'lambda' [varargslist] ':' test or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom_expr ['**' factor] atom_expr: ['await'] atom trailer* atom: ('(' [yield_expr|testlist_comp] ')' | '[' [listmaker] ']' | '{' [dictorsetmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+ | '...') testlist_comp: test ( comp_for | (',' test)* [','] ) listmaker: test ( list_for | (',' test)* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [(testlist | arglist)] ')'] ':' suite arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. argument: test [comp_for] | test '=' test list_iter: list_for | list_if list_for: 'for' exprlist 'in' testlist_safe [list_iter] list_if: 'if' old_test [list_iter] comp_iter: comp_for | comp_if sync_comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_for: ['async'] sync_comp_for comp_if: 'if' old_test [comp_iter] testlist1: test (',' test)* # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist baron-0.10.1/grammar/reference_grammar_python2000066400000000000000000000134301415427440200213760ustar00rootroot00000000000000# Grammar for Python # Note: Changing the grammar specified in this file will most likely # require corresponding changes in the parser module # (../Modules/parsermodule.c). If you can't make the changes to # that module yourself, please co-ordinate the required changes # with someone who can; ask around on python-dev for help. Fred # Drake will probably be listening there. # NOTE WELL: You should also follow all the steps listed in PEP 306, # "How to Change Python's Grammar" # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() and input() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef) funcdef: 'def' NAME parameters ':' suite parameters: '(' [varargslist] ')' varargslist: ((fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [',']) fpdef: NAME | '(' fplist ')' fplist: fpdef (',' fpdef)* [','] stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt) expr_stmt: testlist (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*) augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names import_from: ('from' ('.'* dotted_name | '.'+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [('as' | ',') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: # [ x for x in lambda: True, lambda: False if x() ] # even while also allowing: # lambda x: 5 if x else 2 # (But not a mix of the two) testlist_safe: old_test [(',' old_test)+ [',']] old_test: or_test | old_lambdef old_lambdef: 'lambda' [varargslist] ':' old_test test: or_test ['if' or_test 'else' test] | lambdef lambdef: 'lambda' [varargslist] ':' test or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ['**' factor] atom: ('(' [yield_expr|testlist_comp] ')' | '[' [listmaker] ']' | '{' [dictorsetmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+) testlist_comp: test ( comp_for | (',' test)* [','] ) listmaker: test ( list_for | (',' test)* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: expr (',' expr)* [','] testlist: test (',' test)* [','] dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [testlist] ')'] ':' suite arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. argument: test [comp_for] | test '=' test list_iter: list_for | list_if list_for: 'for' exprlist 'in' testlist_safe [list_iter] list_if: 'if' old_test [list_iter] comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_if: 'if' old_test [comp_iter] testlist1: test (',' test)* # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [testlist] baron-0.10.1/grammar/reference_grammar_python3.3000066400000000000000000000136771415427440200215550ustar00rootroot00000000000000# Grammar for Python # Note: Changing the grammar specified in this file will most likely # require corresponding changes in the parser module # (../Modules/parsermodule.c). If you can't make the changes to # that module yourself, please co-ordinate the required changes # with someone who can; ask around on python-dev for help. Fred # Drake will probably be listening there. # NOTE WELL: You should also follow all the steps listed in PEP 306, # "How to Change Python's Grammar" # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef) funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef) tfpdef: NAME [':' test] varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) vfpdef: NAME stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt) expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond lambdef: 'lambda' [varargslist] ':' test lambdef_nocond: 'lambda' [varargslist] ':' test_nocond or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* # <> isn't actually a valid comparison operator in Python. It's here for the # sake of a __future__ import described in PEP 401 comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ['**' factor] atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. argument: test [comp_for] | test '=' test # Really [keyword '='] test comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_if: 'if' test_nocond [comp_iter] # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist baron-0.10.1/grammar/reference_grammar_python3.4000066400000000000000000000137031415427440200215440ustar00rootroot00000000000000# Grammar for Python # Note: Changing the grammar specified in this file will most likely # require corresponding changes in the parser module # (../Modules/parsermodule.c). If you can't make the changes to # that module yourself, please co-ordinate the required changes # with someone who can; ask around on python-dev for help. Fred # Drake will probably be listening there. # NOTE WELL: You should also follow all the steps listed at # https://docs.python.org/devguide/grammar.html # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef) funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef) tfpdef: NAME [':' test] varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) vfpdef: NAME stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt) expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond lambdef: 'lambda' [varargslist] ':' test lambdef_nocond: 'lambda' [varargslist] ':' test_nocond or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* # <> isn't actually a valid comparison operator in Python. It's here for the # sake of a __future__ import described in PEP 401 comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ['**' factor] atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. argument: test [comp_for] | test '=' test # Really [keyword '='] test comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_if: 'if' test_nocond [comp_iter] # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist baron-0.10.1/grammar/reference_grammar_python3.5000066400000000000000000000151361415427440200215470ustar00rootroot00000000000000# Grammar for Python # Note: Changing the grammar specified in this file will most likely # require corresponding changes in the parser module # (../Modules/parsermodule.c). If you can't make the changes to # that module yourself, please co-ordinate the required changes # with someone who can; ask around on python-dev for help. Fred # Drake will probably be listening there. # NOTE WELL: You should also follow all the steps listed at # https://docs.python.org/devguide/grammar.html # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: ASYNC funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef) tfpdef: NAME [':' test] varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) vfpdef: NAME stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt) expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt async_stmt: ASYNC (funcdef | with_stmt | for_stmt) if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond lambdef: 'lambda' [varargslist] ':' test lambdef_nocond: 'lambda' [varargslist] ':' test_nocond or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* # <> isn't actually a valid comparison operator in Python. It's here for the # sake of a __future__ import described in PEP 401 (which really works :-) comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom_expr ['**' factor] atom_expr: [AWAIT] atom trailer* atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* [','])) | ((test | star_expr) (comp_for | (',' (test | star_expr))* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: argument (',' argument)* [','] # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. # "test '=' test" is really "keyword '=' test", but we have no such token. # These need to be in a single rule to avoid grammar that is ambiguous # to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, # we explicitly match '*' here, too, to give it proper precedence. # Illegal combinations and orderings are blocked in ast.c: # multiple (test comp_for) arguments are blocked; keyword unpackings # that precede iterable unpackings are blocked; etc. argument: ( test [comp_for] | test '=' test | '**' test | '*' test ) comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_if: 'if' test_nocond [comp_iter] # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist baron-0.10.1/grammar/reference_grammar_python3.6000066400000000000000000000145031415427440200215450ustar00rootroot00000000000000# Grammar for Python # NOTE WELL: You should also follow all the steps listed at # https://docs.python.org/devguide/grammar.html # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: ASYNC funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']) tfpdef: NAME [':' test] varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [','] ) vfpdef: NAME stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt) expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) annassign: ':' test ['=' test] testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal and annotated assignments, additional restrictions enforced by the interpreter del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt async_stmt: ASYNC (funcdef | with_stmt | for_stmt) if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond lambdef: 'lambda' [varargslist] ':' test lambdef_nocond: 'lambda' [varargslist] ':' test_nocond or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* # <> isn't actually a valid comparison operator in Python. It's here for the # sake of a __future__ import described in PEP 401 (which really works :-) comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom_expr ['**' factor] atom_expr: [AWAIT] atom trailer* atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* [','])) | ((test | star_expr) (comp_for | (',' (test | star_expr))* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: argument (',' argument)* [','] # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. # "test '=' test" is really "keyword '=' test", but we have no such token. # These need to be in a single rule to avoid grammar that is ambiguous # to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, # we explicitly match '*' here, too, to give it proper precedence. # Illegal combinations and orderings are blocked in ast.c: # multiple (test comp_for) arguments are blocked; keyword unpackings # that precede iterable unpackings are blocked; etc. argument: ( test [comp_for] | test '=' test | '**' test | '*' test ) comp_iter: comp_for | comp_if comp_for: [ASYNC] 'for' exprlist 'in' or_test [comp_iter] comp_if: 'if' test_nocond [comp_iter] # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist baron-0.10.1/grammar/reference_grammar_python3.7000066400000000000000000000143141415427440200215460ustar00rootroot00000000000000# Grammar for Python # NOTE WELL: You should also follow all the steps listed at # https://devguide.python.org/grammar/ # Start symbols for the grammar: # single_input is a single interactive statement; # file_input is a module or sequence of commands read from an input file; # eval_input is the input for the eval() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: 'async' funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [ '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']) tfpdef: NAME [':' test] varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [','] ) vfpdef: NAME stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt) expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) annassign: ':' test ['=' test] testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal and annotated assignments, additional restrictions enforced by the interpreter del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: 'global' NAME (',' NAME)* nonlocal_stmt: 'nonlocal' NAME (',' NAME)* assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt async_stmt: 'async' (funcdef | with_stmt | for_stmt) if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test ['as' NAME]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond lambdef: 'lambda' [varargslist] ':' test lambdef_nocond: 'lambda' [varargslist] ':' test_nocond or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom_expr ['**' factor] atom_expr: ['await'] atom trailer* atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* [','])) | ((test | star_expr) (comp_for | (',' (test | star_expr))* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: argument (',' argument)* [','] # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. # "test '=' test" is really "keyword '=' test", but we have no such token. # These need to be in a single rule to avoid grammar that is ambiguous # to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, # we explicitly match '*' here, too, to give it proper precedence. # Illegal combinations and orderings are blocked in ast.c: # multiple (test comp_for) arguments are blocked; keyword unpackings # that precede iterable unpackings are blocked; etc. argument: ( test [comp_for] | test '=' test | '**' test | '*' test ) comp_iter: comp_for | comp_if sync_comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_for: ['async'] sync_comp_for comp_if: 'if' test_nocond [comp_iter] # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist baron-0.10.1/requirements-docs.txt000066400000000000000000000000321415427440200171020ustar00rootroot00000000000000ipython matplotlib sphinx baron-0.10.1/requirements.txt000066400000000000000000000000051415427440200161540ustar00rootroot00000000000000rply baron-0.10.1/setup.cfg000066400000000000000000000000711415427440200145140ustar00rootroot00000000000000[wheel] universal = 1 [metadata] license_file = LICENSE baron-0.10.1/setup.py000066400000000000000000000023501415427440200144070ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- from setuptools import setup setup(name='baron', version='0.10.1', description='Full Syntax Tree for python to make writing refactoring code a realist task', author='Laurent Peuch', long_description=open("README.md").read() + "\n\n" + open("CHANGELOG", "r").read(), long_description_content_type="text/markdown", author_email='cortex@worlddomination.be', url='https://github.com/PyCQA/baron', install_requires=['rply'], packages=['baron'], license='lgplv3+', scripts=[], keywords='ast fst refactoring syntax tree', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)', 'Topic :: Software Development', 'Topic :: Software Development :: Code Generators', 'Topic :: Software Development :: Libraries', ], ) baron-0.10.1/tests/000077500000000000000000000000001415427440200140375ustar00rootroot00000000000000baron-0.10.1/tests/__init__.py000066400000000000000000000000001415427440200161360ustar00rootroot00000000000000baron-0.10.1/tests/conftest.py000066400000000000000000000006251415427440200162410ustar00rootroot00000000000000import os import json def pytest_assertrepr_compare(config, op, left, right): if isinstance(left, list) and isinstance(right, list) and op == "==": with open("/tmp/a", "w") as a: a.write(json.dumps(left, indent=4, sort_keys=True)) with open("/tmp/b", "w") as b: b.write(json.dumps(right, indent=4, sort_keys=True)) os.system("diff -y /tmp/a /tmp/b") baron-0.10.1/tests/test_baron.py000066400000000000000000000024621415427440200165550ustar00rootroot00000000000000# -*- coding: utf-8 -*- from baron import (parse, BaronError, ParsingError, GroupingError, UntreatedError) import pytest def test_dummy_parse(): parse("pouet") def test_error_parsing_error(): with pytest.raises(ParsingError): parse("(") with pytest.raises(BaronError): parse("(") def test_error_unexpected_formatting(): with pytest.raises(ParsingError): parse(" a\nb") with pytest.raises(BaronError): parse(" a\nb") def test_error_grouping(): with pytest.raises(GroupingError): parse(" (a\n b") with pytest.raises(BaronError): parse(" (a\n b") def test_error_untreated_error(): with pytest.raises(UntreatedError): parse("?") with pytest.raises(BaronError): parse("?") def test_missing_quote_yields_error(): with pytest.raises(UntreatedError): parse("'") with pytest.raises(UntreatedError): parse("'\n") with pytest.raises(BaronError): parse("'\n") def test_error_bad_indentation(): """ Regression test case It shows a discrepency between python2 and python3 in string comparisons with None. """ with pytest.raises(ParsingError): parse("def fun():\nass") with pytest.raises(BaronError): parse("def fun():\nass") baron-0.10.1/tests/test_dumper.py000066400000000000000000000266201415427440200167520ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- import baron from .test_utils import check_dumps def test_empty(): check_dumps("") def test_var(): check_dumps("hello") def test_int(): check_dumps("1") def test_assign(): check_dumps("a = 2") def test_assign_star_expr(): check_dumps("a, *b = 2") check_dumps("a, * b = 2") def test_standalone_annotation(): check_dumps("a : str") def test_assign_annotation(): check_dumps("a : int = 2") def test_binary_operator(): check_dumps("z + 42") check_dumps("z - 42") def test_while(): check_dumps("while a : pass\n") def test_while_else(): check_dumps("while a : pass\nelse : pass\n") def test_while_indent(): check_dumps("while a:\n pass\n") def test_if(): check_dumps("if a:\n pass\n") def test_if_elif(): check_dumps("if a: \n pass\nelif b: pass\n") def test_if_elif_else(): check_dumps("if a: \n pass\nelif b: pass\nelse : \n pouet\n") def test_import(): check_dumps("import a") def test_import_madness(): check_dumps("import a.B . c as saucisse") def test_from_import(): check_dumps("from b import a as rev") def test_from_import_special_notation(): check_dumps("from a import (b)") check_dumps("from a import (b, c, d)") def test_print_empty(): check_dumps("print") def test_print(): check_dumps("print pouet") def test_print_madness(): check_dumps("print >> qsd, pouet, zdzd,") def test_atom_trailers_call(): check_dumps("a.c(b)") def test_atom_trailers_call_default(): check_dumps("caramba(s, b=2)") def test_list_argument(): check_dumps("caramba(* a)") def test_dict_argument(): check_dumps("caramba(** a)") def test_list_argument_funcdef(): check_dumps("def caramba(* a): pass\n") def test_dict_argument_funcdef(): check_dumps("def caramba(** a): pass\n") def test_funcdef_return_annotation(): check_dumps("def caramba() -> Stuff: pass\n") def test_string(): check_dumps("'ama string!'") def test_funcdef(): check_dumps("def a ( ) : pass\n") def test_funcdef_indent(): check_dumps("def a ( ) : \n pass\n") def test_funcdef_parameter(): check_dumps("def a ( b ) : pass\n") def test_funcdef_parameter_named(): check_dumps("def a ( b , c = qsd ) : pass\n") def test_funcdef_parameter_named_star(): check_dumps("def a ( b , c = qsd , * d ) : pass\n") def test_funcdef_parameter_named_star_start(): check_dumps("def a ( b , c = qsd , * d , ** e ) : pass\n") def test_funcdef_typed_parameter(): check_dumps("def a ( b : c ) : pass\n") def test_funcdef_typed_parameter_named(): check_dumps("def a ( b , c : d = qsd ) : pass\n") def test_funcdef_typed_parameter_named_star(): check_dumps("def a ( b , c = qsd , * d : qsd ) : pass\n") def test_funcdef_typed_parameter_named_star_start(): check_dumps("def a ( b , c = qsd , * d , ** e : qsd ) : pass\n") def test_async_funcdef(): check_dumps("async def a ( ) : pass\n") def test_async_funcdef_indent(): check_dumps("async def a ( ) : \n pass\n") def test_async_funcdef_parameter(): check_dumps("async def a ( b ) : pass\n") def test_async_funcdef_parameter_named(): check_dumps("async def a ( b , c = qsd ) : pass\n") def test_return(): check_dumps("return a") def test_getitem(): check_dumps("a[ b ]") def test_slice_empty(): check_dumps("a[ : ]") def test_slice_classical(): check_dumps("a[1: 42]") def test_slice_step(): check_dumps("a[1: 42:]") check_dumps("a[1: 42 : 3]") def test_unitary_operator(): check_dumps("- 1") def test_unicode_string(): check_dumps("u'pouet'") def test_raw_string(): check_dumps("r'pouet'") def test_unicode_raw_string(): check_dumps("ur'pouet'") def test_binary_string(): check_dumps("b'pouet'") def test_binary_raw_string(): check_dumps("br'pouet'") def test_interpolated_string(): check_dumps("f'qsd'") def test_nterporlated_raw_string(): check_dumps("rf'qsd'") def test_for(): check_dumps("for i in pouet : pass\n") def test_for_indent(): check_dumps("for i in pouet : \n pass\n") def test_for_else(): check_dumps("for i in pouet : pass\nelse: pass\n") def test_async_for(): check_dumps("async for i in pouet : pass\n") def test_async_for_indent(): check_dumps("async for i in pouet : \n pass\n") def test_async_for_else(): check_dumps("async for i in pouet : pass\nelse: pass\n") def test_lambda(): check_dumps("lambda : x") def test_lambda_args(): check_dumps("lambda poeut, hompi_dompi: x") def test_try_finally(): check_dumps("try : pass\nfinally : pass\n") def test_try_except(): check_dumps("try : pass\nexcept Exception : pass\n") def test_try_except_comma(): check_dumps("try : pass\nexcept Exception , d : pass\n") def test_try_except_as(): check_dumps("try : pass\nexcept Exception as d : pass\n") def test_try_except_finally(): check_dumps("try : pass\nexcept Exception : pass\nfinally : pass\n") def test_try_except_finally_else(): check_dumps("try : pass\nexcept Exception : pass\nelse: pouet\nfinally : pass\n") def test_comment(): check_dumps("# pouet") def test_comment_formatting(): check_dumps("a # pouet") def test_augassign(): check_dumps("a &= b") def test_call_fourth_formatting(): check_dumps("set(n for e in s() \n if a)") def test_boolean_operator(): check_dumps("a and b") def test_boolean_operator_advanced(): check_dumps("a and b or c and d") def test_comparison(): check_dumps("a < b") def test_with(): check_dumps("with a : \n pass\n") def test_with_as(): check_dumps("with a as b : \n pass\n") def test_async_with(): check_dumps("async with a : \n pass\n") def test_async_with_as(): check_dumps("async with a as b : \n pass\n") def test_dict_empty(): check_dumps("{ }") def test_dict_one(): check_dumps("{ a : b }") def test_dict_more(): check_dumps("{ a : b ,\n123 : 'pouet' }") def test_ternary_operator(): check_dumps("a if b else c") def test_yield_empty(): check_dumps("yield") def test_yield(): check_dumps("yield a") def test_decorator(): check_dumps("@pouet\ndef a(): pass\n") def test_decorator_call(): check_dumps("@pouet('pouet')\ndef a(): pass\n") def test_class(): check_dumps("class A: pass\n") def test_class_parenthesis(): check_dumps("class A(): pass\n") def test_class_parenthesis_inherit(): check_dumps("class A(B): pass\n") def test_class_parenthesis_inherit_arglist(): check_dumps("class A(**B): pass\n") def test_class_parenthesis_inherit_decorated(): check_dumps("@pouet\nclass A(B): pass\n") def test_tuple(): check_dumps("a , b , c") def test_tuple_parenthesis(): check_dumps("( a , b , c )") def test_return_empty(): check_dumps("return") def test_list_empty(): check_dumps("[ ]") def test_list(): check_dumps("[ x ]") def test_list_more(): check_dumps("[ x, r, f, e , e ]") def test_associative_parenthesis(): check_dumps("( \n ( a ) + ( 1 * 4 )\n ) ") def test_fplist(): check_dumps("def a((b, c)): pass\n") def test_break(): check_dumps("break") def test_assert(): check_dumps("assert a == b") check_dumps("assert a == b , c") def test_continue(): check_dumps("continue") def test_raise(): check_dumps("raise") check_dumps("raise a") check_dumps("raise a , b") check_dumps("raise a from b") check_dumps("raise a , b , c") def test_del(): check_dumps("del a") def test_star(): check_dumps("from a import *") def test_string_chain(): check_dumps("'q' 'b'") def test_list_comprehension(): check_dumps("[ x for y in z ]") def test_list_comprehension_ifs(): check_dumps("[ x for y in z if a if qsd ]") def test_list_comprehension_ifs_more(): check_dumps("[ x for y in z if a if qsd for ss in gfgr ]") def test_generator_comprehension(): check_dumps("( x for y in z )") def test_generator_comprehension_ifs(): check_dumps("( x for y in z if a if qsd )") def test_generator_comprehension_ifs_more(): check_dumps("( x for y in z if a if qsd for ss in gfgr )") def test_dict_comprehension(): check_dumps("{ x: z for y in z }") def test_dict_comprehension_ifs(): check_dumps("{ x : z for y in z if a if qsd }") def test_dict_comprehension_ifs_more(): check_dumps("{ x :z for y in z if a if qsd for ss in gfgr }") def test_set_comprehension(): check_dumps("{ x for y in z }") def test_set_comprehension_ifs(): check_dumps("{ x for y in z if a if qsd }") def test_set_comprehension_ifs_more(): check_dumps("{ x for y in z if a if qsd for ss in gfgr }") def test_set_one(): check_dumps("{a}") def test_set_one_comma(): check_dumps("{a,}") def test_set_one_more(): check_dumps("{ a , b }") def test_argument_generator_comprehension(): check_dumps("a( x for y in z)") def test_argument_generator_comprehension_comprehension_ifs(): check_dumps("a( x for y in z if a if qsd)") def test_argument_generator_comprehension_comprehension_ifs_more(): check_dumps("a(x for y in z if a if qsd for ss in gfgr)") def test_hexa(): check_dumps("0x123") def test_octa(): check_dumps("0123") def test_binary(): check_dumps("0b010110101100") def test_float(): check_dumps("1.2") def test_complex(): check_dumps("10j") def test_float_exponant(): check_dumps("1e9") def test_semicolon(): check_dumps("a;b") def test_exec(): check_dumps("exec a") def test_exec_globals(): check_dumps("exec a in b") def test_exec_globals_locals(): check_dumps("exec a in b , c") def test_exec_function(): check_dumps("exec(a)") def test_global(): check_dumps("global a") def test_global_more(): check_dumps("global a , b, d") def test_ellipsis(): check_dumps("a[ ... ]") def test_yield_atom_empty(): check_dumps("a = ( yield )") def test_yield_atom(): check_dumps("a = ( yield b )") def test_repr(): check_dumps("` a `") def test_comment_special_case(): check_dumps("d((s) # Padding\n)") def test_from_import_parenthesis_formatting(): check_dumps("from a import (\nb, c\n)\n") def test_getitem_special_case(): check_dumps("[a[...] ]") def test_print_tuple(): check_dumps("print(pouet, pouet)") def test_raise_special(): check_dumps("raise # pouet") def test_from_import_star_comment(): check_dumps("from a import * # pouet") def test_class_formatting(): check_dumps("class A(pouet) : \n pass\n") def test_backslash_not_in_formatting(): check_dumps("if a not \\\n in b: pass\n") def test_try_import_after_colon(): check_dumps("try: import stuff\nexcept: pass\n") def test_single_object(): assert baron.dumps({"type": "name", "value": "a"}) == "a" def test_crash_issue_85(): check_dumps('d*e-1\n') def test_keyword_only_marker(): check_dumps("def foo(a, *, b, c): pass\n") check_dumps("def foo(a, * , b, c): pass\n") def test_float_with_underscores(): check_dumps("123_456.789_012") baron-0.10.1/tests/test_formatting_grouper.py000066400000000000000000001733571415427440200214050ustar00rootroot00000000000000from .test_utils import zip_longest from baron.formatting_grouper import group as _group def group(inp, out): for i, j in zip_longest(_group(inp), out): assert i == j def test_none(): group([None], []) def test_empty(): group([], []) def test_int(): "1" group([('INT', '1')], [('INT', '1')]) def test_name(): "a" group([('NAME', 'a')], [('NAME', 'a')]) def test_string(): ''' "pouet pouet" """pouet pouet""" ''' group([('STRING', '"pouet pouet"')], [('STRING', '"pouet pouet"')]) group([('STRING', '"""pouet pouet"""')], [('STRING', '"""pouet pouet"""')]) def test_simple_import(): "import pouet" group([ ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'pouet') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet') ]) def test_import_basic_dot(): "import pouet.blob" group([ ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob') ]) def test_import_more_dot(): "import pouet.blob .plop" group([ ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob'), ('SPACE', ' '), ('DOT', '.'), ('NAME', 'plop') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob'), ('DOT', '.', [('SPACE', ' ')]), ('NAME', 'plop') ]) def test_import_as(): "import pouet as b" group([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('SPACE', ' '), ('NAME', 'pouet'), ('SPACE', ' '), ('AS', 'as'), ('SPACE', ' '), ('NAME', 'b') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_import_a_b(): "import a, b" group([ ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_import_a_b_as_c(): "import a, b.d as c" group([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'd'), ('SPACE', ' '), ('AS', 'as'), ('SPACE', ' '), ('NAME', 'c') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'd'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ]) def test_import_a_b_c_d(): "import a, b, c, d" group([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'c'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'd') ], [ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ]) def test_from_a_import_b(): "from a import b" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_a_dot_c_import_b(): "from a.C import b" group([ ('FROM', 'from', [], [('SPACE', ' ')]), ('SPACE', ' '), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_a_dot_c_import_b_d(): "from a.c import b, d" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'd') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ]) def test_from_a_import_b_as_d(): "from a import b as d" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('AS', 'as'), ('SPACE', ' '), ('NAME', 'd') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd') ]) def test_from_a_import_parenthesis_b(): "from a import (b)" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')') ]) def test_from_a_import_parenthesis_b_without_space(): "from a import(b)" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')') ]) def test_from_a_import_parenthesis_b_comma(): "from a import (b,)" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ','), ('RIGHT_PARENTHESIS', ')') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ','), ('RIGHT_PARENTHESIS', ')') ]) def test_from_a_import_parenthesis_b_space(): "from a import (b )" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('SPACE', ' '), ('RIGHT_PARENTHESIS', ')'), ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ]) def test_from_a_import_star(): "from a import *" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('STAR', '*') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('STAR', '*') ]) def test_from_a_import_star_without_space(): "from a import*" group([ ('FROM', 'from'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('STAR', '*') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')]), ('STAR', '*') ]) def test_from_dot_a_import_b(): "from .a import b" group([ ('FROM', 'from'), ('SPACE', ' '), ('DOT', '.'), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_dot_dot_dot_a_import_b(): "from ...a import b" group([ ('FROM', 'from'), ('SPACE', ' '), ('DOT', '.'), ('DOT', '.'), ('DOT', '.'), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('DOT', '.'), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_no_space_dot_a_import_b(): "from.a import b" group([ ('FROM', 'from'), ('DOT', '.'), ('NAME', 'a'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from'), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_dot_import_b(): "from . import b" group([ ('FROM', 'from'), ('SPACE', ' '), ('DOT', '.'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_dot_no_space_import_b(): "from .import b" group([ ('FROM', 'from'), ('SPACE', ' '), ('DOT', '.'), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_no_space_dot_import_b(): "from. import b" group([ ('FROM', 'from'), ('DOT', '.'), ('SPACE', ' '), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from'), ('DOT', '.'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_from_no_space_dot_no_sapceimport_b(): "from.import b" group([ ('FROM', 'from'), ('DOT', '.'), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'b') ], [ ('FROM', 'from'), ('DOT', '.'), ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_simple_power(): "a**b" group([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b') ]) def test_first_space_power(): "a **b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b') ]) def test_second_space_power(): "a** b" group([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_spaces_power(): "a ** b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_power_power(): "a ** b ** c" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'c') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ]) def test_power_power_spaces(): "a** b ** c" group([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'c') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ]) "a **b ** c" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('NAME', 'c') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ]) "a**b**c" group([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ]) def test_power_factor(): "a ** +b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('PLUS', '+'), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('PLUS', '+'), ('NAME', 'b') ]) def test_power_factor_minus(): "a ** -b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('MINUS', '-'), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('MINUS', '-'), ('NAME', 'b') ]) def test_power_factor_tild(): "a ** ~b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('TILDE', '~'), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('NAME', 'b') ]) def test_power_operator_madness(): "a ** ~+-b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ]) def test_power_factor_tild_space(): "a ** ~ b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_STAR', '**'), ('SPACE', ' '), ('TILDE', '~'), ('SPACE', ' '), ('NAME', 'b') ], [ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~', [], [('SPACE', ' ')]), ('NAME', 'b') ]) def test_power_trailer(): "a.b" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ]) def test_power_trailer_spaces(): "a .b" "a. b" "a . b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOT', '.'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOT', '.', [('SPACE', ' ')]), ('NAME', 'b'), ]) group([ ('NAME', 'a'), ('DOT', '.'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOT', '.', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) group([ ('NAME', 'a'), ('SPACE', ' '), ('DOT', '.'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOT', '.', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_power_trailers(): "a.b.c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'c'), ]) "a.b.c.d.e" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'c'), ('DOT', '.'), ('NAME', 'd'), ('DOT', '.'), ('NAME', 'e'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'c'), ('DOT', '.'), ('NAME', 'd'), ('DOT', '.'), ('NAME', 'e'), ]) def test_power_trailers_space(): "a . b . c" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOT', '.'), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('DOT', '.'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOT', '.', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_power_trailer_power(): "a.b**c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c'), ]) def test_power_trailer_getitem_empty(): "a[]" group([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('RIGHT_SQUARE_BRACKET', ']'), ], [ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('RIGHT_SQUARE_BRACKET', ']'), ]) def test_power_trailer_getitem_empty_with_space(): "a [ ]" group([ ('NAME', 'a'), ('SPACE', ' '), ('LEFT_SQUARE_BRACKET', '['), ('SPACE', ' '), ('RIGHT_SQUARE_BRACKET', ']'), ], [ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '[', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_SQUARE_BRACKET', ']'), ]) def test_power_trailer_call_empty(): "a()" group([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ], [ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ]) def test_power_trailer_call_empty_with_space(): "a ( )" group([ ('NAME', 'a'), ('SPACE', ' '), ('LEFT_PARENTHESIS', '('), ('SPACE', ' '), ('RIGHT_PARENTHESIS', ')'), ], [ ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ]) def test_term_mult(): "a*b" group([ ('NAME', 'a'), ('STAR', '*'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('STAR', '*'), ('NAME', 'b'), ]) def test_term_mult_first_space(): "a *b" group([ ('NAME', 'a'), ('SPACE', ' '), ('STAR', '*'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('STAR', '*', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_mult_second_space(): "a* b" group([ ('NAME', 'a'), ('STAR', '*'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('STAR', '*', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_mult_spaces(): "a * b" group([ ('NAME', 'a'), ('SPACE', ' '), ('STAR', '*'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('STAR', '*', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_mult_spaces_atomtrailers(): "a.b * c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('STAR', '*'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('STAR', '*', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_term_div(): "a/b" group([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ]) def test_term_div_first_space(): "a /b" group([ ('NAME', 'a'), ('SPACE', ' '), ('SLASH', '/'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('SLASH', '/', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_div_second_space(): "a/ b" group([ ('NAME', 'a'), ('SLASH', '/'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('SLASH', '/', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_div_spaces(): "a / b" group([ ('NAME', 'a'), ('SPACE', ' '), ('SLASH', '/'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('SLASH', '/', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_div_spaces_atomtrailers(): "a.b / c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('SLASH', '/'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SLASH', '/', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_term_modulo(): "a%b" group([ ('NAME', 'a'), ('PERCENT', '%'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PERCENT', '%'), ('NAME', 'b'), ]) def test_term_modulo_first_space(): "a %b" group([ ('NAME', 'a'), ('SPACE', ' '), ('PERCENT', '%'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PERCENT', '%', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_modulo_second_space(): "a% b" group([ ('NAME', 'a'), ('PERCENT', '%'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PERCENT', '%', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_modulo_spaces(): "a % b" group([ ('NAME', 'a'), ('SPACE', ' '), ('PERCENT', '%'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PERCENT', '%', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_modulo_spaces_atomtrailers(): "a.b % c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('PERCENT', '%'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('PERCENT', '%', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_term_floor_division(): "a//b" group([ ('NAME', 'a'), ('DOUBLE_SLASH', '//'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOUBLE_SLASH', '//'), ('NAME', 'b'), ]) def test_term_floor_division_first_space(): "a //b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_SLASH', '//'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_floor_division_second_space(): "a// b" group([ ('NAME', 'a'), ('DOUBLE_SLASH', '//'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_floor_division_spaces(): "a // b" group([ ('NAME', 'a'), ('SPACE', ' '), ('DOUBLE_SLASH', '//'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_term_floor_division_spaces_atomtrailers(): "a.b // c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('DOUBLE_SLASH', '//'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_combine_div_modulo_mult(): "a/b%c*d" group([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ]) def test_arith_expr_plus(): "a+b" group([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ]) def test_arith_expr_add_first_space(): "a +b" group([ ('NAME', 'a'), ('SPACE', ' '), ('PLUS', '+'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PLUS', '+', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_add_second_space(): "a+ b" group([ ('NAME', 'a'), ('PLUS', '+'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PLUS', '+', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_add_spaces(): "a + b" group([ ('NAME', 'a'), ('SPACE', ' '), ('PLUS', '+'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_add_spaces_atomtrailers(): "a.b + c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('PLUS', '+'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_arith_expr_substract(): "a-b" group([ ('NAME', 'a'), ('MINUS', '-'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('MINUS', '-'), ('NAME', 'b'), ]) def test_arith_expr_substract_first_space(): "a -b" group([ ('NAME', 'a'), ('SPACE', ' '), ('MINUS', '-'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('MINUS', '-', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_substract_second_space(): "a- b" group([ ('NAME', 'a'), ('MINUS', '-'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('MINUS', '-', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_substract_spaces(): "a - b" group([ ('NAME', 'a'), ('SPACE', ' '), ('MINUS', '-'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('MINUS', '-', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_substract_spaces_atomtrailers(): "a.b - c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('MINUS', '-'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('MINUS', '-', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_chained_add_substract(): "a+b-c" group([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ]) def test_arith_expr_left_shift(): "a<>b" group([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('RIGHT_SHIFT', '>>'), ('NAME', 'b'), ]) def test_arith_expr_right_shift_first_space(): "a >>b" group([ ('NAME', 'a'), ('SPACE', ' '), ('RIGHT_SHIFT', '>>'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_right_shift_second_space(): "a>> b" group([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_right_shift_spaces(): "a >> b" group([ ('NAME', 'a'), ('SPACE', ' '), ('RIGHT_SHIFT', '>>'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_arith_expr_right_shift_spaces_atomtrailers(): "a.b >> c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('RIGHT_SHIFT', '>>'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_chained_left_right_shift(): "a<>c" group([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ]) def test_and_expr(): "a&b" group([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ]) def test_and_expr_first_space(): "a &b" group([ ('NAME', 'a'), ('SPACE', ' '), ('AMPER', '&'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('AMPER', '&', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_and_expr_second_space(): "a& b" group([ ('NAME', 'a'), ('AMPER', '&'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('AMPER', '&', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_and_expr_spaces(): "a & b" group([ ('NAME', 'a'), ('SPACE', ' '), ('AMPER', '&'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('AMPER', '&', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_and_expr_spaces_atomtrailers(): "a.b & c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('AMPER', '&'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('AMPER', '&', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_chained_left_and_expr(): "a&b&c" group([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ]) def test_xor_expr(): "a^b" group([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ]) def test_xor_expr_first_space(): "a ^b" group([ ('NAME', 'a'), ('SPACE', ' '), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('CIRCUMFLEX', '^', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_xor_expr_second_space(): "a^ b" group([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('CIRCUMFLEX', '^', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_xor_expr_spaces(): "a ^ b" group([ ('NAME', 'a'), ('SPACE', ' '), ('CIRCUMFLEX', '^'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('CIRCUMFLEX', '^', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_xor_expr_spaces_atomtrailers(): "a.b ^ c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('CIRCUMFLEX', '^'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('CIRCUMFLEX', '^', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_chained_left_xor_expr(): "a^b^c" group([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ]) def test_expr(): "a|b" group([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ]) def test_expr_first_space(): "a |b" group([ ('NAME', 'a'), ('SPACE', ' '), ('VBAR', '|'), ('NAME', 'b'), ], [ ('NAME', 'a'), ('VBAR', '|', [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_expr_second_space(): "a| b" group([ ('NAME', 'a'), ('VBAR', '|'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('VBAR', '|', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_expr_spaces(): "a | b" group([ ('NAME', 'a'), ('SPACE', ' '), ('VBAR', '|'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), ('VBAR', '|', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_expr_spaces_atomtrailers(): "a.b | c" group([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SPACE', ' '), ('VBAR', '|'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('VBAR', '|', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_chained_left_expr(): "a|b|c" group([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ]) comparison_tokens = ( ('LESS', '<'), ('GREATER', '>'), ('EQUAL_EQUAL', '=='), ('LESS_EQUAL', '<='), ('GREATER_EQUAL', '>='), ('NOT_EQUAL', '<>'), ('NOT_EQUAL', '!='), ('IN', 'in'), ('IS', 'is'), ) def test_comparison(): "a>='), ('DOUBLE_STAR_EQUAL', '**='), ('DOUBLE_SLASH_EQUAL', '//='), ) def test_augmented_assignment(): "a += b" for token_name, value in augmented_assignment_tokens: group([ ('NAME', 'a'), ('SPACE', ' '), (token_name, value), ('SPACE', ' '), ('NAME', 'b'), ], [ ('NAME', 'a'), (token_name, value, [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_expr_comma_list(): "a or b,c+d" group([ ('NAME', 'a'), ('SPACE', ' '), ('OR', 'or'), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ], [ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ]) def test_expr_comma_list_3_items(): "a or b,c+d,e" group([ ('NAME', 'a'), ('SPACE', ' '), ('OR', 'or'), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ], [ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ]) def test_implicit_tuple_space(): "a, b , c" group([ ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'c'), ], [ ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_implicit_tuple_one_item(): "a ," group([ ('NAME', 'a'), ('SPACE', ' '), ('COMMA', ','), ], [ ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')]), ]) def test_implicit_tuple_trailing_comma(): "a, b ," group([ ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('COMMA', ','), ], [ ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')]), ]) def test_return(): "return" group([ ('RETURN', 'return'), ], [ ('RETURN', 'return'), ]) def test_return_a(): "return a" group([ ('RETURN', 'return'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('RETURN', 'return', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_yield(): "yield" group([ ('YIELD', 'yield'), ], [ ('YIELD', 'yield'), ]) def test_yield_a(): "yield a" group([ ('YIELD', 'yield'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('YIELD', 'yield', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_del(): "del a" group([ ('DEL', 'del'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('DEL', 'del', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_break(): "break" group([ ('BREAK', 'break'), ], [ ('BREAK', 'break'), ]) def test_continue(): "continue" group([ ('CONTINUE', 'continue'), ], [ ('CONTINUE', 'continue'), ]) def test_pass(): "pass" group([ ('PASS', 'pass'), ], [ ('PASS', 'pass'), ]) def test_assert(): "assert a" group([ ('ASSERT', 'assert'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('ASSERT', 'assert', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_assert_message(): "assert a , b" group([ ('ASSERT', 'assert', [], [('SPACE', ' ')]), ('NAME', 'a'), ('SPACE', ' '), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ], [ ('ASSERT', 'assert', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_raise_empty(): "raise" group([ ('RAISE', 'raise'), ], [ ('RAISE', 'raise'), ]) def test_raise(): "raise a" group([ ('RAISE', 'raise'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_raise_instance(): "raise a, b" group([ ('RAISE', 'raise'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', 'comma'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_raise_instance_traceback(): "raise a, b, c" group([ ('RAISE', 'raise'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', 'comma'), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', 'comma'), ('SPACE', ' '), ('NAME', 'c'), ], [ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_exec(): "exec a" group([ ('EXEC', 'exec'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_exec_in(): "exec a in b" group([ ('EXEC', 'exec'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IN', 'in'), ('SPACE', ' '), ('NAME', 'b'), ], [ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_exec_in_c(): "exec a in b, c" group([ ('EXEC', 'exec'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('IN', 'in'), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'c'), ], [ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_global(): "global a" group([ ('GLOBAL', 'global'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_global_one(): "global a, b" group([ ('GLOBAL', 'global'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ], [ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_global_two(): "global a, b , c" group([ ('GLOBAL', 'global'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'c'), ], [ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ]) def test_nonlocal(): "global a" group([ ('NONLOCAL', 'nonlocal'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('NONLOCAL', 'nonlocal', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_print(): "print" group([ ('PRINT', 'print'), ], [ ('PRINT', 'print'), ]) def test_print_a(): "print a" group([ ('PRINT', 'print'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_print_a_b(): "print a, b" group([ ('PRINT', 'print'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ], [ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_print_a_b_comma(): "print a, b," group([ ('PRINT', 'print'), ('SPACE', ' '), ('NAME', 'a'), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('COMMA', ',', '', ''), ], [ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', '', ''), ]) def test_print_redirect(): "print >> a" group([ ('PRINT', 'print'), ('SPACE', ' '), ('RIGHT_SHIFT', '>>'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_print_redirect_ab(): "print >> a , b" group([ ('PRINT', 'print'), ('SPACE', ' '), ('RIGHT_SHIFT', '>>'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ], [ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ]) def test_print_redirect_ab_comma(): "print >> a , b ," group([ ('PRINT', 'print'), ('SPACE', ' '), ('RIGHT_SHIFT', '>>'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('COMMA', ','), ('SPACE', ' '), ('NAME', 'b'), ('SPACE', ' '), ('COMMA', ','), ], [ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')]), ]) def test_if_a_pass(): "if a : pass" group([ ('IF', 'if'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('COLON', ':'), ('SPACE', ' '), ('PASS', 'pass'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('PASS', 'pass'), ]) def test_if_a_pass_indent(): """ if a: pass """ group([ ('IF', 'if'), ('SPACE', ' '), ('NAME', 'a'), ('SPACE', ' '), ('COLON', ':'), ('ENDL', '\n'), ('INDENT', ''), ('SPACE', ' '), ('PASS', 'pass'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n'), ('INDENT', '', [], [('SPACE', ' ')]), ('PASS', 'pass'), ]) def test_endl_backward(): """ """ group([ ('SPACE', ' '), ('ENDL', '\n'), ], [ ('ENDL', '\n', [('SPACE', ' ')]), ]) def test_endl(): """ """ group([ ('ENDL', '\n'), ('SPACE', ' '), ('ENDL', '\n'), ], [ ('ENDL', '\n', [], [('SPACE', ' ')]), ('ENDL', '\n'), ]) def test_endl_import(): """ """ group([ ('ENDL', '\n'), ('SPACE', ' '), ('IMPORT', 'import'), ], [ ('ENDL', '\n', [], [('SPACE', ' ')]), ('IMPORT', 'import'), ]) def test_while(): """ """ group([ ('WHILE', 'while'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('WHILE', 'while', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_elif(): """ """ group([ ('ELIF', 'elif'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('ELIF', 'elif', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_for(): """ """ group([ ('SPACE', ' '), ('FOR', 'for'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_async_for(): """ """ group([ ('NAME', 'async'), ('SPACE', ' '), ('FOR', 'for'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('NAME', 'async'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_except(): """ """ group([ ('EXCEPT', 'except'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_def(): """ """ group([ ('DEF', 'def'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_async_def(): """ """ group([ ('NAME', 'async'), ('SPACE', ' '), ('DEF', 'def'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('NAME', 'async'), ('SPACE', ' '), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_class(): """ """ group([ ('CLASS', 'class'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_with(): """ """ group([ ('WITH', 'with'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_async_with(): """ """ group([ ('NAME', 'async'), ('SPACE', ' '), ('WITH', 'with'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('NAME', 'async'), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_lambda(): """ """ group([ ('LAMBDA', 'lambda'), ('SPACE', ' '), ('NAME', 'a'), ], [ ('LAMBDA', 'lambda', [], [('SPACE', ' ')]), ('NAME', 'a'), ]) def test_comment(): """ """ group([ ('SPACE', ' '), ('COMMENT', '#'), ], [ ('COMMENT', '#', [('SPACE', ' ')]), ]) def test_repr(): "` " group([ ('BACKQUOTE', '`'), ('SPACE', ' '), ], [ ('BACKQUOTE', '`', [], [('SPACE', ' ')]), ]) def test_semicolon(): " ; " group([ ('SPACE', ' '), ('SEMICOLON', ';'), ('SPACE', ' '), ], [ ('SEMICOLON', ';', [('SPACE', ' ')], [('SPACE', ' ')]), ]) def test_strings(): """ I don't this because python allow to write stuff like 'qsd' rb"qsd" u'pouet' """ for i in ('STRING', 'RAW_STRING', 'UNICODE_STRING', 'INTERPOLATED_STRING', 'UNICODE_RAW_STRING', 'BINARY_STRING', 'INTERPOLATED_RAW_STRING', 'BINARY_RAW_STRING'): group([ ('SPACE', ' '), (i, 'dummy'), ('SPACE', ' '), ], [ (i, 'dummy', [('SPACE', ' ')], [('SPACE', ' ')]), ]) def test_inconsistancy_on_space_grouping(): group([ ('LEFT_PARENTHESIS', '('), ('SPACE', ' '), ('INT', '1'), ('SPACE', ' '), ('RIGHT_PARENTHESIS', ')'), ], [ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('INT', '1'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ]) group([ ('LEFT_PARENTHESIS', '('), ('SPACE', ' '), ('STRING', '"a"'), ('SPACE', ' '), ('RIGHT_PARENTHESIS', ')'), ], [ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('STRING', '"a"'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ]) def test_space_before_comment_simple(): group([ ('ENDL', '\n'), ('SPACE', ' '), ('COMMENT', '# hello'), ('ENDL', '\n'), ], [ ('ENDL', '\n', [], [('SPACE', ' ')]), ('COMMENT', '# hello'), ('ENDL', '\n'), ] ) def test_space_before_comment(): group([ ('ENDL', '\n'), ('SPACE', ' '), ('COMMENT', '# hello'), ('ENDL', '\n'), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 're'), ('ENDL', '\n'), ('COMMENT', '# hi'), ('ENDL', '\n'), ('IMPORT', 'import'), ('SPACE', ' '), ('NAME', 'sys'), ('ENDL', '\n'), ('ENDMARKER', ''), ], [ ('ENDL', '\n', [], [('SPACE', ' ')]), ('COMMENT', '# hello'), ('ENDL', '\n'), ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 're'), ('ENDL', '\n'), ('COMMENT', '# hi'), ('ENDL', '\n'), ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'sys'), ('ENDL', '\n'), ('ENDMARKER', '') ] ) def test_right_arrow(): " -> " group([ ('SPACE', ' '), ('RIGHT_ARROW', '->'), ('SPACE', ' '), ], [ ('RIGHT_ARROW', '->', [('SPACE', ' ')], [('SPACE', ' ')]), ]) baron-0.10.1/tests/test_future.py000066400000000000000000000052561415427440200167720ustar00rootroot00000000000000from baron.future import has_print_function, replace_print_by_name from baron.baron import parse, tokenize import json def print_token_is_a_function(code): return has_print_function(tokenize(code)) def print_is_parsed_as_a_function(parsed_code): code_json = json.dumps(parsed_code) return '"type": "name", "value": "print"' in code_json \ or '"value": "print", "type": "name"' in code_json def test_no_future(): code = "a = 1" assert not print_token_is_a_function(code) def test_other_future(): code = "from __future__ import other" assert not print_token_is_a_function(code) def test_print_future(): code = "from __future__ import print_function" assert print_token_is_a_function(code) def test_print_future_as(): code = "from __future__ import print_function as p_f" assert print_token_is_a_function(code) def test_print_future_comma(): code = "from __future__ import a, b, print_function" assert print_token_is_a_function(code) def test_print_future_comma_as(): code = "from __future__ import a as c, b as d, print_function as e" assert print_token_is_a_function(code) def test_print_no_future_comma_as(): code = "from __future__ import a as c, b as d" assert not print_token_is_a_function(code) def test_print_future_in_parenthesis(): code = "from __future__ import (a, b, print_function)" assert print_token_is_a_function(code) def test_print_future_in_parenthesis_as(): code = "from __future__ import (a as c, b as d, print_function as e)" assert print_token_is_a_function(code) def test_print_no_future_in_parenthesis_as(): code = "from __future__ import (a as c, b as d)" assert not print_token_is_a_function(code) def test_print_future_second(): code = """from __future__ import a, b as e from __future__ import c, print_function""" assert print_token_is_a_function(code) def test_auto_print_as_name(): code = "from __future__ import print_function\nprint(a)" assert print_is_parsed_as_a_function(parse(code)) def test_auto_print_as_print(): code = "print(a)" assert not print_is_parsed_as_a_function(parse(code)) def test_print_as_name(): code = "print(a)" assert print_is_parsed_as_a_function(parse(code, True)) def test_print_as_print(): code = "print(a)" assert not print_is_parsed_as_a_function(parse(code, False)) def test_replace_print_token(): tokens = [('PRINT', 'print'), ('LEFT_PARENTHESIS', '('), ('NAME', 'A'), ('RIGHT_PARENTHESIS', ')'), ('ENDMARKER', '')] after = [('NAME', 'print'), ('LEFT_PARENTHESIS', '('), ('NAME', 'A'), ('RIGHT_PARENTHESIS', ')'), ('ENDMARKER', '')] assert after == replace_print_by_name(tokens) baron-0.10.1/tests/test_grammator.py000066400000000000000000003013221415427440200174420ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- import pytest from baron.parser import ParsingError from .test_utils import parse_simple, parse_multi def test_empty(): "" parse_simple([], []) def test_int(): "1" parse_simple([('INT', '1')], [ { "type": "int", "section": "number", "value": "1", } ]) def test_long(): "123234L" parse_simple([('LONG', '123234L')], [ { "type": "long", "section": "number", "value": "123234L", } ]) def test_name(): "a" parse_simple([('NAME', 'a')], [{"type": "name", "value": "a", }]) def test_string(): ''' "pouet pouet" """pouet pouet""" ''' parse_simple([('STRING', '"pouet pouet"')], [ { "type": "string", "value": '"pouet pouet"', "first_formatting": [], "second_formatting": [], } ]) parse_simple([('STRING', '"""pouet pouet"""')], [ { "type": "string", "value": '"""pouet pouet"""', "first_formatting": [], "second_formatting": [], } ]) def test_file_input_empty(): "" parse_multi([], []) def test_file_input_one_item(): "a" parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_file_input_two_items(): """ a a """ parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_file_input_two_items_endl(): """ a a """ parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, ]) parse_multi([ ('NAME', 'a'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_file_input_simple_stmt_one_item_semicolon(): """ a; """ parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, { "type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_file_input_simple_stmt_two_items_semicolon(): """ a;a """ parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, { "type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, { "type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_file_input_simple_stmt_three_items_semicolon(): """ a;b;a """ parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'b'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": []}, {"type": "name", "value": 'b'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'b'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": []}, {"type": "name", "value": 'b', }, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'b'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": []}, {"type": "name", "value": 'b'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'b'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": []}, {"type": "name", "value": 'b'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'b'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": []}, {"type": "name", "value": 'b', }, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a'}, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';'), ('NAME', 'b'), ('SEMICOLON', ';'), ('NAME', 'a'), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": []}, {"type": "name", "value": 'b'}, {"type": "semicolon", "value": ";", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": 'a', }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_file_input_simple_stmt_one_item_semicolon_space(): """ a ; """ parse_multi([ ('NAME', 'a'), ('SEMICOLON', ';', [('SPACE', ' ')], [('SPACE', ' ')]), ('ENDL', '\n'), ], [ {"type": "name", "value": 'a', }, {"type": "semicolon", "value": ";", "first_formatting": [{"type": "space", "value": ' '}], "second_formatting": [{"type": "space", "value": ' '}], }, {"type": "endl", "value": "\n", "formatting": [], "indent": "", }, ]) def test_ellipsis(): "..." parse_simple([('ELLIPSIS', '...')], [ { "type": "ellipsis", "first_formatting": [], "second_formatting": [], } ]) def test_funcdef_stmt_indent(): """ def a () : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [{"type": "space", "value": " "}], "arguments": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_indent_return_annotation(): """ def a () -> b : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ('RIGHT_ARROW', '->', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "return_annotation": {"type": "name", "value": "b"}, "return_annotation_first_formatting": [{"type": "space", "value": " "}], "return_annotation_second_formatting": [{"type": "space", "value": " "}], "async_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [{"type": "space", "value": " "}], "arguments": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_async(): """ async def a(): pass """ parse_multi([ ('NAME', 'async', [], []), ('SPACE', ' '), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": True, "async_formatting": [{"type": "space", "value": " "}], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "arguments": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_async_bad_keyword(): """ async def a(): pass """ with pytest.raises(ParsingError): parse_multi([ ('NAME', 'not_async', [], []), ('SPACE', ' '), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], []) def test_funcdef_stmt_one_parameter_indent(): """ def a ( x ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": [], "second_formatting": [], "target": { "type": "name", "value": "x", }, "value": {}, } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_one_parameter_typed_indent(): """ def a ( x : int ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'int'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "def_argument", "first_formatting": [], "second_formatting": [], "annotation": {"type": "name", "value": "int"}, "annotation_first_formatting": [{"type": "space", "value": " "}], "annotation_second_formatting": [{"type": "space", "value": " "}], "target": { "type": "name", "value": "x", }, "value": {}, } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_one_parameter_typed_indent_no_format(): """ def a ( x:int ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('COLON', ':', [], []), ('NAME', 'int'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "def_argument", "annotation": {"type": "name", "value": "int"}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": [], "second_formatting": [], "target": { "type": "name", "value": "x", }, "value": {}, } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_star_parameter_typed_indent_no_format(): """ def a ( *x:int ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('STAR', 'x'), ('NAME', 'x'), ('COLON', ':', [], []), ('NAME', 'int'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "list_argument", "annotation": {"type": "name", "value": "int"}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "type": "name", "value": "x", }, } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_double_star_parameter_typed_indent_no_format(): """ def a ( **x:int ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('DOUBLE_STAR', '**'), ('NAME', 'x'), ('COLON', ':', [], []), ('NAME', 'int'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "dict_argument", "annotation": {"type": "name", "value": "int"}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "type": "name", "value": "x", }, } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_one_parameter_comma_indent(): """ def a ( x , ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "name": "a", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": [], "second_formatting": [], "target": { "type": "name", "value": "x", }, "value": {}, }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_funcdef_stmt_one_parameter_comma_default_indent(): """ def a ( x=1 , ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('EQUAL', '='), ('INT', '1'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "name": "a", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": [], "second_formatting": [], "target": { "type": "name", "value": "x", }, "value": { "type": "int", "value": "1", "section": "number", }, }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_funcdef_stmt_two_parameters_typed_with_default_indent(): """ def a ( x : int = 1 , y : List[str] ) : pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'int'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('INT', '1'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'y'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'List'), ('LEFT_SQUARE_BRACKET', '[', [], []), ('NAME', 'str'), ('RIGHT_SQUARE_BRACKET', '[', [], []), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "arguments": [ { "type": "def_argument", "annotation": {"type": "name", "value": "int"}, "annotation_first_formatting": [{"type": "space", "value": " "}], "annotation_second_formatting": [{"type": "space", "value": " "}], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "target": { "type": "name", "value": "x", }, "value": {"section": "number", "type": "int", "value": "1"}, }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "def_argument", "annotation": { "type": "atomtrailers", "value": [ { "type": "name", "value": "List", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": {"type": "name", "value": "str"}, } ] }, "annotation_first_formatting": [{"type": "space", "value": " "}], "annotation_second_formatting": [{"type": "space", "value": " "}], "first_formatting": [], "second_formatting": [], "target": { "type": "name", "value": "y", }, "value": {}, }, ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "formatting": [], "indent": "", "value": "\n" } ], } ]) def test_class_empty(): """ class A: pass """ parse_multi([ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'A'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ], [ { "type": "class", "name": "A", "decorators": [], "parenthesis": False, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "sixth_formatting": [], "inherit_from": [], "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_class_empty_parenthesis(): """ class A ( ) : pass """ parse_multi([ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'A'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')', [], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ], [ { "type": "class", "name": "A", "decorators": [], "parenthesis": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "inherit_from": [], "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_class_inherit(): """ class A ( B ) : pass """ parse_multi([ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'A'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'B'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ], [ { "type": "class", "name": "A", "decorators": [], "parenthesis": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "inherit_from": [ { "type": "name", "value": "B" } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_class_inherit_metaclass(): """ class A ( B = C ) : pass """ parse_multi([ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'A'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'B'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'C'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ], [ { "type": "class", "name": "A", "decorators": [], "parenthesis": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "inherit_from": [ { "first_formatting": [ { "type": "space", "value": " " } ], "second_formatting": [ { "type": "space", "value": " " } ], "target": { "type": "name", "value": "B" }, "type": "call_argument", "value": { "type": "name", "value": "C" } } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_class_inherit_metaclass_arglist(): """ class A ( B, C = D ) : pass """ parse_multi([ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'A'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'B'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'C'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'D'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ], [ { "type": "class", "name": "A", "decorators": [], "parenthesis": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "inherit_from": [ { "type": "name", "value": "B" }, { "first_formatting": [], "second_formatting": [ { "type": "space", "value": " " } ], "type": "comma" }, { "first_formatting": [ { "type": "space", "value": " " } ], "second_formatting": [ { "type": "space", "value": " " } ], "target": { "type": "name", "value": "C" }, "type": "call_argument", "value": { "type": "name", "value": "D" } } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_class_inherit_metaclass_arglist_more(): """ class A ( B, E, F, C = D ) : pass """ parse_multi([ ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'A'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'B'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'E'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'F'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'C'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'D'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ], [ { "type": "class", "name": "A", "decorators": [], "parenthesis": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "fifth_formatting": [{"type": "space", "value": " "}], "sixth_formatting": [], "inherit_from": [ { "type": "name", "value": "B" }, { "first_formatting": [], "second_formatting": [ { "type": "space", "value": " " } ], "type": "comma" }, { "type": "name", "value": "E" }, { "first_formatting": [], "second_formatting": [ { "type": "space", "value": " " } ], "type": "comma" }, { "type": "name", "value": "F" }, { "first_formatting": [], "second_formatting": [ { "type": "space", "value": " " } ], "type": "comma" }, { "first_formatting": [ { "type": "space", "value": " " } ], "second_formatting": [ { "type": "space", "value": " " } ], "target": { "type": "name", "value": "C" }, "type": "call_argument", "value": { "type": "name", "value": "D" } } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_funcdef_stmt_one_start_parameter_indent(): """ def a (*b): pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('STAR', '*'), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "arguments": [ { "type": "list_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "value": "b", "type": "name", } } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_funcdef_stmt_one_star_star_parameter_indent(): """ def a (**b): pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "def", "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "arguments": [ { "type": "dict_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "value": "b", "type": "name", } } ], "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_comment(): """ # comment """ parse_multi([ ('COMMENT', '# comment', [('SPACE', ' ')]), ('ENDL', '\n'), ], [ { "formatting": [{"type": "space", "value": " "}], "type": "comment", "value": "# comment", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ]) def test_comment_consistant(): """ # comment """ parse_multi([ ('COMMENT', '# comment'), ('ENDL', '\n'), ], [ { "formatting": [], "type": "comment", "value": "# comment", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ]) def test_with_a(): """ with a: pass """ parse_multi([ ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "type": "with", "async": False, "async_formatting": [], "contexts": [ { "type": "with_context_item", "value": { "type": "name", "value": "a", }, "first_formatting": [], "second_formatting": [], "as": {}, } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_with_a_as_b(): """ with a as b: pass """ parse_multi([ ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "type": "with", "async": False, "async_formatting": [], "contexts": [ { "type": "with_context_item", "value": { "type": "name", "value": "a", }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "as": { "type": "name", "value": "b", }, } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_with_a_as_b_c(): """ with a as b, c: pass """ parse_multi([ ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "type": "with", "async": False, "async_formatting": [], "contexts": [ { "type": "with_context_item", "value": { "type": "name", "value": "a", }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "as": { "type": "name", "value": "b", }, }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "with_context_item", "value": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [], "as": {}, } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_async_with_a(): """ async with a: pass """ parse_multi([ ('NAME', 'async', [], []), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "type": "with", "async": True, "async_formatting": [{"type": "space", "value": " "}], "contexts": [ { "type": "with_context_item", "value": { "type": "name", "value": "a", }, "first_formatting": [], "second_formatting": [], "as": {}, } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_async_with_a_as_b(): """ async with a as b: pass """ parse_multi([ ('NAME', 'async', [], []), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "type": "with", "async": True, "async_formatting": [{"type": "space", "value": " "}], "contexts": [ { "type": "with_context_item", "value": { "type": "name", "value": "a", }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "as": { "type": "name", "value": "b", }, } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_async_with_a_as_b_c(): """ async with a as b, c: pass """ parse_multi([ ('NAME', 'async', [], []), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "type": "with", "async": True, "async_formatting": [{"type": "space", "value": " "}], "contexts": [ { "type": "with_context_item", "value": { "type": "name", "value": "a", }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "as": { "type": "name", "value": "b", }, }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "with_context_item", "value": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [], "as": {}, } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_async_with_a_bad_keyword(): """ async with a: pass """ with pytest.raises(ParsingError): parse_multi([ ('NAME', 'not_async', [], []), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], []) def test_async_with_a_as_b_bad_keyword(): """ async with a as b: pass """ with pytest.raises(ParsingError): parse_multi([ ('NAME', 'not_async', [], []), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], []) def test_async_with_a_as_b_c_bad_keyword(): """ async with a as b, c: pass """ with pytest.raises(ParsingError): parse_multi([ ('NAME', 'not_async', [], []), ('SPACE', ' '), ('WITH', 'with', [], [('SPACE', ' ')]), ('NAME', 'a'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], []) def test_decorator(): """ @a def b(): pass """ parse_multi([ ('AT', '@', [], []), ('NAME', 'a'), ('ENDL', '\n'), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'b'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [], "name": "b", "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "decorators": [ { "type": "decorator", "formatting": [], "call": {}, "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "a", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_decorator_parenthesis(): """ @a() def b(): pass """ parse_multi([ ('AT', '@', [], []), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('ENDL', '\n'), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'b'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [], "name": "b", "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "decorators": [ { "type": "decorator", "formatting": [], "call": { "third_formatting": [], "type": "call", "first_formatting": [], "value": [], "second_formatting": [], "fourth_formatting": [], }, "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "a", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_decorator_parenthesis_arg(): """ @a(c) def b(): pass """ parse_multi([ ('AT', '@', [], []), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')'), ('ENDL', '\n'), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'b'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [], "name": "b", "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "decorators": [ { "type": "decorator", "formatting": [], "call": { "third_formatting": [], "type": "call", "fourth_formatting": [], "first_formatting": [], "value": [ { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "c", }, } ], "second_formatting": [], }, "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "a", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_decorator_two(): """ @a @ c def b(): pass """ parse_multi([ ('AT', '@', [], []), ('NAME', 'a'), ('ENDL', '\n'), ('AT', '@', [], [('SPACE', ' ')]), ('NAME', 'c'), ('ENDL', '\n'), ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'b'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [], "name": "b", "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "decorators": [ { "type": "decorator", "formatting": [], "call": {}, "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "a", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", }, { "type": "decorator", "formatting": [{"type": "space", "value": " "}], "call": {}, "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "c", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_class_decorator(): """ @a class b(): pass """ parse_multi([ ('AT', '@', [], []), ('NAME', 'a'), ('ENDL', '\n'), ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'b'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "class", "inherit_from": [], "parenthesis": True, "name": "b", "decorators": [ { "type": "decorator", "call": {}, "formatting": [], "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "a", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_class_decorator_two(): """ @a @ c class b(): pass """ parse_multi([ ('AT', '@', [], []), ('NAME', 'a'), ('ENDL', '\n'), ('AT', '@', [], [('SPACE', ' ')]), ('NAME', 'c'), ('ENDL', '\n'), ('CLASS', 'class', [], [('SPACE', ' ')]), ('NAME', 'b'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "class", "inherit_from": [], "parenthesis": True, "name": "b", "decorators": [ { "type": "decorator", "call": {}, "formatting": [], "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "a", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", }, { "type": "decorator", "call": {}, "formatting": [{"type": "space", "value": " "}], "value": { "type": "dotted_name", "value": [ { "type": "name", "value": "c", } ], } }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_fplist(): """ def a((b,)): pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ','), ('RIGHT_PARENTHESIS', ')'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [ { "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": [], "second_formatting": [], "value": {}, "target": { "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "type": "tuple", "with_parenthesis": True, "value": [ { "value": "b", "type": "name", }, { "first_formatting": [], "second_formatting": [], "type": "comma", } ], }, } ], "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_fplist_two(): """ def a((b,c)): pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [ { "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "first_formatting": [], "second_formatting": [], "value": {}, "target": { "type": "tuple", "with_parenthesis": True, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "c", } ], } } ], "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_fplist_alone(): """ def a((b)): pass """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fifth_formatting": [], "fourth_formatting": [], "sixth_formatting": [{"type": "space", "value": " "}], "type": "def", "arguments": [ { "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "value": {}, "first_formatting": [], "second_formatting": [], "target": { "type": "associative_parenthesis", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "name", "value": "b", } } } ], "name": "a", "decorators": [], "async": False, "async_formatting": [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ], } ]) def test_endl_dont_grab_comment_as_indent(): """ \n# pouet """ parse_multi([ ('ENDL', '\n', [], [('COMMENT', '# pouet')]) ], [ {"type": "endl", "value": "\n", "indent": "", "formatting": []}, {"type": "comment", "value": "# pouet", "formatting": []}, ]) def test_regression_def_argument_tuple(): """ def function_name((a,b)=c):\n pass\n """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'function_name'), ('LEFT_PARENTHESIS', '('), ('LEFT_PARENTHESIS', '('), ('NAME', 'a'), ('COMMA', ','), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')'), ('EQUAL', '='), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], []), ('DEDENT', ''), ('ENDMARKER', '') ], [ { 'arguments': [ { 'first_formatting': [], 'second_formatting': [], 'type': 'def_argument', "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], 'target': { 'type': 'tuple', 'first_formatting': [], 'with_parenthesis': True, 'fourth_formatting': [], 'second_formatting': [], 'third_formatting': [], 'value': [ { 'value': 'a', 'type': 'name', }, { 'first_formatting': [], 'second_formatting': [], 'type': 'comma' }, { 'value': 'b', 'type': 'name', } ] }, 'value': { 'type': 'name', 'value': 'c', } } ], 'decorators': [], 'async': False, 'async_formatting': [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], 'fifth_formatting': [], 'first_formatting': [ { 'type': 'space', 'value': ' ' } ], 'fourth_formatting': [], 'name': 'function_name', 'second_formatting': [], 'sixth_formatting': [], 'third_formatting': [], 'type': 'def', 'value': [ { 'formatting': [], 'indent': ' ', 'type': 'endl', 'value': '\n' }, { 'type': 'pass' }, { 'formatting': [], 'indent': '', 'type': 'endl', 'value': '\n' } ] } ]) def test_regression_def_argument_tuple_nested(): """ def function_name((a,(x,y))=c):\n pass\n """ parse_multi([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'function_name'), ('LEFT_PARENTHESIS', '('), ('LEFT_PARENTHESIS', '('), ('NAME', 'a'), ('COMMA', ','), ('LEFT_PARENTHESIS', '('), ('NAME', 'x'), ('COMMA', ','), ('NAME', 'y'), ('RIGHT_PARENTHESIS', ')'), ('RIGHT_PARENTHESIS', ')'), ('EQUAL', '='), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ENDMARKER', ''), ], [ { 'arguments': [ { 'first_formatting': [], 'second_formatting': [], "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], 'type': 'def_argument', 'target': { 'type': 'tuple', 'first_formatting': [], 'with_parenthesis': True, 'fourth_formatting': [], 'second_formatting': [], 'third_formatting': [], 'value': [ { 'value': 'a', 'type': 'name', }, { 'first_formatting': [], 'second_formatting': [], 'type': 'comma' }, { 'type': 'tuple', 'first_formatting': [], 'with_parenthesis': True, 'fourth_formatting': [], 'second_formatting': [], 'third_formatting': [], 'value': [ { 'value': 'x', 'type': 'name', }, { 'first_formatting': [], 'second_formatting': [], 'type': 'comma' }, { 'value': 'y', 'type': 'name', }, ] }, ] }, 'value': { 'type': 'name', 'value': 'c', } } ], 'decorators': [], 'async': False, 'async_formatting': [], "return_annotation": {}, "return_annotation_first_formatting": [], "return_annotation_second_formatting": [], 'fifth_formatting': [], 'first_formatting': [ { 'type': 'space', 'value': ' ' } ], 'fourth_formatting': [], 'name': 'function_name', 'second_formatting': [], 'sixth_formatting': [], 'third_formatting': [], 'type': 'def', 'value': [ { 'formatting': [], 'indent': ' ', 'type': 'endl', 'value': '\n' }, { 'type': 'pass' }, { 'formatting': [], 'indent': '', 'type': 'endl', 'value': '\n' } ] } ]) def test_standalone_annotation(): """ x : int """ parse_simple([ ('NAME', 'x'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'int'), ], [ { "type": "standalone_annotation", "annotation": {"type": "name", "value": "int"}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "target": {"type": "name", "value": "x"}, } ]) def test_typed_variable_with_assignment(): """ x : int = 1 """ parse_simple([ ('NAME', 'x'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'int'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('INT', '1'), ], [ { "type": "assignment", "annotation": {"type": "name", "value": "int"}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "annotation_first_formatting": [{"type": "space", "value": " "}], "annotation_second_formatting": [{"type": "space", "value": " "}], "target": {"type": "name", "value": "x"}, "operator": "", "value": {"section": "number", "type": "int", "value": "1"} } ]) baron-0.10.1/tests/test_grammator_control_structures.py000066400000000000000000001571051415427440200235150ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- import pytest from baron.parser import ParsingError from .test_utils import parse_multi def test_if_stmt(): "if a: pass" parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('PASS', 'pass'), ('ENDL', '\n'), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ], } ]) def test_if_stmt_indent(): """ if a: pass """ parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "formatting": [], "type": "endl", "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ] } ]) def test_if_stmt_indent_two_endls(): """ if a: pass """ parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": "" }, { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ] } ]) def test_if_stmt_indent_multiple_endls(): """ if a: pass """ parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": "" }, { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ] } ]) def test_if_else_stmt_indent(): """ if a: pass else: pass """ parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else', [], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], }, { "type": "else", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ] } ] } ]) def test_if_elif_elif_stmt_indent(): """ if a: pass elif b: pass elif c : pass """ parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELIF', 'elif', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELIF', 'elif', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], }, { "type": "elif", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "b", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], }, { "type": "elif", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "test": { "type": "name", "value": "c", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ] } ]) def test_if_elif_elif_else_stmt_indent(): """ if a: pass elif b: pass elif c : pass else: pass """ parse_multi([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELIF', 'elif', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELIF', 'elif', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else', [], [('SPACE', ' ')]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "ifelseblock", "value": [ { "type": "if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], }, { "type": "elif", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "b", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "value": "\n", "formatting": [], "indent": "", } ], }, { "type": "elif", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "test": { "type": "name", "value": "c", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], }, { "type": "else", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "value": [ { "formatting": [], "type": "endl", "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n", } ] } ] } ]) def test_while_stmt_indent(): """ while a: pass """ parse_multi([ ('WHILE', 'while', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "while", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "else": {}, "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_while_stmt_indent_third_formatting(): """ while a : pass """ parse_multi([ ('WHILE', 'while', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "while", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "else": {}, "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_while_else_stmt_indent(): """ while a: pass else: pass """ parse_multi([ ('WHILE', 'while', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else', [], [('SPACE', " ")]), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "while", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "test": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], "else": { "type": "else", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n", } ] } } ]) def test_for_stmt_indent(): """ for i in a: pass """ parse_multi([ ('FOR', 'for', [], [('SPACE', ' ')]), ('NAME', 'i'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "for", "async": False, "async_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], "else": {}, "iterator": { "type": "name", "value": "i", }, "target": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_async_for_stmt_indent(): """ async for i in a: pass """ parse_multi([ ('NAME', 'async', [], []), ('SPACE', ' '), ('FOR', 'for', [], [('SPACE', ' ')]), ('NAME', 'i'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "for", "async": True, "async_formatting": [{"type": "space", "value": " "}], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], "else": {}, "iterator": { "type": "name", "value": "i", }, "target": { "type": "name", "value": "a", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_async_for_stmt_indent_bad_keyword(): """ not_async for i in a: pass """ with pytest.raises(ParsingError): parse_multi([ ('NAME', 'not_async', [], []), ('SPACE', ' '), ('FOR', 'for', [], [('SPACE', ' ')]), ('NAME', 'i'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], []) def test_for_else_stmt_indent(): """ for i in b: pass else: pass """ parse_multi([ ('FOR', 'for', [], [('SPACE', ' ')]), ('NAME', 'i'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "for", "async": False, "async_formatting": [], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "else": { "type": "else", "first_formatting": [], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n", } ] }, "iterator": { "type": "name", "value": "i", }, "target": { "type": "name", "value": "b", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_async_for_else_stmt_indent(): """ async for i in b: pass else: pass """ parse_multi([ ('NAME', 'async', [], []), ('SPACE', ' '), ('FOR', 'for', [], [('SPACE', ' ')]), ('NAME', 'i'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "for", "async": True, "async_formatting": [{"type": "space", "value": " "}], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "else": { "type": "else", "first_formatting": [], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n", } ] }, "iterator": { "type": "name", "value": "i", }, "target": { "type": "name", "value": "b", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_async_for_else_stmt_indent_bad_keyword(): """ async for i in b: pass else: pass """ with pytest.raises(ParsingError): parse_multi([ ('NAME', 'not_async', [], []), ('SPACE', ' '), ('FOR', 'for', [], [('SPACE', ' ')]), ('NAME', 'i'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], []) def test_try_finally_stmt_indent(): """ try : pass finally : pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('FINALLY', 'finally'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": {}, "finally": { "type": "finally", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], }, "excepts": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_try_excepts_stmt_empty(): """ try : pass except: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], []), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": {}, "finally": {}, "excepts": [ { "type": "except", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "delimiter": "", "target": {}, "exception": {}, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ] } ], "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_try_excepts_stmt_indent(): """ try : pass except IOError: pass except Exception: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'IOError'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'Exception'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": {}, "finally": {}, "excepts": [ { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "delimiter": "", "target": {}, "exception": { "type": "name", "value": "IOError", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ] }, { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "delimiter": "", "target": {}, "exception": { "type": "name", "value": "Exception", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ] } ], "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ], } ]) def test_try_except_comma_stmt_indent(): """ try : pass except IOError, e: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'IOError'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": {}, "finally": {}, "excepts": [ { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "delimiter": ",", "target": { "type": "name", "value": "a" }, "exception": { "type": "name", "value": "IOError", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "indent": "", "formatting": [], "type": "endl", "value": "\n" } ] } ], "value": [ { "formatting": [], "type": "endl", "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_try_except_comma_stmt_else_indent(): """ try : pass except IOError, e: pass else: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'IOError'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": { "type": "else", "first_formatting": [], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "value": "\n", "formatting": [], "indent": "" } ] }, "finally": {}, "excepts": [ { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "delimiter": ",", "target": { "type": "name", "value": "a" }, "exception": { "type": "name", "value": "IOError", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ] } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_try_except_comma_stmt_else_finally_indent(): """ try : pass except IOError, e: pass else: pass finally: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'IOError'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('FINALLY', 'finally'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": { "type": "else", "first_formatting": [], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "value": "\n", "formatting": [], "indent": "" } ] }, "finally": { "type": "finally", "first_formatting": [], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "type": "endl", "value": "\n", "formatting": [], "indent": "", } ], }, "excepts": [ { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "delimiter": ",", "target": { "type": "name", "value": "a" }, "exception": { "type": "name", "value": "IOError", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ] } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_try_except_comma_stmt_finally_indent(): """ try : pass except IOError, e: pass finally: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'IOError'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('FINALLY', 'finally'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": {}, "finally": { "type": "finally", "first_formatting": [], "second_formatting": [], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], }, "excepts": [ { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "delimiter": ",", "target": { "type": "name", "value": "a" }, "exception": { "type": "name", "value": "IOError", }, "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ] } ], "value": [ { "type": "endl", "formatting": [], "value": "\n", "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) def test_try_except_as_stmt_indent(): """ try : pass except IOError as e: pass """ parse_multi([ ('TRY', 'try'), ('COLON', ':', [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('EXCEPT', 'except', [], [('SPACE', ' ')]), ('NAME', 'IOError'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ], [ { "type": "try", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "else": {}, "finally": {}, "excepts": [ { "type": "except", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], "delimiter": "as", "target": { "type": "name", "value": "a" }, "exception": { "type": "name", "value": "IOError", }, "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ] } ], "value": [ { "type": "endl", "value": "\n", "formatting": [], "indent": " " }, { "type": "pass", }, { "formatting": [], "indent": "", "type": "endl", "value": "\n" } ], } ]) baron-0.10.1/tests/test_grammator_data_structures.py000066400000000000000000001605361415427440200227500ustar00rootroot00000000000000# encoding: utf-8 from .test_utils import parse_simple def test_empty_tuple(): "()" parse_simple([ ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ], [ { "with_parenthesis": True, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "type": "tuple", "value": [], } ]) def test_empty_tuple_space(): "( )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ], [ { "with_parenthesis": True, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "type": "tuple", "value": [], } ]) def test_associative_parenthesis(): "( a )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "associative_parenthesis", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "value": { "type": "name", "value": "a", }, } ]) def test_tuple_one(): "( a, )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')', [], []), ], [ { "with_parenthesis": True, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "type": "tuple", "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], } ], } ]) def test_tuple_many(): "(a, b, c)" parse_simple([ ('LEFT_PARENTHESIS', '(', [], []), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')', [], []), ], [ { "with_parenthesis": True, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "type": "tuple", "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "c", } ], } ]) def test_empty_list(): "[ ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('RIGHT_SQUARE_BRACKET', ']', [], []), ], [ { "type": "list", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "value": [], } ]) def test_list_one(): "[ a ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", } ], } ]) def test_list_more(): "[a, b, c]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], []), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']', [], []), ], [ { "type": "list", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "c", } ], } ]) def test_dict_empty(): "{ }" parse_simple([ ('LEFT_BRACKET', '{', [], [('SPACE', ' ')]), ('RIGHT_BRACKET', '}', [], []), ], [ { "type": "dict", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "value": [], } ]) def test_dict_one_colon(): "{a: b}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'b'), ('RIGHT_BRACKET', '}', [], []), ], [ { "type": "dict", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "dictitem", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "key": { "type": "name", "value": "a", }, "value": { "type": "name", "value": "b", } } ], } ]) def test_dict_one_double_star(): "{**a}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('DOUBLE_STAR', '**'), ('NAME', 'a'), ('RIGHT_BRACKET', '}', [], []), ], [ { 'type': 'dict', 'first_formatting': [], 'second_formatting': [], 'third_formatting': [], 'fourth_formatting': [], 'value': [ { 'type': 'dict_argument', 'annotation': {}, 'annotation_first_formatting': [], 'annotation_second_formatting': [], 'formatting': [], 'value': {'type': 'name', 'value': 'a'} } ] } ] ) def test_dict_more_colon(): "{a: b, b: c, c: d}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_BRACKET', '}', [], []), ], [ { "type": "dict", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "dictitem", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "key": { "type": "name", "value": "a", }, "value": { "type": "name", "value": "b", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "dictitem", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "key": { "type": "name", "value": "b", }, "value": { "type": "name", "value": "c", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "dictitem", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "key": { "type": "name", "value": "c", }, "value": { "type": "name", "value": "d", } } ], } ]) def test_dict_more_double_star(): "{**a, b: c}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('DOUBLE_STAR', '**'), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_BRACKET', '}', [], []), ], [ { "first_formatting": [], "fourth_formatting": [], "second_formatting": [], "third_formatting": [], "type": "dict", "value": [ { "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "type": "dict_argument", "value": { "type": "name", "value": "a" } }, { "first_formatting": [], "second_formatting": [ { "type": "space", "value": " " } ], "type": "comma" }, { "first_formatting": [], "key": { "type": "name", "value": "b" }, "second_formatting": [ { "type": "space", "value": " " } ], "type": "dictitem", "value": { "type": "name", "value": "c" } } ] } ]) def test_set_one(): "{a}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('NAME', 'a'), ('RIGHT_BRACKET', '}', [], []), ], [ { "type": "set", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", } ], } ]) def test_set_one_comma(): "{a,}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('NAME', 'a'), ('COMMA', ','), ('RIGHT_BRACKET', '}', [], []), ], [ { "type": "set", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [], } ], } ]) def test_set_more(): "{a, b, c}" parse_simple([ ('LEFT_BRACKET', '{', [], []), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_BRACKET', '}', [], []), ], [ { "type": "set", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "c", } ], } ]) def test_generator_comprehension(): "( a for b in c )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "generator_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [], } ] } ]) def test_generator_comprehension_if(): "( a for b in c if d )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "generator_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "d" }, } ], } ] } ]) def test_generator_comprehension_if_if(): "( a for b in c if d if e )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'e'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "generator_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "d" }, }, { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "e" }, } ], } ] } ]) def test_generator_comprehension_double(): "( a for b in c for d in e )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'e'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "generator_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [], }, { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "d", }, "target": { "type": "name", "value": "e", }, "ifs": [], } ] } ]) def test_generator_comprehension_double_if_if(): "( a for b in c if x for d in e if y )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'e'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'y'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "generator_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "x" }, } ], }, { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "d", }, "target": { "type": "name", "value": "e", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "y" }, } ], } ] } ]) def test_list_comprehension(): "[ a for b in c ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [], } ] } ]) def test_list_comprehension_if(): "[ a for b in c if d ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "d" }, } ], } ] } ]) def test_list_comprehension_if_if(): "[ a for b in c if d if d ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "d" }, }, { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "d" }, } ], } ] } ]) def test_list_comprehension_tuple(): "[ a for b in c, d ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "c", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "d", } ], }, "ifs": [], } ] } ]) def test_list_comprehension_tuple_more(): "[ a for b in c, d, e ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'e'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "c", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "d", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "e", } ], }, "ifs": [], } ] } ]) def test_list_comprehension_lambda(): "[ a for b in lambda: c ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('LAMBDA', 'lambda', [], []), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "lambda", "first_formatting": [], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "arguments": [], "value": { "type": "name", "value": "c", } }, "ifs": [], } ] } ]) def test_list_comprehension_lambda_with_arguments(): "[ a for b in lambda argument: c ]" parse_simple([ ('LEFT_SQUARE_BRACKET', '[', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('LAMBDA', 'lambda', [], [('SPACE', ' ')]), ('NAME', 'argument'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "list_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "lambda", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "arguments": [ { "value": {}, "first_formatting": [], "second_formatting": [], "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "type": "def_argument", "target": { "type": "name", "value": "argument", } } ], "value": { "type": "name", "value": "c", } }, "ifs": [], } ] } ]) def test_set_comprehension(): "{ a for b in c }" parse_simple([ ('LEFT_BRACKET', '{', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_BRACKET', '}', [('SPACE', ' ')]), ], [ { "type": "set_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [], } ] } ]) def test_set_comprehension_if(): "{ a for b in c if d }" parse_simple([ ('LEFT_BRACKET', '{', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_BRACKET', '}', [('SPACE', ' ')]), ], [ { "type": "set_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "d" }, } ], } ] } ]) def test_set_comprehension_double_if_if(): "{ a for b in c if x for d in e if y }" parse_simple([ ('LEFT_BRACKET', '{', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'x'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'e'), ('IF', 'if', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'y'), ('RIGHT_BRACKET', '}', [('SPACE', ' ')]), ], [ { "type": "set_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "type": "name", "value": "a", }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "x" }, } ], }, { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "d", }, "target": { "type": "name", "value": "e", }, "ifs": [ { "type": "comprehension_if", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "y" }, } ], } ] } ]) def test_dict_comprehension(): "{ a: x for b in c }" parse_simple([ ('LEFT_BRACKET', '{', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'x'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_BRACKET', '}', [('SPACE', ' ')]), ], [ { "type": "dict_comprehension", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "result": { "key": { "type": "name", "value": "a", }, "first_formatting": [], "type": "dictitem", "second_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "x", }, }, "generators": [ { "type": "comprehension_loop", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "iterator": { "type": "name", "value": "b", }, "target": { "type": "name", "value": "c", }, "ifs": [], } ] } ]) def test_yield_atom_empty(): "( yield )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('YIELD', 'yield', [], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')', []), ], [ { "type": "yield_atom", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "value": None, } ]) def test_yield_atom(): "( yield a )" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('SPACE', ' ')]), ('YIELD', 'yield', [], [('SPACE', ' ')]), ('NAME', 'a'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "yield_atom", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "a", }, } ]) def test_repr_quote(): "` a `" parse_simple([ ('BACKQUOTE', '`', [], [('SPACE', ' ')]), ('NAME', 'a'), ('BACKQUOTE', '`', [('SPACE', ' ')]), ], [ { "type": "repr", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": [ { "type": "name", "value": "a", } ], } ]) def test_repr_quote_double(): "` a, b `" parse_simple([ ('BACKQUOTE', '`', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('BACKQUOTE', '`', [('SPACE', ' ')]), ], [ { "type": "repr", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "value": [ { "type": "name", "value": "a", }, { "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "type": "comma", }, { "type": "name", "value": "b", } ], } ]) def test_empty_tuple_endl(): "(\n)" parse_simple([ ('LEFT_PARENTHESIS', '(', [], [('ENDL', '\n')]), ('RIGHT_PARENTHESIS', ')'), ], [ { "with_parenthesis": True, "first_formatting": [], "second_formatting": [ { "indent": "", "formatting": [], "type": "endl", "value": "\n", } ], "third_formatting": [], "fourth_formatting": [], "type": "tuple", "value": [], } ]) def test_subscript_special_case(): "z[a, b, c,]" parse_simple([ ('NAME', 'z'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ','), ('RIGHT_SQUARE_BRACKET', ']') ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "z" }, { "first_formatting": [], "type": "getitem", "value": { "first_formatting": [], "with_parenthesis": False, "third_formatting": [], "fourth_formatting": [], "type": "tuple", "value": [ { "type": "name", "value": "a" }, { "first_formatting": [], "type": "comma", "second_formatting": [ { "type": "space", "value": " " } ] }, { "type": "name", "value": "b" }, { "first_formatting": [], "type": "comma", "second_formatting": [ { "type": "space", "value": " " } ] }, { "type": "name", "value": "c" }, { "first_formatting": [], "type": "comma", "second_formatting": [] } ], "second_formatting": [] }, "second_formatting": [], "third_formatting": [], "fourth_formatting": [] } ] } ]) baron-0.10.1/tests/test_grammator_imports.py000066400000000000000000001227171415427440200212300ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- from .test_utils import parse_simple def test_simple_import(): "import pouet" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": "pouet", } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], } ]) def test_import_basic_dot(): "import pouet.blob" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": "pouet", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "blob" } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob') ], [ { "type": "import", "value": [ { "value": [ {"type": "name", "value": "pouet"}, { "type": "dot", "first_formatting": [], "second_formatting": [], }, {"type": "name", "value": "blob", } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_import_more_dot(): "import pouet.blob .plop" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('DOT', '.'), ('NAME', 'blob'), ('DOT', '.', [('SPACE', ' ')]), ('NAME', 'plop') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": "pouet", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "blob" }, { "type": "dot", "first_formatting": [ { "type": "space", "value": " ", } ], "second_formatting": [], }, { "type": "name", "value": "plop" } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_import_as(): "import pouet as b" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'pouet'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": "pouet", } ], "second_formatting": [{"type": "space", "value": " "}], "first_formatting": [{"type": "space", "value": " "}], "target": 'b', "type": "dotted_as_name", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_import_a_b(): "import a, b" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": 'a', } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "value": [ { "type": "name", "value": 'b' } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_import_a_b_as_c(): "import a, b.d as c" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'd'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": 'a', } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "value": [ { "type": "name", "value": 'b' }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'd' } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "target": "c", "type": "dotted_as_name", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_import_a_b_c_d(): "import a, b, c, d" parse_simple([ ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ], [ { "type": "import", "value": [ { "value": [ { "type": "name", "value": 'a', } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "value": [ { "type": "name", "value": 'b' } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "value": [ { "type": "name", "value": 'c' } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "value": [ { "type": "name", "value": 'd' } ], "type": "dotted_as_name", "first_formatting": [], "second_formatting": [], "target": "" } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_b(): "from a import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_dot_c_import_b(): "from a.C import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'c' } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a' }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'c', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_dot_c_import_b_d(): "from a.c import b, d" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'c' } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "type": "name_as_name", "value": 'd', "first_formatting": [], "second_formatting": [], "target": "" } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ( 'FROM', 'from', [], [('SPACE', ' ')] ), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'c' } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "type": "name_as_name", "value": 'd', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ( 'FROM', 'from', [], [('SPACE', ' ')] ), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a' }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'c', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "type": "name_as_name", "value": 'd', "first_formatting": [], "second_formatting": [], "target": "" } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('DOT', '.'), ('NAME', 'c'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'd') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a' }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'c', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "" }, { "type": "comma", "first_formatting": [], "second_formatting": [ { "type": "space", "value": " ", } ], }, { "type": "name_as_name", "value": 'd', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_b_as_d(): "from a import b as d" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('AS', 'as', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a' } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "target": "d", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_parenthesis_b(): "from a import (b)" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "left_parenthesis", "value": "(", }, { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", }, { "type": "right_parenthesis", "value": ")", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_parenthesis_b_without_space(): "from a import(b)" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "left_parenthesis", "value": "(", }, { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", }, { "type": "right_parenthesis", "value": ")", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [] } ]) def test_from_a_import_parenthesis_b_comma(): "from a import (b,)" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ','), ('RIGHT_PARENTHESIS', ')') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "left_parenthesis", "value": "(", }, { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", }, { "type": "comma", "first_formatting": [], "second_formatting": [], }, { "type": "right_parenthesis", "value": ")", }, ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_parenthesis_b_space(): "from a import (b )" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')', [('SPACE', ' ')]), ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "left_parenthesis", "value": "(", }, { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", }, { "type": "space", "value": " ", }, { "type": "right_parenthesis", "value": ")", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_star(): "from a import *" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('STAR', '*') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "star", "value": "*", "first_formatting": [], "second_formatting": [], } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_a_import_star_without_space(): "from a import*" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')]), ('STAR', '*') ], [ { "type": "from_import", "value": [ { "type": "name", "value": 'a', } ], "targets": [ { "type": "star", "value": "*", "first_formatting": [], "second_formatting": [], } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [] } ]) def test_from_dot_a_import_b(): "from .a import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'a', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_dot_dot_dot_a_import_b(): "from ...a import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('DOT', '.'), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'a', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('DOT', '.'), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'a', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('DOT', '.'), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'a', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_no_space_dot_a_import_b(): "from.a import b" parse_simple([ ('FROM', 'from'), ('DOT', '.'), ('NAME', 'a'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": 'a', } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_dot_import_b(): "from . import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_dot_dot_dot_import_b(): "from ... import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('ELLIPSIS', '...'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "ellipsis", "first_formatting": [], "second_formatting": [], } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_dot_no_space_import_b(): "from .import b" parse_simple([ ('FROM', 'from', [], [('SPACE', ' ')]), ('DOT', '.'), ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_no_space_dot_import_b(): "from. import b" parse_simple([ ('FROM', 'from'), ('DOT', '.'), ('IMPORT', 'import', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_from_no_space_dot_no_sapceimport_b(): "from.import b" parse_simple([ ('FROM', 'from'), ('DOT', '.'), ('IMPORT', 'import', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "from_import", "value": [ { "type": "dot", "first_formatting": [], "second_formatting": [], } ], "targets": [ { "type": "name_as_name", "value": 'b', "first_formatting": [], "second_formatting": [], "target": "", } ], "first_formatting": [], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}] } ]) # TODO: 'from. .import* baron-0.10.1/tests/test_grammator_operators.py000066400000000000000000010757361415427440200215620ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- import pytest from baron.parser import ParsingError from .test_utils import parse_simple def test_simple_power(): "a**b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_first_space_power(): "a **b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_second_space_power(): "a** b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_spaces_power(): "a ** b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_power(): "a ** b ** c" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'a'}, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'b'}, "second": {"type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_power_spaces(): "a** b ** c" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'b'}, "second": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'a'}, "second": { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'b', }, "second": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'a'}, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b', }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [], [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) "a **b ** c" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b', }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b', }, "second": { "type": "name", "value": 'c' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')]), ('NAME', 'b'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) "a**b**c" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b', }, "second": { "type": "name", "value": 'c' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b', }, "second": { "type": "name", "value": 'c' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c') ], [ { "type": "binary_operator", "value": '**', "first": {"type": "name", "value": 'a'}, "second": { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'b' }, "second": { "type": "name", "value": 'c', }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) def test_power_factor(): "a ** +b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('PLUS', '+'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": '+', "target": { "type": "name", "value": 'b' }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('PLUS', '+'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": '+', "target": { "type": "name", "value": 'b', }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_factor_minus(): "a ** -b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": '-', "target": { "type": "name", "value": 'b' }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": '-', "target": { "type": "name", "value": 'b', }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_factor_tild(): "a ** ~b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "name", "value": 'b' }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "name", "value": 'b', }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_operator_madness(): "a ** ~+-b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "unitary_operator", "value": '+', "target": { "type": "unitary_operator", "value": "-", "target": { "type": "name", "value": 'b' }, "formatting": [], }, "formatting": [], }, "formatting": [] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "unitary_operator", "value": '+', "target": { "type": "unitary_operator", "value": "-", "target": { "type": "name", "value": 'b', }, "formatting": [], }, "formatting": [], }, "formatting": [] }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "unitary_operator", "value": '+', "target": { "type": "unitary_operator", "value": "-", "target": { "type": "name", "value": 'b' }, "formatting": [], }, "formatting": [] }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ( 'NAME', 'a' ), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "unitary_operator", "value": '+', "target": { "type": "unitary_operator", "value": "-", "target": { "type": "name", "value": 'b', }, "formatting": [], }, "formatting": [] }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ( 'NAME', 'a' ), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": "~", "target": { "type": "unitary_operator", "value": '+', "target": { "type": "unitary_operator", "value": "-", "target": { "type": "name", "value": 'b' }, "formatting": [] }, "formatting": [], }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~'), ('PLUS', '+'), ('MINUS', '-'), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": "~", "target": { "type": "unitary_operator", "value": '+', "target": { "type": "unitary_operator", "value": "-", "target": { "type": "name", "value": 'b', }, "formatting": [] }, "formatting": [], }, "formatting": [], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_factor_tild_space(): "a ** ~ b" parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a', }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "name", "value": 'b' }, "formatting": [{"type": "space", "value": " "}], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_STAR', '**', [('SPACE', ' ')], [('SPACE', ' ')]), ('TILDE', '~', [], [('SPACE', ' ')]), ('NAME', 'b') ], [ { "type": "binary_operator", "value": '**', "first": { "type": "name", "value": 'a' }, "second": { "type": "unitary_operator", "value": '~', "target": { "type": "name", "value": 'b', }, "formatting": [{"type": "space", "value": " "}], }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_power_trailer(): "a.b" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", }, ], } ]) def test_power_trailer_spaces(): "a .b" "a. b" "a . b" parse_simple([ ('NAME', 'a'), ('DOT', '.', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], }, { "type": "name", "value": "b", }, ], } ]) parse_simple([ ('NAME', 'a'), ('DOT', '.', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, ], } ]) parse_simple([ ('NAME', 'a'), ('DOT', '.', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, ], } ]) def test_power_trailers(): "a.b.c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'c'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "c", }, ], } ]) "a.b.c.d.e" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOT', '.'), ('NAME', 'c'), ('DOT', '.'), ('NAME', 'd'), ('DOT', '.'), ('NAME', 'e'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "c", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "d", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "e", }, ], } ]) def test_power_trailers_space(): "a . b . c" parse_simple([ ('NAME', 'a'), ('DOT', '.', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('DOT', '.', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, { "type": "dot", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "c", }, ], } ]) def test_power_trailer_power(): "a.b**c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOUBLE_STAR', '**'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": "**", "first_formatting": [], "second_formatting": [], "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": "c", } } ]) def test_term_mult(): "a*b" parse_simple([ ('NAME', 'a'), ('STAR', '*'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('STAR', '*'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_term_mult_first_space(): "a *b" parse_simple([ ('NAME', 'a'), ('STAR', '*', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('STAR', '*', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_term_mult_second_space(): "a* b" parse_simple([ ('NAME', 'a'), ('STAR', '*', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('STAR', '*', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_mult_spaces(): "a * b" parse_simple([ ('NAME', 'a'), ('STAR', '*', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('STAR', '*', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_mult_spaces_atomtrailers(): "a.b * c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('STAR', '*', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '*', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_div(): "a/b" parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_term_div_first_space(): "a /b" parse_simple([ ('NAME', 'a'), ('SLASH', '/', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_term_div_second_space(): "a/ b" parse_simple([ ('NAME', 'a'), ('SLASH', '/', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_div_spaces(): "a / b" parse_simple([ ('NAME', 'a'), ('SLASH', '/', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_div_spaces_atomtrailers(): "a.b / c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('SLASH', '/', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_modulo(): "a%b" parse_simple([ ('NAME', 'a'), ('PERCENT', '%'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PERCENT', '%'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_term_modulo_first_space(): "a %b" parse_simple([ ('NAME', 'a'), ('PERCENT', '%', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PERCENT', '%', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_term_modulo_second_space(): "a% b" parse_simple([ ('NAME', 'a'), ('PERCENT', '%', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('PERCENT', '%', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_modulo_spaces(): "a % b" parse_simple([ ('NAME', 'a'), ('PERCENT', '%', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('PERCENT', '%', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_modulo_spaces_atomtrailers(): "a.b % c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('PERCENT', '%', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '%', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_floor_division(): "a//b" parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_term_floor_division_first_space(): "a //b" parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_term_floor_division_second_space(): "a// b" parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_floor_division_spaces(): "a // b" parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_term_floor_division_spaces_atomtrailers(): "a.b // c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('DOUBLE_SLASH', '//', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '//', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_combine_div_modulo_mult(): "a/b%c*d" parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b', }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b', }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b', }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c", }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c", }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c", }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd', }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd', }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('SLASH', '/'), ('NAME', 'b'), ('PERCENT', '%'), ('NAME', 'c'), ('STAR', '*'), ('NAME', 'd'), ], [ { "type": "binary_operator", "value": '/', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '%', "first": { "type": "name", "value": 'b' }, "second": { "type": "binary_operator", "value": '*', "first": { "type": "name", "value": "c" }, "second": { "type": "name", "value": 'd', }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], }, "first_formatting": [], "second_formatting": [], } ]) def test_arith_expr_plus(): "a+b" parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_arith_expr_add_first_space(): "a +b" parse_simple([ ('NAME', 'a'), ('PLUS', '+', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_arith_expr_add_second_space(): "a+ b" parse_simple([ ('NAME', 'a'), ('PLUS', '+', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_add_spaces(): "a + b" parse_simple([ ('NAME', 'a'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_add_spaces_atomtrailers(): "a.b + c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_substract(): "a-b" parse_simple([ ('NAME', 'a'), ('MINUS', '-'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '-'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_arith_expr_substract_first_space(): "a -b" parse_simple([ ('NAME', 'a'), ('MINUS', '-', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '-', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_arith_expr_substract_second_space(): "a- b" parse_simple([ ('NAME', 'a'), ('MINUS', '-', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '-', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_substract_spaces(): "a - b" parse_simple([ ('NAME', 'a'), ('MINUS', '-', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '-', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_substract_spaces_atomtrailers(): "a.b - c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('MINUS', '-', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_at(): "a@b" parse_simple([ ('NAME', 'a'), ('MINUS', '@'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '@'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_arith_expr_at_first_space(): "a @b" parse_simple([ ('NAME', 'a'), ('MINUS', '@', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '@', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_arith_expr_at_second_space(): "a@ b" parse_simple([ ('NAME', 'a'), ('MINUS', '@', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '@', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_at_spaces(): "a @ b" parse_simple([ ('NAME', 'a'), ('MINUS', '@', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('MINUS', '@', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '@', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_at_spaces_atomtrailers(): "a.b - c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('MINUS', '-', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '-', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_chained_add_substract(): "a+b-c" parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('PLUS', '+'), ('NAME', 'b'), ('MINUS', '-'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '-', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) def test_arith_expr_left_shift(): "a<>b" parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_arith_expr_right_shift_first_space(): "a >>b" parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_arith_expr_right_shift_second_space(): "a>> b" parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_right_shift_spaces(): "a >> b" parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_arith_expr_right_shift_spaces_atomtrailers(): "a.b >> c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '>>', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_chained_left_right_shift(): "a<>c" parse_simple([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '<<', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '<<', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '<<', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '<<', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '<<', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('LEFT_SHIFT', '<<'), ('NAME', 'b'), ('RIGHT_SHIFT', '>>'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '<<', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '>>', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) def test_and_expr(): "a&b" parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_and_expr_first_space(): "a &b" parse_simple([ ('NAME', 'a'), ('AMPER', '&', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_and_expr_second_space(): "a& b" parse_simple([ ('NAME', 'a'), ('AMPER', '&', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_and_expr_spaces(): "a & b" parse_simple([ ('NAME', 'a'), ('AMPER', '&', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_and_expr_spaces_atomtrailers(): "a.b & c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('AMPER', '&', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_chained_left_and_expr(): "a&b&c" parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('AMPER', '&'), ('NAME', 'b'), ('AMPER', '&'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '&', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) def test_xor_expr(): "a^b" parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_xor_expr_first_space(): "a ^b" parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_xor_expr_second_space(): "a^ b" parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_xor_expr_spaces(): "a ^ b" parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_xor_expr_spaces_atomtrailers(): "a.b ^ c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('CIRCUMFLEX', '^', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_chained_left_xor_expr(): "a^b^c" parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('CIRCUMFLEX', '^'), ('NAME', 'b'), ('CIRCUMFLEX', '^'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '^', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) def test_expr(): "a|b" parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [] } ]) def test_expr_first_space(): "a |b" parse_simple([ ('NAME', 'a'), ('VBAR', '|', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|', [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] } ]) def test_expr_second_space(): "a| b" parse_simple([ ('NAME', 'a'), ('VBAR', '|', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_expr_spaces(): "a | b" parse_simple([ ('NAME', 'a'), ('VBAR', '|', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_expr_spaces_atomtrailers(): "a.b | c" parse_simple([ ('NAME', 'a'), ('DOT', '.'), ('NAME', 'b'), ('VBAR', '|', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "dot", "first_formatting": [], "second_formatting": [], }, { "type": "name", "value": "b", } ], }, "second": { "type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] } ]) def test_chained_left_expr(): "a|b|c" parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a', }, "second": { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": "b", }, "second": { "type": "name", "value": "c" }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [] } ]) parse_simple([ ('NAME', 'a'), ('VBAR', '|'), ('NAME', 'b'), ('VBAR', '|'), ('NAME', 'c'), ], [ { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": 'a' }, "second": { "type": "binary_operator", "value": '|', "first": { "type": "name", "value": "b" }, "second": { "type": "name", "value": "c", }, "first_formatting": [], "second_formatting": [] }, "first_formatting": [], "second_formatting": [], } ]) comparison_tokens = ( ('LESS', '<'), ('GREATER', '>'), ('EQUAL_EQUAL', '=='), ('LESS_EQUAL', '<='), ('GREATER_EQUAL', '>='), ('NOT_EQUAL', '<>'), ('NOT_EQUAL', '!='), ('IN', 'in'), ('IS', 'is'), ) def test_comparison(): "a>='), ('DOUBLE_STAR_EQUAL', '**='), ('DOUBLE_SLASH_EQUAL', '//='), ) def test_augmented_assignment(): "a += b" for token_name, value in augmented_assignment_tokens: parse_simple([ ('NAME', 'a'), (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), ('NAME', 'b'), ], [ { "type": "assignment", "operator": value[:-1], "value": { "type": "name", "value": 'b', }, "target": { "type": "name", "value": 'a' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], } ]) parse_simple([ ('NAME', 'a'), (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), ('NAME', 'b'), ], [ { "type": "assignment", "operator": value[:-1], "value": { "type": "name", "value": 'b' }, "target": { "type": "name", "value": 'a', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], } ]) # TODO fix this mess def test_augmented_assignment_augmented_assignment(): "a += b" # for token_name, value in augmented_assignment_tokens: # with pytest.raises(Exception): # parse_simple([ # ('NAME', 'a'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'b'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'c'), # ], [ # { # "type": "assignment", # "operator": augmented_assignment(__2__operator=__2__value[:-1], __2__value={ # "type": "name", # "value": 'c', # }, __2__target={ # "type": "name", # "value": 'b' # }, __2__first_space=" ", __2__second_space=" ", )[:-1], # "value": augmented_assignment(__2__operator=__2__value[:-1], __2__value={ # "type": "name", # "value": 'c', # }, __2__target={ # "type": "name", # "value": 'b' # }, __2__first_space=" ", __2__second_space=" ", ), # "target": { # "type": "name", # "value": 'a' # }, # "first_formatting": [{"type": "space", "value": " "}], # "second_formatting": [{"type": "space", "value": " "}], # } # ]) # parse_simple([ # ('NAME', 'a'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'b'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'c'), # ], [ # augmented_assignment(operator=value[:-1], value={ # "type": "assignment", # "operator": value[:-1], # "value": { # "type": "name", # "value": 'c', # }, # "target": { # "type": "name", # "value": 'b' # }, # "first_formatting": [{"type": "space", "value": " "}], # "second_formatting": [{"type": "space", "value": " "}], # }, target={ # "type": "name", # "value": 'a' # }, first_space=" ", second_space=" ", ) # ]) # parse_simple([ # ('NAME', 'a'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'b'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'c'), # ], [ # { # "type": "assignment", # "operator": augmented_assignment(__4__operator=__4__value[:-1], __4__value={ # "type": "name", # "value": 'c' # }, __4__target={ # "type": "name", # "value": 'b', # }, __4__first_space=" ", __4__second_space=" ", )[:-1], # "value": augmented_assignment(__4__operator=__4__value[:-1], __4__value={ # "type": "name", # "value": 'c' # }, __4__target={ # "type": "name", # "value": 'b', # }, __4__first_space=" ", __4__second_space=" ", ), # "target": { # "type": "name", # "value": 'a' # }, # "first_formatting": [{"type": "space", "value": " "}], # "second_formatting": [{"type": "space", "value": " "}], # } # ]) # parse_simple([ # ('NAME', 'a'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'b'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'c'), # ], [ # augmented_assignment(operator=value[:-1], value={ # "type": "assignment", # "operator": value[:-1], # "value": { # "type": "name", # "value": 'c' # }, # "target": { # "type": "name", # "value": 'b', # }, # "first_formatting": [{"type": "space", "value": " "}], # "second_formatting": [{"type": "space", "value": " "}], # }, target={"type": "name", "value": 'a'}, first_space=" ", second_space=" ", ) # ]) # parse_simple([ # ('NAME', 'a'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'b'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'c'), # ], [ # { # "type": "assignment", # "operator": augmented_assignment(__6__operator=__6__value[:-1], __6__value={ # "type": "name", # "value": 'c' # }, __6__target={ # "type": "name", # "value": 'b' # }, __6__first_space=" ", __6__second_space=" ", )[:-1], # "value": augmented_assignment(__6__operator=__6__value[:-1], __6__value={ # "type": "name", # "value": 'c' # }, __6__target={ # "type": "name", # "value": 'b' # }, __6__first_space=" ", __6__second_space=" ", ), # "target": { # "type": "name", # "value": 'a', # }, # "first_formatting": [{"type": "space", "value": " "}], # "second_formatting": [{"type": "space", "value": " "}], # } # ]) # parse_simple([ # ('NAME', 'a'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'b'), # (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), # ('NAME', 'c'), # ], [ # augmented_assignment(operator=value[:-1], value={ # "type": "assignment", # "operator": value[:-1], # "value": { # "type": "name", # "value": 'c' # }, # "target": { # "type": "name", # "value": 'b' # }, # "first_formatting": [{"type": "space", "value": " "}], # "second_formatting": [{"type": "space", "value": " "}], # }, target={ # "type": "name", # "value": 'a', # }, first_space=" ", second_space=" ", ) # ]) def test_augmented_assignment_yield_b(): "a += yield b" for token_name, value in augmented_assignment_tokens: parse_simple([ ('NAME', 'a'), (token_name, value, [("SPACE", " ")], [("SPACE", " ")]), ('YIELD', 'yield', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "assignment", "operator": value[:-1], "value": { "formatting": [ { "type": "space", "value": " " } ], "type": "yield", "value": { "type": "name", "value": "b", }, }, "target": { "type": "name", "value": 'a', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], } ]) def test_a_equal_yield_b(): """ a = yield b """ parse_simple([ ('NAME', 'a'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('YIELD', 'yield', [("SPACE", "")], [("SPACE", " ")]), ('NAME', 'b'), ], [ { "first_formatting": [{"type": "space", "value": " "}], "type": "assignment", "operator": "", "target": { "type": "name", "value": "a" }, "value": { "type": "yield", "formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "b" }, }, "second_formatting": [{"type": "space", "value": " "}], "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], } ]) def test_expr_comma_list(): "a or b,c+d" parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] } ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] } ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c', }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] } ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd', }, "first_formatting": [], "second_formatting": [] } ], } ]) def test_expr_comma_list_3_items(): "a or b,c+d,e" parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a', }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "name", "value": 'e' }, ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "name", "value": 'e' }, ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c', }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "name", "value": 'e' }, ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd', }, "first_formatting": [], "second_formatting": [] }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "name", "value": 'e' }, ], } ]) parse_simple([ ('NAME', 'a'), ('OR', 'or', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ','), ('NAME', 'c'), ('PLUS', '+'), ('NAME', 'd'), ('COMMA', ','), ('NAME', 'e'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "boolean_operator", "value": 'or', "first": { "type": "name", "value": 'a' }, "second": { "type": "name", "value": 'b' }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "binary_operator", "value": '+', "first": { "type": "name", "value": 'c' }, "second": { "type": "name", "value": 'd' }, "first_formatting": [], "second_formatting": [] }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, { "type": "name", "value": 'e', }, ], } ]) def test_await_a(): "await a" parse_simple([ ('NAME', 'await', [], []), ('SPACE', ' '), ('NAME', 'a'), ], [ { 'formatting': [{'type': 'space', 'value': ' '}], 'type': 'await', "value": {'type': 'atomtrailers', 'value': [{'type': 'name', 'value': 'a'}]}, }, ]) def test_await_a_bad_keyword(): "await a" with pytest.raises(ParsingError): parse_simple([ ('NAME', 'not_await', [], []), ('SPACE', ' '), ('NAME', 'a'), ], []) def test_implicit_tuple_space(): "a, b , c" parse_simple([ ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "c", } ], } ]) def test_implicit_tuple_one_item(): "a ," parse_simple([ ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')]), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], } ] } ]) def test_implicit_tuple_trailing_comma(): "a, b ," parse_simple([ ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')]), ], [ { "type": "tuple", "with_parenthesis": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "type": "name", "value": "a", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], } ] } ]) def test_subscript_ellipsis(): "a[...]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('ELLIPSIS', '...'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "ellipsis", "first_formatting": [], "second_formatting": [], } } ] } ]) def test_subscript_ellipsis_space(): "a[ ... ]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '[', [('SPACE', ' ')]), ('ELLIPSIS', '...'), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "value": { "type": "ellipsis", "first_formatting": [], "second_formatting": [], } } ] } ]) def test_subscript_test(): "a[b]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "name", "value": "b", } } ] } ]) def test_subscript_slice_empty(): "a[:]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('COLON', ':'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": {}, "upper": {}, "step": {}, "has_two_colons": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_empty_both(): "a[: :]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('COLON', ':', [], [('SPACE', ' ')]), ('COLON', ':'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": {}, "upper": {}, "step": {}, "has_two_colons": True, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_one(): "a[b :]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')]), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": { "type": "name", "value": "b", }, "upper": {}, "step": {}, "has_two_colons": False, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_both_one(): "a[b : : ]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('COLON', ':', [], []), ('RIGHT_SQUARE_BRACKET', ']', [('SPACE', ' ')]), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "value": { "type": "slice", "lower": { "type": "name", "value": "b", }, "upper": {}, "step": {}, "has_two_colons": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_upper(): "a[:b]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('COLON', ':'), ('NAME', 'b'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "upper": { "type": "name", "value": "b", }, "lower": {}, "step": {}, "has_two_colons": False, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_upper_both(): "a[:b :]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('COLON', ':'), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')]), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "upper": { "type": "name", "value": "b", }, "lower": {}, "step": {}, "has_two_colons": True, "first_formatting": [], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_step(): "a[: : b]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('COLON', ':', [], [('SPACE', ' ')]), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'b'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "upper": {}, "lower": {}, "step": { "type": "name", "value": "b", }, "has_two_colons": True, "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [{"type": "space", "value": " "}], } } ] } ]) def test_subscript_slice_lower_upper(): "a[b : c]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": { "type": "name", "value": "b", }, "upper": { "type": "name", "value": "c", }, "step": {}, "has_two_colons": False, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_lower_upper_both(): "a[b : c :]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [('SPACE', ' ')]), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": { "type": "name", "value": "b", }, "upper": { "type": "name", "value": "c", }, "step": {}, "has_two_colons": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], } } ] } ]) def test_subscript_slice_lower_step(): "a[b:: c]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COLON', ':'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": { "type": "name", "value": "b", }, "step": { "type": "name", "value": "c", }, "upper": {}, "has_two_colons": True, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [{"type": "space", "value": " "}], } } ] } ]) def test_subscript_slice_upper_step(): "a[:b: c]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('COLON', ':'), ('NAME', 'b'), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "upper": { "type": "name", "value": "b", }, "step": { "type": "name", "value": "c", }, "lower": {}, "has_two_colons": True, "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [{"type": "space", "value": " "}], } } ] } ]) def test_subscript_slice_lower_upper_step(): "a[b : c : d]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'd'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "slice", "lower": { "type": "name", "value": "b", }, "upper": { "type": "name", "value": "c", }, "step": { "type": "name", "value": "d", }, "has_two_colons": True, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], } } ] } ]) def test_subscript_test_implicit_tuple(): "a[b, c]" parse_simple([ ('NAME', 'a'), ('LEFT_SQUARE_BRACKET', '['), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_SQUARE_BRACKET', ']'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "getitem", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": { "type": "tuple", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "with_parenthesis": False, "value": [ { "type": "name", "value": "b", }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "name", "value": "c", } ], } } ] } ]) def test_call_empty(): "a()" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [], } ] } ]) def test_call_empty_with_space(): "a ( )" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [], "value": [], } ] } ]) def test_call_empty_with_space_fourth_formatting(): "a ( )" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')', [], [('SPACE', ' ')]), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [], "fourth_formatting": [{"type": "space", "value": " "}], "value": [], } ] } ]) def test_call_one(): "a(b)" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "b", } } ], } ] } ]) def test_call_two(): "a(b, c)" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "b", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "c", } } ], } ] } ]) def test_call_two_star_arg(): "a(b, c, *d)" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('STAR', '*'), ('NAME', 'd'), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "b", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "c", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "list_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "type": "name", "value": "d", }, } ], } ] } ]) def test_call_two_star_arg_kwarg(): "a(b, c, *d, **e)" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COMMA', ',', [], [('SPACE', ' ')]), ('STAR', '*'), ('NAME', 'd'), ('COMMA', ',', [], [('SPACE', ' ')]), ('DOUBLE_STAR', '**'), ('NAME', 'e'), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "b", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "target": {}, "first_formatting": [], "second_formatting": [], "type": "call_argument", "value": { "type": "name", "value": "c", } }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "list_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "type": "name", "value": "d", }, }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}], }, { "type": "dict_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "formatting": [], "value": { "type": "name", "value": "e", }, } ], } ] } ]) def test_call_named(): "a(b = c)" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "value": { "type": "name", "value": "c", }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "type": "call_argument", "target": { "value": "b", "type": "name", } } ], } ] } ]) def test_call_generator(): "a(x for y in z)" parse_simple([ ('NAME', 'a'), ('LEFT_PARENTHESIS', '('), ('NAME', 'x'), ('FOR', 'for', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'y'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'z'), ('RIGHT_PARENTHESIS', ')'), ], [ { "type": "atomtrailers", "value": [ { "type": "name", "value": "a", }, { "type": "call", "first_formatting": [], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "value": [ { "generators": [ { "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [{"type": "space", "value": " "}], "type": "comprehension_loop", "ifs": [], "target": { "type": "name", "value": "z", }, "iterator": { "type": "name", "value": "y", }, } ], "type": "argument_generator_comprehension", "result": { "type": "name", "value": "x", } } ], } ] } ]) baron-0.10.1/tests/test_grammator_primitives.py000066400000000000000000000660131415427440200217220ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- from .test_utils import parse_simple def test_return(): "return" parse_simple([ ('RETURN', 'return'), ], [{"type": "return", "value": None, "formatting": [], }]) def test_return_a(): "return a" parse_simple([ ('RETURN', 'return', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [{"type": "return", "value": {"type": "name", "value": 'a', }, "formatting": [{"type": "space", "value": " "}], }]) def test_yield(): "yield" parse_simple([ ('YIELD', 'yield'), ], [{ "type": "yield", "value": None, "formatting": [], }]) def test_yield_from(): "yield from a" parse_simple([ ('YIELD', 'yield', [], [('SPACE', ' ')]), ('FROM', 'from', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [{ "type": "yield_from", "first_formatting": [{"type": "space", "value": " "}], "value": {"type": "name", "value": 'a', }, "formatting": [{"type": "space", "value": " "}], }]) def test_yield_a(): "yield a" parse_simple([ ('YIELD', 'yield', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [{"type": "yield", "value": {"type": "name", "value": 'a', }, "formatting": [{"type": "space", "value": " "}], }]) def test_del(): "del a" parse_simple([ ('DEL', 'del', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "del", "value": {"type": "name", "value": 'a', }, "formatting": [{"type": "space", "value": " "}], } ]) def test_break(): "break" parse_simple([ ('BREAK', 'break'), ], [ { "type": "break", } ]) def test_continue(): "continue" parse_simple([ ('CONTINUE', 'continue'), ], [ { "type": "continue", } ]) def test_pass(): "pass" parse_simple([ ('PASS', 'pass'), ], [ { "type": "pass", } ]) def test_assert(): "assert a" parse_simple([ ('ASSERT', 'assert', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "assert", "value": {"type": "name", "value": 'a', }, "message": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [] } ]) def test_assert_message(): "assert a , b" parse_simple([ ('ASSERT', 'assert', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "assert", "value": {"type": "name", "value": 'a', }, "message": {"type": "name", "value": 'b'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('ASSERT', 'assert', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "assert", "value": {"type": "name", "value": 'a'}, "message": {"type": "name", "value": 'b', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}] } ]) def test_raise_empty(): "raise" parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ], [ { "type": "raise", "value": None, "instance": None, "traceback": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "comma_or_from": None, } ]) def test_raise(): "raise a" parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "raise", "value": {"type": "name", "value": 'a'}, "instance": None, "traceback": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [], "comma_or_from": None, } ]) def test_raise_from(): "raise a from b" parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('FROM', 'from', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "raise", "comma_or_from": "from", "value": {"type": "name", "value": 'a'}, "instance": {'type': 'name', 'value': 'b'}, "traceback": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{'type': 'space', 'value': ' '}], "third_formatting": [{'type': 'space', 'value': ' '}], "fourth_formatting": [], "fifth_formatting": [], } ]) def test_raise_instance(): "raise a, b" parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "raise", "comma_or_from": ",", "value": {"type": "name", "value": 'a'}, "instance": {"type": "name", "value": 'b'}, "traceback": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], } ]) parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "raise", "comma_or_from": ",", "value": {"type": "name", "value": 'a'}, "instance": {"type": "name", "value": 'b'}, "traceback": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [], } ]) def test_raise_instance_traceback(): "raise a, b, c" parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "raise", "comma_or_from": ",", "value": {"type": "name", "value": 'a'}, "instance": {"type": "name", "value": 'b'}, "traceback": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], } ]) parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "raise", "comma_or_from": ",", "value": {"type": "name", "value": 'a'}, "instance": {"type": "name", "value": 'b'}, "traceback": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], } ]) parse_simple([ ('RAISE', 'raise', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', 'comma', [], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "raise", "comma_or_from": ",", "value": {"type": "name", "value": 'a'}, "instance": {"type": "name", "value": 'b'}, "traceback": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}], } ]) def test_exec(): "exec a" parse_simple([ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "exec", "value": {"type": "name", "value": 'a', }, "globals": None, "locals": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [], "fourth_formatting": [], "fifth_formatting": [] } ]) def test_exec_in(): "exec a in b" parse_simple([ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "exec", "value": {"type": "name", "value": 'a', }, "globals": {"type": "name", "value": 'b'}, "locals": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [] } ]) parse_simple([ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "exec", "value": {"type": "name", "value": 'a'}, "globals": {"type": "name", "value": 'b', }, "locals": None, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [] } ]) def test_exec_in_c(): "exec a in b, c" parse_simple([ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "exec", "value": {"type": "name", "value": 'a', }, "globals": {"type": "name", "value": 'b'}, "locals": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "exec", "value": {"type": "name", "value": 'a'}, "globals": {"type": "name", "value": 'b', }, "locals": {"type": "name", "value": 'c'}, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}] } ]) parse_simple([ ('EXEC', 'exec', [], [('SPACE', ' ')]), ('NAME', 'a'), ('IN', 'in', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "exec", "value": {"type": "name", "value": 'a'}, "globals": {"type": "name", "value": 'b'}, "locals": {"type": "name", "value": 'c', }, "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "fourth_formatting": [], "fifth_formatting": [{"type": "space", "value": " "}] } ]) def test_global(): "global a" parse_simple([ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "global", "formatting": [{"type": "space", "value": " "}], "value": [ {"type": "name", "value": 'a', }, ] } ]) def test_global_one(): "global a, b" parse_simple([ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "global", "formatting": [{"type": "space", "value": " "}], "value": [ {"type": "name", "value": 'a', }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " ", }, ], }, {"type": "name", "value": 'b'}, ] } ]) parse_simple([ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "global", "formatting": [{"type": "space", "value": " "}], "value": [ {"type": "name", "value": 'a'}, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " ", }, ], }, {"type": "name", "value": 'b', }, ] } ]) def test_global_two(): "global a, b , c" parse_simple([ ('GLOBAL', 'global', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'c'), ], [ { "type": "global", "formatting": [{"type": "space", "value": " "}], "value": [ {"type": "name", "value": "a"}, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " ", }, ], }, {"type": "name", "value": "b"}, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}, ], "second_formatting": [{"type": "space", "value": " "}, ], }, {"type": "name", "value": "c"}, ] } ]) def test_print(): "print" parse_simple([ ('PRINT', 'print', [], []), ], [ { "type": "print", "formatting": [], "value": [], "destination_formatting": [], "destination": None, } ]) def test_print_a(): "print a" parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "print", "formatting": [{"type": "space", "value": " "}], "value": [{"type": "name", "value": 'a', }], "destination_formatting": [], "destination": None, } ]) def test_print_a_b(): "print a, b" parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "name", "value": 'a', }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b' }, ], "destination_formatting": [], "destination": None, } ]) parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "name", "value": 'a' }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b', }, ], "destination_formatting": [], "destination": None, } ]) def test_print_a_b_comma(): "print a, b," parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], []), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "name", "value": 'a', }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b' }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, ], "destination_formatting": [], "destination": None, } ]) parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [], []), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "name", "value": 'a' }, { "type": "comma", "first_formatting": [], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b', }, { "type": "comma", "first_formatting": [], "second_formatting": [] }, ], "destination_formatting": [], "destination": None, } ]) def test_print_redirect(): "print >> a" parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [], "destination_formatting": [ { "type": "space", "value": " " } ], "destination": { "type": "name", "value": 'a', }, } ]) def test_print_redirect_ab(): "print >> a , b" parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b', }, ], "destination": {"type": "name", "value": 'a'}, "destination_formatting": [{"type": "space", "value": " "}], } ]) parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ], [ { "type": "print", "formatting": [{"type": "space", "value": " "}], "value": [ { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b' }, ], "destination": { "type": "name", "value": 'a', }, "destination_formatting": [ { "type": "space", "value": " " } ], } ]) def test_print_redirect_ab_comma(): "print >> a , b ," parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')]), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b', }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] }, ], "destination": {"type": "name", "value": 'a'}, "destination_formatting": [{"type": "space", "value": " "}], } ]) parse_simple([ ('PRINT', 'print', [], [('SPACE', ' ')]), ('RIGHT_SHIFT', '>>', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COMMA', ',', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'b'), ('COMMA', ',', [('SPACE', ' ')]), ], [ { "type": "print", "formatting": [ { "type": "space", "value": " " } ], "value": [ { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}] }, { "type": "name", "value": 'b' }, { "type": "comma", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [] }, ], "destination": { "type": "name", "value": 'a', }, "destination_formatting": [ { "type": "space", "value": " " } ], } ]) def test_lambda(): "lambda : a" parse_simple([ ('LAMBDA', 'lambda', [], [('SPACE', ' ')]), ('COLON', ':', [], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "lambda", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [], "third_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "a", }, "arguments": [] } ]) def test_lambda_arguments(): "lambda argument : a" parse_simple([ ('LAMBDA', 'lambda', [], [('SPACE', ' ')]), ('NAME', 'argument'), ('COLON', ':', [('SPACE', ' ')], [('SPACE', ' ')]), ('NAME', 'a'), ], [ { "type": "lambda", "first_formatting": [{"type": "space", "value": " "}], "second_formatting": [{"type": "space", "value": " "}], "third_formatting": [{"type": "space", "value": " "}], "value": { "type": "name", "value": "a", }, "arguments": [ { "value": {}, "first_formatting": [], "second_formatting": [], "type": "def_argument", "annotation": {}, "annotation_first_formatting": [], "annotation_second_formatting": [], "target": { "value": "argument", "type": "name", } } ] } ]) baron-0.10.1/tests/test_grouper.py000066400000000000000000000143341415427440200171400ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- from baron.grouper import group from baron.spliter import split def grouper_test(input_, split_output, group_output): assert split(input_) == split_output assert group(split_output) == group_output def test_empty(): grouper_test("", [], []) def test_one(): grouper_test('a', ['a'], ['a']) def test_random(): assert group(list("abcdef")) == list("abcdef") def test_add_egual(): grouper_test("+=", ["+", "="], ["+="]) def test_add_add(): grouper_test("++", ["+", "+"], ["+", "+"]) def test_add_egual_double(): grouper_test("+=+=", ["+", "=", "+", "="], ["+=", "+="]) def test_add_egual_random(): grouper_test(" qsd+=qsd", [' ', 'qsd', '+', '=', 'qsd'], [' ', 'qsd', '+=', 'qsd']) def test_minus_egual(): grouper_test("-=", ["-", "="], ["-="]) def test_mult_egual(): grouper_test("*=", ["*", "="], ["*="]) def test_div_egual(): grouper_test("/=", ["/", "="], ["/="]) def test_modulo_egual(): grouper_test("%=", ["%", "="], ["%="]) def test_amper_egual(): grouper_test("&=", ["&", "="], ["&="]) def test_bar_egual(): grouper_test("|=", ["|", "="], ["|="]) def test_power_egual(): grouper_test("^=", ["^", "="], ["^="]) def test_less_less(): grouper_test("<<", ["<", "<"], ["<<"]) def test_more_more(): grouper_test(">>", [">", ">"], [">>"]) def test_egual_egual(): grouper_test("==", ["=", "="], ["=="]) def test_different(): grouper_test("!=", ["!", "="], ["!="]) def test_inferior_egual(): grouper_test(">=", [">", "="], [">="]) def test_superior_egual(): grouper_test("<=", ["<", "="], ["<="]) def test_different_old_style(): grouper_test("<>", ["<", ">"], ["<>"]) def test_power_power_egual(): grouper_test("**=", ["*", "*", "="], ["**="]) def test_div_div_egual(): grouper_test("//=", ["/", "/", "="], ["//="]) def test_less_less_egual(): grouper_test("<<=", ["<", "<", "="], ["<<="]) def test_more_more_egual(): grouper_test(">>=", [">", ">", "="], [">>="]) def test_decorator(): grouper_test("@pouet", ["@", "pouet"], ["@", "pouet"]) def test_endl(): grouper_test("\r\n", ["\r", "\n"], ["\r\n"]) def test_raw_string(): grouper_test("r'pouet'", ["r", "'pouet'"], ["r'pouet'"]) grouper_test("R'pouet'", ["R", "'pouet'"], ["R'pouet'"]) def test_unicode_string(): grouper_test("u'pouet'", ["u", "'pouet'"], ["u'pouet'"]) grouper_test("U'pouet'", ["U", "'pouet'"], ["U'pouet'"]) def test_binary_string(): grouper_test("b'pouet'", ["b", "'pouet'"], ["b'pouet'"]) grouper_test("B'pouet'", ["B", "'pouet'"], ["B'pouet'"]) def test_binary_raw_string(): grouper_test("br'pouet'", ["br", "'pouet'"], ["br'pouet'"]) grouper_test("Br'pouet'", ["Br", "'pouet'"], ["Br'pouet'"]) grouper_test("bR'pouet'", ["bR", "'pouet'"], ["bR'pouet'"]) grouper_test("BR'pouet'", ["BR", "'pouet'"], ["BR'pouet'"]) def test_unicode_raw_string(): grouper_test("ur'pouet'", ["ur", "'pouet'"], ["ur'pouet'"]) grouper_test("Ur'pouet'", ["Ur", "'pouet'"], ["Ur'pouet'"]) grouper_test("uR'pouet'", ["uR", "'pouet'"], ["uR'pouet'"]) grouper_test("UR'pouet'", ["UR", "'pouet'"], ["UR'pouet'"]) def test_exponant(): grouper_test("1e+123", ['1e', '+', '123'], ['1e+123']) grouper_test("1e-123", ['1e', '-', '123'], ['1e-123']) grouper_test("1.1e+123", ['1', '.', '1e', '+', '123'], ['1.1e+123']) grouper_test("1.1e-123", ['1', '.', '1e', '-', '123'], ['1.1e-123']) grouper_test(".1e+123", ['.', '1e', '+', '123'], ['.1e+123']) grouper_test(".1e-123", ['.', '1e', '-', '123'], ['.1e-123']) def test_endl_with_backslash(): grouper_test("\\\n", ['\\', '\n'], ['\\\n']) def test_space_endl_with_backslash(): grouper_test(" \\\n ", [' ', '\\', '\n', ' '], [' \\\n ']) grouper_test(" \\\npouet", [' ', '\\', '\n', 'pouet'], [' \\\n', 'pouet']) def test_number_with_backslash(): grouper_test("3\\\n", ['3', '\\', '\n'], ['3', '\\\n']) def test_regression(): grouper_test("0x045e: ", ['0x045e', ':', ' '], ['0x045e', ':', ' ']) grouper_test("180.\n", ['180', '.', '\n'], ['180.', '\n']) def test_backslash_window_endl(): grouper_test("\\\r\n", ['\\', '\r', '\n'], ['\\\r\n']) def test_regression_float(): grouper_test('1.', ['1', '.'], ['1.']) grouper_test('.1', ['.', '1'], ['.1']) grouper_test('1.1', ['1', '.', '1'], ['1.1']) grouper_test('7.629e-6', ['7', '.', '629e', '-', '6'], ['7.629e-6']) def test_complex(): grouper_test(".1j", ['.', '1j'], ['.1j']) grouper_test(".1J", ['.', '1J'], ['.1J']) grouper_test("1.j", ['1', '.', 'j'], ['1.j']) grouper_test("1.J", ['1', '.', 'J'], ['1.J']) grouper_test("1.1j", ['1', '.', '1j'], ['1.1j']) grouper_test("1.1J", ['1', '.', '1J'], ['1.1J']) grouper_test("1J", ['1J'], ['1J']) grouper_test("1e-1j", ['1e', '-', '1j'], ['1e-1j']) grouper_test("1e1j", ['1e1j'], ['1e1j']) def test_float_exponant(): grouper_test("1E1", ['1E1'], ['1E1']) grouper_test("1E-2", ['1E', '-', '2'], ['1E-2']) grouper_test("1E+2", ['1E', '+', '2'], ['1E+2']) grouper_test("1.E+2", ['1', '.', 'E', '+', '2'], ['1.E+2']) grouper_test("1.E-2", ['1', '.', 'E', '-', '2'], ['1.E-2']) grouper_test("1.E2", ['1', '.', 'E2'], ['1.E2']) grouper_test("1e1", ['1e1'], ['1e1']) grouper_test("1e-2", ['1e', '-', '2'], ['1e-2']) grouper_test("1e+2", ['1e', '+', '2'], ['1e+2']) grouper_test("1.e+2", ['1', '.', 'e', '+', '2'], ['1.e+2']) grouper_test("1.e-2", ['1', '.', 'e', '-', '2'], ['1.e-2']) grouper_test("1.e2", ['1', '.', 'e2'], ['1.e2']) grouper_test(".3e55", ['.', '3e55'], ['.3e55']) def test_float_with_underscores(): grouper_test(".098_765", ['.', '098_765'], ['.098_765']) grouper_test("123.098_765", ['123', '.', '098_765'], ['123.098_765']) grouper_test("123_456.098", ['123_456', '.', '098'], ['123_456.098']) grouper_test("123_456.098_765", ['123_456', '.', '098_765'], ['123_456.098_765']) def test_arrow(): grouper_test("->", ['-', '>'], ['->']) def test_dot_dot(): grouper_test("..", ['.', '.'], ['.', '.']) def test_dot_dot_dot(): grouper_test("...", ['.', '.', '.'], ['...']) def test_split_float_notation(): grouper_test("a._", ["a", ".", "_"], ["a", ".", "_"]) baron-0.10.1/tests/test_indentation_marker.py000066400000000000000000000241511415427440200213300ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- # flake8: noqa from baron.indentation_marker import mark_indentation from .test_utils import zip_longest def check(input_, output): for i, j in zip_longest(mark_indentation(input_ + [('ENDMARKER', ''), None]), output + [('ENDMARKER', ''), None]): assert i == j def test_empty(): "" check([], []) def test_dummy(): "a" check([ ('NAME', 'a'), ], [ ('NAME', 'a'), ]) def test_dumy_if(): """ if a: pass """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('DEDENT', ''), ]) def test_dumy_def_space(): """ def foo(): pass """ # https://github.com/PyCQA/baron/issues/101 check([ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'foo'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n', [('SPACE', ' ')]), ], [ ('DEF', 'def', [], [('SPACE', ' ')]), ('NAME', 'foo'), ('LEFT_PARENTHESIS', '('), ('RIGHT_PARENTHESIS', ')'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [('SPACE', ' ')]), ('DEDENT', ''), ]) def test_dumy_if_if(): """ if a: if b: pass """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('DEDENT', ''), ]) def test_dummy_if_followed(): """ if a: pass pouet """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ('NAME', 'pouet'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('NAME', 'pouet'), ]) def test_dummy_if_followed_blank_line(): """ if a: pass """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n'), ('INDENT', ''), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ]) def test_dumy_if_dendent_quite_a_lot(): """ if a: if b: if c: pass pouet """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 1)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 3)]), ('PASS', 'pass'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'pouet'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 1)]), ('INDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('INDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 3)]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('ENDL', '\n'), ('DEDENT', ''), ('DEDENT', ''), ('DEDENT', ''), ('NAME', 'pouet'), ]) def test_dumy_if_dendent_a_lot(): """ if a: if b: if c: pass if d: pass if e: pass pouet """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 1)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 3)]), ('PASS', 'pass'), ('ENDL', '\n', [], [('SPACE', ' ' * 1)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'd'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('PASS', 'pass'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'e'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 3)]), ('PASS', 'pass'), ('ENDL', '\n'), ('ENDL', '\n'), ('NAME', 'pouet'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 1)]), ('INDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('INDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'c'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 3)]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], [('SPACE', ' ' * 1)]), ('DEDENT', ''), ('DEDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'd'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'e'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 3)]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('ENDL', '\n'), ('DEDENT', ''), ('DEDENT', ''), ('DEDENT', ''), ('NAME', 'pouet'), ]) def test_trailing_spaces(): """ if a: if b: pass """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'b'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ('DEDENT', ''), ]) def test_tab_and_spaces_because_some_people_are_horrible(): """ if a: pass pass """ check([ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('PASS', 'pass'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ], [ ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ' * 2)]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('DEDENT', ''), ]) def test_comment_in_middle_of_ifelseblock(): check([ ('ENDL', '\n'), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ('COMMENT', '# comment'), ('ENDL', '\n'), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('PASS', 'pass'), ('ENDL', '\n'), ], [ ('ENDL', '\n'), ('IF', 'if', [], [('SPACE', ' ')]), ('NAME', 'a'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('COMMENT', '# comment'), ('ENDL', '\n'), ('DEDENT', ''), ('ELSE', 'else'), ('COLON', ':'), ('ENDL', '\n', [], [('SPACE', ' ')]), ('INDENT', ''), ('PASS', 'pass'), ('ENDL', '\n'), ('DEDENT', ''), ]) baron-0.10.1/tests/test_inner_formatting_grouper.py000066400000000000000000000125571415427440200225720ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:utf-8 -*- from baron.inner_formatting_grouper import group def test_empty(): assert group([]) == [] def test_some_stuff(): assert group([ ('INT', '1'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('INT', '2') ]) == [ ('INT', '1'), ('PLUS', '+', [('SPACE', ' ')], [('SPACE', ' ')]), ('INT', '2') ] def test_parenthesis(): assert group([ ('LEFT_PARENTHESIS', '('), ('ENDL', '\n'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '(', [], [('ENDL', '\n')]), ('RIGHT_PARENTHESIS', ')'), ] def test_parenthesis_one_space(): assert group([ ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')]), ('ENDL', '\n'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('ENDL', '\n')]), ('RIGHT_PARENTHESIS', ')'), ] def test_parenthesis_two_space(): assert group([ ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' ')]), ('ENDL', '\n'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '(', [('SPACE', ' ')], [('SPACE', ' '), ('ENDL', '\n')]), ('RIGHT_PARENTHESIS', ')'), ] def test_two_parenthesis(): assert group([ ('LEFT_PARENTHESIS', '('), ('ENDL', '\n'), ('ENDL', '\n'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '(', [], [('ENDL', '\n'), ('ENDL', '\n')]), ('RIGHT_PARENTHESIS', ')'), ] def test_two_parenthesis_comma(): assert group([ ('LEFT_PARENTHESIS', '('), ('ENDL', '\n'), ('COMMA', ','), ('ENDL', '\n'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '(', [], [('ENDL', '\n'), ]), ('COMMA', ',', [], [('ENDL', '\n')]), ('RIGHT_PARENTHESIS', ')'), ] def test_tuple_one(): assert group([ ('LEFT_PARENTHESIS', '('), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('COMMA', ','), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '(', [], [('ENDL', '\n'), ]), ('NAME', 'a'), ('COMMA', ',', [('ENDL', '\n')], [('ENDL', '\n')]), ('NAME', 'a'), ('RIGHT_PARENTHESIS', ')', [('ENDL', '\n')], []), ] def test_set_one(): assert group([ ('LEFT_BRACKET', '{'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('COMMA', ','), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('RIGHT_BRACKET', '}'), ]) == [ ('LEFT_BRACKET', '{', [], [('ENDL', '\n'), ]), ('NAME', 'a'), ('COMMA', ',', [('ENDL', '\n')], [('ENDL', '\n')]), ('NAME', 'a'), ('RIGHT_BRACKET', '}', [('ENDL', '\n')], []), ] def test_list_one(): assert group([ ('LEFT_SQUARE_BRACKET', '['), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('COMMA', ','), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('RIGHT_SQUARE_BRACKET', ']'), ]) == [ ('LEFT_SQUARE_BRACKET', '[', [], [('ENDL', '\n'), ]), ('NAME', 'a'), ('COMMA', ',', [('ENDL', '\n')], [('ENDL', '\n')]), ('NAME', 'a'), ('RIGHT_SQUARE_BRACKET', ']', [('ENDL', '\n')], []), ] def test_dict_one(): assert group([ ('LEFT_BRACKET', '{'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('COLON', ':'), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('COMMA', ','), ('ENDL', '\n'), ('NAME', 'a'), ('ENDL', '\n'), ('RIGHT_BRACKET', '}'), ]) == [ ('LEFT_BRACKET', '{', [], [('ENDL', '\n')]), ('NAME', 'a'), ('COLON', ':', [('ENDL', '\n')], [('ENDL', '\n')]), ('NAME', 'a'), ('COMMA', ',', [('ENDL', '\n')], [('ENDL', '\n')]), ('NAME', 'a'), ('RIGHT_BRACKET', '}', [('ENDL', '\n')], []), ] def test_number_backslash(): assert group([ ('INT', '3'), ('SPACE', '\\'), ]) == [ ('INT', '3'), ('SPACE', '\\'), ] def test_number_backslash_newline(): assert group([ ('INT', '3'), ('SPACE', '\\\n'), ]) == [ ('INT', '3'), ('SPACE', '\\\n'), ] def test_nested_grouping_after_endl(): """ (b [0]) """ assert group([ ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('ENDL', '\n'), ('SPACE', ' '), ('LEFT_SQUARE_BRACKET', '['), ('INT', '0'), ('RIGHT_SQUARE_BRACKET', ']'), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '('), ('NAME', 'b'), ('LEFT_SQUARE_BRACKET', '[', [('ENDL', '\n'), ('SPACE', ' ')], []), ('INT', '0'), ('RIGHT_SQUARE_BRACKET', ']'), ('RIGHT_PARENTHESIS', ')'), ] def test_equal(): """ (a = b) """ assert group([ ('LEFT_PARENTHESIS', '('), ('NAME', 'a'), ('SPACE', ' '), ('EQUAL', '='), ('SPACE', ' '), ('RIGHT_PARENTHESIS', ')'), ]) == [ ('LEFT_PARENTHESIS', '('), ('NAME', 'a'), ('EQUAL', '=', [('SPACE', ' ')], [('SPACE', ' ')]), ('RIGHT_PARENTHESIS', ')'), ] baron-0.10.1/tests/test_loop.sh000077500000000000000000000020011415427440200163770ustar00rootroot00000000000000#!/bin/bash while true do clear if [ "$1" == "grammator" ] then py.test test_grammator* -x | tee /tmp/.baron_test_ouput else py.test -x | tee /tmp/.baron_test_ouput fi if ([ ! "$1" ] || [ "$1" == "grammator" ]) && [ "$(grep ': AssertionError' /tmp/.baron_test_ouput)" ] then grep " def" /tmp/.baron_test_ouput | head -n 1 | sed 's/^ *//' sed 's/, *$//' /tmp/a > /tmp/aa sed 's/, *$//' /tmp/b > /tmp/bb colordiff -W $(stty size | cut -d " " -f 2) -y /tmp/aa /tmp/bb echo grep ":[0-9]\+:" /tmp/.baron_test_ouput | sed -n '$d;1p' elif [ "$1" == "dump" ] && [ "$(grep ': AssertionError' /tmp/.baron_test_ouput)" ] && [ ! "$(grep 'Warning: couldn.t write dumps output to debug file' /tmp/.baron_test_ouput)" ] then grep " def" /tmp/.baron_test_ouput | head -n 1 | sed 's/^ *//' colordiff -W $(stty size | cut -d " " -f 2) -y /tmp/c /tmp/d echo fi inotifywait -e modify *.py ../baron/*.py done baron-0.10.1/tests/test_path.py000066400000000000000000000377421415427440200164210ustar00rootroot00000000000000# flake8: noqa from baron.baron import parse from baron.path import PathWalker, Position, BoundingBox from baron.path import position_to_path, path_to_node, position_to_node from baron.path import path_to_bounding_box, node_to_bounding_box from baron.utils import string_instance def test_position(): pos1 = (1, 2) pos2 = Position((1, 2)) pos3 = Position((1, 2)) pos4 = Position(Position((1, 2))) assert pos1 == pos2 assert pos2 == pos3 assert pos3 == pos4 assert isinstance(pos2, Position) assert isinstance(pos3, Position) assert isinstance(pos4, Position) def test_position_compare(): assert Position((1, 2)) < Position((1, 3)) assert Position((0, 9)) < Position((1, 3)) assert Position((1, 2)) <= Position((1, 3)) assert Position((0, 9)) <= Position((1, 3)) assert Position((1, 2)) <= Position((1, 2)) assert Position((1, 2)) == Position((1, 2)) assert Position((1, 4)) > Position((1, 3)) assert Position((2, 0)) > Position((1, 3)) assert Position((1, 4)) >= Position((1, 3)) assert Position((2, 0)) >= Position((1, 3)) assert Position((1, 4)) >= Position((1, 4)) assert Position((1, 4)) == Position((1, 4)) def test_position_bool(): assert bool(Position((1, 2))) assert not bool(Position((-1, 2))) assert not bool(Position((1, -2))) assert not bool(Position((-1, -2))) def test_bounding_box(): bb1 = ((1, 2), (3, 4)) bb2 = BoundingBox(((1, 2), (3, 4))) bb3 = BoundingBox((Position((1, 2)), (3, 4))) bb4 = BoundingBox(((1, 2), Position((3, 4)))) bb5 = BoundingBox((Position((1, 2)), Position((3, 4)))) bb6 = BoundingBox(((1, 2), (3, 4))) bb7 = BoundingBox((Position((1, 2)), (3, 4))) bb8 = BoundingBox(((1, 2), Position((3, 4)))) bb9 = BoundingBox((Position((1, 2)), Position((3, 4)))) bb10 = BoundingBox(BoundingBox(((1, 2), (3, 4)))) assert bb1 == bb2 assert bb2 == bb3 assert bb3 == bb4 assert bb4 == bb5 assert bb5 == bb6 assert bb6 == bb7 assert bb7 == bb8 assert bb8 == bb9 assert bb9 == bb10 assert isinstance(bb2, BoundingBox) assert isinstance(bb3, BoundingBox) assert isinstance(bb4, BoundingBox) assert isinstance(bb5, BoundingBox) assert isinstance(bb6, BoundingBox) assert isinstance(bb7, BoundingBox) assert isinstance(bb8, BoundingBox) assert isinstance(bb9, BoundingBox) assert isinstance(bb10, BoundingBox) simplecode = """vara = 1""" bigcode = """\ def fun(arg1, arg2): var *= 1 @deco("arg") def fun2(arg1 = default, **kwargs): arg1.attr = 3 """ splitcode = """var \\\n = 2""" windows_splitcode = """var \\\r\n = 2""" classcode = """\ class MyClass(BaseClass): def __init__(self, arg1): self.a = arg1 def getA(): return self.a """ class PathWalkerTester(PathWalker): """This class is used exclusively to test the PathWalker It works by walking along with the PathWalker and for each step, i.e. for each before, after and on_leaf method called, it checks if that step was indeed expected. To specify the expected steps, you should simply pass a list of tuples. The first field tells what kind of step it should be: * '>' for calling the `before` method, i.e. going down the tree, * '<' for calling the `after` method, i.e. going up the tree and the second is what the current path should be at that step. """ def __init__(self, paths): super(PathWalkerTester, self).__init__(strict=True) self.paths = paths def before(self, *args): super(PathWalkerTester, self).before(*args) self.process_test('>') def after(self, *args): self.process_test('<') super(PathWalkerTester, self).after(*args) def process_test(self, node_type): _node_type, _path = self.paths.pop(0) assert _node_type == node_type assert _path == self.current_path def check_path(code, positions, target_path): tree = parse(code) for position in positions: path = position_to_path(tree, position) assert path == target_path if path is None: assert position_to_node(tree, position) is None return node = path_to_node(tree, path) assert isinstance(node, string_instance) assert position_to_node(tree, position) is node if target_path is not None: bounding_box = (positions[0], positions[-1]) assert path_to_bounding_box(tree, path) == bounding_box def test_path_walker_assignment(): node = parse("a = 1") # Indentation is purely visual sugar walker = PathWalkerTester([ ('>', [0]), ('>', [0, 'target']), ('>', [0, 'target', 'value']), ('<', [0, 'target', 'value']), ('<', [0, 'target']), ('>', [0, 'first_formatting']), ('>', [0, 'first_formatting', 0]), ('>', [0, 'first_formatting', 0, 'value']), ('<', [0, 'first_formatting', 0, 'value']), ('<', [0, 'first_formatting', 0]), ('<', [0, 'first_formatting']), ('>', [0, '=']), ('<', [0, '=']), ('>', [0, 'second_formatting']), ('>', [0, 'second_formatting', 0]), ('>', [0, 'second_formatting', 0, 'value']), ('<', [0, 'second_formatting', 0, 'value']), ('<', [0, 'second_formatting', 0]), ('<', [0, 'second_formatting']), ('>', [0, 'value']), ('>', [0, 'value', 'value']), ('<', [0, 'value', 'value']), ('<', [0, 'value']), ('<', [0]), ]) walker.walk(node) def test_bb_name(): node = parse("var")[0] assert node_to_bounding_box(node) == ((1, 1), (1, 3)) def test_bb_string(): node = parse("\"hello\"")[0] assert path_to_bounding_box(node, []) == ((1, 1), (1, 7)) def test_bb_comment(): node = parse("# comment")[0] assert path_to_bounding_box(node, None) == ((1, 1), (1, 9)) def test_bb_funcdef(): node = parse(bigcode)[0] assert node_to_bounding_box(node) == ((1, 1), (4, 0)) def test_bb_class(): node = parse(classcode)[0] assert node_to_bounding_box(node) == ((1, 1), (7, 0)) def test_bb_split_assignment(): node = parse(splitcode)[0] assert node_to_bounding_box(node) == ((1, 1), (2, 5)) def test_sc_out_of_scope(): check_path(simplecode, [(-1, 3), (1, -3), (3, 3), (1, 100)], None) def test_sc_assignement_target(): path = [0, "target", "value"] check_path(simplecode, [(1, 1), (1, 2), (1, 3), (1, 4)], path) def test_sc_assignement_first_formatting(): path = [0, "first_formatting", 0, "value"] check_path(simplecode, [(1, 5)], path) def test_sc_assignement_operator(): path = [0, "="] check_path(simplecode, [(1, 6)], path) def test_sc_assignement_second_formatting(): path = [0, "second_formatting", 0, "value"] check_path(simplecode, [(1, 7)], path) def test_sc_assignement_value(): path = [0, "value", "value"] check_path(simplecode, [(1, 8)], path) def test_bc_l1_def(): path = [0, "def"] check_path(bigcode, [(1, 1), (1, 2), (1, 3)], path) def test_bc_l1_def_first_formatting(): tree = parse(bigcode) path = [0, "first_formatting"] assert path_to_bounding_box(tree, path) == ((1, 4), (1, 4)) path = [0, "first_formatting", 0] assert path_to_bounding_box(tree, path) == ((1, 4), (1, 4)) path = [0, "first_formatting", 0, "value"] check_path(bigcode, [(1, 4)], path) def test_bc_l1_def_name(): path = [0, "name"] check_path(bigcode, [(1, 5), (1, 6), (1, 7)], path) def test_bc_l1_def_second_formatting(): path = [0, "second_formatting"] tree = parse(bigcode) assert path_to_bounding_box(tree, path) == ((1, 8), (1, 7)) def test_bc_l1_def_left_paren(): path = [0, "("] check_path(bigcode, [(1, 8)], path) def test_bc_l1_arg1(): path = [0, "arguments", 0, "target", "value"] check_path(bigcode, [(1, 9), (1, 10), (1, 11), (1, 12)], path) def test_bc_l1_comma(): path = [0, "arguments", 1, ","] check_path(bigcode, [(1, 13)], path) def test_bc_l1_comma_second_formatting(): path = [0, "arguments", 1, "second_formatting", 0, "value"] check_path(bigcode, [(1, 14)], path) def test_bc_l1_arg2(): path = [0, "arguments", 2, "target", "value"] check_path(bigcode, [(1, 15), (1, 16), (1, 17), (1, 18)], path) def test_bc_l1_right_paren(): path = [0, ")"] check_path(bigcode, [(1, 19)], path) def test_bc_l1_colon(): path = [0, ":"] check_path(bigcode, [(1, 20)], path) def test_bc_l1_space(): path = [0, "value", 0, "formatting", 0, "value"] check_path(bigcode, [(1, 21)], path) def test_bc_l1_out_of_scope(): check_path(bigcode, [(1, 22), (2, 0)], None) def test_bc_l2_endl(): path = [0, "value", 0, "indent"] check_path(bigcode, [(2, 1), (2, 2), (2, 3), (2, 4)], path) def test_bc_l2_assign_var(): path = [0, "value", 1, "target", "value"] check_path(bigcode, [(2, 5), (2, 6), (2, 7)], path) def test_bc_l2_assign_first_formatting(): path = [0, "value", 1, "first_formatting", 0, "value"] check_path(bigcode, [(2, 8)], path) def test_bc_l2_assign_operator(): path = [0, "value", 1, "operator"] check_path(bigcode, [(2, 9)], path) def test_bc_l2_assign_equal(): path = [0, "value", 1, "="] check_path(bigcode, [(2, 10)], path) def test_bc_l2_assign_second_formatting(): path = [0, "value", 1, "second_formatting", 0, "value"] check_path(bigcode, [(2, 11)], path) def test_bc_l2_assign_value(): path = [0, "value", 1, "value", "value"] check_path(bigcode, [(2, 12)], path) def test_bc_l2_out_of_scope(): check_path(bigcode, [(2, 13), (3, 0)], None) def test_bc_l3_empty(): check_path(bigcode, [(3, 1)], None) def test_bc_l4_decorator_at(): path = [1, "decorators", 0, "@"] check_path(bigcode, [(4, 1)], path) def test_bc_l4_decorator_name(): path = [1, "decorators", 0, "value", "value", 0, "value"] check_path(bigcode, [(4, 2), (4, 3), (4, 4), (4, 5)], path) def test_bc_l4_decorator_left_paren(): path = [1, "decorators", 0, "call", "("] check_path(bigcode, [(4, 6)], path) def test_bc_l4_decorator_arg1(): path = [1, "decorators", 0, "call", "value", 0, "value", "value"] check_path(bigcode, [(4, 7), (4, 8), (4, 9), (4, 10), (4, 11)], path) def test_bc_l4_decorator_right_paren(): path = [1, "decorators", 0, "call", ")"] check_path(bigcode, [(4, 12)], path) def test_bc_l4_out_of_scope(): check_path(bigcode, [(4, 13), (5, 0)], None) def test_bc_l5_def(): path = [1, "def"] check_path(bigcode, [(5, 1), (5, 2), (5, 3)], path) def test_bc_l5_def_first_formatting(): path = [1, "first_formatting", 0, "value"] check_path(bigcode, [(5, 4)], path) def test_bc_l5_def_name(): path = [1, "name"] check_path(bigcode, [(5, 5), (5, 6), (5, 7), (5, 8)], path) def test_bc_l5_left_paren(): path = [1, "("] check_path(bigcode, [(5, 9)], path) def test_bc_l5_arg1(): path = [1, "arguments", 0, "target", "value"] check_path(bigcode, [(5, 10), (5, 11), (5, 12), (5, 13)], path) def test_bc_l5_arg1_first_formatting(): path = [1, "arguments", 0, "first_formatting", 0, "value"] check_path(bigcode, [(5, 14)], path) def test_bc_l5_arg1_equal(): path = [1, "arguments", 0, "="] check_path(bigcode, [(5, 15)], path) def test_bc_l5_arg1_second_formatting(): path = [1, "arguments", 0, "second_formatting", 0, "value"] check_path(bigcode, [(5, 16)], path) def test_bc_l5_arg1_value(): path = [1, "arguments", 0, "value", "value"] check_path(bigcode, [(5, 17), (5, 18), (5, 19), (5, 20), (5, 21), (5, 22), (5, 23)], path) def test_bc_l5_args_comma(): path = [1, "arguments", 1, ","] check_path(bigcode, [(5, 24)], path) def test_bc_l5_args_comma_second_formatting(): path = [1, "arguments", 1, "second_formatting", 0, "value"] check_path(bigcode, [(5, 25)], path) def test_bc_l5_arg2_operator(): path = [1, "arguments", 2, "**"] check_path(bigcode, [(5, 26), (5, 27)], path) def test_bc_l5_arg2_name(): path = [1, "arguments", 2, "value", "value"] check_path(bigcode, [(5, 28), (5, 29), (5, 30), (5, 31), (5, 32), (5, 33)], path) def test_bc_l5_right_paren(): path = [1, ")"] check_path(bigcode, [(5, 34)], path) def test_bc_l5_colon(): path = [1, ":"] check_path(bigcode, [(5, 35)], path) def test_bc_l5_out_of_scope(): check_path(bigcode, [(5, 36), (6, 0)], None) def test_bc_l6_endl(): path = [1, "value", 0, "indent"] check_path(bigcode, [(6, 1), (6, 2), (6, 3), (6, 4)], path) def test_bc_l6_assign_var(): path = [1, "value", 1, "target", "value", 0, "value"] check_path(bigcode, [(6, 5), (6, 6), (6, 7), (6, 8)], path) def test_bc_l6_assign_var_dot(): path = [1, "value", 1, "target", "value", 1, "."] check_path(bigcode, [(6, 9)], path) def test_bc_l6_assign_var_dot_name(): path = [1, "value", 1, "target", "value", 2, "value"] check_path(bigcode, [(6, 10), (6, 11), (6, 12), (6, 13)], path) def test_bc_l6_assign_first_formatting(): path = [1, "value", 1, "first_formatting", 0, "value"] check_path(bigcode, [(6, 14)], path) def test_bc_l6_assign_equal(): path = [1, "value", 1, "="] check_path(bigcode, [(6, 15)], path) def test_bc_l6_assign_second_formatting(): path = [1, "value", 1, "second_formatting", 0, "value"] check_path(bigcode, [(6, 16)], path) def test_bc_l6_assign_value(): path = [1, "value", 1, "value", "value"] check_path(bigcode, [(6, 17)], path) def test_bc_l6_out_of_scope(): check_path(bigcode, [(6, 18), (7, 0)], None) def test_sc_l1_var(): path = [0, "target", "value"] check_path(splitcode, [(1, 1), (1, 2), (1, 3)], path) def test_sc_l1_var_win(): path = [0, "target", "value"] check_path(windows_splitcode, [(1, 1), (1, 2), (1, 3)], path) def test_sc_l1_l2_first_space(): path = [0, "first_formatting", 0, "value"] check_path(splitcode, [(1, 4), (1, 5), (2, 1), (2, 2)], path) def test_sc_l1_l2_first_space_win(): path = [0, "first_formatting", 0, "value"] check_path(windows_splitcode, [(1, 4), (1, 5), (2, 1), (2, 2)], path) def test_sc_l1_out_of_scope(): check_path(splitcode, [(1, 6), (2, 0)], None) def test_sc_l1_out_of_scope_win(): check_path(windows_splitcode, [(1, 6), (2, 0)], None) def test_sc_l2_operator(): path = [0, "="] check_path(splitcode, [(2, 3)], path) def test_sc_l2_operator_win(): path = [0, "="] check_path(windows_splitcode, [(2, 3)], path) def test_sc_l2_second_space(): path = [0, "second_formatting", 0, "value"] check_path(splitcode, [(2, 4)], path) def test_sc_l2_second_space_win(): path = [0, "second_formatting", 0, "value"] check_path(windows_splitcode, [(2, 4)], path) def test_sc_l2_value(): path = [0, "value", "value"] check_path(splitcode, [(2, 5)], path) def test_sc_l2_value_win(): path = [0, "value", "value"] check_path(windows_splitcode, [(2, 5)], path) def test_sc_l2_out_of_scope(): check_path(splitcode, [(2, 6), (3, 0)], None) def test_sc_l2_out_of_scope_win(): check_path(windows_splitcode, [(2, 6), (3, 0)], None) def test_position_equality(): assert Position((1, 2)) == Position((1, 2)) assert Position((1, 2)) == (1, 2) assert Position((1, 2)) != Position((2, 1)) assert Position((1, 2)) != (2, 1) def test_position_opposite(): assert Position((1, 2)) == - Position((-1, -2)) def test_position_arithmetic(): assert Position((1, 2)) + Position((1, 2)) == (2, 4) assert Position((1, 2)) + (1, 2) == (2, 4) assert Position((1, 2)) - Position((2, 1)) == (-1, 1) assert Position((1, 2)) - (2, 1) == (-1, 1) def test_position_advance(): position = Position((1, 1)) position.advance_columns(3) assert position == (1, 4) position.advance_line() assert position == (2, 1) position.advance_columns(4) assert position == (2, 5) def test_position_left(): assert Position((1, 2)).left == (1, 1) def test_position_right(): assert Position((1, 2)).right == (1, 3) def test_postion_around_the_world(): assert Position((1, 2)) == Position(Position((1, 2)).to_tuple()) baron-0.10.1/tests/test_regression.py000066400000000000000000000014461415427440200176350ustar00rootroot00000000000000from baron import parse, dumps, tokenize def test_regression_trailing_comment_after_colon(): assert parse("def a(): # pouf\n pass") def test_regression_trailing_comment_after_colon_no_space(): assert parse("def a():# pouf\n pass") def test_regression_trailing_comment_after_colon_dump(): code = "def a(): # pouf\n pass\n" assert dumps(parse(code)) == code def test_regression_trailing_comment_after_colon_no_space_dump(): code = "def a():# pouf\n pass\n" assert dumps(parse(code)) == code def test_comment_in_middle_of_ifelseblock(): code = 'if a:\n pass\n# comment\nelse:\n pass\n' assert dumps(parse(code)) == code def test_new_float_notation(): code = 'a._' assert tokenize(code)[:-1] == [('NAME', 'a'), ('DOT', '.'), ('NAME', '_')] baron-0.10.1/tests/test_render.py000066400000000000000000000226611415427440200167360ustar00rootroot00000000000000import pytest from baron import parse from baron.render import render, node_types, nodes_rendering_order, RenderWalker @pytest.fixture(params=nodes_rendering_order.keys()) def dictionnary_node(request): return nodes_rendering_order[request.param] def test_render_crap(): with pytest.raises(NotImplementedError): render("crap") def test_dictionnary_key_validity(dictionnary_node): for key_type, _, _ in dictionnary_node: assert key_type in node_types def test_dictionnary_dependent_validity(dictionnary_node): keys = set([t[1] for t in dictionnary_node]) for key_type, _, dependent in dictionnary_node: assert isinstance(dependent, bool) \ or (isinstance(dependent, str) and dependent in keys) \ or (isinstance(dependent, list) and all([d in keys for d in dependent])) if key_type == 'bool': assert dependent is False def test_render_dictionnary_bad_type(): nodes_rendering_order['bad_type'] = [('wtf', 'hello', True)] with pytest.raises(NotImplementedError) as e: list(render({'type': 'bad_type'})) assert str(e.value) == "Unknown key type \"wtf\" in \"bad_type\" node" def test_render_dictionnary_bad_bool_dependency(): nodes_rendering_order['bad_bool_dependency'] = [('bool', True, True)] with pytest.raises(NotImplementedError) as e: list(render({'type': 'bad_bool_dependency'})) assert str(e.value) == "Bool keys are only used for dependency, they cannot be rendered. Please set the \"('bool', True, True)\"'s dependent key in \"bad_bool_dependency\" node to False" def test_render_dictionnary_bad_bool_dependency2(): nodes_rendering_order['bad_bool_dependency2'] = [('bool', False, 'other_key')] with pytest.raises(NotImplementedError) as e: list(render({'type': 'bad_bool_dependency2'})) assert str(e.value) == "Bool keys are only used for dependency, they cannot be rendered. Please set the \"('bool', False, 'other_key')\"'s dependent key in \"bad_bool_dependency2\" node to False" class RenderWalkerTester(RenderWalker): def __init__(self, steps): super(RenderWalkerTester, self).__init__(strict=True) self.steps = steps def before(self, *args): super(RenderWalkerTester, self).before(*args) return self.process_test('>', *args) def after(self, *args): stop = self.process_test('<', *args) super(RenderWalkerTester, self).after(*args) return stop def process_test(self, direction, node_type, node, render_key): _direction, _node_type, _node, _render_key, _stop = self.steps.pop(0) target = (_direction, _node_type, _node, _render_key) if node_type in ['constant', 'string']: assert target == (direction, node_type, node, render_key) elif "type" in node: assert target == (direction, node_type, node["type"], render_key) else: assert target == (direction, node_type, node.__class__.__name__, render_key) return _stop # flake8: noqa def test_walk_stop(): node = parse("a = 1") walker = RenderWalkerTester([ ('>', 'node', 'assignment', 0, False), ('>', 'key', 'name', 'target', False), ('>', 'string', 'a', 'value', True), ('<', 'key', 'name', 'target', False), ('<', 'node', 'assignment', 0, False), ]) walker.walk(node) def test_walk_assignment(): node = parse("a = 1") walker = RenderWalkerTester([ ('>', 'node', 'assignment', 0, False), ('>', 'key', 'name', 'target', False), ('>', 'string', 'a', 'value', False), ('<', 'string', 'a', 'value', False), ('<', 'key', 'name', 'target', False), ('>', 'formatting', 'list', 'first_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'string', ' ', 'value', False), ('<', 'string', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'first_formatting', False), ('>', 'constant', '=', '=', False), ('<', 'constant', '=', '=', False), ('>', 'formatting', 'list', 'second_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'string', ' ', 'value', False), ('<', 'string', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'second_formatting', False), ('>', 'key', 'int', 'value', False), ('>', 'string', '1', 'value', False), ('<', 'string', '1', 'value', False), ('<', 'key', 'int', 'value', False), ('<', 'node', 'assignment', 0, False), ]) walker.walk(node) def test_walk_funcdef_with_leading_space(): node = parse("""\ @deco def fun(arg1): pass """) walker = RenderWalkerTester([ ('>', 'node', 'endl', 0, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'string', '\n', 'value', False), ('<', 'string', '\n', 'value', False), ('>', 'string', '', 'indent', False), ('<', 'string', '', 'indent', False), ('<', 'node', 'endl', 0, False), ('>', 'node', 'def', 1, False), ('>', 'list', 'list', 'decorators', False), ('>', 'node', 'decorator', 0, False), ('>', 'constant', '@', '@', False), ('<', 'constant', '@', '@', False), ('>', 'key', 'dotted_name', 'value', False), ('>', 'list', 'list', 'value', False), ('>', 'node', 'name', 0, False), ('>', 'string', 'deco', 'value', False), ('<', 'string', 'deco', 'value', False), ('<', 'node', 'name', 0, False), ('<', 'list', 'list', 'value', False), ('<', 'key', 'dotted_name', 'value', False), ('<', 'node', 'decorator', 0, False), ('>', 'node', 'endl', 1, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'string', '\n', 'value', False), ('<', 'string', '\n', 'value', False), ('>', 'string', '', 'indent', False), ('<', 'string', '', 'indent', False), ('<', 'node', 'endl', 1, False), ('<', 'list', 'list', 'decorators', False), ('>', 'constant', 'def', 'def', False), ('<', 'constant', 'def', 'def', False), ('>', 'formatting', 'list', 'first_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'string', ' ', 'value', False), ('<', 'string', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'first_formatting', False), ('>', 'string', 'fun', 'name', False), ('<', 'string', 'fun', 'name', False), ('>', 'formatting', 'list', 'second_formatting', False), ('<', 'formatting', 'list', 'second_formatting', False), ('>', 'constant', '(', '(', False), ('<', 'constant', '(', '(', False), ('>', 'formatting', 'list', 'third_formatting', False), ('<', 'formatting', 'list', 'third_formatting', False), ('>', 'list', 'list', 'arguments', False), ('>', 'node', 'def_argument', 0, False), ('>', 'key', 'name', 'target', False), ('>', 'string', 'arg1', 'value', False), ('<', 'string', 'arg1', 'value', False), ('<', 'key', 'name', 'target', False), ('<', 'node', 'def_argument', 0, False), ('<', 'list', 'list', 'arguments', False), ('>', 'formatting', 'list', 'fourth_formatting', False), ('<', 'formatting', 'list', 'fourth_formatting', False), ('>', 'constant', ')', ')', False), ('<', 'constant', ')', ')', False), ('>', 'formatting', 'list', 'fifth_formatting', False), ('<', 'formatting', 'list', 'fifth_formatting', False), ('>', 'constant', ':', ':', False), ('<', 'constant', ':', ':', False), ('>', 'formatting', 'list', 'sixth_formatting', False), ('<', 'formatting', 'list', 'sixth_formatting', False), ('>', 'list', 'list', 'value', False), ('>', 'node', 'endl', 0, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'string', '\n', 'value', False), ('<', 'string', '\n', 'value', False), ('>', 'string', ' ', 'indent', False), ('<', 'string', ' ', 'indent', False), ('<', 'node', 'endl', 0, False), ('>', 'node', 'pass', 1, False), ('>', 'string', 'pass', 'type', False), ('<', 'string', 'pass', 'type', False), ('<', 'node', 'pass', 1, False), ('>', 'node', 'endl', 2, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'string', '\n', 'value', False), ('<', 'string', '\n', 'value', False), ('>', 'string', '', 'indent', False), ('<', 'string', '', 'indent', False), ('<', 'node', 'endl', 2, False), ('<', 'list', 'list', 'value', False), ('<', 'node', 'def', 1, False), ]) walker.walk(node) baron-0.10.1/tests/test_spliter.py000066400000000000000000000205661415427440200171430ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- from baron.spliter import split, UntreatedError from baron.utils import python_version import pytest def test_empty(): assert split("") == [] def test_print(): assert split("print") == ["print"] def test_print_space(): assert split("print ") == ['print', ' '] def test_import(): assert split("import pouet") == ["import", " ", "pouet"] def test_from_import(): assert split(" from zob import pouet ") == [" ", "from", " ", "zob", " ", "import", " ", "pouet", " "] def test_from_import_as(): assert split("from a import b as c") == ["from", " ", "a", " ", "import", " ", "b", " ", "as", " ", "c"] def test_underscore_variable(): assert split("some_variable") == ["some_variable"] def test_different_case(): assert split("AbCd cDeF") == ["AbCd", " ", "cDeF"] def test_decorator(): assert split("@pouet") == ["@", "pouet"] def test_tab_n_space(): assert split(" ") == [" "] def test_several_spaces(): assert split(" ") == [" "] def test_numbers(): assert split("1234") == ["1234"] def test_several_numbers(): assert split("12 34") == ["12", " ", "34"] def test_comma(): assert split(",") == [","] def test_comma_with_words(): assert split("a, b") == ["a", ",", " ", "b"] def test_dot(): assert split(".") == ["."] def test_dot_with_word(): assert split("a.b") == ["a", ".", "b"] def test_dot_with_words(): assert split("a.b.c") == ["a", ".", "b", ".", "c"] def test_colon(): assert split(";") == [";"] def test_colon_word(): assert split("pouet;") == ["pouet", ";"] def test_assign(): assert split("a = b") == ["a", " ", "=", " ", "b"] def test_call(): assert split("function()") == ["function", "(", ")"] def test_call_with_arg(): assert split("function(a)") == ["function", "(", "a", ")"] def test_call_with_args(): assert split("function(a, b, c)") == ["function", "(", "a", ",", " ", "b", ",", " ", "c", ")"] def test_call_with_kwarg(): assert split("function(a=b)") == ["function", "(", "a", "=", "b", ")"] def test_call_with_kwargs(): assert split("function(a=b, c= d)") == ["function", "(", "a", "=", "b", ",", " ", "c", "=", " ", "d", ")"] def test_call_with_start_args(): assert split("function(*args)") == ["function", "(", "*", "args", ")"] def test_call_with_start_kwargs(): assert split("function(**kwargs)") == ["function", "(", "*", "*", "kwargs", ")"] def test_function_def(): assert split("def pouet(): pass") == ["def", " ", "pouet", "(", ")", ":", " ", "pass"] def test_addition(): assert split("a + 2") == ["a", " ", "+", " ", "2"] def test_substraction(): assert split("a - 2") == ["a", " ", "-", " ", "2"] def test_multiplication(): assert split("a * 2") == ["a", " ", "*", " ", "2"] def test_division(): assert split("a/2") == ["a", "/", "2"] def test_power(): assert split("a**2") == ["a", "*", "*", "2"] def test_modulo(): assert split("a % 2") == ["a", " ", "%", " ", "2"] def test_binary_stuff(): assert split("a^2") == ["a", "^", "2"] assert split("a&2") == ["a", "&", "2"] assert split("a|2") == ["a", "|", "2"] assert split("a << 2") == ["a", " ", "<", "<", " ", "2"] assert split("a >> 2") == ["a", " ", ">", ">", " ", "2"] def test_operator_assign(): assert split("a += 2") == ["a", " ", "+", "=", " ", "2"] assert split("a -= 2") == ["a", " ", "-", "=", " ", "2"] assert split("a *= 2") == ["a", " ", "*", "=", " ", "2"] assert split("a /= 2") == ["a", " ", "/", "=", " ", "2"] assert split("a %= 2") == ["a", " ", "%", "=", " ", "2"] assert split("a &= 2") == ["a", " ", "&", "=", " ", "2"] assert split("a |= 2") == ["a", " ", "|", "=", " ", "2"] assert split("a ^= 2") == ["a", " ", "^", "=", " ", "2"] assert split("a //= 2") == ["a", " ", "/", "/", "=", " ", "2"] assert split("a **= 2") == ["a", " ", "*", "*", "=", " ", "2"] assert split("a <<= 2") == ["a", " ", "<", "<", "=", " ", "2"] assert split("a >>= 2") == ["a", " ", ">", ">", "=", " ", "2"] def test_factor(): assert split("~a") == ["~", "a"] def test_del_pouet(): assert split("del pouet") == ["del", " ", "pouet"] def test_pass(): assert split("pass") == ["pass"] def test_break(): assert split("break") == ["break"] def test_continue(): assert split("continue") == ["continue"] def test_return(): assert split("return") == ["return"] def test_return_stuff(): assert split("return stuff") == ["return", " ", "stuff"] def test_yield(): assert split("yield") == ["yield"] def test_yield_stuff(): assert split("yield stuff") == ["yield", " ", "stuff"] def test_raise(): assert split("raise") == ["raise"] def test_raise_stuff(): assert split("raise Exception()") == ["raise", " ", "Exception", "(", ")"] def test_global_stuff(): assert split("global stuff") == ["global", " ", "stuff"] def test_exec(): assert split("exec") == ["exec"] def test_exec_stuff(): assert split("exec stuff") == ["exec", " ", "stuff"] def test_assert(): assert split("assert") == ["assert"] def test_assert_stuff(): assert split("assert stuff") == ["assert", " ", "stuff"] def test_line_end(): assert split("\n") == ["\n"] def test_line_end_windows(): assert split("\r\n") == ["\r", "\n"] def test_if(): assert split("if ab: pass") == ["if", " ", "ab", ":", " ", "pass"] def test_if_elif_else(): assert split("if a:\n pass\nelif b:\n pass\nelse: \n pass") == ["if", " ", "a", ":", "\n", " ", "pass", "\n", "elif", " ", "b", ":", "\n", " ", "pass", "\n", "else", ":", " ", "\n", " ", "pass"] def test_while(): assert split("while a: pass") == ["while", " ", "a", ":", " ", "pass"] def test_lambda(): assert split("lambda x: x + 1") == ["lambda", " ", "x", ":", " ", "x", " ", "+", " ", "1"] def test_for(): assert split("for a in b: pass") == ["for", " ", "a", " ", "in", " ", "b", ":", " ", "pass"] def test_empty_list(): assert split("[]") == ["[", "]"] def test_list(): assert split("[a, b, c]") == ["[", "a", ",", " ", "b", ",", " ", "c", "]"] def test_empty_dict(): assert split("{}") == ["{", "}"] def test_dict(): assert split("{a: b, c: d}") == ["{", "a", ":", " ", "b", ",", " ", "c", ":", " ", "d", "}"] def test_not(): assert split("!a") == ["!", "a"] def test_not_equal(): assert split("a != b") == ["a", " ", "!", "=", " ", "b"] def test_backquote(): assert split("`a`") == ["`", "a", "`"] def test_number_in_var(): assert split("a1") == ["a1"] def test_comment(): assert split("# a b c d") == ["# a b c d"] def test_comments(): assert split("# a b c d\n# pouet") == ["# a b c d", "\n", "# pouet"] def test_empty_string(): assert split("''") == ["''"] def test_string(): assert split("'pouet pouet'") == ["'pouet pouet'"] def test_empty_string_other_quotes(): assert split('"pouet pouet"') == ['"pouet pouet"'] def test_multi_string(): assert split("'''pouet pouet'''") == ["'''pouet pouet'''"] def test_multi_string_other_quotes(): assert split('"""pouet pouet"""') == ['"""pouet pouet"""'] def test_missing_quote_yields_error(): with pytest.raises(UntreatedError): split("'") with pytest.raises(UntreatedError): split("'''") with pytest.raises(UntreatedError): split('"') with pytest.raises(UntreatedError): split('"""') def test_escape(): assert split("\\\\") == ["\\", "\\"] def test_escape_in_string(): assert split("'\\\\'") == ["'\\\\'"] def test_other_escape_string(): assert split("'\\\\'") == ["'\\\\'"] def test_hexa(): assert split("0x7F") == ["0x7F"] def test_multi_string_with_same_quotes_in(): assert split('"""pouet " "" pouet"""') == ['"""pouet " "" pouet"""'] def test_comment_backslash(): assert split('# pouet \\\npouet') == ["# pouet \\", "\n", "pouet"] def test_backslash_in_comment(): assert split("# pouet \\t pouet\npouet") == ["# pouet \\t pouet", "\n", "pouet"] def test_regression(): assert split("(r'[\"\\'](.|\n|\r)*[\"\\']', 'STRING'),") == ["(", "r", "'[\"\\'](.|\n|\r)*[\"\\']'", ",", " ", "'STRING'", ")", ","] # TODO: make this test pass in python3 also # requires to remove dependency on ast.py if python_version == 2: def test_remove_crap(): assert split("\x0c\xef\xbb\xbf") == [] def test_split_float_notation(): assert split("a._") == ["a", ".", "_"] baron-0.10.1/tests/test_tokenizer.py000066400000000000000000000355471415427440200175000ustar00rootroot00000000000000#!/usr/bin/python # -*- coding:Utf-8 -*- from baron.tokenizer import tokenize, KEYWORDS def match(string, token): assert tokenize([string]) == [(token, string), ('ENDMARKER', ''), None] def test_empty(): assert tokenize([]) == [('ENDMARKER', ''), None] def test_name(): match('a', 'NAME') match('pouet', 'NAME') def test_name__(): match('_a', 'NAME') def test_name_number(): match('a123', 'NAME') def test_await_as_name(): # not a real keyword in python match('await', 'NAME') def test_asyc_as_name(): # not a real keyword in python match('async', 'NAME') def test_number(): match('1234', 'INT') match('1234L', 'LONG') match('1234l', 'LONG') def test_float(): match('1234.', 'FLOAT') match('.1234', 'FLOAT') match('1234.1234', 'FLOAT') match('1234.L', 'FLOAT') match('.1234L', 'FLOAT') match('1234.1234L', 'FLOAT') match('1234.l', 'FLOAT') match('.1234l', 'FLOAT') match('1234.1234l', 'FLOAT') def test_hexa(): match('0x123ABCD', 'HEXA') match('0X123ABCD', 'HEXA') match('0x123ABCDl', 'HEXA') match('0x123ABCDL', 'HEXA') def test_grouped(): match('100_000', 'INT') match('10_000_000.', 'FLOAT') match('10_000_000.0', 'FLOAT') match('0xCAFE_F00D', 'HEXA') match('0o123_45', 'OCTA') match('0b_0011_1111_0100_1110', 'BINARY') def test_octa(): match('012345', 'OCTA') match('0o12345', 'OCTA') match('0O1235', 'OCTA') match('0O1235l', 'OCTA') match('0O1235L', 'OCTA') def test_float_exponant(): match('1234e10', 'FLOAT_EXPONANT') match('1234E10', 'FLOAT_EXPONANT') match('1234e+10', 'FLOAT_EXPONANT') match('1234e-10', 'FLOAT_EXPONANT') match('1234E+10', 'FLOAT_EXPONANT') match('1234E-10', 'FLOAT_EXPONANT') match('1234.5678e10', 'FLOAT_EXPONANT') match('1234.5678E10', 'FLOAT_EXPONANT') match('1234.5678e+10', 'FLOAT_EXPONANT') match('1234.5678e-10', 'FLOAT_EXPONANT') match('1234.5678E+10', 'FLOAT_EXPONANT') match('1234.5678E-10', 'FLOAT_EXPONANT') match('.5678e10', 'FLOAT_EXPONANT') match('.5678E10', 'FLOAT_EXPONANT') match('.5678e+10', 'FLOAT_EXPONANT') match('.5678e-10', 'FLOAT_EXPONANT') match('.5678E+10', 'FLOAT_EXPONANT') match('.5678E-10', 'FLOAT_EXPONANT') def test_floating_point_parser_bug_85(): from baron import parse assert parse('d*e-1') == [ {'first': {'first': {'type': 'name', 'value': 'd'}, 'first_formatting': [], 'second': {'type': 'name', 'value': 'e'}, 'second_formatting': [], 'type': 'binary_operator', 'value': '*'}, 'first_formatting': [], 'second': {'section': 'number', 'type': 'int', 'value': '1'}, 'second_formatting': [], 'type': 'binary_operator', 'value': '-'}] def test_left_parenthesis(): match('(', 'LEFT_PARENTHESIS') def test_right_parenthesis(): match(')', 'RIGHT_PARENTHESIS') def test_colon(): match(':', 'COLON') assert tokenize([':']) == [('COLON', ':'), ('ENDMARKER', ''), None] def test_comma(): match(',', 'COMMA') def test_semicolon(): match(';', 'SEMICOLON') def test_sequence(): assert tokenize(['a', '123']) == [('NAME', 'a'), ('INT', '123'), ('ENDMARKER', ''), None] def test_plus(): match('+', 'PLUS') def test_minus(): match('-', 'MINUS') def test_start(): match('*', 'STAR') def test_slash(): match('/', 'SLASH') def test_vbar(): match('|', 'VBAR') def test_amper(): match('&', 'AMPER') def test_less(): match('<', 'LESS') def test_greater(): match('>', 'GREATER') def test_equal(): match('=', 'EQUAL') def test_dot(): match('.', 'DOT') def test_percent(): match('%', 'PERCENT') def test_left_square_bracket(): match('[', 'LEFT_SQUARE_BRACKET') def test_right_square_bracket(): match(']', 'RIGHT_SQUARE_BRACKET') def test_left_bracket(): match('{', 'LEFT_BRACKET') def test_right_bracket(): match('}', 'RIGHT_BRACKET') def test_back_quote(): match('`', 'BACKQUOTE') def test_equal_equal(): match('==', 'EQUAL_EQUAL') def test_not_equal(): match('!=', 'NOT_EQUAL') match('<>', 'NOT_EQUAL') def test_less_equal(): match('<=', 'LESS_EQUAL') def test_greater_equal(): match('>=', 'GREATER_EQUAL') def test_tilde(): match('~', 'TILDE') def test_circumflex(): match('^', 'CIRCUMFLEX') def test_left_shift(): match('<<', 'LEFT_SHIFT') def test_right_shift(): match('>>', 'RIGHT_SHIFT') def test_double_star(): match('**', 'DOUBLE_STAR') def test_plus_equal(): match('+=', 'PLUS_EQUAL') def test_minus_equal(): match('-=', 'MINUS_EQUAL') def test_star_equal(): match('*=', 'STAR_EQUAL') def test_slash_equal(): match('/=', 'SLASH_EQUAL') def test_percent_equal(): match('%=', 'PERCENT_EQUAL') def test_amper_equal(): match('&=', 'AMPER_EQUAL') def test_at_equal(): match('@=', 'AT_EQUAL') def test_vbar_equal(): match('|=', 'VBAR_EQUAL') def test_circumflex_equal(): match('^=', 'CIRCUMFLEX_EQUAL') def test_left_shift_equal(): match('<<=', 'LEFT_SHIFT_EQUAL') def test_right_shift_equal(): match('>>=', 'RIGHT_SHIFT_EQUAL') def test_double_star_equal(): match('**=', 'DOUBLE_STAR_EQUAL') def test_double_slash(): match('//', 'DOUBLE_SLASH') def test_double_slash_equal(): match('//=', 'DOUBLE_SLASH_EQUAL') def test_keywords(): for keyword in KEYWORDS: assert tokenize([keyword]) == [(keyword.upper(), keyword), ('ENDMARKER', ''), None] def test_endl(): match('\n', 'ENDL') match('\r\n', 'ENDL') def test_simple_string(): match('"pouet pouet"', 'STRING') match("'pouet pouet'", "STRING") def test_multi_string(): match('"""pouet pouet"""', 'STRING') match("'''pouet pouet'''", "STRING") def test_unicode_string(): match('u"pouet pouet"', 'UNICODE_STRING') match("u'pouet pouet'", "UNICODE_STRING") match('u"""pouet pouet"""', 'UNICODE_STRING') match("u'''pouet pouet'''", "UNICODE_STRING") match('U"pouet pouet"', 'UNICODE_STRING') match("U'pouet pouet'", "UNICODE_STRING") match('U"""pouet pouet"""', 'UNICODE_STRING') match("U'''pouet pouet'''", "UNICODE_STRING") def test_interpolated_string(): match("f'He said his name is {name!r}.'", 'INTERPOLATED_STRING') match("f'The value is {value}.'", 'INTERPOLATED_STRING') match('F"He said his name is {name!r}."', 'INTERPOLATED_STRING') match('f"The value is {value}."', 'INTERPOLATED_STRING') match("F'{date} was on a {date:%A}'", 'INTERPOLATED_STRING') match("f'a={d[\"a\"]}'", 'INTERPOLATED_STRING') match("F'{(lambda x: x*2)(3)}'", 'INTERPOLATED_STRING') def test_interpolated_raw_string(): match("fr'He said his name is {name!r}.'", 'INTERPOLATED_RAW_STRING') match("fr'The value is {value}.'", 'INTERPOLATED_RAW_STRING') match('Fr"He said his name is {name!r}."', 'INTERPOLATED_RAW_STRING') match('fR"The value is {value}."', 'INTERPOLATED_RAW_STRING') match("FR'{date} was on a {date:%A}'", 'INTERPOLATED_RAW_STRING') match("fr'a={d[\"a\"]}'", 'INTERPOLATED_RAW_STRING') match("FR'{(lambda x: x*2)(3)}'", 'INTERPOLATED_RAW_STRING') match("FR'{(lambda x: x*2)(3)}'", 'INTERPOLATED_RAW_STRING') match("rf'He said his name is {name!r}.'", 'INTERPOLATED_RAW_STRING') match("rf'The value is {value}.'", 'INTERPOLATED_RAW_STRING') match('rF"He said his name is {name!r}."', 'INTERPOLATED_RAW_STRING') match('Rf"The value is {value}."', 'INTERPOLATED_RAW_STRING') match("RF'{date} was on a {date:%A}'", 'INTERPOLATED_RAW_STRING') match("rf'a={d[\"a\"]}'", 'INTERPOLATED_RAW_STRING') match("RF'{(lambda x: x*2)(3)}'", 'INTERPOLATED_RAW_STRING') match("RF'{(lambda x: x*2)(3)}'", 'INTERPOLATED_RAW_STRING') def test_raw_string(): match('r"pouet pouet"', 'RAW_STRING') match("r'pouet pouet'", "RAW_STRING") match('r"""pouet pouet"""', 'RAW_STRING') match("r'''pouet pouet'''", "RAW_STRING") match('R"pouet pouet"', 'RAW_STRING') match("R'pouet pouet'", "RAW_STRING") match('R"""pouet pouet"""', 'RAW_STRING') match("R'''pouet pouet'''", "RAW_STRING") def test_binary_string(): match('b"pouet pouet"', 'BINARY_STRING') match("b'pouet pouet'", "BINARY_STRING") match('b"""pouet pouet"""', 'BINARY_STRING') match("b'''pouet pouet'''", "BINARY_STRING") match('B"pouet pouet"', 'BINARY_STRING') match("B'pouet pouet'", "BINARY_STRING") match('B"""pouet pouet"""', 'BINARY_STRING') match("B'''pouet pouet'''", "BINARY_STRING") def test_raw_unicode_string(): match('ur"pouet pouet"', 'UNICODE_RAW_STRING') match("uR'pouet pouet'", "UNICODE_RAW_STRING") match('uR"""pouet pouet"""', 'UNICODE_RAW_STRING') match("ur'''pouet pouet'''", "UNICODE_RAW_STRING") match('Ur"pouet pouet"', 'UNICODE_RAW_STRING') match("UR'pouet pouet'", "UNICODE_RAW_STRING") match('UR"""pouet pouet"""', 'UNICODE_RAW_STRING') match("Ur'''pouet pouet'''", "UNICODE_RAW_STRING") def test_raw_binary_string(): match('br"pouet pouet"', 'BINARY_RAW_STRING') match("bR'pouet pouet'", "BINARY_RAW_STRING") match('bR"""pouet pouet"""', 'BINARY_RAW_STRING') match("br'''pouet pouet'''", "BINARY_RAW_STRING") match('Br"pouet pouet"', 'BINARY_RAW_STRING') match("BR'pouet pouet'", "BINARY_RAW_STRING") match('BR"""pouet pouet"""', 'BINARY_RAW_STRING') match("Br'''pouet pouet'''", "BINARY_RAW_STRING") def test_big_string_with_endl(): match('"""pouet\n \r\npouet"""', 'STRING') match('u"""pouet\n \r\npouet"""', 'UNICODE_STRING') match('r"""pouet\n \r\npouet"""', 'RAW_STRING') match('b"""pouet\n \r\npouet"""', 'BINARY_STRING') match('ur"""pouet\n \r\npouet"""', 'UNICODE_RAW_STRING') match('br"""pouet\n \r\npouet"""', 'BINARY_RAW_STRING') def test_comment(): match('# pouet pouet', 'COMMENT') def test_space(): match(' ', 'SPACE') match(' ', 'SPACE') match(' ', 'SPACE') match(' \\\n ', 'SPACE') match(' \\\r\n ', 'SPACE') def test_arobase(): match('@', 'AT') def test_binary(): match("0b01010101", "BINARY") def test_zero(): match("0", "INT") def test_float_exponant_advanced(): match("1E1", "FLOAT_EXPONANT") match("1E-2", "FLOAT_EXPONANT") match("1E+2", "FLOAT_EXPONANT") match("1.E1", "FLOAT_EXPONANT") match(".1E1", "FLOAT_EXPONANT") match("1e1", "FLOAT_EXPONANT") match("1e-2", "FLOAT_EXPONANT") match("1e+2", "FLOAT_EXPONANT") match("1.e1", "FLOAT_EXPONANT") match(".1e1", "FLOAT_EXPONANT") def test_complex(): match(".1j", "COMPLEX") match("1.j", "COMPLEX") match("1.1j", "COMPLEX") match("11j", "COMPLEX") match(".1J", "COMPLEX") match("1.J", "COMPLEX") match("1.1J", "COMPLEX") match("11J", "COMPLEX") def test_float_advanced(): match("1.", "FLOAT") match(".1", "FLOAT") match("1.1", "FLOAT") def test_exponant_complex(): match("1e1j", "FLOAT_EXPONANT_COMPLEX") match("1.e1j", "FLOAT_EXPONANT_COMPLEX") match("1.1e1j", "FLOAT_EXPONANT_COMPLEX") match(".1e1j", "FLOAT_EXPONANT_COMPLEX") match("-1.e1j", "FLOAT_EXPONANT_COMPLEX") match("-1.1e1j", "FLOAT_EXPONANT_COMPLEX") match("-.1e1j", "FLOAT_EXPONANT_COMPLEX") match("1e-1j", "FLOAT_EXPONANT_COMPLEX") match("1.e-1j", "FLOAT_EXPONANT_COMPLEX") match("1.1e-1j", "FLOAT_EXPONANT_COMPLEX") match(".1e-1j", "FLOAT_EXPONANT_COMPLEX") match("-1.e-1j", "FLOAT_EXPONANT_COMPLEX") match("-1.1e-1j", "FLOAT_EXPONANT_COMPLEX") match("-.1e-1j", "FLOAT_EXPONANT_COMPLEX") match("1e+1j", "FLOAT_EXPONANT_COMPLEX") match("1.e+1j", "FLOAT_EXPONANT_COMPLEX") match("1.1e+1j", "FLOAT_EXPONANT_COMPLEX") match(".1e+1j", "FLOAT_EXPONANT_COMPLEX") match("-1.e+1j", "FLOAT_EXPONANT_COMPLEX") match("-1.1e+1j", "FLOAT_EXPONANT_COMPLEX") match("-.1e+1j", "FLOAT_EXPONANT_COMPLEX") match("1e1J", "FLOAT_EXPONANT_COMPLEX") match("1.e1J", "FLOAT_EXPONANT_COMPLEX") match("1.1e1J", "FLOAT_EXPONANT_COMPLEX") match(".1e1J", "FLOAT_EXPONANT_COMPLEX") match("-1.e1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1e1J", "FLOAT_EXPONANT_COMPLEX") match("-.1e1J", "FLOAT_EXPONANT_COMPLEX") match("1e-1J", "FLOAT_EXPONANT_COMPLEX") match("1.e-1J", "FLOAT_EXPONANT_COMPLEX") match("1.1e-1J", "FLOAT_EXPONANT_COMPLEX") match(".1e-1J", "FLOAT_EXPONANT_COMPLEX") match("-1.e-1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1e-1J", "FLOAT_EXPONANT_COMPLEX") match("-.1e-1J", "FLOAT_EXPONANT_COMPLEX") match("1e+1J", "FLOAT_EXPONANT_COMPLEX") match("1.e+1J", "FLOAT_EXPONANT_COMPLEX") match("1.1e+1J", "FLOAT_EXPONANT_COMPLEX") match(".1e+1J", "FLOAT_EXPONANT_COMPLEX") match("-1.e+1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1e+1J", "FLOAT_EXPONANT_COMPLEX") match("-.1e+1J", "FLOAT_EXPONANT_COMPLEX") match("1e1J", "FLOAT_EXPONANT_COMPLEX") match("1.e1J", "FLOAT_EXPONANT_COMPLEX") match("1.1e1J", "FLOAT_EXPONANT_COMPLEX") match(".1e1J", "FLOAT_EXPONANT_COMPLEX") match("-1.e1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1e1J", "FLOAT_EXPONANT_COMPLEX") match("-.1e1J", "FLOAT_EXPONANT_COMPLEX") match("1e-1J", "FLOAT_EXPONANT_COMPLEX") match("1.e-1J", "FLOAT_EXPONANT_COMPLEX") match("1.1e-1J", "FLOAT_EXPONANT_COMPLEX") match(".1e-1J", "FLOAT_EXPONANT_COMPLEX") match("-1.e-1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1e-1J", "FLOAT_EXPONANT_COMPLEX") match("-.1e-1J", "FLOAT_EXPONANT_COMPLEX") match("1e+1J", "FLOAT_EXPONANT_COMPLEX") match("1.e+1J", "FLOAT_EXPONANT_COMPLEX") match("1.1e+1J", "FLOAT_EXPONANT_COMPLEX") match(".1e+1J", "FLOAT_EXPONANT_COMPLEX") match("-1.e+1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1e+1J", "FLOAT_EXPONANT_COMPLEX") match("-.1e+1J", "FLOAT_EXPONANT_COMPLEX") match("1E1J", "FLOAT_EXPONANT_COMPLEX") match("1.E1J", "FLOAT_EXPONANT_COMPLEX") match("1.1E1J", "FLOAT_EXPONANT_COMPLEX") match(".1E1J", "FLOAT_EXPONANT_COMPLEX") match("-1.E1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1E1J", "FLOAT_EXPONANT_COMPLEX") match("-.1E1J", "FLOAT_EXPONANT_COMPLEX") match("1E-1J", "FLOAT_EXPONANT_COMPLEX") match("1.E-1J", "FLOAT_EXPONANT_COMPLEX") match("1.1E-1J", "FLOAT_EXPONANT_COMPLEX") match(".1E-1J", "FLOAT_EXPONANT_COMPLEX") match("-1.E-1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1E-1J", "FLOAT_EXPONANT_COMPLEX") match("-.1E-1J", "FLOAT_EXPONANT_COMPLEX") match("1E+1J", "FLOAT_EXPONANT_COMPLEX") match("1.E+1J", "FLOAT_EXPONANT_COMPLEX") match("1.1E+1J", "FLOAT_EXPONANT_COMPLEX") match(".1E+1J", "FLOAT_EXPONANT_COMPLEX") match("-1.E+1J", "FLOAT_EXPONANT_COMPLEX") match("-1.1E+1J", "FLOAT_EXPONANT_COMPLEX") match("-.1E+1J", "FLOAT_EXPONANT_COMPLEX") # TODO 1.1e1j def test_backslash(): match("\\\n", "SPACE") def test_ellipsis(): match("...", "ELLIPSIS") def test_right_arrow(): match("->", "RIGHT_ARROW") baron-0.10.1/tests/test_utils.py000066400000000000000000000023131415427440200166070ustar00rootroot00000000000000import sys from baron.grammator import generate_parse from baron.dumper import dumps from baron.baron import parse as baron_parse from baron.utils import python_version if python_version == 3: from itertools import zip_longest else: from itertools import izip_longest zip_longest = izip_longest parse = generate_parse(False) def parse_simple(tokens, result): if not tokens or tokens[-1][0] != "ENDL": tokens += [('ENDL', '\n')] assert parse(tokens + [('ENDMARKER', ''), None]) == (result + [{"type": "endl", "value": "\n", "formatting": [], "indent": ""}]) def parse_multi(tokens, result): assert parse(tokens + [('ENDMARKER', ''), None]) == result def check_dumps(source_code): try: open("/tmp/c", "w").write(source_code) open("/tmp/d", "w").write(dumps(baron_parse(source_code))) except Exception as e: import json import traceback traceback.print_exc(file=sys.stdout) sys.stdout.write("Warning: couldn't write dumps output to debug file, exception: %s\n\n" % e) sys.stdout.write("Tree: %s" % json.dumps(baron_parse(source_code), indent=4) + "\n") assert dumps(baron_parse(source_code), strict=True) == source_code baron-0.10.1/tox.ini000066400000000000000000000006451415427440200142150ustar00rootroot00000000000000[tox] envlist=py2,py3,flake8,check-manifest [testenv] commands = pytest {posargs:{toxinidir}/tests} deps = pytest -r requirements.txt [testenv:flake8] skip_install = true deps = flake8 commands = flake8 [flake8] format = pylint ignore = E501,E218,W503 exclude = docs/*,.tox/*,ve/*,ve3/* [testenv:check-manifest] skip_install = true deps = check-manifest commands = {envpython} -m check_manifest {toxinidir}