treetop-1.4.14/0000755000004100000410000000000012157663062013323 5ustar www-datawww-datatreetop-1.4.14/doc/0000755000004100000410000000000012157663062014070 5ustar www-datawww-datatreetop-1.4.14/doc/grammar_composition.markdown0000644000004100000410000000435212157663062021711 0ustar www-datawww-data#Grammar Composition A unique property of parsing expression grammars is that they are _closed under composition_. This means that when you compose two grammars they yield another grammar that can be composed yet again. This is a radical departure from parsing frameworks require on lexical scanning, which makes compositionally impossible. Treetop's facilities for composition are built upon those of Ruby. ##The Mapping of Treetop Constructs to Ruby Constructs When Treetop compiles a grammar definition, it produces a module and a class. The module contains methods implementing all of the rules defined in the grammar. The generated class is a subclass of Treetop::Runtime::CompiledParser and includes the module. For example: grammar Foo ... end results in a Ruby module named `Foo` and a Ruby class named `FooParser` that `include`s the `Foo` module. ##Using Mixin Semantics to Compose Grammars Because grammars are just modules, they can be mixed into one another. This enables grammars to share rules. grammar A rule a 'a' end end grammar B include A rule ab a 'b' end end Grammar `B` above references rule `a` defined in a separate grammar that it includes. Because module inclusion places modules in the ancestor chain, rules may also be overridden with the use of the `super` keyword accessing the overridden rule. grammar A rule a 'a' end end grammar B include A rule a super / 'b' end end Now rule `a` in grammar `B` matches either `'a'` or `'b'`. ##Motivation Imagine a grammar for Ruby that took account of SQL queries embedded in strings within the language. That could be achieved by combining two existing grammars. grammar RubyPlusSQL include Ruby include SQL rule expression ruby_expression end rule ruby_string ruby_quote sql_expression ruby_quote / ruby_string end end ##Work to be Done It has become clear that the include facility in grammars would be more useful if it had the ability to name prefix all rules from the included grammar to avoid collision. This is a planned but currently unimplemented feature.treetop-1.4.14/doc/using_in_ruby.markdown0000644000004100000410000001074312157663062020515 0ustar www-datawww-data#Using Treetop Grammars in Ruby ##Using the Command Line Compiler You can compile `.treetop` files into Ruby source code with the `tt` command line script. `tt` takes an list of files with a `.treetop` extension and compiles them into `.rb` files of the same name. You can then `require` these files like any other Ruby script. Alternately, you can supply just one `.treetop` file and a `-o` flag to name specify the name of the output file. Improvements to this compilation script are welcome. tt foo.treetop bar.treetop tt foo.treetop -o foogrammar.rb ##Loading A Grammar Directly The Polyglot gem makes it possible to load `.treetop` or `.tt` files directly with `require`. This will invoke `Treetop.load`, which automatically compiles the grammar to Ruby and then evaluates the Ruby source. If you are getting errors in methods you define on the syntax tree, try using the command line compiler for better stack trace feedback. A better solution to this issue is in the works. In order to use Polyglot dynamic loading of `.treetop` or `.tt` files though, you need to require the Polyglot gem before you require the Treetop gem as Treetop will only create hooks into Polyglot for the treetop files if Polyglot is already loaded. So you need to use: require 'polyglot' require 'treetop' in order to use Polyglot auto loading with Treetop in Ruby. ##Instantiating and Using Parsers If a grammar by the name of `Foo` is defined, the compiled Ruby source will define a `FooParser` class. To parse input, create an instance and call its `parse` method with a string. The parser will return the syntax tree of the match or `nil` if there is a failure. Note that by default, the parser will fail unless *all* input is consumed. Treetop.load "arithmetic" parser = ArithmeticParser.new if parser.parse('1+1') puts 'success' else puts 'failure' end ##Parser Options A Treetop parser has several options you may set. Some are settable permanently by methods on the parser, but all may be passed in as options to the `parse` method. parser = ArithmeticParser.new input = 'x = 2; y = x+3;' # Temporarily override an option: result1 = parser.parse(input, :consume_all_input => false) puts "consumed #{parser.index} characters" parser.consume_all_input = false result1 = parser.parse(input) puts "consumed #{parser.index} characters" # Continue the parse with the next character: result2 = parser.parse(input, :index => parser.index) # Parse, but match rule `variable` instead of the normal root rule: parser.parse(input, :root => :variable) parser.root = :variable # Permanent setting If you have a statement-oriented language, you can save memory by parsing just one statement at a time, and discarding the parse tree after each statement. ##Learning From Failure If a parse fails, it returns nil. In this case, you can ask the parser for an explanation. The failure reasons include the terminal nodes which were tried at the furthermost point the parse reached. parser = ArithmeticParser.new result = parser.parse('4+=3') if !result puts parser.failure_reason puts parser.failure_line puts parser.failure_column end => Expected one of (, - at line 1, column 3 (byte 3) after + 1 3 ##Using Parse Results Please don't try to walk down the syntax tree yourself, and please don't use the tree as your own convenient data structure. It contains many more nodes than your application needs, often even more than one for every character of input. parser = ArithmeticParser.new p parser.parse('2+3') => SyntaxNode+Additive1 offset=0, "2+3" (multitive): SyntaxNode+Multitive1 offset=0, "2" (primary): SyntaxNode+Number0 offset=0, "2": SyntaxNode offset=0, "" SyntaxNode offset=0, "2" SyntaxNode offset=1, "" SyntaxNode offset=1, "" SyntaxNode offset=1, "+3": SyntaxNode+Additive0 offset=1, "+3" (multitive): SyntaxNode offset=1, "+" SyntaxNode+Multitive1 offset=2, "3" (primary): SyntaxNode+Number0 offset=2, "3": SyntaxNode offset=2, "" SyntaxNode offset=2, "3" SyntaxNode offset=3, "" SyntaxNode offset=3, "" Instead, add methods to the root rule which return the information you require in a sensible form. Each rule can call its sub-rules, and this method of walking the syntax tree is much preferable to attempting to walk it from the outside. treetop-1.4.14/doc/sitegen.rb0000644000004100000410000000250512157663062016055 0ustar www-datawww-dataclass Layout < Erector::Widget class << self def inherited(page_class) puts page_class (@@page_classes ||= []) << page_class end def generate_site FileUtils.mkdir_p(site_dir) @@page_classes.each do |page_class| page_class.generate_html unless page_class.abstract? puts page_class end end def generate_html File.open(absolute_path, 'w') do |file| file.write(new.to_html) end end def absolute_path absolutize(relative_path) end def relative_path "#{name.gsub('::', '_').underscore}.html" end def absolutize(relative_path) File.join(site_dir, relative_path) end def abstract @abstract = true end def abstract? @abstract end def site_dir File.join(File.dirname(__FILE__), "site") end end def bluecloth(relative_path) File.open(File.join(File.dirname(__FILE__), relative_path)) do |file| rawtext BlueCloth.new(file.read).to_html end end def absolutize(relative_path) self.class.absolutize(relative_path) end def link_to(link_text, page_class, section_class=nil) if instance_of?(page_class) || section_class && is_a?(section_class) text link_text else a link_text, :href => page_class.relative_path end end end treetop-1.4.14/doc/semantic_interpretation.markdown0000644000004100000410000001637512157663062022602 0ustar www-datawww-data#Semantic Interpretation Lets use the below grammar as an example. It describes parentheses wrapping a single character to an arbitrary depth. grammar ParenLanguage rule parenthesized_letter '(' parenthesized_letter ')' / [a-z] end end Matches: * `'a'` * `'(a)'` * `'((a))'` * etc. Output from a parser for this grammar looks like this: ![Tree Returned By ParenLanguageParser](./images/paren_language_output.png) This is a parse tree whose nodes are instances of `Treetop::Runtime::SyntaxNode`. What if we could define methods on these node objects? We would then have an object-oriented program whose structure corresponded to the structure of our language. Treetop provides two techniques for doing just this. ##Associating Methods with Node-Instantiating Expressions Sequences and all types of terminals are node-instantiating expressions. When they match, they create instances of `Treetop::Runtime::SyntaxNode`. Methods can be added to these nodes in the following ways: ###Inline Method Definition Methods can be added to the nodes instantiated by the successful match of an expression grammar ParenLanguage rule parenthesized_letter '(' parenthesized_letter ')' { def depth parenthesized_letter.depth + 1 end } / [a-z] { def depth 0 end } end end Note that each alternative expression is followed by a block containing a method definition. A `depth` method is defined on both expressions. The recursive `depth` method defined in the block following the first expression determines the depth of the nested parentheses and adds one to it. The base case is implemented in the block following the second expression; a single character has a depth of 0. ###Custom `SyntaxNode` Subclass Declarations You can instruct the parser to instantiate a custom subclass of Treetop::Runtime::SyntaxNode for an expression by following it by the name of that class enclosed in angle brackets (`<>`). The above inline method definitions could have been moved out into a single class like so. # in .treetop file grammar ParenLanguage rule parenthesized_letter '(' parenthesized_letter ')' / [a-z] end end # in separate .rb file class ParenNode < Treetop::Runtime::SyntaxNode def depth if nonterminal? parenthesized_letter.depth + 1 else 0 end end end ##Automatic Extension of Results Nonterminal and ordered choice expressions do not instantiate new nodes, but rather pass through nodes that are instantiated by other expressions. They can extend nodes they propagate with anonymous or declared modules, using similar constructs used with expressions that instantiate their own syntax nodes. ###Extending a Propagated Node with an Anonymous Module rule parenthesized_letter ('(' parenthesized_letter ')' / [a-z]) { def depth if nonterminal? parenthesized_letter.depth + 1 else 0 end end } end The parenthesized choice above can result in a node matching either of the two choices. The node will be extended with methods defined in the subsequent block. Note that a choice must always be parenthesized to be associated with a following block, otherwise the block will apply to just the last alternative. ###Extending A Propagated Node with a Declared Module # in .treetop file rule parenthesized_letter ('(' parenthesized_letter ')' / [a-z]) end # in separate .rb file module ParenNode def depth if nonterminal? parenthesized_letter.depth + 1 else 0 end end end Here the result is extended with the `ParenNode` module. Note the previous example for node-instantiating expressions, the constant in the declaration must be a module because the result is extended with it. ##Automatically-Defined Element Accessor Methods ###Default Accessors Nodes instantiated upon the matching of sequences have methods automatically defined for any nonterminals in the sequence. rule abc a b c { def to_s a.to_s + b.to_s + c.to_s end } end In the above code, the `to_s` method calls automatically-defined element accessors for the nodes returned by parsing nonterminals `a`, `b`, and `c`. ###Labels Subexpressions can be given an explicit label to have an element accessor method defined for them. This is useful in cases of ambiguity between two references to the same nonterminal or when you need to access an unnamed subexpression. rule labels first_letter:[a-z] rest_letters:(', ' letter:[a-z])* { def letters [first_letter] + rest_letters.elements.map do |comma_and_letter| comma_and_letter.letter end end } end The above grammar uses label-derived accessors to determine the letters in a comma-delimited list of letters. The labeled expressions _could_ have been extracted to their own rules, but if they aren't used elsewhere, labels still enable them to be referenced by a name within the expression's methods. ###Overriding Element Accessors The module containing automatically defined element accessor methods is an ancestor of the module in which you define your own methods, meaning you can override them with access to the `super` keyword. Here's an example of how this fact can improve the readability of the example above. rule labels first_letter:[a-z] rest_letters:(', ' letter:[a-z])* { def letters [first_letter] + rest_letters end def rest_letters super.elements.map { |comma_and_letter| comma_and_letter.letter } end } end ##Methods Available on `Treetop::Runtime::SyntaxNode`
terminal? Was this node produced by the matching of a terminal symbol?
nonterminal? Was this node produced by the matching of a nonterminal symbol?
text_value The substring of the input represented by this node.
elements Available only on nonterminal nodes, returns the nodes parsed by the elements of the matched sequence.
input The entire input string, which is useful mainly in conjunction with interval
interval The Range of characters in input matched by this rule
empty? returns true if this rule matched no characters of input
inspect Handy-dandy method that returns an indented subtree dump of the syntax tree starting here. This dump includes, for each node, the offset and a snippet of the text this rule matched, and the names of mixin modules and the accessor and extension methods.
treetop-1.4.14/doc/index.markdown0000644000004100000410000000617312157663062016752 0ustar www-datawww-data

Treetop is a language for describing languages. Combining the elegance of Ruby with cutting-edge parsing expression grammars, it helps you analyze syntax with revolutionary ease.

sudo gem install treetop #Intuitive Grammar Specifications Parsing expression grammars (PEGs) are simple to write and easy to maintain. They are a simple but powerful generalization of regular expressions that are easier to work with than the LALR or LR-1 grammars of traditional parser generators. There's no need for a tokenization phase, and _lookahead assertions_ can be used for a limited degree of context-sensitivity. Here's an extremely simple Treetop grammar that matches a subset of arithmetic, respecting operator precedence: grammar Arithmetic rule additive multitive ( '+' multitive )* end rule multitive primary ( [*/%] primary )* end rule primary '(' additive ')' / number end rule number '-'? [1-9] [0-9]* end end #Syntax-Oriented Programming Rather than implementing semantic actions that construct parse trees, Treetop lets you define methods on trees that it constructs for you automatically. You can define these methods directly within the grammar... grammar Arithmetic rule additive multitive a:( '+' multitive )* { def value a.elements.inject(multitive.value) { |sum, e| sum+e.multitive.value } end } end # other rules below ... end ...or associate rules with classes of nodes you wish your parsers to instantiate upon matching a rule. grammar Arithmetic rule additive multitive ('+' multitive)* end # other rules below ... end #Reusable, Composable Language Descriptions Because PEGs are closed under composition, Treetop grammars can be treated like Ruby modules. You can mix them into one another and override rules with access to the `super` keyword. You can break large grammars down into coherent units or make your language's syntax modular. This is especially useful if you want other programmers to be able to reuse your work. grammar RubyWithEmbeddedSQL include SQL rule string quote sql_expression quote / super end end #Acknowledgements First, thank you to my employer Rob Mee of Pivotal Labs for funding a substantial portion of Treetop's development. He gets it. I'd also like to thank: * Damon McCormick for several hours of pair programming. * Nick Kallen for lots of well-considered feedback and a few afternoons of programming. * Brian Takita for a night of pair programming. * Eliot Miranda for urging me rewrite as a compiler right away rather than putting it off. * Ryan Davis and Eric Hodel for hurting my code. * Dav Yaginuma for kicking me into action on my idea. * Bryan Ford for his seminal work on Packrat Parsers. * The editors of Lambda the Ultimate, where I discovered parsing expression grammars. treetop-1.4.14/doc/site.rb0000644000004100000410000000444412157663062015367 0ustar www-datawww-datarequire 'rubygems' require 'erector' require "#{File.dirname(__FILE__)}/sitegen" require 'fileutils' require 'bluecloth' class Layout < Erector::Widget def content html do head do link :rel => "stylesheet", :type => "text/css", :href => "./screen.css" rawtext %( ) end body do div :id => 'top' do div :id => 'main_navigation' do main_navigation end end div :id => 'middle' do div :id => 'main_content' do main_content end end div :id => 'bottom' do end end end end def main_navigation ul do li { link_to "Documentation", SyntacticRecognition, Documentation } li { link_to "Contribute", Contribute } li { link_to "Home", Index } end end def main_content end end class Index < Layout def main_content bluecloth "index.markdown" end end class Documentation < Layout abstract def main_content div :id => 'secondary_navigation' do ul do li { link_to 'Syntax', SyntacticRecognition } li { link_to 'Semantics', SemanticInterpretation } li { link_to 'Using In Ruby', UsingInRuby } li { link_to 'Advanced Techniques', PitfallsAndAdvancedTechniques } end end div :id => 'documentation_content' do documentation_content end end end class SyntacticRecognition < Documentation def documentation_content bluecloth "syntactic_recognition.markdown" end end class SemanticInterpretation < Documentation def documentation_content bluecloth "semantic_interpretation.markdown" end end class UsingInRuby < Documentation def documentation_content bluecloth "using_in_ruby.markdown" end end class PitfallsAndAdvancedTechniques < Documentation def documentation_content bluecloth "pitfalls_and_advanced_techniques.markdown" end end class Contribute < Layout def main_content bluecloth "contributing_and_planned_features.markdown" end end Layout.generate_sitetreetop-1.4.14/doc/pitfalls_and_advanced_techniques.markdown0000644000004100000410000000577712157663062024371 0ustar www-datawww-data#Pitfalls ##Left Recursion An weakness shared by all recursive descent parsers is the inability to parse left-recursive rules. Consider the following rule: rule left_recursive left_recursive 'a' / 'a' end Logically it should match a list of 'a' characters. But it never consumes anything, because attempting to recognize `left_recursive` begins by attempting to recognize `left_recursive`, and so goes an infinite recursion. There's always a way to eliminate these types of structures from your grammar. There's a mechanistic transformation called _left factorization_ that can eliminate it, but it isn't always pretty, especially in combination with automatically constructed syntax trees. So far, I have found more thoughtful ways around the problem. For instance, in the interpreter example I interpret inherently left-recursive function application right recursively in syntax, then correct the directionality in my semantic interpretation. You may have to be clever. #Advanced Techniques Here are a few interesting problems I've encountered. I figure sharing them may give you insight into how these types of issues are addressed with the tools of parsing expressions. ##Matching a String rule string '"' ('\"' / !'"' .)* '"' end This expression says: Match a quote, then zero or more of, an escaped quote or any character but a quote, followed by a quote. Lookahead assertions are essential for these types of problems. ##Matching Nested Structures With Non-Unique Delimeters Say I want to parse a diabolical wiki syntax in which the following interpretations apply. ** *hello* ** --> hello * **hello** * --> hello rule strong '**' (em / !'*' . / '\*')+ '**' end rule em '**' (strong / !'*' . / '\*')+ '**' end Emphasized text is allowed within strong text by virtue of `em` being the first alternative. Since `em` will only successfully parse if a matching `*` is found, it is permitted, but other than that, no `*` characters are allowed unless they are escaped. ##Matching a Keyword But Not Words Prefixed Therewith Say I want to consider a given string a characters only when it occurs in isolation. Lets use the `end` keyword as an example. We don't want the prefix of `'enders_game'` to be considered a keyword. A naiive implementation might be the following. rule end_keyword 'end' &space end This says that `'end'` must be followed by a space, but this space is not consumed as part of the matching of `keyword`. This works in most cases, but is actually incorrect. What if `end` occurs at the end of the buffer? In that case, it occurs in isolation but will not match the above expression. What we really mean is that `'end'` cannot be followed by a _non-space_ character. rule end_keyword 'end' !(!' ' .) end In general, when the syntax gets tough, it helps to focus on what you really mean. A keyword is a character not followed by another character that isn't a space. treetop-1.4.14/doc/site/0000755000004100000410000000000012157663062015034 5ustar www-datawww-datatreetop-1.4.14/doc/site/index.html0000755000004100000410000000754312157663062017045 0ustar www-datawww-data

Treetop is a language for describing languages. Combining the elegance of Ruby with cutting-edge parsing expression grammars, it helps you analyze syntax with revolutionary ease.

sudo gem install treetop

Intuitive Grammar Specifications

Parsing expression grammars (PEGs) are simple to write and easy to maintain. They are a simple but powerful generalization of regular expressions that are easier to work with than the LALR or LR-1 grammars of traditional parser generators. There's no need for a tokenization phase, and lookahead assertions can be used for a limited degree of context-sensitivity. Here's an extremely simple Treetop grammar that matches a subset of arithmetic, respecting operator precedence:

grammar Arithmetic
  rule additive
    multitive ( '+' multitive )*
  end

  rule multitive
    primary ( [*/%] primary )*
  end

  rule primary
    '(' additive ')' / number
  end

  rule number
    '-'? [1-9] [0-9]*
  end
end

Syntax-Oriented Programming

Rather than implementing semantic actions that construct parse trees, Treetop lets you define methods on trees that it constructs for you automatically. You can define these methods directly within the grammar...

grammar Arithmetic
  rule additive
    multitive a:( '+' multitive )* {
      def value
        a.elements.inject(multitive.value) { |sum, e|
          sum+e.multitive.value
        }
      end
    }
  end

  # other rules below ...
end

...or associate rules with classes of nodes you wish your parsers to instantiate upon matching a rule.

grammar Arithmetic
  rule additive
    multitive ('+' multitive)* <AdditiveNode>
  end

  # other rules below ...
end

Reusable, Composable Language Descriptions

Because PEGs are closed under composition, Treetop grammars can be treated like Ruby modules. You can mix them into one another and override rules with access to the super keyword. You can break large grammars down into coherent units or make your language's syntax modular. This is especially useful if you want other programmers to be able to reuse your work.

grammar RubyWithEmbeddedSQL
  include SQL

  rule string
    quote sql_expression quote / super
  end
end

Acknowledgements

First, thank you to my employer Rob Mee of Pivotal Labs for funding a substantial portion of Treetop's development. He gets it.

I'd also like to thank:

  • Damon McCormick for several hours of pair programming.
  • Nick Kallen for lots of well-considered feedback and a few afternoons of programming.
  • Brian Takita for a night of pair programming.
  • Eliot Miranda for urging me rewrite as a compiler right away rather than putting it off.
  • Ryan Davis and Eric Hodel for hurting my code.
  • Dav Yaginuma for kicking me into action on my idea.
  • Bryan Ford for his seminal work on Packrat Parsers.
  • The editors of Lambda the Ultimate, where I discovered parsing expression grammars.
treetop-1.4.14/doc/site/semantic_interpretation.html0000644000004100000410000002062412157663062022660 0ustar www-datawww-data

Semantic Interpretation

Lets use the below grammar as an example. It describes parentheses wrapping a single character to an arbitrary depth.

grammar ParenLanguage
  rule parenthesized_letter
    '(' parenthesized_letter ')'
    /
    [a-z]
  end
end

Matches:

  • 'a'
  • '(a)'
  • '((a))'
  • etc.

Output from a parser for this grammar looks like this:

Tree Returned By ParenLanguageParser

This is a parse tree whose nodes are instances of Treetop::Runtime::SyntaxNode. What if we could define methods on these node objects? We would then have an object-oriented program whose structure corresponded to the structure of our language. Treetop provides two techniques for doing just this.

Associating Methods with Node-Instantiating Expressions

Sequences and all types of terminals are node-instantiating expressions. When they match, they create instances of Treetop::Runtime::SyntaxNode. Methods can be added to these nodes in the following ways:

Inline Method Definition

Methods can be added to the nodes instantiated by the successful match of an expression

grammar ParenLanguage
  rule parenthesized_letter
    '(' parenthesized_letter ')' {
      def depth
        parenthesized_letter.depth + 1
      end
    }
    /
    [a-z] {
      def depth
        0
      end
    }
  end
end

Note that each alternative expression is followed by a block containing a method definition. A depth method is defined on both expressions. The recursive depth method defined in the block following the first expression determines the depth of the nested parentheses and adds one to it. The base case is implemented in the block following the second expression; a single character has a depth of 0.

Custom SyntaxNode Subclass Declarations

You can instruct the parser to instantiate a custom subclass of Treetop::Runtime::SyntaxNode for an expression by following it by the name of that class enclosed in angle brackets (<>). The above inline method definitions could have been moved out into a single class like so.

# in .treetop file
grammar ParenLanguage
  rule parenthesized_letter
    '(' parenthesized_letter ')' <ParenNode>
    /
    [a-z] <ParenNode>
  end
end

# in separate .rb file
class ParenNode < Treetop::Runtime::SyntaxNode
  def depth
    if nonterminal?
      parenthesized_letter.depth + 1
    else
      0
    end
  end
end

Automatic Extension of Results

Nonterminal and ordered choice expressions do not instantiate new nodes, but rather pass through nodes that are instantiated by other expressions. They can extend nodes they propagate with anonymous or declared modules, using similar constructs used with expressions that instantiate their own syntax nodes.

Extending a Propagated Node with an Anonymous Module

rule parenthesized_letter
  ('(' parenthesized_letter ')' / [a-z]) {
    def depth
      if nonterminal?
        parenthesized_letter.depth + 1
      else
        0
      end
    end
  }
end

The parenthesized choice above can result in a node matching either of the two choices. The node will be extended with methods defined in the subsequent block. Note that a choice must always be parenthesized to be associated with a following block, otherwise the block will apply to just the last alternative.

Extending A Propagated Node with a Declared Module

# in .treetop file
rule parenthesized_letter
  ('(' parenthesized_letter ')' / [a-z]) <ParenNode>
end

# in separate .rb file
module ParenNode
  def depth
    if nonterminal?
      parenthesized_letter.depth + 1
    else
      0
    end
  end
end

Here the result is extended with the ParenNode module. Note the previous example for node-instantiating expressions, the constant in the declaration must be a module because the result is extended with it.

Automatically-Defined Element Accessor Methods

Default Accessors

Nodes instantiated upon the matching of sequences have methods automatically defined for any nonterminals in the sequence.

rule abc
  a b c {
    def to_s
      a.to_s + b.to_s + c.to_s
    end
  }
end

In the above code, the to_s method calls automatically-defined element accessors for the nodes returned by parsing nonterminals a, b, and c.

Labels

Subexpressions can be given an explicit label to have an element accessor method defined for them. This is useful in cases of ambiguity between two references to the same nonterminal or when you need to access an unnamed subexpression.

rule labels
  first_letter:[a-z] rest_letters:(', ' letter:[a-z])* {
    def letters
      [first_letter] + rest_letters.elements.map do |comma_and_letter|
        comma_and_letter.letter
      end
    end
  }
end

The above grammar uses label-derived accessors to determine the letters in a comma-delimited list of letters. The labeled expressions could have been extracted to their own rules, but if they aren't used elsewhere, labels still enable them to be referenced by a name within the expression's methods.

Overriding Element Accessors

The module containing automatically defined element accessor methods is an ancestor of the module in which you define your own methods, meaning you can override them with access to the super keyword. Here's an example of how this fact can improve the readability of the example above.

rule labels
  first_letter:[a-z] rest_letters:(', ' letter:[a-z])* {
    def letters
      [first_letter] + rest_letters
    end

    def rest_letters
      super.elements.map { |comma_and_letter| comma_and_letter.letter }
    end
  }
end

Methods Available on Treetop::Runtime::SyntaxNode

terminal? Was this node produced by the matching of a terminal symbol?
nonterminal? Was this node produced by the matching of a nonterminal symbol?
text_value The substring of the input represented by this node.
elements Available only on nonterminal nodes, returns the nodes parsed by the elements of the matched sequence.
input The entire input string, which is useful mainly in conjunction with interval
interval The Range of characters in input matched by this rule
empty? returns true if this rule matched no characters of input
inspect Handy-dandy method that returns an indented subtree dump of the syntax tree starting here. This dump includes, for each node, the offset and a snippet of the text this rule matched, and the names of mixin modules and the accessor and extension methods.
treetop-1.4.14/doc/site/syntactic_recognition.html0000644000004100000410000002364612157663062022336 0ustar www-datawww-data

Syntactic Recognition

Treetop grammars are written in a custom language based on parsing expression grammars. Literature on the subject of parsing expression grammars (PEGs) is useful in writing Treetop grammars.

PEGs have no separate lexical analyser (since the algorithm has the same time-complexity guarantees as the best lexical analysers) so all whitespace and other lexical niceties (like comments) must be explicitly handled in the grammar. A further benefit is that multiple PEG grammars may be seamlessly composed into a single parser.

Grammar Structure

Treetop grammars look like this:

require "my_stuff"

grammar GrammarName
  include Module::Submodule

  rule rule_name
    ...
  end

  rule rule_name
    ...
  end

  ...
end

The main keywords are:

  • grammar : This introduces a new grammar. It is followed by a constant name to which the grammar will be bound when it is loaded.

  • include: This causes the generated parser to include the referenced Ruby module (which may be another parser)

  • require: This must be at the start of the file, and is passed through to the emitted Ruby grammar

  • rule : This defines a parsing rule within the grammar. It is followed by a name by which this rule can be referenced within other rules. It is then followed by a parsing expression defining the rule.

A grammar may be surrounded by one or more nested module statements, which provides a namespace for the generated Ruby parser.

Treetop will emit a module called GrammarName and a parser class called GrammarNameParser (in the module namespace, if specified).

Parsing Expressions

Each rule associates a name with a parsing expression. Parsing expressions are a generalization of vanilla regular expressions. Their key feature is the ability to reference other expressions in the grammar by name.

Terminal Symbols

Strings

Strings are surrounded in double or single quotes and must be matched exactly.

  • "foo"
  • 'foo'

Character Classes

Character classes are surrounded by brackets. Their semantics are identical to those used in Ruby's regular expressions.

  • [a-zA-Z]
  • [0-9]

The Anything Symbol

The anything symbol is represented by a dot (.) and matches any single character.

Ellipsis

An empty string matches at any position and consumes no input. It's useful when you wish to treat a single symbol as part of a sequence, for example when an alternate rule will be processed using shared code.

    rule alts
      ( foo bar / baz '' )
      {
        def value
          elements.map{|e| e.text_value }
        end
      }
    end

Nonterminal Symbols

Nonterminal symbols are unquoted references to other named rules. They are equivalent to an inline substitution of the named expression.

rule foo
  "the dog " bar
end

rule bar
  "jumped"
end

The above grammar is equivalent to:

rule foo
  "the dog jumped"
end

Ordered Choice

Parsers attempt to match ordered choices in left-to-right order, and stop after the first successful match.

"foobar" / "foo" / "bar"

Note that if "foo" in the above expression came first, "foobar" would never be matched. Note also that the above rule will match "bar" as a prefix of "barbie". Care is required when it's desired to match language keywords exactly.

Sequences

Sequences are a space-separated list of parsing expressions. They have higher precedence than choices, so choices must be parenthesized to be used as the elements of a sequence.

"foo" "bar" ("baz" / "bop")

Zero or More

Parsers will greedily match an expression zero or more times if it is followed by the star (*) symbol.

  • 'foo'* matches the empty string, "foo", "foofoo", etc.

One or More

Parsers will greedily match an expression one or more times if it is followed by the plus (+) symbol.

  • 'foo'+ does not match the empty string, but matches "foo", "foofoo", etc.

Optional Expressions

An expression can be declared optional by following it with a question mark (?).

  • 'foo'? matches "foo" or the empty string.

Repetition count

A generalised repetition count (minimum, maximum) is also available.

  • 'foo' 2.. matches 'foo' two or more times
  • 'foo' 3..5 matches 'foo' from three to five times
  • 'foo' ..4 matches 'foo' from zero to four times

Lookahead Assertions

Lookahead assertions can be used to make parsing expressions context-sensitive. The parser will look ahead into the buffer and attempt to match an expression without consuming input.

Positive Lookahead Assertion

Preceding an expression with an ampersand (&) indicates that it must match, but no input will be consumed in the process of determining whether this is true.

  • "foo" &"bar" matches "foobar" but only consumes up to the end "foo". It will not match "foobaz".

Negative Lookahead Assertion

Preceding an expression with a bang (!) indicates that the expression must not match, but no input will be consumed in the process of determining whether this is true.

  • "foo" !"bar" matches "foobaz" but only consumes up to the end "foo". It will not match "foobar".

Note that a lookahead assertion may be used on any rule, not just a string terminal.

rule things
  thing (!(disallowed / ',') following)*
end

Here's a common use case:

rule word
  [a-zA-Z]+
end

rule conjunction
  primitive ('and' ' '+ primitive)*
end

rule primitive
  (!'and' word ' '+)*
end

Here's the easiest way to handle C-style comments:

rule c_comment
  '/*'
  (
    !'*/'
    (. / "\n")
  )*
  '*/'
end

Semantic predicates (positive and negative)

Sometimes you must execute Ruby code during parsing in order to decide how to proceed. This is an advanced feature, and must be used with great care, because it can change the way a Treetop parser backtracks in a way that breaks the parsing algorithm. See the notes below on how to use this feature safely.

The code block is the body of a Ruby lambda block, and should return true or false, to cause this parse rule to continue or fail (for positive sempreds), fail or continue (for negative sempreds).

  • &{ ... } Evaluate the block and fail this rule if the result is false or nil
  • !{ ... } Evaluate the block and fail this rule if the result is not false or nil

The lambda is passed a single argument which is the array of syntax nodes matched so far in the current sequence. Note that because the current rule has not yet succeeded, no syntax node has yet been constructed, and so the lambda block is being run in a context where the names of the preceding rules (or as assigned by labels) are not available to access the sub-rules.

rule id
  [a-zA-Z][a-zA-Z0-9]*
  {
    def is_reserved
      ReservedSymbols.include? text_value
    end
  }
end

rule foo_rule
  foo id &{|seq| seq[1].is_reserved } baz
end

Match "foo id baz" only if id.is_reserved. Note that id cannot be referenced by name from foo_rule, since that rule has not yet succeeded, but id has completed and so its added methods are available.

rule test_it
  foo bar &{|s| debugger; true } baz
end

Match foo then bar, stop to enter the debugger (make sure you have said require "ruby-debug" somewhere), then continue by trying to match baz.

Treetop, like other PEG parsers, achieves its performance guarantee by remembering which rules it has tried at which locations in the input, and what the result was. This process, called memoization, requires that the rule would produce the same result (if run again) as it produced the first time when the result was remembered. If you violate this principle in your semantic predicates, be prepared to fight Cerberus before you're allowed out of Hades again.

treetop-1.4.14/doc/site/robots.txt0000644000004100000410000000037512157663062017112 0ustar www-datawww-dataUser-agent: * Disallow: /softwaremap/ # This is an infinite virtual URL space Disallow: /statcvs/ # This is an infinite virtual URL space Disallow: /usage/ # This is an infinite virtual URL space Disallow: /wiki/ # This is an infinite virtual URL space treetop-1.4.14/doc/site/screen.css0000644000004100000410000000365312157663062017034 0ustar www-datawww-databody { margin: 0; padding: 0; background: #666666; font-family: "Lucida Grande", Geneva, Arial, Verdana, sans-serif; color: #333333; } div { margin: 0; background-position: center; background-repeat: none; } h1 { font-size: 125%; margin-top: 1.5em; margin-bottom: .5em; } h2 { font-size: 115%; margin-top: 3em; margin-bottom: .5em; } h3 { font-size: 105%; margin-top: 1.5em; margin-bottom: .5em; } a { color: #ff8429; } div#top { background-image: url( "images/top_background.png" ); height: 200px; width: 100%; } div#middle { padding-top: 10px; background-image: url( "images/middle_background.png" ); background-repeat: repeat-y; } div#bottom { background-image: url( "images/bottom_background.png" ); height: 13px; margin-bottom: 30px; } div#main_navigation { width: 300px; margin: 0px auto 0 auto; padding-top: 43px; padding-right: 10px; position: relative; right: 500px; text-align: right; line-height: 130%; font-size: 90%; } div#main_navigation ul { list-style-type: none; padding: 0; } div#main_navigation a, div#main_navigation a:visited { color: white; text-decoration: none; } div#main_navigation a:hover { text-decoration: underline; } div#secondary_navigation { position: relative; font-size: 90%; margin: 0 auto 0 auto; padding: 0px; text-align: center; position: relative; top: -10px; } div#secondary_navigation ul { list-style-type: none; padding: 0; } div#secondary_navigation li { display: inline; margin-left: 10px; margin-right: 10px; } div#main_content { width: 545px; margin: 0 auto 0 auto; padding: 0 60px 25px 60px; } pre { background: #333333; color: white; padding: 15px; border: 1px solid #666666; } p { line-height: 150%; } p.intro_text { color: #C45900; font-size: 115%; } img#pivotal_logo { border: none; margin-left: auto; margin-right: auto; } tr td { vertical-align: top; padding: 0.3em; } treetop-1.4.14/doc/site/pitfalls_and_advanced_techniques.html0000644000004100000410000001027312157663062024442 0ustar www-datawww-data

Pitfalls

Left Recursion

An weakness shared by all recursive descent parsers is the inability to parse left-recursive rules. Consider the following rule:

rule left_recursive
  left_recursive 'a' / 'a'
end

Logically it should match a list of 'a' characters. But it never consumes anything, because attempting to recognize left_recursive begins by attempting to recognize left_recursive, and so goes an infinite recursion. There's always a way to eliminate these types of structures from your grammar. There's a mechanistic transformation called left factorization that can eliminate it, but it isn't always pretty, especially in combination with automatically constructed syntax trees. So far, I have found more thoughtful ways around the problem. For instance, in the interpreter example I interpret inherently left-recursive function application right recursively in syntax, then correct the directionality in my semantic interpretation. You may have to be clever.

Advanced Techniques

Here are a few interesting problems I've encountered. I figure sharing them may give you insight into how these types of issues are addressed with the tools of parsing expressions.

Matching a String

rule string
  '"' ('\"' / !'"' .)* '"'
end

This expression says: Match a quote, then zero or more of, an escaped quote or any character but a quote, followed by a quote. Lookahead assertions are essential for these types of problems.

Matching Nested Structures With Non-Unique Delimeters

Say I want to parse a diabolical wiki syntax in which the following interpretations apply.

** *hello* ** --> <strong><em>hello</em></strong>
* **hello** * --> <em><strong>hello</strong></em>

rule strong
  '**' (em / !'*' . / '\*')+ '**'
end

rule em
  '**' (strong / !'*' . / '\*')+ '**'    
end

Emphasized text is allowed within strong text by virtue of em being the first alternative. Since em will only successfully parse if a matching * is found, it is permitted, but other than that, no * characters are allowed unless they are escaped.

Matching a Keyword But Not Words Prefixed Therewith

Say I want to consider a given string a characters only when it occurs in isolation. Lets use the end keyword as an example. We don't want the prefix of 'enders_game' to be considered a keyword. A naiive implementation might be the following.

rule end_keyword
  'end' &space
end

This says that 'end' must be followed by a space, but this space is not consumed as part of the matching of keyword. This works in most cases, but is actually incorrect. What if end occurs at the end of the buffer? In that case, it occurs in isolation but will not match the above expression. What we really mean is that 'end' cannot be followed by a non-space character.

rule end_keyword
  'end' !(!' ' .)
end

In general, when the syntax gets tough, it helps to focus on what you really mean. A keyword is a character not followed by another character that isn't a space.

treetop-1.4.14/doc/site/images/0000755000004100000410000000000012157663062016301 5ustar www-datawww-datatreetop-1.4.14/doc/site/images/top_background.png0000644000004100000410000006275512157663062022027 0ustar www-datawww-data‰PNG  IHDRÚÊ+~”sBIT|dˆ pHYs  ÒÝ~ütEXtSoftwareAdobe Fireworks CS3˜ÖFtEXtXML:com.adobe.xmp Adobe Fireworks CS3 2007-11-06T02:20:42Z 2007-11-06T05:17:23Z image/png EDg¨ IDATxœìÝ}t\õ}ïûÏÞɲ呥ä„q &ĶŒSbl$š@Á¦I.‹®šrﺤ'v’{=ëâ$ä\Ⱥ&MÖº¤±›z=&gµë^¤¤✤i°)Mhr°Iã'ÆD2A¦X–,?èaöýã7¿Ù{öìy’æyÞ¯vª™={öüfÏX¦óñ÷ûuî¸ã/™LjvvV333šU2™Í&‹)‹Éu]Åb±Z/@ƒ‹I’ëºr]Wííí’$‚7@£s]WmmmŠÅbjkk“뺵^€&×ç Þ¦§§533SÕPŒ`¨ÖÖÖ&Çqj½$M®¨ºØpð6;;›®x#xT›ýÞ:¬@µÍ©­ý¥ÕÑÑ!‰à PY6T³óÕh  ”eÒ#Á€Ïó¼ª<@uÌ¥Ý-Šæ/Ø2+ËWÙPvùíDðZU1¡ÐX¢þÌ Ò‚!t(ÌuÝt f¯@#¨Ê? x 9…¿|Î µR°”ïµÂ£Øp¬˜ýÚ rrýŽ oçw1Pìwƶb?§UMêm ÞhlÁ0¨˜ë¹Ûlæòš›ù|ͪØ/u‹½PšàïÔb*ˆÇIïÇïc v‚³Õh  ™ÔÅo4‚7‡ý’"ª·[éÖ,J ÒJ=Í~þ€Z›ë—®nP{Q•k6X ^·÷Ùí*+ز­­M®ëÖzIP1u´…¼PŸÂ![ðg2™ÌÚVL…[£+GÈ6ßsӬ瘯r‘u¼¹„mÅÜ(,ø»4°IÊøb?xaP~ÁP6ZM]maoÔp–ïÞ¿´Så׬çhdó™ýCØ•e/Éd2}ÝÞOÈÌŸëºéöö{[he ´…¼P}Q­"í%™LF^o…ª¶b沪ÍåÜ4ãù*i>_¬¤À•c=ÐꢪÙìÅuÝŒëQ#pŠgC5;_6©!ƒ¶0‚7ª#*l³ÁZ2™L_òU¸5“bB¶¹Ü.´@e•Òr>•m|Á óØ‚í#mL&Ó¡!Pœ`¥Z,Ö_@E5åoJ‚7*'ª’mvvVßÿìáZ/­â¹—ØfC±¤g¶¥/²3ìüýƒÛííìãånåþžµ­+¡¶®„¹OÒÌØ!y3ãrû:NêË]I®kö³Û]׉ØWém~û2¥Ÿ#ßzsw˃«ÔÖÖ–Û쯲>×uÓš½(MSmao”W¸Ud2™¬õ’*.ty¡méÀ,°Ý\<%=©}Åg´`åg3x`§¹ ¦¦äÉSíRL§o@7þ]ƶäCšþç×hE-¦½[Jl–^#·wµÚ{VçÜuúÔ‹š=}HS'‡4ýúS&|s$/)9rLˆæI’—¾î‡iŽùœÎ~P3o¥jÕLh–ú' ’㤫ל`¢¨¸`ÐfC6泡™Ù0Í~×iç*‹ -B8x›™™Io³³³5^õ!¸µ¢Œ-GkÉ`KI5Ò7ÛÊ-å?ôÅתýâkuáø:ûë¿f&Låš²«ÔRlòÒm%=yžCõTHp6›Ç¿|B¢ $Ô‚¶"Øë H"x´®`¸n!Ùê•kT³u¢g•týCRW¢øÇüîtaBZ—ÞÞ_ÔC\v›b]«³{ÿ³’ã‡ÒUmáï»lQ-" ò¢þ›•ª64*×uÓš½êAÛ¼Z]Ô­,£°Í ´L]§¤ ¨‘囤µÛ¤ŽîÜûœ—Žì‘Žî‘Þ8,>‘½Ï’K¤¥«¤¤•¤Îèãµu-SüCÿ¨³ûïÑÌo¿#I™@ùCµ@Ñ L¢þÐ(lH;_6P¿ÚÊ€à Њ¢ªÛZA®Wl™þ¸¨²å›¤Á¹ï‘~ö Ù.Lä?Öéærôié©¿4aÛõwJ=ÑUr‹®þšÎ9Òôo¿c~8hP ­úß«hLÁ±_Ù@#á·v¼šYðKŠVŸÑ&åi ìÉ÷:@u%6äÙ~ú Ùæâ„ô«ïš€n`³ôÁ;#w[¸ök’¤Ùá路Ñ.ª+™Lf…ln¨¶ ¤­V£ $46‚¶* x4£Vþ’¼ôܯ?£²Î‘@uõ¬Ê²HO|Ú´ˆœ¯ ÒésÌ•m ×~Mç%%Oìšÿó楕ÿÛµgC5[±ÆŒ@h.m5@ðhtÌhóC´|÷¨²ö¸týCÑ3Ù~wHú»OnYŒK¯‘nÙž3`ËXÒ;ÿDRA›ãPÍÕÄŒ6ÔJp¶m  ùñ›¾¼A«jÅHW®yž©^K}‘ì   ®¾Wꊿʲ]ziyÙ@Á]gÞ|NSGÿZÞ[CrI× ®ðßµ('¦Ùj5×uk½$@•´Õ!‚7ßÛ5Ð7 -ß”½}ldþ![ Ûô›ÏéÂá¿Vò߇ä8’ý®¬ €æ@H@A[ x A¥7‚7  rÍe{âÓsÙ–\bZD°ÍNkrß=š}k¯InïÜÂßÉñõÇuÝt f/„´5 ‚7êŸ'ZGU³|StËÈŸ>$½q¸ôã-¹DºþN骈 ¹ÙÉa=ô .R®+¹Ž“žÅf.Nv¨æØŸÄkÔÛÒÎW£ $ mM€à -mÍÖìmc#ÒÏ*í8%l“ÔÔkO¦[DºŽ“Ñ*ÒqüJµðm¶€Ú¶€ŒÅøš07ü Ò„Þ¨*Ø€*ËUÍöý{‹?Æ‚¸™Á6°¹à®É©qM|Pç^z$°ÙÍrìm ¶lH[­FH@¹´µ‚74­åÕgÇ÷J¯ý¢ðcÄM¸6ðq©³;ï®É©q}éa}éiz"PÅ&É‘™j6G~åš#'£’-˜»ÂPY6T³k´lT A[ "x@SèJH}ÙÛõÝü+1`›<š ØfLÀ渒«ÌlÁ€MR:I‹n!éw¡$eœ­FH@5ñ·2‚7ÏóÒ¡ÛÌÌŒ’Éd­—DKlÈÞv~<ÐvÍÇM›È›$9ò°Î¼ø`:`˨XsB3Ùd[Fš”,Ø>2*d³ÈÔ( ÓlµškÿB ÚÁqœtð&‰à €ÉÔPTÛÈ\!Ûïÿ±týROÄ<·³ÇžÐ™wî„ ÖR-"íwx®ãÂ6³Í†h™·ý`Îlˬd‹B5Ùh ¨gmÈ‹à €ù!ˆ*¤=.õögo?²'óvÉÛƒš=;l‚µTRæ(PÍžÃf+Ö•k¢Z €¹p]7¨Ù õŒ  %!x@]ˆ ÙÎK¯ýÂ\¿ôé–íElFŸÓØÞ{ä–ãHmŽ“®b“ü6‘á*µôŒ6ùûeW±e¶‹ þü`Ç?Ì´*ÛÒÎW£ $ Ñ´a^ÞP}ÙÛŽÿÂl¼Sº,âþ o<§‰Ðô›Crä˜Ð,ÐÒÍœˆ6‘9B¶`–#d#S´²` Hû}Œ¿ÍPVoHý"ÊëY•½í²k¤• >4°JÍUsüÖé ÍɨJs`•𓱝Ý'XÉf÷Sx[Äz¨f4+ÛÒV«ÑÐŒÚPQo¨ˆ®ˆ–Ýy239¬±¡»5urÈ„g®¹Š´¬l-#ØGÊÐϭȆj¶bÍá/D@ hCU¼ ,¢f´å0sfX/> ³Çž”› Ø\ù-!3ZE†ªÕÂí#¥è -};Ç<6‰j6@ó ÎV£ $ Uñ7 jŠà PïæÞÒ$ iµÛÌ™a>ð€ÎÙ€-Ð2c›ëdTµI©ð͘Á&¥³\­"Øž/G#d4¦Ùj5×uk½$êAê Á Y0§ ¨ ÕlÉ©qýú9òHº‚ÍQ*8 „l®ãWªÙï ýj6GnD[p³ 6@s¢ $Å!hC]#x4 /uP;³Sã?ü°ÎyXšžH‡lmá€ÍÍl™YÉæäœÅU½VL¸æ?¦L/€2s]7¨Ù (A Á Q½ÔÞ…·êõ§þwizÜÌ`sœÔOeW±É¯rËœÃ=-œ˜miç«Ñ€¹#hCC#xT YPß’Óãò¦ÇÕæ:éyl¶z-Ü*Ò …kvn›”9‡-8ŸÍü,­MdÔ~ÔB°¤ý”³¢©¼j-»ºÍ“GLT\Fuš“ å ÙœÀ>…6ÚDmi«Õh @e´¡©¼*‰ø ¨/np¾šë‡gv&›_åØ?ÌI™³ØJ Ø×µ`C5[±æðUEІ–Þ’Éd:x›%x¤åš»æyænxž$/:lKßç1¿ ¨¶¼3×·ÝÐm)3d ^g«Ñ€Úãoc´4;ð·½½]Á`nL°æe„jäk@õe¶Ž ·Œn)™~œ‚Á[v%Ul€Z°aš­VsmY6¨m@Á@Ê®B+&4óB?K>€yqË2~:9g²)¼*d+¦U$ h @ã!hò xäC~Ô‘tËH'T½ Þ”+dˬbË÷µ&ßyÊÁuÝt f/ ñ´% x€Öe«Üì|6/°ÝSæ<¶àmf´Õ“1ŸM™áYd5›2·§“ãØÌ‡miç«Ñ€æ@ÐÌÁ4Ÿ¢ÛFæÑL¸æ…wPEQ¡˜º/³]$ål‹ñÍŠ¿å2"x€Öà)TÑ– Öl%[pG*Ú€êÊ={-W¨F5`þlH[­FHZAPAoÐXr…bf»—·¤HßÒí$è%  âòU²©P˜Väñ”ÕlÅšÃ_´,‚6 ŠÞ qåj™¾®Ì<ÍÛÔšã8%·ŠäûR@Pp¶m @ÿeÔÁÔ¯b²p»H‚5 ¶l˜V(T3÷;ÑUp„lÐÒl˜f«Õ\×­õ’@#hêÁ4†¨’Ám¶¤ÝFø†º×—zûýÛSãÒØáÚ­€*¢ $˜‚6 Ž¼@íej¡[™¡›ç‡m_PË7I+6g†lÖäˆtl—täQiz¢úk ìÿÝÞÞ®ŽŽµµµÕzI Á´ „à êKÔܶ†Ñ—ú²[É4º·:ëèzVIÝ™ÛG÷J§U/àéJ˜u„ÏÇäˆYG³UwµÇ¥ë2ç?—®„´f« ã~vgeÏAÏ)E 0@ó±ÿ?ô‚ ÔÑÑ¡ööv¹®›®^˜/‚6 ¼@uxž—3TëXýçrºûû¦ªÙ-#Û-Ë~àòMùCÉ /ì(¼À¾éÆÇ2·î•žÞý¼¹*˜‚¦Æ¥‘=¦š©ÜK߀YÇòM…÷ÞmÖqlWy× ™°É®£Ðù˜1k9ú˜¹^ŒžUÒÕ÷^CÔãÂïg”¨÷·Øu]ÿ ·ŠÑ•>ò]ihÛÜ߇5[Í%ÈVÊ-ßTx-¶ºîØ®âÏJCâ€yY´h‘:::‹Å‹Å˜µ*‚  h"oP}î’~µ½íÚÒØ•(>è(‡ÄúûœÝ~5¼Û~%YlðT(` Z¶Ñ\Öl5AO¹*íVl6Ç WÒåÒ•Vn1—c»¤ýÛ WÛut—öZçû¸b´ÇMˆWìëÜá°å°rKñûÚêº5[¥;MƒçI¢2 P%üS ‰ÙÐmáÂ…Z¼x±/^¬ÎÎNÅbdìÐ2Úã& )¥‚)lÙFéÃ»Š«@ËeÅfS5ש+a¢µÛæ¾Éš®¾wna“dÎÃ-{*†UR¾mrÄoÙ™ËàŽêÄQÖl5ëÈÃódJJkQͶôféÒOø—bu&JÛ¿=ëͺjéÒOH_ªþóVóµG½Æ¥7›5«ÔýË­g½tÃ>ó:6ä©fîYŸù9Ÿë9®Õç(#¾mZˆëºêèèPGG‡$ivv6]ñ633SãÕÊΆJ…Ú"££Û„=«Škg4¸c~!]ÐÊ-&àzzséóÛJm™˜OG·9·ói§Xmk¶F¦ÆM•ØÑ@»Ê¾j†÷·Ÿƒ¹¶­,—"BÒ`Îæy^jþZ¸Ô­åoý÷Im]Òì¤ù¹â^éÄÒÁmDûn’V|Azí›å]$½ûsR|•ôÆÊìzWë×ÞŸ4qXÚ÷§•Ù¿Ü®üª”¼ í~OþÀïÝŸ“z¯‘fR¿‡cÝfíÏý‘t~žÕÏ@ƒ!hZ˜þLðM¨˜ÍV0[Bö ä¯ÔZ¾©´9eÅ„lû3çÀõ¬2kȦôö›×VJØf+âò4áóÑ7ëÈwmeU½‡m¶õbØÔ¸9á9|vÆ_ÔgÈÎØ+÷k>uÈ<¯}O‹9ÿóàyJ…o0¶ÏJ¿']r[á íµoV&d“ªÚܰ¯¶aQP­×ð̺ùíé'L»û=e[R^í=潓¤±çóï;3᯷g½´þÛÒÊ/HÿöVv@!hFðÑÇ‘­ñB­è¦^ü ymÝò<³GÒóä%¥¤g/ž½ë6u]~[æí*TLÏ}Ñù‰S‡LS®Y[íqS9¶bsf0eC™bC6;ã-ÊÔ¸©ŒÞ;,ËÒ•¶µÇ¥ëvæÙF÷šó‘kþ[¡J¸\aÛ©C…+¿ìܺðãJ­,$*d“Ìó„C6kzBzv«i>wk¶æïJql—täÑÜë°!aU‘á?Ÿáûìý6` ß®ˆ×¿#ÅïqÏzS ´ïO¥ÕÛ¥…—™ëÁíÖêíÒ™£ÒèS&Àˆ-‘~óõì¤3áßò)³mñ ?Ü»ô™·%iÝãæX’yÞ™ÓÒ‘¯dW#ÙuIfÿKn5kÊ ®Þn*ùâ«Ìsœ;ž2^ú é⛢ï ßÿÊC…+¤:Òåwšs9sZ:þ°Žò½öK¥eó×åÒ³*÷­áݦåb®¦oÀ+…f õö›ý …RùZ&¾°#wà™+pŒ²v[vuàôÄÜÞã¹>.—®DtH5¼»pØ;9bÞ«ëÊ>æ²ó«j›7A^¡×j×plWþÀ4ņÞ^ª+d-Æ´¥u&¤wÝáWIR÷©w@ú@*è>ÿ»ÌíA}–.ºAzÏÿmÂIZÿ÷Òó·ûˆ­$š™0Ïsù§ýÖ•6¬¸ø&žæÞÓ&°3a*ð–¼Ï¬iÏ*Ÿ+î–ÞõgÒ¹×Ì:¯~DrH§~1÷ê»ìñ«¦Þ~‹Ô;(ýëÿþÁï™@klŸyýo¿Ezú½¹×™Þÿ#óú'IËLeÏO¾×¾ O:ý+Sq_#u-7ÇXp‘9§Ï~Èw.¾IZòûfMÓcÒ̤i zñMùÞ¾›ð(x¾nØ'ÅâæÌL˜õÚÐ,jÿ(—ý§Ì méÍf-ÇÎý˜u›vöóøÞ¯—/¬Zz³i9üm[Ôg:j›d>m ÍùÇ­æ<<³Î¼=ëL|W~Aš=7ÿue@РhoZ‘ãdVÉøµmæ–ãHŽãÉñ$ÏqRÓžÌ<(§¦ßðG(užØäˆ ×Ö¦WlÈ&eWiYÇv™uD±Õ]…6ɯú*Òô ˜°,¬Pp¸|“ 芙çvl—´{yª»*aEDUÝÔxî÷!ld9Ïá÷eÍÖùmG+-PÝ+ýx“©d,rÎ^Íþö¬óÔS¿ˆ2N n')II¿þœ_ytã¯3+‚®üª4õ¦ôÓ÷ûüž´°ˆs´ Ï„\çGL`uÝ3¦rˆ<—ý'Sµlxã¯óóà½&$É×:Ò¶´Ažµôf)Þ/={ƒpm8lö WoY}7In§´÷#¥Ï³ž  ‚çyãKæØÁÀËi—~ùI?ijëïLÿÜW}Ã|.‚!^.cÏK¿ý–i<—ç_7á`ð¼\ñ_¤™ñÜhKo6ׯïò_cÏzÜ.½Ùl+æ½ jë2ç®óíæœø‡¹ÏÂûí·üsm?‹öõí3k°Ê­ãbéèWæö\@™¹µ^€ÆeC·E‹©»»[]]]êììT,F† ¹™p-¼Qr÷§·¶×ÔþísEòµŒ²|StXf+Ùº¦úí#ß-²Ùê¦o*.¤ÉÕ2ñ٭ѯiù&é–=f=…œc»¤ïoÈ_W¢ªÙŽí*mÍQU]‰âBÑrš‘~vgd[ÕöžÕrÚãÕ]O.çG¤Wþ» Ùz¯ñÛþ²IæÁð"9•yÿÂK¥ßÉÜ6Sä{ûò_ùaO8ô¹ô’ÓfÚI…Ÿ¿TÁ굩73ï[ö1É›•®ü¯æœÙóf[,F}JJž7QW}Ä4Åøí·2oÏL‰f'3ƒ¬tÚMÅ=§d*ø&— ‘ÎýÖTÂIæ5/|§4úãÜYö1sž‚¯qìyÎÙV’sÕÞ#M¿Uüg:J0ÐÇ«“à­Ð ³rêY=í…~U{Ü´ˆ,&¤)4G-Ÿ¨ãOŽHGõo;N2aÓþí¥U÷ÕÚ²ÙÛ†wÏ- <úXöܽĆè}+-G;Ëøš»táøwÌŒ6Iò¼Y3Ó,(V†Ê¾ñægÏúÌ*.·cþÇÎåô &”|ñó¥|çGüö–W}ôUœOuU±l…Õhž 0ì܈™7_¯}ÓÌî[ù0Ží+ð¼Ç͹ ‹ÅÍ}óq~DzõoÍ<Âá¿ÏÿÞEÍg‹‹›Ïƒ5úcó¾®Þ.9®ôÊC¹ Tmª†Š7õ.«dÆvGŽãäßÇñ¯››vCy×Y’c»ª[u•+Ü:¶Ëlk¶WÁ65n*ÏJ©` jG?Ç&ðë0³¾n|¬pÈ6º×ÌsË7Ó­^E½¶‘=s;ÖðîìmÝ&\­…ˆv–±®eŠõøAoVåš—˜WÜêíR¬;UÖ|ÿýâÒOHüyvð6cÏK‡¤«1•JWÜmæ³9í…;=f¤bÛ8Z/ß/%/Hÿ`>É„Y6Њ²ôfóÚíþ±%¦º«bq¿=egBê¿O:÷Zi¡à‘ûÌqÖ=|•`6ðŒÚçͧ¥‹7šŸ¿ùzþç}å!s^¿ç¯ÿ{̶r„V/ßo*+¯ý^öÚ/ý„ùyÕ7Ìz£ ~Ï¿gÖœËgƒÓKn3m3k]i ´¨‚7*ØVÒÌksüíN掹‚¹ª VoUCTÕ±]~À¶fkt+C+°ÙPl.r…gSãs ØŠ™WozVE·ÁŒ ÌŠ1=Ý>²Úsڬѽ‘!ò‚ÄM GlÅ„keÍßz¤/™Ë;n5![¥æI½|¿©&êû°tù§¥7Ÿ)\ÝT¬¡?’NÿJZv»™öò_™v×ôßÌÏëž‘n(q-?ÿˆ4{NZÿmsþ®üK)Q%kþ¥™{f÷¯’ü_¥=g±’¤Îeæu]÷Œ ÷E´ÊÍgìyéן3ë¼îiãQÖZ®ýOí5Õb_òC+)5?ϑՀé IDAT¦NfVF9?"íûÒ‚‹üõ·-4ÛÊZíý_ý0Ò®ýäSÒŠ{ÍÚ¯4ŸÕ,žt~Ø&¢ßÉÒÿóD‰÷›?'W~Õ|ΪÀ¹ãŽ;ªýo: (´šêËì쬒ɤ’ÉdÖŸÏééiýËOÔz‰e5ÏÉnóéé÷Öz%¨'½ƒ&\ë4—PëÜ~ô£êèèP,S{{»b±˜ÚÚÚäºnzÔÀ|Q6 n1ã @=ñ+Ó™þs©yOv[ê~Ïó+Û²*ܪ­ÚUXs­l:¶Ë.ålq5'®PÈ69bÖ1—V•õ(ª¥ã|?Q:×Õ±ž}צCðtHÞ,Z”+î6óßlkÊwÜ*u\$ýê3ó?¶­L:µ×ó’[MUW«…lõêÝŸ33úZ!dëLH ß)x¢Ö+A-ź3CµbgþTA€†Að Þ¤"·úUí -ªMa>•جRB¿f ج¨l¾Ÿ‰¨Ö‘] 3¯•ˆ¥Ê13/Ö³ZÉñˆµ6£‰CÒÛ>hÚFJÒ¹éùn%XŒÉW¤¥5_hKÒ©¡T»ÂtîxV¥LÍu-—^ÿN­WQËn—f&üYmh ±î@¨6hªJêA€†Eð R'³}d1šÝ'²p¦VÕ49BˆŠ)6ÜÞ-½°£2›T|à75.}¬|-<ëMTEÛ|Ïùô„9Fø÷ö×nŽÝèެϞÛÑ­dh7O’'ON³•·½ñs©„—ïoj©bÔcÀóÓ÷×zÕÃg±5,Ldk%þ€!hÐ4roÓÓÓš­ñê43ÇQêë{/ÐÕÅWù• ²æjt¯ µ*È ÚlÀV®ypõ*ªUf9Âר ­½†•>SãY›bKVkæÍ!CŽ$Üó$ÇiöÞ’P§‚m ãýk a´hZáàmff&]ñFð à̵ìíæ[{ûõ|ä>õ0£­^T+`+¤U6)ºš-"š“S‡²«{û¥‘=å9~©ÆKË6flr Íã ð<þœ@Ud´ì¯¿v¬sDРeÄb1Åb1-X°@Á€ù«ëmµµ¢ZGþìÎÚ0A“#Òþ¸ù6«RÕlRëœCÀÜÙùj骵f§4‚6-‹à @%8Yé›Ó|3¡JQ!›d‚6¢ÖåIrk½héÍÒ…7¤±çk½’üÖ=.ÅWIϬ+Ïñåuóaç«-^ Ø"*«šA¤¼ÈÇFeu[ÁTË©CÙÛ¢ªëŒéèšz;ŽäÐ7²zúï“&Kûþ´Ö+©®V}ÝhnñþÌkÌW-Œ  r xP¬ì*6 ‰Õ[e`Ä<ºÙÉá,$å†}ªTb½¹*ÂÊU!ÖhZõu£¹d´d¾@A‰à @>T¼5Ò•]E‘<;œªVó/U±z»ÔÖeB¦uKçŽKïõï_z³´ìcæúð·¥7~Pø˜=ë¥Ë>%Å–˜ã½òt~Ä?|ŒÎ„tå•~óuÓ¦pÝãæº$½ûsÒÌiéÈWÌã ­·3!]~§´ð²Ìç ¾»OßMæxm]昒â­Þ.9*½öÍÌã\q·´d­¹~úéåûóŸ“|çÑ>ÇèSÒÊ/˜ófÏG®óšï9{Ö›s÷âç3_¿]ƒ}m¹Þ§\¯;ßþ@=°óÕ bRÌ‘ ݺººÔÝÝ­E‹iÁ‚jkk«õÒԺѥDTeÓ•zû³6O,øÐªÿ]÷¸ôÞ¯›*XÜ\·AT.Ko–Ö[ê\fn÷JKÞg®w¾]ºâ¿dî¿ò RÏ:?Tê®üª´îïÌí%ï“>PäÜÄì1Ï'Iï¸Uºö{¯ç³ŽðÚréû°tñM™ÛnØ'½ë¿:æ’[óãªoHWþ¥¹Þùv³†K?‘ùïºÃ¬¿s™9îú¿7Á–µôfsNìýïº#÷{1ö¼9§—ß™¹}åüמï}ŠzÝ…öª-Öm>£+þ\ü¾´ñ%ógäòO²Š6(*Þ€æä8’7§25GõmRGw­W€r‹šÇ5·­"Ö2=vPÞô„\·´À»,ÁÛÁ{M¨nŸôfóeõ¯ïò«¯zÖ›hé͹+Û–}LJ^†þ(û¾ß~KZñSyf+¡.ºQÛ—¹ß‚>é_7˜}:ÒuϘ`êµoæ^¯ä?F2û¯øBöë9ú•ìê4É|a_U¸åUß0A׳*¾š+X‘'™ îâ›2×Ñq‘ôëÏùçõÆ_›ª4»žÓ¿”öþ€mu™ËØ>éí·øÕ~=륎‹Íë—ò¿OQJÝ(·… ¿ZmñêüŸDEToZN­ÂÔ^­æ¶­Øœµizô¹@hæ¤Ã6GUn#´ìcRò|f 6ö¼43î·@Œ2ümÉ]`¤ÕÛ3ï{í›’7k*«$†9m~«Hëå¿òƒ©RZž1-×=.½óãѯ'*d+Eï  ùJ]WÏzÒ­{Ü´¨ ;õ‹ÌsœÊ>FgœÓB!›dΩÛiFÉ„vÞ¬ÿúó½OQJݘ¯x¿ùqÕÿ0aûž‘VÕT«²ÌAT Á€¦W«°Åi×zåÕ7Ù6òüñ'ýÙl©máp­&]ÃaO1ÞøôüǤs#Ò%·Iûad*­Þv½¹þÎKç^ËžE6Ko–6•ÞöAéäSÒ™#ÙûÌåõD™)ñ÷ÆöHW?"M™µyÓ¥?çêíÒuÿ,µ÷˜cLåß߆¢ïú3s»gôúwüû ½Oa¥î”ªwPºü3&X»a¿4ø=S•zñF2 ¬h 5B«I-¡«N¾Ð‹jwØÌ¢ª #B©9‰:—Sãå9v)ÖlÍÚ4;9¬ÙñCre„mŽãÔ¶¢íÜq©÷šìí±¸¹/Ÿ±çýƒü¹©`³ÕZ¿ùºi?yÅÝÒÂKýV†óµò ¦Ò,ØÚ08cìô æõÛVÎŹ‘Òªi–Þl^ç³7øÏ{ù§KÞKn“^ý[éåûÍí‹o2¡[>£?6[½]r\镇2ïÏ÷>E)u —X· Öâý©v-ö÷@ ¢ êoÞdÄîµÚF÷Vÿ9ëM®êÂJ½c‡+sÜ\–oŠ üμø ¤`À–û ݦÇLx¬yå!ÉKšª’΄¹|`Ùl‚®¸Û\ìc$iöœÿØóÒÔIé]wd¶2œïz%3é3aÚ4ÚÖ‘vŸ—ï73ÆþÁÜ/™Ì^?wÜ„ˆöv.Gî3û­{Ü?öw^ó²Ûý}cqs)ÕÛ>è¯{ÉïKnGþýí|¶Kn“Îý63`,ô>…ÚõvÓV’*7DY˜0áðŠ?—¿o>+W}Ä΄l5AÐuŠà @É Úzj4û%ªÂŠª¶òmQç1꽯”®„´v[ÖæÙÉaÓ6ÒnH¥hùÃ4§üaÛËÿÍü¼îó¸dB™}ÿQZp‘Ù~Ý3RÛB³-_EØÄ!é’[ýÇÌž“ö…æÒøŽ$Gzóéò­÷ÈWümW?"ýö[f&Ûuÿì?îç1ëYÿ÷ÒÆ—¤þûüû^yÈ„Qö¾\Æž—~ý9ô]÷ŒiWyÉ­¹÷ãÒ©½&X´­-O ÏÎ@ ·2Dù-»]š™È¬žJåvJKÞ']¼ÑlkM  šã8ojcdOvж|“täÑêVµ6í Ã3ÉÖl•žÎ3;©™DmÝó £‚ºj—Ë7IWGÿöeygG䤂6× T³)»m¤dþž”š l{>ºU"Ê/ªÝ$PHÇÛ¤Þk¤‹>$-^ÍL5€&åÖz€Ê³Á[gg§/^¬x<®E‹©££C®Ë_Êhx·45ž½}pGõ×r`gö¶¾èª¬f5¼;{Û\_bCäl´Šmk·åüüœ{õ ]8þ¤ Øh)Û*²ÉÛF¨/‹.“–}Lºò«ÒuÏH|Nzï—Þq+!@ãÛUhAo*fz"zZo¿ LªéØ.SÕ6¸cþ³ÊETÑ~±(áJEÉyÓs;^!íqó^­Üy÷¹WŸÐÄóŸ—ëÈ´tSͦìj6®gÌl€ùè~¯tùg¤«þ‡tÃ~éý»¥Uÿ Ö:…€¦À·©‚7åuäÑè€kå–¹‡t%¢uürèJH7>–sÓcuæ—_öC6™‹½í†µ\™Zp;Á€¼Úšùj—FZ÷¸´ñ%ià;ÒåŸ63×b-ðw "ñí) Á€y™žöo¾oí¶êV“Û]ÕÕÛ/]ÿPõÖQ+“#Ñí#×l-í8+"æÚMG{¾¤ï2ïQ„鱃û—Û¥Ù‰tˆfÃ5+°El€¢´-2³ÕVü¹4ø}éC¿’®ù¬õFÌ«@ËâÛR@AoJ6²Ç„\aݦR©šaÛжè¹q}µ™WmQ­<»ÑáY”®DtûÆ‘=åmÙ—®ÛiШYp2í"ßzêfifÂT¯9’ë:éê5×µ•lNdûHÉ!lmÁEÒ%·úóÕ>ôoÒûþVºt óÕW¬Ö 4¼Åbæ¯Ïó4;;«™™ÍÌÌ(™LÖx…êÂþí&P W&Ù°íéÍÒØáʯcrÄ„mQl¶5áP•çÇUÓè^sºBó‚Öl5aYT›Ï \adT[ιZ±Ù¬'GÀ&I/> ³ÿ:³%d0P³·ƒ ìÚœy›ð h=]Ë¥·ý©wÐ\hý€9"hÌÁ€HÓÒ³[MÀp€Rí°md þ®¾7û¾VÛöoÏ;ºMÙÓ›sW¦ î0•aÇvèŠa« Ã!`@rj\§q·¦NìN·ˆ´3Øüyl~Èf ­£f³¨-lÉû¤·}Єjñ~‚5” A ìÞ¤MŽ˜ çÆÇj¶}ÌT×Ù`-ÈnÛ¿½¼íëÅÈSÙÍzûý÷ üºwDŸ«©ñÜ3øJa«Øò¸0úœNÿâyg‡M°˜½æ‚´p‹Èì–‘ZJ[—™£ö{0¡3ÕPAm€Š#xZÜØáÂaÛ ;¢gº•›­Z˶õ¬Ê_áÕȆ¶EWööK·¤fêì1Õek¶æ®2ÚVžó“§Mdrj\/> s/=’®V V¯¹ö‘Áð-}Q ts2ç²Qå4¡}ÒÛ®“¯NU¬1S ÕCШ:‚7  Ûl‹ÂjT”å Ûzû¥|WúÙÕ©²«¦|³ê:º¥•[Ì%ÆUйáŸhü…û”<7’Ô2ÚEfkN T#dZB×&X‹÷›`­3wûY ÒÚ5Gð´ˆ|a›äW” m«|È•/lëJ˜5m«x¨Tu#{ÌëÜQúcíªè»™3ÃzkènMŸJU¯9jsƒ­"MU› Ò•mQ!›Ež4¸žõR÷ªõ2_ u…  PwÞ€&föëŠnMh+Êöo73Õ*ih›têtõ½Ù÷ut›5m«NKËj²¯gí¶¼í³S¡-95®‰#kâÀƒr]¥ÂµT«Èt°–Ù:Òq9JÝœËæ„6':d£’ ¨s6Pëd¾êA î¼Mfì°ô£?6AV_Ž/P¯¾WZ¶Ñ„;“#•[ËÑÇL«Ê\¡“miYÁJ®š8¶KÝ뿾\&GLèYʾé3ÃûÕ:?òiz"š9ŽüPM9l T­IY-! Ï€ÕÖ%ýÞûý`ùjh0m€†Þ’Éd:x›%xÁô„©l[³Õ\¢ô HÞ%ØYÙê¶c»Le[¾––] 3·­Òóãªirļ] 麦š0¨ÂÕ|g^yB“Çž0-!sØ‚í ]×Éhi+ÙŠj™#x#j¬óí™ÁóÕÐàÚ Ïu]¹®«öövIo¨=Ç‘äÕz âÀNSYuÝÎè«£Û¯nÛ¿½r³ÛÆK?Þ8I&ô³sÛ*=?®Ú&G¢ÄJVJÙY0`Sà¶²Cµ|![¸Ò-ã9 Ù€ê‹÷ªÕú ÖÐtÚM‡à h0£{¥ïo0m —mŒÞ§oÀÌn;°Ó\*ÁVxåZGo¿ ÛžÝjÖŒysäÏZóç±IŽëd¶‹LUº¹nêq÷EW±356 Š‚óÕâýR,^ëEÐhzo@˜ž0V"¸EU·I¦ÍäòM¦²¬a—]ÇÚmÒÊ-Ù÷wtû•ml«Ø ‚•iémn D˵9“, ¨Øb©÷Ukyf>MŠ  ÐrÞ€:6²§pu[W„]G5Õm•˜›öÂó3*l“ÌúzVùûaN‚Õj‘­!Ó-"œí"󵊔¨fʪóÒïý´xuªbmU­WÔA å¼a> cã;þ9(¶ºmåSÝöÂŽòV—µÇó}Ö²ÒÑÇ*>ˬYÙÊ47kþZ TsœÈmRfËH{¼¬çà 0?ñþÌkÌW²´BðÔ‰bªÛ:ºÍý¶ä|C¯›M{Ê\áž$M›€­R³âj¡«_ž§[Bš`-=£MÙÁZ¸…¤ Ùì>‘‡'dJ Õz™¯  €ÞP÷zš¸u—­në0Z®@¨o@ºe ¿ŽÐð&ÕjƒÌWAu.¼ÍÎΦƒ·™™™¯®5™àÌ‘äÉóÌmSÉf[Û™²¶¨ÙSeµfkö¶©ñÖ$Så—ØPx¿Vl%WûÑ£Š M-£ $óÕ€FFÐ@ƒikkS[[›:::$¼Õ#;gÊ“læ–-ªŠ¨=«¢+¶Ž>6¿ã6²žU¦’-ל6«ÞÛD¶Wñ ÷®„ÔÛŸ½½Jm޽„æ¯9¡Ÿ9O‡F Õ˜¯4‚6Á[}rÉIU»ÍŽÌÞ!j.V)wdo›7Z­¦=nªûVnÉ¿_=¶‰Œ û¢‚¯J‰ªü›©YIp†¦ëÌVë'XšAM†à­²LÃÈÀíTÛHÛMÒ‹¸3yn8û@½ý¦šh.ÆÚmÑaÌÑÇZ¯ âòMæ|ttç߯^ÛDÖºª.*œ¬æŒ¿ˆ`¬ '8_mñj)>ÏH ¡´ÐäÞ*Ï‘ä¥8;—Íñü¶x³§ivrXm]Ë2xÝNéÇíóIlˆG&GZ«š­YÚDÖÒòMÑ-L[¹ý(P ;_Íþìœg+`   €CðVYŽ#9©º·tè&éüñ'Õµú³™;÷ö›°mh[q•V=«¢[FJ¦%b½UkUB±m"§ÆÍy­§6‘¹LgWäõ TvNš=a£{ %°`¨Ö;(Ū8G@Ý#h Å¼æ„[BÊÎ’2Mî<ÏKÏ–²ûÙÛN*v»ð›‡µðŠOÊ *Ë6šª¢¡mÒØáÜ‹h›-ªEâ‘G#Pš¯bÛDyÔ´Šl”àqìpve^ϪÊmk¶FW³ØY¹ç qœÀE´ŒDˆug†jÌWPAÈ+x»pႦ¦¦j¼ºÆ‘1»M’7=¡3ûîQ÷üMöνýÒ™–}¹‚Ž‹žËvêPUÑšèJ˜±˜6‘û·ç,ëÑèÞì×¶|SåZ8æj?:º·²á^ R7TK¬;ª 2_ @ÉÚ@^6xkkkÓ‚ 4==­©©)]¸pŠ·”ŒP-5Ÿ-½]’+3Ãmêõ§4ñü=НÿZöA:ºM•QbƒôÂŽÌÀcpGtÈfÛ#6JåV©Úã&Šjq45nÎÙ±]ÕYW¹ ïÎ~½ýæ³PîJÅBíG«Ì¶WÍÚµ(‡…‰Ì`ùj扠 ”ÄV»¹®«X,¦ .Èi±oÄͶˆmŽxräÈ3¡›#9Ž#Çótáø“ò<©ûšˆ°Mò«ÛŽí2•jË7™K”g·6^õV±¤«ïnoÔhm"£Œ6sѯup‡ôý å{míqéú‡¢[oØYÙÏR{Ž™V¡PÍŸqØÅþùi­_3(—Œ6ÌWP~m`^ÚÚÚ‹5ÿR„g°·¥£7ó¿&Îjó$בä:J&MØvêì°–üÁßdÏl³–o2aS®û‡¶ÕM›¿²jö6‘¹Ø™]iÖÑmB×§7Ï?lk›cE—Õh?Q‘™<;œ ¦Í¤¨ p %ËhÙO° âšÿ[1€°+))Źò¯ÌœÒ¿ÿðzu¯ÿš$þ0ú ¹B¶#6n›Ä\Z¥Md.ÇvI+6gR¶ÂñÙ­¦êm.lÈ–«ýè³Îù|µÇMËÊääpÖ6›«°¡(Áùjñ~©·@@@Ð0‘í#íÆôOsÅIm’g[ãI®+%§'túçÿY—ܤøû¾¨¶®e…Ÿxx· ššI+µ‰Ìgh› ÄÂko¿ôá]&+µŠ1_È&™j¹¹xÅZ¹%24žzsHmv«Áö‘¹¿µ8;_mñêT¸–à@µ´Ì“ yž—Û¼@ØæHr<ÏÌj“#Wž’J…mž4õúSú÷“Ïiá{>©®÷|*w;IIZ¶ÑT}y´ñ§bÛDž:dB¨fi™ËØa¢†[HJ~ÉRÂÆB![5ÎéòM‘UŠNüÄüY m’2’4B5(ÞŸ9c­³@5@ÐPÇñç´Ù \Ùf÷³w:ùl¦•¤#W&Œs$×ñC5'\Ù&»ÝI_G²Zï óÕ4,‚6€ HÏkSƸ6I¦e¤ç)UÝf~¦«âR÷M¿9¤“ÿx½­ø¤âWÞ•»d߀ô‘ïÖ0Õ•Ön˾¤:d*õJEÖlF÷šùiù³å›Ì|»`Õ_Ϫè9oV¥C¶å›ÌûœãùgÆêÌóŸÏ×܈\­ ź3ƒ5æ«hm% ¶”L(ÓR[ÒóÚ²­`³IÛJÒqdJÜdªÜIIW:÷Ò#év’‹–ß–{QQ¡K½°­.óÍžkÅ6‘…Œ–~œ ®Vn‰Þ§£Û´g\¾Éœ»y© ·Ôc=¥n'%Of›³h™z¾–»¤59bÚ3Žì™×kÍ©Ø6‘ûMCÚDÎ_bƒiÛXèœî5ç|¾•EV*ÎLkâ—_ÖÔ‰Ÿ¤Û¡šJ6ÉMÝv7\Ñ–ªf“r‡qT´UØÂ„´xu bmU­WsòÑ~TŠÅbjooW,S[[›\×U[[›ÚÚÚj½DÐÚ@QŠÚ‚f&LèvjH:¹[:7\ý…WITÉpàævò‚š¡›ÁZ*h“!\è’ô¤¤ç©3q“º×~I±®eùZ®ÐÅ*¶Määˆy^ÚD–_1U„’täQSWjÈÙ—Vn)ê9&< ³/="ÍŒ§C6Ç‘\×IW²¹Ži“j‚5'u¨Ê-Ô6’ ­Ââý™3Ö˜¯ I´€j hE™SÐfƒ·“{¤·~.?Qù…WQ1a›ùé¥o‡ïO&ý°-½O p V¸¥·%MØæyRüÊϪkŧrÏo³æº1£KSãÕm]Ùªºæ½X¾)ÿ~Sãf.Þ±]ŷȪ¹ £Ïilï=òÎŽ¤C³Œ*6×ìçªØØ'WÈFÀV!ÁP­wùjšA¨‚6P”²ma6x;ñ„4¶Oš+ÿÂk`.›Ý'«¤2+Ü‚û$½ÌÊ·ô,¸…—hñ•wiÑòÛò/´ÔÐÅê0Ul½ýù÷ÞmŽ_®ê9Vì{3º×„Ÿ¹* »EÍ›™Öé½wkúä©` T¦¹©v6›äos2ng¶‹”üð-Œ mŽ‚¡óÕ´‚6P m ( ÚÂΤæ»ý@:½_š93ÿcÖ@±A›äB·Ô>¡›ÝÏS°â-5§-±=Õf²ãâkÕý¾/ª½wuþ ]¬ö¸©n*T5E›ÈÚ+¦ÚP2!ëþí~ec{Ü%MþFòf*ÿœóT¨º-¼ Ç‚ûÃ7 )´ùm#M%[2iö·û&=ɉukñšÏjñŠOå_° ]Ž>fnÓ&²ñõ¬2•ˆÚ@2}ê ÆùeM|ίVsÃaš“Y½&Éq@Ж=“MÇ¥o‡ž›-ÀÎW³?;óÏÏ€VFЪ  ¥.‚¶°‰ÃÒï¾'½ù´töUÉ›­þŠTJ…›Ø9X¹–¾ÞæÏx Îh V³[J&=O±%ýê^û%-è»6ÿ‚'GLëGÚD6å›L…[WiÁLrj\ÐÙ—ñÛC+ØBAš¨T V¼¥·)w›”²°)Ð2¬Åâµ^4 ‚6P ±Z/`Îâ«Ìå=Ÿ7·ÇöI¯?)½5$6=ë„ Â›#?lóC…`º`Rµôã`Øæ¤·)ée'™tä9’ãxé Îñ%Çë­¾]ïúÅ×Ü¥Xײèw% ‡lvÒ&²‘Ûe*Wn1[Î1sØ43¡67³í£méºf_»ÝM%má*¶Ìm™óØì}A-²Åºý@­wPê_" òÚ@óèYg.Öÿ$½ñÒé_JNÖn]óéœÔÿqR¡›§ñîÓìéC&KU­eÌcST…ZfÀ&ùZ¸]$dæ«-^¨Zc¾4‚6м–þ/æb¨³¯>©ž¯n')™ª¨¡m…÷C}éJ˜Y{Ë6æÝmfrXg< s¯>i>+™kR0ds2g®ZAfÞm¡v‘ÛBëhÚ@na"P­Æ|5hm u$n3ëµGMÅÛ™£ÒìÙª-#"ä Ý‚m =/N˜†‘^0pKÌ„¦²ÍKW°yNªm¤çow\;ËÍ‘wvXo=s»b ªwà~Åçh')™j¨®m¢=nZE®Ø,utçÝuüÀ:ûÒÃÒô„™»šÅfç­I~€æº9k ‡nÙUl6ˆ jê-£ $óÕ ´€Öués‘¤ó¯K¯ýÒ¿ÿ«tœ®Êr…nEm¡^F(—n)~› Ü$)™´¡ Ü$ÉIz©yo¦Þmöͽ:ùO×kñêϪkÅ§äæ fú¤[öHG53Ú¦'æðÊQq‰ ÒÕ÷š`4sÃ?Ñø ÷É;wÂo™ Ù‚óÖ\×ÿôÙ€-«md(ü-v[𾆠՘¯-  @’:ß!­øsÿö™£¦âíÔsÒùÉ›­ÝÚ"„[PFeq¶™¤©ˆSºÕ¤›Úœëæy’RsÝ&>¨É£¨{íµhùmÊiåSáöÂÓRõ¡+! î0h3“Ã:½÷M>g‚5×ÉËÜð6´<³Ø¤Ìð­iź³Õú Ö E´DY¼BZýÿö›ÏH¯ÿOéÔÏ¥©·*ò”QóÛ¤Ìék6¸ð¼` >ÏÓ"-¹òüP-®9~‹I;ÿ-™ª„›×é_Ü£³ÇžÐ’µ_R{ïêèEwt›PgÅf¸îã«Ç¼µÇ¥5[MšGrj\“GÖ™ÌØlÅš Ïì|¶Œ€M’œÌj¶pОÅV¨UdÔ>uÉÎW[¼:®­ªõŠu€   Ý`.’43!½ñCiô‡ÒØþ²Îwóƒ´ÐöÀuÏîçÙëÁ(NéʵôÏÀf·Éo1™ôRaœkÃ8GJJÓoéͧnÖÂËþDÝk¿”»do¿tãc¦²mÿvÚIVÛòMÒÚmç°=ö„N¿ðeif<«ýcz›œ@Ø–#\Ko‹žÃæ_Oý̳¦º Ùì|5û³3 N@k"h(U,.%þ7s‘LkÉÑI¯_š]8þ9ŽÔfÛD¦>"®­TKµŽ”!›ãdkÁªµô¶ìêµà>Qê"d‹ug†jÌWÌA@¹ÅW™Ë»?cnŸÜmZMž’.¼Qե羅ºH¦¯z’’vCªÝ¤+ó87Ð96 s¥ÙÓõÖ3·«ó’?T|íëZýä] ÓNrx·™ß69Rö××’Öl53ñ ´‰<“šÃ¦éñ습àE~‹È`[H+£z-°­¡Äº¡óÕåCÐPio4ÉÌw;ù”©x{^š>]Ò¡‚ÁYz[êg¸Udxv›ÙyT¬Éó«Þd+àÓJ2u[ž™á•ô¤ '~¢©“ÏiÑ{>©øš»r/zÙFs9°S:ò(óÛæªo@ÜaÌ<.Œ>§‰_~Y3cMHæ:þüµô%Ô:28w-0£Íßf+ÜÒsÿBÁm”ªs ™ÁóÕBÐPM±¸ôŽ[ÍE2m&O ™ª·SÏuZä Ü‚7<Ï „^Æ«Ý2ʘ¼ô!’¡#»ò”LU¼%åH3:sðAM{BKÖ~I —ýaî…Ûv’û·K#{Šx¥d‚µµÛLX™ÇÌ™a~á>M½þT*DóÛDúš¢IÁûœŒ0-#hSö¶ŒmyÖTµ€-£ $óÕÕCÐPK¶Íä¥[ÌíS{Mðö»ÿ)=ž÷¡¹f·I~KÈœ³ÛR?ìì6{ SÍæ¤·)¨f“”L:rÚ$Ïóä¤úM:ž£ä¹ûùŸéìŃZ2pþv’×?dæ¶íß.Îû[Z{\Z¹Å”Œx@gþÿíÝ_l\ezÇñßûŽmâØãÄQ± Ž A"¶.&ô© ì ÔÒ6-7TÚM©ô@ìÅ¢ ¤ä"Häb{±©è-t¹&…‹•¨pRPµ»ÅK"mÈs‘¬g+Ûk;3¶'öŒÏÛ‹÷œ™sÆçÌ8Á‰íäû‘†ÌyÏ;gÎs÷Óó<ïIÕ’rá¶(D[Ñ62þ¾¡²Mj°­v[ÚÞ5•h9D°X7mIoÁ¿xÕ·™œñ­&ÿð?ÒâÔš|E½µd¸à’m'£óñmµc+áfkÃ5)üTÑäÏŸT÷¾×Ôµç%Ù¬9b}éÙ|+ÉsïÐN²QÿÓÒ#o¶lY¾ü‰Šg*X÷³Ö¢PÍÆæ®)YÕ&ÅÚE&ZAÖ÷o(Ñ|µZÕZa½ï€‚6€ª-ŸœïvmÜo'¥é_JË µ­Íf·IÉê¶x;I眢QnÆ„›‹¸>ç-þN&1Ó-*{s’d¥ùóÇ5?öžzöÖÖÝ/dÿÆC¾ä™cÒůãáܦ¶ú€­¯y˜T¿¬«£?ÖÒ䈌‘rQušm Öêí#¥xE›iYÅ&¥·Š”nò,¶h¾Z÷Þ0`\ƒ‹ps´l[úWÎw›–¦%Í~Ѳ•¤Ô¸EAJl³ól&ñY ¹pƒUTåf䜟㖠C· «à£`¹¨«§_WùÒ õ<|Xí½{ÓWGtà˜´ç>p›½‘§³¹µç}‹ÈCM·KEͽ«ÒWÇec3×âkƘz5›ix©Þ²1dK ØnI¸–JÎXÛÒ¼Š€„  `³Šæ»=ðª?ž<é+Þ¦ÿWfîkIÍ«ÜT ÜL,,q¾†-6¿-º†Q}~›s®¾™XèfrR89În“o'95ügÚrÿßhÛþ#Ùí${‡¤§Þ÷•mçÞ‘æÇ¿ÝóÙ,v”ö¿áÇ&æ/~ â™£RÅÏa‹Â²Dõš|KO©žEí$¥dèí©¯§W¯Å÷%Ön4`K´<À|5À¦FÐp»Hi3ifF¤‰Oä*s’\¬Š­ÞÒ¤¥oªõˆ¬nR}V[¸Ia°¦úžZœs2AøÎhñwÿ©‰ñauï{MÝ/eÿŽÝýŒ²±÷}àv»ê+ø€­w¨é¶ÊÌyϾ¥ÊäˆÕr&QÁfcÕgÖÖÿ‚6Ö:2m[tœV½ß“æºB¶(Pc¾à6d^~ùe×z¸Ó-//kyyYAhyyYÕjU•JEÕjUKKKúøã×ûÑL邯v›‘›}ðOMj3ØÂ7.ÙU2y†ns±ÏEkò3Ü¢ã@µð-p’ÝÚ¯í…Õ]}O4¿ïùqiäÛ«d{ÞÏaÛ}°é¶`©¨âÙ£*_<‘l iëíašâ-"W†h+ÛCFÿ®aÐÖÖ“ Ö˜¯XGÏ=÷œ:::ÔÖÖ¦öövµµµ)—ËÉZ«\.§\.·Þ·nT´Ü ¢6“÷òÊÌh8ßmD*ýV’Æjµnµ$%™´®8Õ’+ãC5Em$ýyçÂuS¿’sF&p ÊãšþìEmÙù]å÷Q[×®ôûîê÷í$'F}à¶ÙÛI>ôŠŸEתM䨻*;.-}•ZÖ,6…Á›âaZr[<`[´­n[f°ÖÙŸ Ö˜¯¸Ã´܉z RoÁ‡*Õ’Üôç2áŒ7WÖ(d3j Üœ‘L,ló #£]N6|Ý&›ëf}Zç$-þ~X‹“#êzð‡êÚóRöü¶¾‚ôü)ßJòëŸI•Ò>Œ[ ¯ 8æƒÃ&'>Wñì[Zž=/Éøùj±°,š·Ñ¢ð-ú4¶Š\Yɶr[-Vu.`ëk^ V¿¬Ù‘×U™ú<Ñ2^­–h©x[H³"P3µìÌ%Z?&ÚEJ¾R-?Îç; Ó™Q1V  ×­ÖjrK¿tïAéÞƒ2{É/ÈÎŒHS§ä¦G­!£MÎ)g¤ ˆ*Ý|àfrRDUn>h ª%]=ýºÊ—>P÷¾鮾'Òo¨£Ç‡\»JgŽI£·îa´ç}‹ÈCM·KEͽ«¹¯ŽË“ÓlXÑ&Å7µØVk¶ö]ÆHê¬ÏXÛÁ|5n‚6dʪl‹Î9ç•Sêô¯ûùtmzTfê¤Üô¨4w! Ý|‹HÙ0T ?’±þšA4û- âªS£šùìou×ý­mûd·“ì’žz_ºø¡¯p›_ç‘b÷Aiÿ>èkbáâ*ž=*UJÊY#fbÖ4T°)®Å[G:Éú*@)¥bÍ_©¶½¶‚,$ÿ.1Yëàú´ ¥ÌV’ sÝj•nѹÿrÎÏw›:%MJ3£² WŠ6¸Y#ßvÒH6¬‚³Šæºù@nñw'4qeXÝû^S÷ž—²ox÷A?+mì}¸­µ¾‚Øz‡šn«ÌœWñìQU&G|8fëlÁZ¼u¤;§0p‹íW[ÓzHù!™õv•lÜ:mXµÆ`-ë\t>QuÕ±MîÞƒÒ=%9'síŠÜÄ)¹™Q¹™Ó>ˆ +Þ¹dÛÉð%käªEÍ}K cïi[á'ÍÛI>ôŠݾ|[?õí@{¾Þ¢²‰`©¨â™£*_:!c}[ÈôP­¾­ÉÙÆlýa°VÉï•òƒáù†ª¶„kÜ\m¸!«©rköY×Ù/Ý÷}™û¾ï«ÚfNËMÊMþ·LéBl®›8§ p²~2™áÊ—5ýÙ‹ºkçwÕ³ÿˆÚºv¥YW¿ôä¿û¹m#oÜx;ɇ^‘öü e›È¹±w5wî¸\µè¶”pͦ´‰ŒÚGJ’é Cµ!°uöמ[ü߯÷q„lÜ|m¸eâáœo‡Xo5©ÞÇez—{àŸå*%Ó#ÒÌi™©OeÊWdü¤2o5HÊ£¥+'51^o'™9¿­¯ =Ê·’üúgR¥´º›î+HŽùÀ®‰Å‰ÏuõÌQW/H’rµÍÉÉëÛb®ÙŒLøÛMÏLoAjËG¬öœŸ!XmøVZU¶Å[H6¶“ÌÚï:z¤¾§åî~JÚó/råq™™Ó &>•ýBA¥$ë¤ LN2´pþ¸/P÷Çչë{Ù7U¦9&]ü0{_W¿ŸÃ¶ë™¦¿¿:YÅ3GµxeXÖY›œ·fŒMÌd³=R÷€Övdz¯ý~Ó"XK«hËzŽàæ#hÀš¸žÀ-í³Î¹Äkm}më.¹Î~™{ÿRAÈ–¾–›ùBfòS¹Ù/jÕn®<®«¿úG-Ü]PÏÇÕÞ»/ýf;z|•Z4¿möBý\{^8ä¹J_ýTåoÞ“«kló×ìÖ2݃2½ù`-?ÓZl´‰`ã"hÀšŠ‡>ñÐmµn͹Úuò2ù»^”œ“üLnö 3¿–-©:5ª? ?¯­þº÷½&Û±-ýb}éÙ|eÛ—oûãGÞlÙ&²|ù•ξ¥`aÜW°YSoÙ¹SvÇc2ÛóáZgÿŠ0-+h‹?§Õ¶‹$d`ý´`Ý$f´)=4jܯt³Ö*™¾ïÈÝý§RÈUJrSŸÉÍþZåËÿ¥ò¥Ê?|X[w¿}#»úW Õù˺:úcU&G}õš•L~lï£2Û“¶?*ÛÑS άµµß`­M ØkÖsAnšÆ,Z‹¤U¯e}& ×$)‚D«ÉøûÀôH;ÿBÁ=î×Kc*Í|©…É#Êÿñsº«ïO®ûwKW5÷Õq-|ó²½(÷ÀßËlÔ·lÏ×B´è^³BµfA­"Ø|ÚpSeµ’ŒŸËj'™6÷-ªd‹ÂµÆW¼c´mP®g@AhÖ9mù¿ß(ÿGʶmYÕý—ÿ ÍM|%×u@¹ïüÓŠÐ,+d‹Ž›l­‚¶fϬ?‚6Ü2iÁYãz«™m­*Þ‚ H„mÑZÎ-éMÏΩ³sY]]]™÷Z¹vUså@•Ü™²sÖZ½¢ûkUÉÖø¾ÙØÚpËÝHàÖØ>2~ÕâŸïÿëœS¹\Öââ¢òù¼ÚÛÛkßæç絸X‘$år¹Ú÷5Î][mÀÖ¬r 66/‚6lhlYU_Ñž( ‚ v>Z‹s‘b±¨öövuuu©R©¨\.×ÚSF×nÕ 2­]dÚ½œp{!hÀºYMe[tœVå–v½¬Š·èzA[ÔZ²¬äH‹&IDATT*Õ>—U‘–´5þÛªŠ­ñ}ÚoAÖ]<\jU½–5³-­udZØ–îeµ«Œ¿Ï Øš­¥]§Õ3›A6”fUn«©j‹ïÍZ‹_§1€kõ>-DkVÝ–v´ß 6‚6lz-##« æÒ®—õ¾U¨–5Ÿ Ü~Ú°!eU¥E²Z=6¶žL«^kœÑ–öÝiÇÍ*ÕZ­µú°ù´`ÃÊšÝ?—VÉ7ÎnK ÞV†­¦d«€p €Û A6…¬Ð-«Êm5m#ÓªæÒ¾s5áZÖq«u°y´`Ó!ÌÁÿž¶ Êh_IEND®B`‚treetop-1.4.14/doc/site/images/paren_language_output.png0000644000004100000410000020275712157663062023414 0ustar www-datawww-data‰PNG  IHDR@°΂Må\iCCPICC Profilexœ•WwPÓÛÖÝ¿Tj轊€˜@¤#Ò¤÷^TŠš€   ¨ Ml4Å"‚ bô*EDD/‚EQ¤Šæûï½3ï›÷Þ¼ý×:{ÖÚkŸ3gfÏ“ a³™(ˆ‰ãxÚQ‰þDü3àE" !a\¶µ»»3üÛ˜à 9„ÍfV";­ùÜŒ–‡8ñgÿ^Ž@ BɈl’¡+Ø$ãØqH$H†E†ÐT q¼=iH"Vp BWð} $„EÄ C8ñXzT,~gAgpÃ$ Ó¹a1„C(˜@ôh…±9q¢€ìH\i9(À  ×øOŽÛÐh <ûONó0€¬(À…´r3ž€"ÝË ××Dˆ €áñf4ð…Ë<ÞÏ*o¹= p‹ÏIøý^Ò ðßÎ+wþh€ìAËcNáÖá¯ñÛ <Ú$ÜõÀ‰ƒ9y±ù^‡Œ ä – GŠn>VœRPjX&V6QÞu¤²"ù¨×1íã¨ãÏO\:¹§2°J§U=Xs¦6õ”ëiâé麻gŸ ;§}¾ÿBåEÖ%ózÁú¡†S—¹VW„® 5Õ\e7›µà[ú¯khÓk[ºÞu£àf`»Zû—[Wo§Ý±»+r÷Ù½:s]×ïg>°ÿƒðÇ“‡e6w«t¿ï9ÓËìÓí›~ÜÔŸøÄäÉâ@ÛÓÔÁ ƒËÏ®¥>7{þóEëŸIÃÆÃó/¯ŒpGõF§^5¼ÞþFïÍÌÛ¦wIïÍÇPc>~Ü4®9>÷©ãséó í«â×ߚ§*¦3g¢gýæ6Î~×ZPü!±(ô·K?—-òxHjÃÄ~ÁGñ½ð|*ìD¸/j!Ö,A–<#­ S$Ç'Ÿ®0£ÄP~JtPiRSWÏ_½ ¹U«S{íÚ\Ò¸Ž­î1ÊŒž­~©Á[#ã8“fÓ93½ LóJ‹'Vk 5–nS½±Ãö­ÏAÞQÏÉÎ9È…éšêvÀ½Üã”gƒ× ïNŸßg~£þc_gƒ7#[pÁB[ÅCdC•ÂTéš R¸^„Qäú(Ëm´h[¦CŒS¬+Ëí¾ÝãÆusŽ·O°I´L2ݱ.Y+eUªäN¾?Ó¾¤ìêɸ‘y.«twÖž˜lß˽û„öMç>ÛßzàøÁ]y!ùÔC*P0Rx½¨üp|±G ©WúªìZyá‘mÔ£rG¿ë:~ì÷¤C¥rålÕƒêã5œZ»SЧ¾î¨+?{–zNúÜçó·.¾yɼ^¼~¬¡íò¡FÆ•õM¢Mﯶ6j ¿fÞ*Ñú©íÖõÒ¬›ví«Únõß>'ûnÈ=ó¹ŽùήË÷ pþðzhøHöÑR÷랮ދ}%Óû£žxX=ÕT|&øìçÐÄóÑýv·¾¬95zôUÑëÜ7o“Þ±Þ‡múàñÑv|ý'Ògå ÂÄÒ—_û'[¿˜Êš¦ÏPgWÍþ˜ë¯ùž°`ûCòÇ«Å3?ÙKÆKËË·eñh<‚F‘Жl ._Éw¿WàƒJX†@±õ‹Ï(’¬“j“î–‘”ã)+*(i)ë­2%Z«8¨:©¹ª»¯vÕpÔܨe¾Æ@[s­,‰Ÿ4KÕéÒ½@)XÇÕóÒ§¼5l3:dL711Å›®¯1Û¾ÁÂoÞgQnbµÆjÒº‰šB³¶ÁÚü±1ßÖËNÆnØþ¤ÝqãW§ËΉ.殈k§Ûw/YÏZ/¦·¾÷¢Ïmß}~þrþ¯Îr‚Ì6a6uo.Ù²5X;xvëÍ}¡^aÊaŸèW™á®ò"¯Dels‹VŒþÄl‰ÉŽõf©²¦ØíÛó8AÜ5ÜïqñE [ɉ?’:v$oNÑL™JmÛ¹'Í%]*ý定Œm™”̹¬ÖÝi{¨ÙØì®œÜ½Nû„÷õäæïw; r ç`^žk¾p~÷¡Î…‚…‹r; ?,9PêRF(ë+/:â[!Wñòh屈ãäã³'ÚNfU:WIW½®>_³£Öî”ô©±ÓÍu¹g¶œ58'xîÝùö G/¦^ ®§5¬½,݈m\¸2ÙôùêDóÌ5¤UªrÝëFÚÍËíS·×ß9xw¢Ã¿³ç¾Ïƒ±‡{»M{¾÷Ýë¯ÈÜ?Tú¢qøÏQ©×›ß6Œ‰Ìø´ð%å~úÄœþ÷þÅ”e=`eöàŒJ ü[|¬HhùH׸ x›ê[5 šîR7÷×ü° b j  fà)UнðD1D<’‡\Dz‘)”ʌڃº€Dš„öGg£›Ðï0Ò{L*¦ó«ŒõÃ`áøqö¸Ü}¼ Þ ?̧ÎÇâkãçç÷ç?ÿ$à!P'ˆ 6 I %=6®! oEÖj!­ÙfÔVÀÎÔžéPå8ì,çàzÌí½‡®çN¯^ußT¿¡ãÀò ÞæÈ-O·Ú„´„éÐO‡«GÔFim»Ä4‰é`ù°Ç9éq²ñM‰ÞIß“¥ÚîœJ?™á™Å·ûVvê^³}ËûïÜŸïW Y¸xøqÉù²Ü#ÑG=ޝ?©Y%S#t Sgá<æ¢`½Ìe+&W]["[w_¯¾yïÖ‡»‚”.ß)Otßî}ýxy@f¿úÒ>Y1?ãR‹þŠ1À¤bº°RX¶'ŒcàÚñJø4ü>¾F~þBœ@ºÀOÁAžPް„p Á”Ð/Âm£‹KˆwI¤Kn\–º#½_Æ_vì²Ü |ƒB"W)@™ºŠLTT!¨¢TÕfÕ¿­þ¦1­9¯µ¬_+IR#èØëS’ÖÖ»¬ÿÄ`ÎHÁ˜fcZ¾¾ËlÁ|­ÅVËR«>ªÍÑ&wc·¸}€Cµã¤³¥K똻…G¹ç‚w O»Ÿ–q 6(yÓôVðdH\è2=7\!¢!ÊiÛGfn,…õ|{×$n"¡&iK²bÊðÎéŒ RæüîÛÙy{7å’ö/ìͯ*ˆ/²/V*™*ë8rähìqë“’•cÕ͵9§}Ψœý|¾ñbb½qÃlã…¦f‘––Ö ¶ï7¶+ܪº£r·¬ƒ¯“ÝõøöÉïtcz¬zãúN>îê@=•Ô|F2|nø‚ò§Ö°üK—³#ãí¯*_§½ xKy‡{÷ì}ÝXüêGþýã%Ÿ?+~ž8úÅÿ«Ô×Þɽ߬¿-L]š¦ÏÈÎ<šM›[7÷jþÐwëï3 µ?¼1‹?·.–Z—é¿¿šx<Àʾ4“Å!:ÓlþËr÷¿F 3þ/QŠŠsðIè çØzÞņºº€8¢ÁànôúM£lV´ˆ#;ÎÝdÀäHo? œm!Žî¿ñ®X¦«3H yt†ÍÆßÚN¼§¨ W¢YNž € 1b}þòzÇMðú‹?O±qE.9’æºÂG©‚3ÐÀˆ,` 8 8±@„W@„0à@p!B ’€Lˆ‚íQ@pëã ˆØBp @þíðÿ}|áp ê?0¢€¬à¨LNÌåð„2ÖŽõ¾‘”s”qʳþvd@ìß•VÜCÿ:c40zC cޱÀ˜#‘2Æc‚±ÆXbÌ0†Óž‰æ‰¿«Òþî€øwÅwÀˆé• áHp!Æ€1ÁQ™ÿè`eWÀ‰ ¸¥ÄØõ¯ÿ*Ž‘@c±wp¢""ãˆÖl6“A¤±bØñq ‰è¦C"êQ(†ÿ¨Y3@f IDATxœìwXTÇ×Çl…e¥*  HG°vEl`‰1V,±ÅnLýE&öX#¾±D±ÆØK°D v,J_¤nß÷ “ë²P–-ÌçñÙ纳åÜf¾sΜ™Ñ“Ëå@ ‚¶¡¯n@øˆ€A+!F ­„@ ´"`@ÐJˆ€A+!F ­„@ ´"`@ÐJˆ€A+!F ­„@ ´"`@ÐJˆ€A+!F ­„@ ´"`@ÐJˆ€A+!F ­„@ ´"`@ÐJèê6€@Ð>ärù'!ôôô>¡ˆ@ Ô„PTAÂ× JEKáI¥â„žÄE5/>öFDÀ*5åJ.—SUJ^ zL&ïÇ×µ8aXôõÿÞãk½j€¢m "DÒ„jôþ3âA è65Ý),Q2™ŒzQøP·jºhT¨–‚’é))¼>â«M "`„¦ˆ‚Ò(Ò$Y5Ôg¨× •Jß¿Ïçóù|~QQQii©H$‰Db±]H$:Îd2 “ÉD¦¦¦fff<Ç㙘˜Ðh4¨V2}}}¬Xø¡PJ½@÷BÄŒÐÔ FhBPu )\.—J¥@‘+¬RèB*•ÊåòŠŠŠôôôÌÌÌììì7ÙYo²ßdgçäç—ðßr yf¦MIIy–úôyÚóœì·ŽNvŽ6-ZÚÚ·²³oi×ÂÑÖÖÞÆ„gŒü§OF*•–¿ûæÝ›Œœ79™¯Þ¼y“ñ6ãU¦­‹«‹»«ÂÁÁF£Ñh4¤U胴 ?¢'JFÐmˆ€t–ÚuK"‘  !‘HžƒzõØ©k{3 žºÍ¯+Å…ü»q.ž¾zíB¬••U@@Ÿà `&“©¯¯Ï`0ôõõ±s†gшŒt "`A!ß)ŽŠÅb‰D’‘‘ñÇGO>Å6d… ìй-uI–Ö!“Éîß~tù̵Kg® *Æûê«QŽŽŽt:Á`à#Ò3…ì|uÛN |.DÀZUº°Ë…‚„b±eº_¸páøÉãi©©ÃÇ…Œ6ÒÕÓYÝV7ZœEhjàôB3‰D@ ”——8p  O¼Ø” ³O!êE…cÄ™µxJlÊ…¢Š¼€€Þ(//G?H$B^,þmÉ – -Œ à°!JÖ@iñb±X(fdd,X¸@¦'^µým;µQ·¥šÎã{Oþ7ë'}cÓ/›Y,rÅPÚ=^þL\1‚æC<0‚€}/ìx …B@PQQñçŸÜwhÏó LjzÕŸŽmÎ'ë7¼çàÁþùgEEòÃÐ&úØ#C[‚æC<0‚¦ƒ³ qr¼X,EEEáKÂÓ^¤þßñÍ^mÝÕm¦ö‘ü(eÚóúö›1ýsss6›Í`0pÂ=ÉN$h>Ä#h4xÚMù^UUU_úÊÚÑìï¤3D½> ¯¶î×’Ï õ+¾õUFFFUU•P(Ä~>PFÝf…AsÁK¥RÔ±"õzôèÑ—#¿:~àêˆelu›©Å°Ù¬ÕˆŽøåÈ/?~Œ4 p ‘hAc¡«ÛA9ÔÈ!:ÚX(VVV>þÚ¼ù¿GzbßK«ž!è$„HÐ,°ï…‚‡h½WyyùÂï¾µimµrëu¨û,›»úíËü~122b³Ù, q,QÝÿ@ÆSÍBið0**êYÊÓðµ Ôm]“ |í‚g)O£¢¢H ‘ á"AƒÀK¾°z ‚ÜÜÜ5k×ì;¿ƒdÌ7ìm‡×O ™Ù¡C;;;äxÎã D‚†@þ õ\J?ܵ{Wè¨;·S·uMˆŽÛ…ޏ{Ïn@€V7£®‰FÐ(ˆ€4|¼2uÓ‚‚‚óçÏÏø~²ê¿_XQ&üÔR*’:}¤ÖWÖ^ ©ÝŒdúw“Ο?_PP@Ý&Q&“AuMj‡ASPØð Ø‘£GúîmÛ¢ù¿_‘ŠÓÓÂlõB#¢‹¡ a’Oh`Àæ—e¯Ë|zpÉ÷z>.ÆS”Õ¯ âɹc³B : Úô´.VõëàÄp1-"öI~=K¡âÁQc[Ÿ°Í¿ÝÌSv/‚Ô #ô܇ìÉH\ÿ½­žÛŠ#éu°J ¶-š÷ é}äè´Õ/ÚþŸÌ„4 "`MŸQ‰¶ë‰D•••ýuaÞ3>éó¤å/ÒX¦,àr!)-%æe•Xá5’û׸8_¼æ\ ¸ `ƨ{)H /òéºüTLš{hHXǺýLoõÍ´ oˆßµmŒwÀùŠêQ 4sçÙcû@RâÆéSÚ„{P¬xÏ•üx€”R–€!»²Êªê`•ræ,þ×_*++‘€‰Åb4 FЈ€4ê9ËhL$¥§§Ëd²Ön­>é#=ƒûüs‰r•B{´â~ðŠ—GV ž ³{.?»}õHGv]KAð|©ÕÈCI½§Ï¸õÌúq6u°ŠÕuÚüß'ß¹±º @Ê–…Þó/ êZ lÿÅwd–^Ù4Ï mA‡.½ú ¢ÈiéÑ¥úšÁèÚɱV)ÇÙÝI&“¥§§£ê@®©OþX¡¡ FÐÐÞQ8ciX\\\¯ànŸü™†&àÚ¢è<(Qg—$ooNs V&Ä/í£p~sí¥’Ø•ß€Ð¥IÑóÛ;Ô÷ôgºm÷aÇsöÀ–¹;£óëS t®ýÈÍ‘§Öõ€©Ãæ}PÆæ¸û;r¸Í[ˆ¥õ´ízw‹‹‹Ãê…*ˆìðKЈ€4ª†'À%= Üë“?“ë`\0±g“ …Ñ?NIè²îðd?³o­½$¯®Y“àwjß8se_-á§Ÿ^¿yÒ™“†Ìœ=mÍŠùË÷^ÊR|‘ÿ†ks`cŸÃ95?¢öR¿ï—/ôHÚ¸óÜ[Ê=óìRLÍÀ´¥8µ2VöîºÒ7¤÷£¤GÔcVˆFЈ€Ôê QÏˆÆøhÆ¥¤„oÕÌò“?Ö¶×̸—;]¹À’qåÎ|J">?y÷.¹fN%﬽ éä{x¹Ÿ²i¯ŠÔËÁff-úíòÙkY¯¯Ú¹{˱KÏ•d€˜„m ¿]zPZßR«©‡VÀî-7ßÿû¤ÍüŒ+w&¶ŽóÀ¸—ÑþŸþûX6³àó‹Qu ªÁêE4Œ vˆ€4¼ý<ÞGJ,—ðK,¬•z8uƒmìèdƒ¢{æö¶–,\’—x#À=¼kek£k/x{åp"€kÿ^öJ %YÜç¦t ßú *õêãÔg K€«ä¥Àé—n½®)pÚtœ17^QÄÑß)ÛÌÑÉæ3×~[Z[ðù%È÷¢žrIÔ‹  #h¨[¤nÃ!•J‹‹Š›Û5SÅ×å? öÍ”ËJí¥PÆžvæ\%Ù¼üsïn]½u5€nȬÅs/Wˆ?“ZQÿRs÷P¸öð…R­hn׬¤˜O­\S*úF¡î#h 2 ¨Ç4äpJŠKTñ]àâ¢<¾V{)0€ÞžfÊ®4»–†Ö1¯Cø^1¾î¥Ò"å¾YƒQR\b`h€¥ £Úo%ê0‚A $Êd2SS“‚ÜBU|QUa!<^ð ¥ † HzZ¬dV«ôé¥kÀ¢®«Tò: ËÄ à#™µ—ÐÌ[ÖòÙ @~n¡)‡k„ 0‚ú‘W”„¹\nlb\TP» ò‰X¹x@V®ri©½¸¼6Þ]TVsÓ'&ƒVýLñk6ÖbIQrx)õØj/IQÊYèÓÎù³R k¡¸ ØØ˜«´vˆ’Ô0‚ÆûÇæÍlîÆ=PÅWXûùuHYs1UÙ†Lµ—Øôãv1¶Ff<°¬[º@ÌÅ'P|zþÄegQ £Æ‹ ôÖÙHèÚ­EýK¡"åÞnèÝÃé#³uŸÏ[÷mšÛÅ"h&DÀš…^5úúúî×.ÜPÉ×ð|¦Ìs8öÆûõ.ð9ù1N1ÊH÷ûj0\^4aĸå“ôºÌÚ’† .?x]S ó.í]p¦·WâBÕ^ ðvר%0ûûî&ÊŠ„knx¸{ s,ÉQ–MƒA#Àý#V/===WWש¯Jøïÿóíõ‡Þï»…îñËÆDÔØêâ¿Jîôg¸+@â—#÷ä}Xdâ7áüÿ€øCÇ.LÙw,S5òJ¶‘—dÞœÕÿ7Xz#̶ÆWÔ^ ‰]¾1 À{á”àºlaõ)¼/)}žòÒÕÕ׈ÂÁ`‚z!FP?Xºô?„Íf{x¸Ÿ>|^%ßjÓ}ÏÙ0ø¹OE¿Ý,Ô§ ëÊí³ fc{Ÿå±©Ô‰:zûi?¾*¾q'ãÆ³ªÔ|èôVëä©9gFR÷I½t0ØqJ<€{øî©Ý6û¨½Ï÷N>fY"€ë¾s>c¡Üpêðyw6›­P/¸¾TöÍB FаㅠÑh ƒF£öé»eÕN±XqùÁ1$üÚñiphúo·IãödêZ tûÅÅçf÷H:6ƽ‹­OXĹ§ÄØ<+[+%«ˆ…±ë—êùôéÿs @Ðʈ“«»ÓëZ ‚Ì›‹B¬B–íJè³+å`?Uª.‹·®Úا/® ª€õ"hDÀV/F§Ó Ng±X-[¶47·8y𜊾×í‹ù™ùQ¿® ëâ —=,×£x.‹£“¯_Û8e¬$%ÆdÔ–._äÍ¥c)à:lÞÒS)w~ÿ!À¤¥ -}{(&ͽwÈÊÇ“Ä;º©*ùN>offÞªU+‹…kË0‚& G2‹j­ý‹ÅB¡°²²²¢¢¢´´´¼¼¼¸¸˜Ïç'&&ž=æÖËËŸ¹/¡®TU ºµ <Ä×××ÌÌÌÌÌÌÈÈÈØØ˜Ãá²X,ƒAdŒ vˆFP?¨DC{:ŽÆûL&“Åb1™LOOO{{‡EÓ–«ÛÌ&ÄâiËíí<==q-(x`@æÀ0‚F€ã‡hÆ ›Íf±Xƒ нxóZÔuu›Ù$ˆ¾x#úâÍA°Ùl6›¬¦†ê…ü4¬ahàÔ‹Ífóx¼ýÎ —“÷ߟBø ÞåäÍ [<°ÿ@Çf³ PE0™LT5Dºšù[$h ('q 300044400ðññéìßyß—…ùEê¶Tg)È+ì?Ò߯³þåk†Ið !#h8 ©!²ÙlÃjºuíæìäòeÀ„ò²ruÛ«ƒ”—•·mÖ­u+çn]»áß¼f‘d!4"` ;aØCN§š ~A¦\3WãŽy*Ù¥¾ÉR\Èï×vhß À ~Aè§622BNöÀˆûEÐ4Tµ ’@¨/H½är9Š"Êår‹%¡€Ž¤êÜ___@ÇÇc#”‰L¨'¯²Fô s°wìÚ¹›Q5†††åÑE`Í„x`ÍBOOGY,Ê#À>‘‘—Ë êäåÙf`§O>S·½ZÏ“‡ÏváåÙ&¨_—ËE?2úÁQ 0¤aDºmÅŠê¶@øêEzzzèô ºÀëî­­¬9£µË~‘É庶'ë' “ɶ¯Ùõý”e}ûvìБË嚘˜ G4P@s` )ˆä§&hd'‚fDK*•J¥R‰D" AeeeeeeyyyiiiiiiY5ÙÙÙWþ¾bfmúÛñ-¶-š«Ûvm"çÍ»i#æåñƒúÙÙÙq«166666Æ!D”Câ‡4ì‚HÐ(H‘ Yà]}Q§‰S9PŠ{X„½½ý¨¯FqFžƒN:GFcuA.—ŸŸ¦nó „ YˆMõ˜2™ŒF£›Í¦)l]O§Ómll=z46xJ×>×D,³´¶PŸùšHA^á’™+o]½íçëß6¸-*jj ºF 﨑C¢^…x`ÍM†Éd24†ü04%VQQQUUU^ Õ9K¼“˜œœDÀZÊé j˜H$‰DH«Ð#’1ìœ r,//¿ÿþÓgOAO>r°1S¿líÖJÝ7¤*^¦¥þíÏcûO\ÏÓóC‡FFFh=8šÜB†¥ ýívXóÐ/¢^ §I H ÚÎ#@]*uç_|&Ú¹ƒÅb 6›5ìåË—> 033»w#éèÞŽ­†<$о¥ºï¬aÈz}éÌÕS‡Î¿~‘éââ2(´¸¸8&&ÆÖÖ¶C‡TõBh›y¤^t:‡ IÆ:ñá$#.ÇÚª™•¥•½½½©©)R ìH±ªA~R¬´´´Ÿ~úÉ××÷‡~033Ùx‘2Î× êEÐ.ˆ€´ä„:iycÑÑÑsçÎíÕ«×Â… ét:rÈÐ#V2œÇˆL("ñ“J¥b±¸¢¢âÍ›7ù¥e¥B¡ÈÙ­U›žmÝìlì[ÚÙ·´304PÅUUVe½ÎÎzùöÙãÔ'÷ž¾HMg±˜–––ÆÆ&––-Z´àp8èh.$Bx³ œCˆu ;[L&S"‘lܸ166vëÖ­ØëBi™Äñ"h)DÀZ vÅäryYYYxxøùóçýõ×®]»Êd2ª§…•Œz” ûaÔƒÇÐ…L&«¨¨ÈÏÏ/,,,+/«¬ª(+-+**644°iÑÜÖÁÆÌÜÔ²™…¹•ÏÜ”gnÊ33¥ÑiLt$“Ád2Xl–H(‰ÄèQ,KÄ~q ¿¨„_TR”_\[XTPüöMî»ìÜŠŠJss3®1×ЀcÄ1²´´´²²âp88]ï<‚£Hºna¹ÂTÏL__?..nÖ¬Y!!!«W¯ær¹ ©1‚ÖAŒ õÈåòøøø°°0ÿ_~ù…ËåREH\ -är¡gj:aÈÃ×r¹ÉJÁAËòòò÷ïߣ@„B¡P$”HÄ"±H$ɤ2‰D"•IeR™T*‰Ä F£Ñè4š>MŸ¦´‡É`Òé “…¶*622Béâ€N©@§pá¹ïUÓýÂy˜ÿ|>“ɨ†*~eee ,HLLŒŒŒìÒ¥ ‘.‚VCŒ Ý…ÂeË–EFFîܹ344TFiõLg$WHÌ´ ¿F(RʼnQâiÈíC€þ‹Zz±mÛ¶9sæàÿ¢ô¼#z¹AúÕ #=iÕèëëSEIv¨*…ó ñëHõ)œ={vÆŒaaa+W®d±X]gBAÖ´˜Œ?ÞÍÍ-99Ùª—ˆ!i¡Ñh2™ŒÁ` BnºÆJ†žÁÚFÕ9ìŠQ5LÁÃJ†®¡Z½°˜€‰‰ PÎêĺEÝ•XÁñª©^È¢*Ö*<Æ`0Ðë©Òˆ:th÷îݧOŸÞ¡C‡´oß^]5H |DÀZ‰D"Y½zõ¯¿þºeË–Ñ£GãçQŽoFJ&•Ji4šT*¥Óé2™ŒÅb‰Åbôˆý3$cØÍ¢ *Rˆ%*uÅ4 cnnޝ©ê¥Ôñª9ÄÙT1C¢…§Äj*–Bf<[baaqâĉ#GŽÏœ9séÒ¥MdŸ-‚.Aþd ÚdzgÏÆgeeõøñãæÍ•ÄŒe ]Nǫǰ’aMÂXðPÕt¼°n)8a‹"bSˆ*u¿¨«‰i5P-âmŸp„°æŠ.ü¥JÉÑ£G÷îÝ{òäÉ~~~ôððhØš"T 0‚6!“É6mÚ´víÚµk×~ýõ×µ¿õÚ4ªd(®ˆ” å—#íAX«D‹ªUøyªã%ÿ DÍÍÍ©›`Q©éŠQ÷!ÄB…•‰*QxÏ'ä«áƒ»°“×-*Í›7ŠŠÚ³gO=-Zôí·ßjì:nA’ÄAÐ^½zF§Ó###>á¨îÞуªL¨TÁÍ¢&†P_¢áàaMÌßß?!!]S=0¨$Bõ2,ê4u⪦s†ÞB}}ý­ÚÉÌÌœ0a‚H$:pà€““Ó'|ÐÈŒ Èåò;w.[¶ì‡~˜3gÎ''+õÉ\(¬LX–t]céRê{áG $qP€jSP2t 5vÈô(+·ô(%Žna¢££·oßîëë»jÕª3f|檆x`MçÍ›7“&M*++;pà€‹KÃM©à–%'žš—žÄ¯¤¾(¾5ÿììì²³³ñb‰@3…Ð5¨ðš-¥¼xñbܸqFFFûöíkÑ¢Eƒ>êÚ˜ IDATÐP#h4‘‘‘ .\°`Á÷ßÜ•‚›UÏjúX+­ù<Ïç×|^ÁýRФZJA5¢¥€T*ݰaÃÆ7nÜ8aÂUði#h(yyyS¦LÉÌÌ~ü¸ºÌ >ñÀšEqqñÌ™3mÕª•z­j|^¼x1~üx‡CÎÆ$¨âž´k×®wïÞñññMP½ eË–îîîø¿nnnMP½ÀÙÙùÖ­[íÚµÛ·oŸºÍ!èÄ#4$ùùùS§NMOO?tè···ºÍQ'û÷ïŸ={vyy¹‘‘ѶmÛ&Nœ¨n‹ÔIrrò¸qãìììvïÞݬY3u›CЈFh0Nž<Ù¦MOOÏû÷ï7qõ€#FˆÅb‹Å#FŒP·9jÆËËëÎ;íÚµóññ!gc â>Ÿ?sæÌû÷ïð -®öfXóÉšU ´*}†  ˆ€5< ­¢î]¡Â¥}|ØÖÒ÷Aƒ¶¥ªªªÅ‹Ÿìø˜È>"` €‚bÉd2øp^?ƒ.po¨TÞ>ö-5-jóÐ××׫Pÿ¾O&“YZZ¿{÷®Y³f ãÇ÷õõݾ};Çû„ŸKs¨Ù£¡:ÂB¡0%%åéÓ§O’Ÿ¤§¿zñ:+ó N³s°káhkçÐܘÇ5³àñÌMÑ£©™)Ag2 &ƒÉb2™ &•JE"±X„$M,•HøE%Å…|~Q º(å—eg¾{“‘“™-‘HíZ888´vrnãÕÆÓÓÓÝÝÅb!Ã:&fïß¿Ÿ3gN\\ܺté’——׬Y3WXXˆý׺ ´B?FÍvŠ?>¢^ˆZ$ Y‹êj´JjѳØ'RK߇¯ñqŸXUU•™™™•••““S\\Ì/..á—òùü÷¥¥UUUb±X$‹D"‘X,“Jå ƒÉ`0™LtaÌåšòx¦¦¦<ÏÔÌÌÌÌÌ¢E‹Í›7Gs-¸ÙèëëS¯k6°ºô}K—.ݲe‹H$ò÷÷ïÖ­Û¾}û"""† Ö?²*¨YkR©ªGb±øÉ“'ñññÞ’ü$ýåëŽvîÞ.žmÝœ=œìmí[Ú›¨p3âÒ÷eY¯³s2ß>úòé£Ô”¤çY¯³œœ¼<½:´ïØ¥K—6mÚ0 \•4­¦ž©Î<•röìÙéÓ§7îöíÛ L&sÞ¼y?ÿüsíDê‘ÚúZ¢D"y÷îj‰EEEÅÅÅ%ÅÅ|>ŸÏç—”””—— E"qu3‹Åzú4“Á`0,&“Á`°Ùìj7ÚÜ”gÊ33333³µµµ··wpp000PmP[¢®ŽBÔ°ú[‹ÒF‚› ºÈÌÌLNN~öìÙ‹´´¬ÌÌ윜’÷ïìZ8ØØ8µ°336F£v Sž¹©©Çb¢±;]0 ¹\^=v‹Ä"‘X\VQQÈç•” …%%yEE¯Þ¼É|û¶ˆÏ·mÞÜÎÎαeK7wwOOO///===ÜÍ¡ è±v1KLLìÕ«ÚÉÀÀÀÕÕõÊ•+ÚxŽU·z4¡PxïÞ½¸ø¸øÛq‰ w,­-ü{tìе­‡·«‹§3›­æS†…BQZòó”'ÏïÝzxçæý¼Ü?ßÎþ]ºuíÖ±cG‹¥´—íT²Â   ”””ªª*`³Ù±±±~~~ /«)Zh"•JшMäryiié“'Ož>}šš’’ùúõ›ììœwïÌy<'{{k33 SSsSSÔ-LyCCŠøV·D==½F–b±P„ÜiqAqqaÉ?-±Ï/.-}õ&;óíÛÌì7¦&&v¶¶öή®^^^¸vô)Ô\%«DÀê„Bð·™L†ÛŒL&ËÎξ}ûöÝÄÄ”gÏž¦¤p9oW×¶nîm]]lmmm›[Z©î¯S(eæädää¤g¿¹Ÿ’ò(5õéóçæffîî^>>¾¾¾~~~‡F£¡ƒ.¨CE…&T^^Þºuë¼¼<ü†††OŸ>Õ®mykúÄèâýû÷W¯^ºø×åËWì[ÚuêÖÞ¿gGÿÌ-5zqRQAq»‰7îß¹y?ëuvPP¿ýš˜˜(t‘Ô¾¶‘‘áééYYY‰Ÿ±¶¶~ùò%ÊR:|Dµ‰š!º¨¨¨HLL¼sçNòãÇ)©©EE^..mÝÜ:¸»·´³kikç`kËb2Ut r¹ü]A~FNNfÎÛGiiRSž<^Z^îéîîîáÑÉϯsçÎvvvúúúx4‰®¡†?­]u§ˆ€ÕµÁP»?‰D‚DK"‘¼~ýúÖ­[ ññwîÜ©¨¬ìÞ¡c€o§6..>®nf¦¦j·ÿUVÖã´ÔÏR¢ïÞyôô©»››¯Ÿ_ç.]ºvíjjjŠz:…&„}²1cÆœ9sïH úúú­[·NMMÕü¦U³î|>ÿäÉ“þ:ŸØ±s»~C‚Bû4·µV·½ŸÂ»œ¼Ëg¯]9}/þgÿ}ñÅ<OÿC@KÆõr¹Œœ*›Í =räTû[ ÃGT­%%%qqq·ããïÞ¹ó,%¥­§g@'ßöîÞ.®­Ô~ïÅ%%ÓR“_¼¸–xçæý{CC___¿Î»uë†VY é¢Óé ^hIÝ© "`J F'p éj3"‘èîÝ»—.^üûÊAUUNzuìØ£c'7ÍÞ°U &>~|ýÞÝØ»÷î%?içãÓ78888¸E‹ ‹jKçÎ C‘Æáp*++W¯^R¯©õF†êrẋÅ7nÜ8xèÀåK—{w8"¨wp7#®ŽdÿW”WD_¼uâ×û7¾G¨Nñ_óõ2™ìܹsK–,yñâ…¡¡aEEÒ*ƒÈÈÈÔ±tI$’7oÞ\ºtéïK—>~ÜÑ«M¯NztìàïÓ–ÍRsà·vRÓÓoÜ»{ýÞ½ëwïöíÜ¿§N˜L&ª,¬d¨1*¤~0DÀ>€:lDZAÔ`$‰H$Љ‰9îÜÕ«W›[X اƒ§—º­þ*«ª.ߺu:úÚ…˜[[Û>#¿úªU«V¨×+((pqq144‹Åîîî èÚµkf9«jŒ Ì%IAAÁîÝ»9bdb8jòðaãBÌ̵;y²Š‹ø§?²çDùûÊÑ£FM:ÍÒÒõ†8f¥á2•••qqqÑÑÑQQQ)))t:½ªªêùóç–––h,’žž~ì?®]½š““3¨wï¡}‚ºu340P·áŸÂ½ä'g¯EŸ‰Ž~WX88$¤wïÞL&ÕP"aâ}°P:l—H$R©T,¿zõêÈáÃ'Ž·µ¶žÒ;ÀAWއ—Édqœ‰ÞwêTëÖ­¿üê«¡C‡2™ÌãÇ»¹¹ùùùRÓ@4³ýÔœ‘H$YYY[·m9qâdèWFOù¢M{Ou›Ùx?ü‹áóæÎ···Gq*…YOu›©œ_ƒšaUUUbbbJJʈ#D"ÑéÓ§ÿüã—/_N6,´w@×öí59P/2srÎÅDï?{6'/ï‹#FݺukƒA£Ñ¨™V8Ó°3Óp›Aº%‘HÁÉ“':ôòåËñ¡C¾>ÜÓÙYÝöª ‰Dr!6v÷É7ïÝ þzÊÜ~ð0çM©ÛÞPÈEu—œœ¼eë–¿ÿ¾2fê—Sæ‡Y5Ó¾´É¡ ¯p÷æÈC¿ œ?o——î R5éBm “’’vïÚuñâÅ:MþÅ ^½ètººíUO_¼ØsòäÁsgœœF;|øp6›Ú Z'C+jNõ©…&-` Ò…g¹Äbqiié¡C‡vÿö›[ËV³FÒí£@^aáÁsç6EîwqsûfæL4›‚OÍö£F;ªõw¹¹¹?®\q-:zòœ±a3Gsud–ës(+-Œ8ºwË>}ú,_¶¢Y³f¨7Ôœ~°æK×Í›7wüúkZJÊ·&Ž ±¶°P£ Pþzôhêëô)Ó¦;ÖØØEøqtQCªO4]£÷p÷‡¦LöîÙÙ­}û¥S§ujÓFÝ–ª‘Htðܹu{÷™˜L›1#$$„Á`PêDÕ”®ÊÊÊ;¶oß6jò WÎ60ÔÊÕQUYµqÙö£{OÌš5{ÖÌY†††5e¬ñ­RˆýbÝ‹ÅçÏŸÿ¿ˆˆ²÷ïOþz\HSe‰ïÎÝ'O~ÞõÛ­ÂÂÂ&ý5šÔÄu§A‘Ƥ) XÍ6#‹%IUUÕï{÷îøõ×A½z-þúk×–RØ8Èd²3W¯®Ù³G¢+V®ôõõEÓËÔ¸b#kÆ ÅbñÕ«W¿]¸ÀÍÛyùæÅ-[;4Ž%ÚÈë—™+¬Kyü|ã†_úöíË`0ÔQTp qÜ^$ݹsgŲe4¹|É×S†6Í®Y´×ék÷ì¹;sÖ¬I“'ÐétjõiBP¤ñir†¥ ·‘H$‘H®\¹²rÅŠ–66ÿûÁ¥eKu›©q8sfѦM~þ~KøÁÞÞµœÆÂã.÷wåååËW,¿ð×…í‡×uíí¯jtƒ¸˜„9c 0èÇ?QçW¹©Á±Xœ••õóªU‰ ‰ë,?dˆªÍÐ:ž¿~ýÍO«^¿}»lÅŠ~ýúÑét”yOM6)½oBFM2Ä#w‘H”™™ùÝ· ßf¿Ùº8|`¯^ê6Ss©¨¬\½k׎£G&Ožyòdò¤Iƒº÷Ø´h‘›­nµ’§/^|¹`¾{ï5ëÖ£ä$cxVùó¿…ª^¨úÁÜysR_¦º¸ËÂÊüó¿‚P˜_4¶ÿT·ÖîÛ·ýŠãQ ;¡†@Ð R$•––~÷í·/RRŽý²ÉËÅåó¿¥ R%|»~Ýù7öþþ{›6mªÏ±ø·êö”˜Ž ˜B¨]$ …ÂëׯϞ5kïªUCûªÛ@íF(ùþûl~ño»vYYYaW¬¡€Ô1;v×mXwýVÌñ˜ý$Q¾©ª¬jÍi×'0ààChÙ,’±Ñ0…r¼òóó§MjÇ3;¼~½êö†o"œ¾ú÷×?ü°í×_{öìÉb±¨³bº­a:{cð¡záI¯?›;{öé­Ûˆz}>,&óøæÍ~nnÇ-..è@¼ägÔK |»ðÛ-›¶œºy¨WÃb`hðZ˜T%©üî»…ÿæòê·>¬^È÷BÍ0++køÐ¡~nnÇ7o&êõù ì{rëÖ¹³gÇDG£fˆ’«q¨nU…Î XMõªªªºµð»ïböïïéë«nu==½­áKšñx^^^ééé@(¢IŽÏÑ0…È!R¯7=ùÜù6.®ê6P׸uøÈšßN?þÝ»wB¡PAÃ>aH]«‡:¾ãÇŸHRë+k/m4ètú·?Îܳw7JiÓaõ­Dü7ðîÝ»ŸV­:¸vÙ#ªqX5kvvfæ©S§ðP× .%%ꎀQÏFÁ}_nnîÆ NmÛNòÖn:L:tíš5Ô–SÇñ»ìÃ*…BáÍ›7ß—½0¬_C›YqzZ˜­^hDt1$Lò ØüR ìu™O.ù>PÏÇÅxêƒ2%åOΛêdÐaЦ§uùÞ£~œn#¦EÄ>ɯg)€ õÂ=·À!{ò×o«ç¶âHz¾·Þ Öï}Ùû[·nQ0T;µ¿‘êCãqäÚ5k&„†vïØQ¦jÂd2OoÛ¾aýúÜÜ\” €óªê2 ÑtMÀšÍGöëÒÅ]»79–UÔ6ö×@§L‰ÉÊÊÂ-uµ·TDU/¡P¸ç÷=󗣂™giù‹D€4–) ¸\HJK‰yY%VxäÁþ5.ŽÃ¯9—®Ã˜}¸EŸ¤àñ"ŸÁ¡ËOŤ¹‡†„uäÕá{é­¾™ä ñ»¶ñî8ÿBQ=J¤•üx€”R–€!»²ÊªêwëuC__ÁŠ™{öîF5 ªkJ) Í#333oܸ±øë)ª°S5H´®ÑÕÄÝÉ)¨k·£G* %‰€iÔÜ œ:_RRrì?–N¦në¨8²zCÂV»ùVYû¤_pwó™µç-Àͽß빻Ϳ ?ø3Y2eÊŸüj;aº¤a:"`PÝr¨[\Ÿ:uªkûöš·Çš´,3 mÌÒÒ’_V*N{HO¯1î3|ú®sIà:vê zÝß«üoÚ´‹QQ………5ç•¶œšû” …Âøøx¯v#Ž*,44×Í8@ç¹@©ˆúCJÞÞœ>æ¬Lˆ_<Ú§†’ؕ߀ХIÑóÛ;Ô×Bºm÷aÇsöÀ–¹;£óëQJgsÜý9Üæ­ÄÒz~{]1äz·÷Œ¯™ÊQ{%R³¨òóó£þúëÓ§«ÈÈO¥¶¦Ä0uÜÒ—­˜bÛ6tÿ³b…7‹ü€¤r€Ã¬€×*ñƒ?/—®íÛŸVÊåÙ¤˜š€iK pj¥ÂƒÐ÷JH¸Ú’¥ÿt£!·oßîäímÁ«K|µ1©­)±müW¯ß!¾we_˜@ÚÄá]Nd}àˆqí¿¹Æ ØÇÉÍx -->2ö×6¬,, p³©%ú„Ú’”‚D"1噿¾U¾žW¥TÀóçÊ‹ÅPIO‹•Ìj•>½t XÔc•J^‡a™˜|$þT{i#û6ß”gŠhT×—Ô80Jæçç[[X4ºÕ ޹O¸–˜©dªRóiniYÂçã¾0P‘¶µ^Ààà l<úTVr9™ŸW+†< ðpÔ>éU —鬬D5BÖ%“^*•šššä6¾ÙV.ž•ûááòÚx@vQYÍ&ƒVýLñk6Öò]EÉià¥ôµöÒF  ·ÐÔÔ>dßÖ’Z¹¸Æ+µ³Ö@šŸ­n>®!GX}8Õ‡ÖvõÝ0¨R‰\“ìÜâCkº `¸û£6#.÷mú¾Ï¤™£'¼.¬-è¤E䙘˜ÔeÄGM ÀUéâìzéÔÕF´·žÏ”y®Ç~Øp_i¹÷ÈÑphÌqŠ# ºßWƒàò¢ #Æ-Ÿ¤×eÖ–4TpùÁëšj˜wiï‚C0-¸½’(aí¥Ã¥SW]œ]j°.U‰Þbll\P¬æi¼@ZôøôñsÐÐTÃÚÉÉÏçr¹ ƒHÐþø!膀!˜©©iÖ»wê6ªÞØøøõHÚuñ‰æmU_**+ʼn¡¡¡Bä°îÍÆËËëúßqêhfô~ß-tˆ_6&Bq› ºCПᮉ_ŽÜ£àæ›øM8ÿ# þбËSöËG€¼…*•dÞœÕÿ7Xz#̶ÆWÔ^Ú8ÈåòÇyzzÖýõða,ÑÐÐP,‘TTVªÒL•SöêÞðëá¢ÑЬwïÐ8’äP·Q ƒîÕ§§ç•¸8ù,D===7—‹7o¨ÈÂFáí–ï—@øäî»æ²¤R镸8///u¢tGÀpÓBÍÌÄÄÄÒÂ"1é±z­ª?ôI ½b¶YŸ }!P*®Ç:W XÍG*ÔΟ㬯¯O£Ñ:ûwÙðÃöF·À1$üÚñiphúo·IãödPeŒn¿¸øÜìÞIÇÆ¸w±õ ‹8÷ï”›geë`e¢$·Z»~y žOŸþ?§­Œ8¹º;½®¥ÍÆeÛýý:Óh4T u¤´k>:»º^¸~½Ñmo($—"—¥¸.œß½.›5k [YX˜˜˜P«LgeÖÃMEÿCœZ·Žº®…C?«î§"Â`ÑÄÓŽÝ,ÐÎX¢\.¿çææFíûjo6TÝB4Íßß?ñæÝ—iêÙêÛí‹ù™ùQ¿® ëâ —=,S8o…ç²8:ùúµSÆúARbLF]f.%o.K×aó–žJ¹óû&õ(mT^¦¥'ܸ۹sgT¸^PmÖòF\×èÅîîî—oÝÒÆéAñómˇ÷ßžàz6b‚–fGݸުuk…¾ñcCI­COÿ°¨È«wÏ«ªªª¨¨(+++---///,,LKKÛ´qcvl,—c¤n3ëÍ“+›½çþ†®C/üeÕ×N½dY‘gάÙ÷û·ß}gaaÁåry<ž±±±‘‘‘¡¡!‹Å¢Óé4N4¹\Ž6n¨ß¿_ZZZ\\\TTtòÔI‹¦Û¬Sãí4AæŒ_Tø¦dø°áæææfffÆÆÆ&&&\.—Ãá°Ùl&“I§Ó©= J …•••åå奥¥|>¿¬¬¬°°ð— Â'N?dˆo§^ÞÞœ»dã®D”€Óçø_k¾PåŽÉª£¬¢Ü®W¯ ºººZXX£J400`04M«eLw<04²@=#F£ÓéÖÖÖ...;Q·ŸB›~óÅqQ‡†õv…³ç¾×Ø-{•!—ËŒØÑ£W/:Žk¤vW ØõôôhÕ0ªéÙ£gìśѵЙÖZb.ÝŒ‰ºÙ³GO\ ¸^pM)¼EÁñÂÍN§÷èÕëLjZ4V—¿Ý•˜æí²uÃáüäZª^q䨳³³µµ5µcD:ái½€Qƒò¨—¤WÃ`0ºvï¾é@¤P$R·™ŸݬÕèÉáÑgRå);ÚkUúÓù˜h‰\îááÁ`0PEP5 >> †Ûî7™L&—Ëí<`^Øâ÷%Z¹‚Öñ¾¤tîøEúàr¹L&×îk™£ª®}‰\~!6Fwó)p]FÊSRï_?gPKÚ¿^3ŠD¿DîïÖ£ªªêt¦ºÍü,´^À8¶‹¥‹Éd²X¬V­Z9::ÎøñGuØ„(.)™ô¿ÿÀb±X,–BãA#t…·Pû>T‰¨Q¨ŠÅb9;;;Ø;„ÏX¡†ûiz„ÏXá`ïàììÌb±p- zÄuÊú>\¿ÔA$ú30`âÒ¥Å%%긡&ÊŒtttlÕªªGÜ©•¨íèÄ=èë£G4BÄ#wTm :ýw\œºÍl*L]±ÜÕÕÕÕÕu|ª¦tÐG­Dj ²Ùl6›лϽ[ׄÿÒè7Ô´X¾éޭǽûà_wX຾@ê…Ýh\ûl6ýIL]±¼Ño¨‰òw\ܹ˜èƒáž‡‚k¯DíBëo;Gµ`WcjjÔ¿ÿ¸Å‹JËËÕm¦îsúï¿oÞ¿دúñQãQúÁGx–õ}häŽúPccãÐУ{Nîßq¸Ño«©ðóâGvŸ 566Æ¿<ª”µë¨æ{¦¢Qw‰}86›دßÍû÷Oÿýw£ßV“£´¼|ÜâEAýû›ššâž÷x¡n3]0Ürðô jrl6ÛÐÐÍf·iÓÆÙÕµçøq•UUê6V—¹uÿþ„¥KB† 111AÝ¿S§O>6xe˜a5fffƒ…¬ ß|`çÑF¿9ÝçЮcëö bff†~p$`5=°¹ÑÔ‰LìC#!411 :4,|ñ­ûZ¿H_“©¬ªê1n¬³«k›6mpH磱>hÿÐV¬X¡n===ê>°(-›z„MJZÚùk×F¤޳ÿðÁ 3úèææ†Ru¨ý &„ü°-ÃOR÷¥nÐ,•J FË–-7ü´¹ª²ªGß®z‡:Mý—m5j´µµµ‘‘ª;´ò¥\+„‚kéûP¶!uëz¼9=›Í615]¹yó ž½¬ÌÕpT©Î#•JÛFc±„›!Z¾‚Æ”u¬DmAG [>Ó÷}r¹¼…½}\BBTlìèDØÔôôöÇõïßßÇÇ5Ô÷¡!<›ÍÆ)õuüñ©ý u3Y}}}''§s'/d¤gê¥Úk,ž±âØÞSƒ¶¶¶Æ½º@F"êS¶äP=‰7½¤ z”Ëå\.—N§/^»vx¿~š{Ö¥v"•JûNž$’ˆ„ E{¨9uRû8R»Ð‘~\! GŸ Påñå—_¼°è­í»‹jw’’ºŒújðàÁÞ>>†††øG¾NúÏA^E„*OŸ ÏD=)z´²² ukÜÀiÅEü} á?).â/ž¾"6êVÈàP+++…ß× ^{^‹z!ÖBàħCÇŽý ð40îÁƒÆ¼Yݦ¢²2xê”7Æ¢…t Çk_¡è”FE® ™LæááñöíÛÝÇþ5` [“Ï×¢®_™5³W@€··7ö½ÐžGÁéOŸ¼KÎCõ¡9HçìíRŸ¦m]áÕÎÝÑÉ^%·§Ó\¿rkD¯°Š÷U½û ;Ú©×#Ò04r§Ö`í&§†þ‹ëùMLLx<ÞOÛ¶ù¸º:;:6Îýê0ü÷ﻎ])• 5¦€ã‡(†O#¦Y(ìS‰’B@ìróó×îÜÙ­}[kkõ™¬ÝÈd²µ»w-X¿nà AnnnXºhôGm68úTËg*ì‹êNiŸˆ†Í›ÛqŒvnÞù¶gPWÝH¬jÄbñÿfÿ„öêmëÓÏ” 311A5xˆœªåàPQÝSÏС©cbbbai¹."B.—um×^7úSµp')©WØx+›À¾}±ná vÂ>g©±èŽ€Q¡vy@™MÁ}_óæÍe?ÿú«@(ìѱ£ÎTg£ñæÝ»à©S®ß0(d°½½=îûðÔ!Ö·ÙP"X¨àÃn‘ªs\.×ÁÞáöÍÄ]›÷;´náäÚRU÷¬+\9=6xê»Ì¼>666 ®AjLJÆ(÷új>œÃê…*×ÈÈÈÞÞþøù Ç¢þ êÚÍ„ËUå}ë R©ôÇ;¾Yµ²ƒ¯¯Ÿ¿¿B=¢P05’_ûZLmD§LaüŽžÄ îÑóŽÿÏÞuÇ5y}ïÈ"!öÞ[†2œ¸Z­u´Vk]­mj­Õj[GÝV­£uï¶np!ÊYÊ)+ae'ðûã~¹¿ë@D !äù#Ÿ7áMrßÎyžsîyﵿpõêÑ Æ l ßóüUÎ\»6rîGfVVÃGŽàr¹xÑ õ­ÁE{ÑÜI܆ô*p;‚æŽm2™lccKÖ¥Ù{ìÚ¥h¿ >ƦÚ·ýôÙÜIKN<ßÇ˧¯_”x!Þ‹N„)Ì×[Áï*„D"Ñh4'gç’—/×lÝêbgïéìÜù—­¡(~ùrè‡ħ§?ÞÙÙ·#ZvV€ñ °öäÐ=E`@éÎ¥btžJ>õ–­©´¿¯/™¬ÂÝ—zròó§~ñÅÁóç†éããƒ|-UŽOþCñÞöí_-B9ÌW7ÍiñÑÐÐÐÑѱ¢¬rûÆ=%…¥^þž,­(ùÊJÊZùëªO×™ hffÆ`0`®lð*pöÂ{7Þˆ½Z”’øŽŽ®H,,-MLMw:tí^l__®QOÜ9²û –HÖíÙ3cÅrk‡ˆaÃ8^À‡`”{¡­4¬x¡i†€¼_4…Ô¼T6~`aaaieyíÎ{÷ÚYZyi5`K¨­¯_þ˦…?®å˜› >Ü‚ÉdâsÅø´ÿÛˆ><Ù•õPé`€/êêêšššÚÛÙ§&¥mùqGNF®«—3ǸWGÃçÙy«—®ÿvÑZQdPø {{{ÈOx¯E}ùÎU;¶”–z{{ûøúB;ÜÖ„!uáÝ7¨wTóØ h0%ƒÛÅB6CÙs Ãeggg¤§3iôuŸ}6yĈÞ&+ª«7Ø¿çÄ [;»>>>(öÁÀC>_ëNË^øjH‹@r …b±Ê܈ðžƒfqqqFfŸÇ ‹0çÓa4̦r¹<6úÁÁíÇÞŒ3âp<=<­­­a*ŒØ ­Ï‹HK___y¹<´ÞkgE=‡A BÛ!7D"‘ybYYÙ“´´Â/æOºrî¼Þ¶ú”\.?{ýúwÛ¶ $bOoo777”Z!#¢VC¤BP󔯳Ðl¯r˜B¡J¥r¹8!HcðO"‘ƾ¼¼¼Œôt>Ÿ?{„ùïNÕø)¹\þïíÛ;{ðè‘““S__ccc´*nca±è½éï§y¬¼¼]ǹxÁÐÐÐÞÑÑÕÕ’\ E:(ñàŸðåA 7ùwE³nG¹\µ<”#8c‰^…D")((8uꔉ‰É AƒH$ÌÅëëë_¼xQÍ«*+{éàõÞ˜Àоž>n=ÂÕ›šš2Ÿä$Ä&_<þßãÄ'–\ޱ\f†­;wî”——¿ûî»öööˆ½p>Ãóf¼é¦Ó œÃ  þ…|Õ‘ÂGxŽ@ ÈÉÉ)ÈË«­­5aá{ï¹;:vîUŽº††¿ÿùgçñcEeeNÎÎnîî&&&„EýW¡†)$"•\Ölö½À Zs¨âqB±OÜ DxyÏŸù{zN1ÔÞÊZÕWÖq(ЏGÎÞ¸~öúuHdgoïîáÁårÑ&„ÈmpºB¨è„Š]¡Ü P¶#ª £„ —&—/_þçŸÆŽëíí-‘H Ýá»d2™B¡‹ÅÅÅÅU<O(ö ö 2`po€·ZÉ|¹\þ8)ýÁí„»×ãRâ3z.×ÔØÔÚÚšN§Ã}\Ñ^BðñéÓ§—.]7nܘ1cpÆB)WkæëºNkåL™OÙ á’’È«««³23_0õô&1yøˆÿ½KAIñÅ蘗/§feÚÚØ8:;ÛÛÛ#BB>ˆë‚vˆTCô­;L&CÎC¨Jáyô¹\. KŠ‹‹ŠŠÌ¸Üi£F àç×SVV,)/¿›˜øÏÛÿÞºÅb±Ì-,ìÌÌÌ|#°^hBÀåa¯¯®V|¸ñl 5ÀÇòòò 6ðùü ¢ù0øqø^˜—766 ‚òòòêê*~-ŸWų²µôòs÷ öñòu÷ôu713îÒë" ª¢úijfFZö£‡Ÿ¦f•–rŒ9F†F\®±™™“ÉÔÑÑA쪾9$§ºººÝ»w~õÕWp"핌²®n„ŠôD¤Å”Ý_^^^Ÿÿ²¬¬¾¾~ì!ã  ì)‹Ã‰Äâ©©·âãO\¹\^]mcccemmkkË`0 5QmCÙ ‘ }†Ý,"Õ ½ˆÀ@K΃Ï*#¢"z:¯¤RiYYYዼªª—••ŽŽýû îÀbªW1¯¨èvBüõ¸¸»‰Iu‚+KK®‰‰£££,—£ˆ†„9] èOŸÁ[¢»çrв°¨5%UP‘ܹsç›o¾‰ŒŒœ5kÞô·u@»C  «àìáñx|>¿¾¡N TUV“H$3KS;Gk;;k+[K6ÇÃeë1ô:v!"¡ˆW]ï®)-*+.(ÉË)Èö¢0¯øeiESS£±‰1“Ádéq8Ø[øPšA° Þ”qôèÑË—/ÿôÓOC† A)š²ùP³{7ß%‡ &ñ|ZÙ „ÛuuuyyyÕ••%¥¥LýðÀ€áB9Ùª×Ïõ‚†»‰I1ñ£>ÌÌË371áÛÚÙYXX@1q#*{":Pûí%eC½‹À ΃ú³‘²C4†¢îÍÊË£ÓhfffF\®••—Ë…ÊÆ/¤Ü ¢Dw9!7Cµ>C#Ðb±xݺuçÎÛ´iSß¾}‘5%P”„ìå¤1˜Š¡”Ëåho9±X\__{¾¥2‰X" E"‘X(‚&À2Ô7dê’ui0áQ©4Šž],–H%R ,€I¤ yc ¯¦¶¦®¾¶ƒÁÐÓ£ë1ôhTJ‡-Ñ, !© Ÿêkeó¡]ÈÑŠ€Ð²©©©Ë—/ŠŠúþûïá­èÕÄ|òfH$TWD¶ÃQžgÒÈ|ÕÕÕ%%%üêꊊ ‘XìîèØÏÓ+°·«›Ÿ‡G7ß“ŸŸ–“ý(#3!=ýINvM]¥…›Ã±°°€¤ I/ÿ Ñ’)ˆº ”é~©&è0çA4†|9†D 0>"ÃNc¨Éª¦¦¦ªªŠW]-lh¨ª®®o˜›ÛYY¹ØÚºÚÙ;X[;ÚØp ¹l¶!‹Õ±Ø!“ÉxµµU|~¯:¯¨8·¨0»  ·¨¨¨¬¬¾¡ÁÔÄÄÐÐÉb™˜˜ÀQÀBá)w$åð¨‡*QètK¿2u©Jñá;t(ŠìììÙ³g[XXlÙ²ÅÀÀE7Bñ…?ô'”UãÙLű=Q‘îÁ¿{IÄb1ú@yyyŽŽŽø=×ðLJñN³§ÀoïEïB¡ §.¤Öá” „B""¹úúú/¾ø¢¸¸øÐ¡Cjh>ôË£Ì7ÎgÈ”èeÒðB TUUUUU5ÔÕÕÖÖVTV²ôõm,,œllÜìí­mœlm̸Æ\6›chH¡P:v µõõÕ55¼ÚÚ¼¢¢‚’’ì‚üg……/JJÊ«ªô™L.‡Ãd±8\®±±1›ÍFmºêB": Aˆàùê0$¬QÙ«/„^J`çAÕ Hc¸ áÞ‚$< |¨”kI<ŠI¥ÒÚÚÚúúúºº:¡@ ‹…E{L> IDATP$ŠDb‰Ä@_ßÅâ²ÙT …F¥Ânt•ÊÔcÈä2±~“L"•J¤R¡X\]SS[_/‘Jzzú †\º‰Fca7ä·ûð¢Ê¥Û G<ð¡R!Òìª*:µmǦ¦¦ƒ®\¹rõêÕsçÎEe@tï´ b,<áÆÿ Ÿ¢¹ ñæ$};]ö c;xðàœ9sàq‹ë*¥5bðIx\v ;¢¨‡8 O£‘ÉÐ_ó‘É䃮^½zÆ sçÎU+óŠ"ˆÆp‘l‡Súº¿— }°®®®¾¾^Š:…B¡HD£R¡2èt*…J£Rh*J¥Ñ¨T U(I$R‰L S*“Uñùµõõu t¡§ÇÐÓc0™T©¯©¡R©È ¸BêB¥{äk·pM‰ËGøÄ[½³fH@¯&0€…B{ò…B †xщPÁ€Å+!ÐsPøC*ò%ú^X›‚ý#ÊoÁWÙAŒÖ|WÒì$Ò+k<êb€#šŽŽ¡ÔŽ*_ §x D,¨žr¯¶¶öã?~úôé‰'ÜÝÝÑ/Œ›%Ùè'-”C£ ‰ž*Wñ< ÏÆ€{¶nݺtéRôç0<ë"ä^Ê5C”ûâ©0 ˆ®ðÉ-x€Ø -&”““3mÚ477·?þøƒÍfw·µZ¡(‚OFâù1®,ÑS\ˆÀGôFܧ[¡oÁ-(i¾ó z=¤RdkÜ ¡; N TéE¿0ž=Üq*Åãâ?FEE$:‘) R}<±û¡FÂ*4?\[GG§±±þ«) ø¿%“Éà£\.§ÓéÊîÍ„¡"®ßPlÅ+Q¸xo[O VRóò¸„ØG`/$ú(±ä9\¶ã£VÔ¸ÿþôéÓ£¢¢Ž9B£Ñào¨lJ$í‘uð‰Äj¸pAB· â°¶í0344­¤_¸òÐm^ùg/Ü‚„@†,¨‹õÐë6—ˆ¡ÕÈØ}](Þyzz&&&®\¹ÒÇÇçØ±caaa*3ø O„ÿÉ9 …BÉ´žžžrÒŒ,¨,A”-ˆçÓx Âoä†-ÚÜ:hö ò“²dlѠʦT+OT z;Aà4Ýà±þp–Ây #½ßÔ¼H;´¤âÛˆ}m(we·ÁÃ*.!ÒŦXð؇«º9ŒB¡X·nÝîÝ»80fÌø¢²)Q(¤P(r¹œJ¥âFecÁãF¬ÁGYÅã©®â ÁápÚcAh>\‚ ÙŽ ¥V$ #Cë4¯hL~uV_§y+d>¶uëÖ‘#GN™2eþüù«V­ÒUû¨éèèÀ@C A)o^X÷;ÜIq÷T–’mdÒ­©ÐÒFí‘ÊÆRö;‚{âNªƒ• u›×ÅV7OT!´öÿ ä7MMMÚšš`ìà Œrìþ!<¼…PƒB±ïµú¢ Û ¾‚ \îµXw"cS_:Ø=Cº¯Î‡é¼Ú  ójm]=© PXX8}út==½ÔÔTsssÂ_•M j(G -h4š¢¹N…‘q«¡§Àæ5Q†—•…ÀÄļþpö‚ÐÅZBÈÃ>X¥¢EŸQ îExìSŽ€8K)ÇDÂ'5æ-ˆ”””©S§8055•Édvàð „ÖXŒ+qez#N]ÊvÄ¿ÔÀÀ@y„Ø¢)[¤¨.2œŸŸ_jjêgŸ}æççwâĉ€€€·ù´®þÓAïkl®‹àf"x"´ZÔè@‡Ü@°îkJkѶϸ–·ÞÚ ¬# yðjÄã]k¯±¥û‡Úö‚úÃÿÑ ðHzuª ? ½…fïN455mÞ¼yãÆ;wî|çw:ýÃñGÜ 8pÁÑš ++«’’xŒ‡|8mÚ´±cÇþúë¯ô²[P‹P­éðnZQ!jhY–ÀT€µ^ Î±ï-‘‘‘1mÚ4ww÷}ûö©ÏrG‰Ô³]¬®®nþüùOž<9qâ„···ª‡ÓÉh§ y-4ØÕ½kí}5^aÐy ॠMž={ÂÃ×.]zêÔ©Í^ƒãÇ/_¾|ðàÁ;wîTõp:â†ì‰êž-µÐ0ðx¼9sæž|xøðáªNgBc20„[·n͘1cÆŒëÖ­ëØ&ZhÑYÐf`Z¨yyy!!!?NKKÓ0öÒH 2$---33sÀ€Ïž=Sõp´èÕИªÄ_ý4sæÌÿþûO;³ÒSÀår/]º4gΜC‡©z8Zô^hZ}C‹ž‚ººº… ¦¤¤œªNWAóJˆ8ž>}:mÚ4//¯½{÷Â};µÐ¢;¡ÍÀ´PâããýüüX,Vrr²³—ÆÃËË+11ÑÄÄÄÇÇ'..NÕÃÑ¢×A“å¡jˆÆÆÆŸþyÛ¶mûö틊ŠRõpºš!ü÷ßsæÌY´hÑ·ß~«’¿´èèÞ¥…𠏏xÆŒ$鯿þ²²²Rõpº½„À/_¾œ1c†D"ùûï¿mmmU=-z´%D-º çÏŸïÛ·ïÈ‘#£££{ {õ*˜››ß¸qcüøñýúõ;s挪‡£E¯@o‘‡Z¨"‘héÒ¥7oÞ}:“É~ü¸¬¬,000##CÕÃÑBC %0-: ]°`Á¹s猌ŒT=COOoÒ¤I:::‰'2 UJÅ`³Ù§NZºtixxøž={T=-4Ú&-Þ555óæÍËÉÉ9yò¤»»»ª‡£.¸ÿ~dddCCƒ¾¾þ•+WÂÂÂT="uÁ³gϦNjkk{àÀ.—«êáhу¡ÍÀ´x+ÄÆÆöéÓÇÊÊ*!!AË^8BCCám¼ CË^8Ц۾¾¾·nÝRõp´èÁÐ]³fªÇ E„B¡øá‡V®\yðàÁÅ‹÷ª~& „§ !!aÉ’%áááèŦW> @"‘T}eÝ]]Ý#FøøøÌœ9³ººzРA°Üª…om Q‹Ž   `úôé,ëÈ‘#fffªN¢±±@`åW”ý¨©©éåË—NNN¹¹¹æææÊä_!‘H轎¿¢Ù‘½ªªjöìÙ•••ÇwrrRõp´èaÐXwC9âzíÛñ8ˆ‡<ÐúýäÉ“‹/þúë¯?ÿüsÍK`’^%'‹ðt>@9¡šÉ –þЙÊe@¡PÈçóy<^]]D"‘J¥R©T&“ÁG2™Lm…B¡Ñh†††ÇÈȈÁ`^j\„ÃÐSÂÉ@ƒò³'OžL›6ÍÏÏo÷îÝ™LVYYÉápÞòpB–Üþ4ºýnZ×%¸±´èth ¬3A…@),âJÖ¹â¼ZƒêX¼ûòË/wìØñÍ7߬^½:))iÚ´iC† Ù¶m›4…ã<„Žñ™*üQ¡PTWW¿xñ¢°°°°°°¸¸¨¸¤¸¢²‚WÍçóùMMMF¶‡mÄ5Ò%ëÐh4 •L¡R¨4*N“H¤R‰T*‘ʤr©Tª+xU|>¯†Ï«!‘HFFFŽ‘©©©µ•µµµ­­­­­­—ËÕÕÕEyzD¬†^Ä™¯GC$}ùå—W®\9~üxÿþýøá‡õë×/^¼ø·ß~{£ÏÁ«¾„ãNL£[d¯Ö^e2 0–š@K`o äÈUÑPYÚãî$“Éjjj ~‹ÅR r¹œD"AÙŽ$<‹Å222222244$¸AÂ+8Ÿ½Ö‹’’’(‹õôôV¬X±k׮ݻw÷èrñÔŠ`&…BáP(ÌÌÌLOOÏÌÊÈÌÊÌÌÈ$‘HV¶–¶66–vN6ÖöV–6lŽ!‡ËÖcèul<"¡ˆW]Së--*+.(y‘[T”_Z˜_TRXÚÔÔäáéáîæîéáååååéé Ó5]]]hJx€Û7}gþjÝ‹K—.Í›7oÞ¼y›7o‰Dt:ýÞ½{m¿« 7ĵÀ„ AnÖÖÖòù|>Ÿ___Sg‰D"“Éd2Ycc#!ÖÓÓƒ94›Í¦P(¸dTN”•5x7Ô¢ h ¬# P‹úÊvø¢@ (,,„ú½¸¨¨¸¨¨¬´”ÇçókjB¡‘¡!‡Í6år)d2J¥’)T …F¥êÑér¹\,•He2©T&•Ë$R©@$ªâó«ù|¡HÄ12â°Ù\cc+++k›fñniiI&“aŒkC¼ƒ6½H*•º¸¸§zzzÉÉÉÝûKwZä-…B ¤P(ärySSSyyy\\\|B|BB|~~½£­‡¯›—¿»—¯»§¯»±i·Þ±TUQñ8+#-;=%3+-'ÿyƒ£CPPppPpHHˆ™™‰D"“ÉÐĺººð@3˜,''ÇÏÏO$Á§¶¶¶9994p´ÚH£¡¡åryii)tâÂÂ⢢’’’êª*^M ÏgèéqŒŒŒ˜zzTÊÿ|>RÈ‘X,•Á,úÎXQ]Í«©á×Ö2 #6›cddaiimccmcÝÐÖÖ–Éd"µ[‡ÀgZ2ë0´ö è8ô” ÞårynnnzzzfFFvfffVVeUµµ…¹ƒµƒ¥¥“½••ƒµ5ÇÐËf³ :6¹\^]SSÅçWòyyEEyÅÅy%%ùÅÅ/JJøµµ.ÎÎîîîn^^^}úôár¹:::ˆÏà±²xÇ]hÙ²e»wï …ð)N5jÔ¹sç:ã‡ì>à“Xˆ·är9|E.—744ܼyóÖ[‰ ••UÁaýôèÓÏK­n P(“ÒÞIŒ¿“üð^¢‰‰q``ÐÐ!C#""ôõõÉd24"¢4\ø÷¸°8iÒ¤+W®ˆÅbø”Á`,X°à×_…OqÞÂIK¡P Wàquuõ“'O222²22²²²ž=ndhhgeå`míheåhmíhccbÄ162â²Ù6wM]]uM ¯¶6¿¸¸ ¤$·¨(¿´4¿¸¨¸ì¥‰1×ÝÍÍÝÓÓÃÓÓÛÛÛÑѦk„4ZYvô8“© Z{=”ƒ Œ}Èm …@ HLLŒOŒ”šjÌáø¸¹ù¹ºùº»ùº¹»ØÛwç€%RijffZvvjvVjvvZV–‹<`Àwww]]]˜¢A&É zNJJJxx8Š —/_5jTw^KÇ@ÐÈLˆ½JJJ®^½zãæõĄĀ¾#'F…õóèãÚ#R–¦¦¦Ì'9‰÷S®œ½‘üàQ`Pàða#"##­¬¬‡Aà6í) Ù•+WFMx‘N§ß¹s§_¿~³)J£á±\.W(YYY8(°¿¯Ÿ^Ùí©´¢ünbÒÕ¸û—¢£­¬¬† >|ÄÄd_}õÕ‘#Gär¹ÍøñãG®<¡n€ R”ä2™L.—ß½{÷ÄÉã1Ñ1á#ÂfÌ',b€®®®ª‡Ü™P(±ÑþÞ{úÖµ{ÆEL›ú^xx8™L†L†jŒðªa Tõ_‰Dr÷îÝË—/_ºt©¨¨ˆL&=zÿþý·=ztãúõ›7n”––Ž:42$4<0ÀÒ´gÜV/‹>N½“”tæúõ—UUÆ:t(,C!«i²Ö %°ÿ^wB³Y0Âf¤›7ož:qâ^ll@Ÿ>† age¥êQw …"îÑ£óÑ7/ÆÄˆ¥Ò 'N6ÍÅÅåñãÇEEEfff=Âpê‚ö‚†“Ëåuuuÿý÷ƒô ÓçN™8c‡«á+åóy5çþúçØ§j…Íùèý÷ß700€1D(ðÓ˜²‚,//‰‰±¶¶öõõ}öìÙÉ'.œ?O§R£†1,Äß¿GË‘%%¢£/ÜŠIzòd`XػӦ 6ŒB¡@A‰ þ0-=§Ü ЭפR©B¡xöìÙ‰ãÇÏž9cca1wÒäécÇè÷à¢S‹ÈÊËÛwúô‘‹ß™:u„ xÔà hNEÐuÁ{`ÿüóàá#G‚Âú.]½°¿§ªÛÝxò(cë»bSfÏšõá‡sàÝèjNcxoÔ‘¸¹páÂé“'óòòfEMøøwÜU=ÞNF]CñÿÝîlQYÙä)S¦½÷ž‹‹‹®®.•Jí¡Õà®Fo'0uÁd F@…BqãÆ=»v={ölVTÔÜÉSÿÒÄÄÖQ¯‡ºYñ”#r¹\WWꘖii ¢W¡— A‰DrñâÅÝ;w¹bõÂ…“GŒÐx‡! ’Çûåà}§N ˆX°p¡··7¤1”©V¼/æ¤R©X,>tèÐïÛŸøþØ…+çZXõŒén@YIù®ûÏÿýï§K>ýàƒèt:•JE6U7k"›¦§§ïÞµ+&:úãwß]>ç#§û‡§BÈåò³×¯¯Ý³»IGgÁ¢EQQQ4 xÿ°ª«ôRS–{º¤RéñcÇvîÜimbòíÇóG¤ê‘ªu ;ÛrøwŸ>+¾úÊÇÇÖåu1€n|¸à@¶“H$111?üøƒ¹µéºߺy¹tÛxz²Ÿ>ûnñO/‹+V¿zèС4Ü ü†Šnº à|óãÇÙ¸ñéÓ§KgÎZ4}ºæíß—ïÜùißÞ¢òòÅK–¼7}:\ éõ)Št?z#ÉårðªÜƒÔuÿþýµkÖpôõ7~ñEˆ_US] ‘J?÷í¶mÆ [ñÕW°…˜¬;‡`;¸äOeeå×ß|•‘•±jóŠ‘ã#ºa=×.E¯ýb“§»ç†õ?›˜˜ hˆI÷Ô`È[r¹¼¬¬lÓÏ?GGG¯ûôÓÙ&ÒÕ¾ýµÛðàÑ£›ã54¬Z³&44ŽPémµ¢Þ•xÂÆBøßD"‰DsçÌY¶téêçß;ú—–½pШÔùS§å^»nÁ`D ²mÛ6>Ÿ/‹á²ëp²ÒI—Z € '‹ÅbqLL̈‘Ã͸·3ÿÕ²W{0r|ÄíÌ͸ÃG ‹‰‰‰D‰®û‡~á®ÖµP8"í­Éçó·mÛ1dˆƒñüêµùS§iÙ Çÿ{GÿZýñüeK—Îû裌Œ h;¸n*Šl½*'éEa® ÅÁ?þøc÷ÎKgÍ^>gŽÖaÚÆ³‚‚Ï~ÞSX¸õ÷ßýüü` ŠJ¥Bº¬œˆ¯¹ã¬D"ihhX¿á§Ë—/o=²aЈ°NÿRÇÝ÷?›ùÕ|8÷£¹, Ί¡; »Ô” ™Ã`ð•H$©©©K?ýÔÕÖvÛW_wóÊ5=b‰dÓ[Y¸hѼyóh4aF³÷”{ JOPrùùç2àüöV½­pçâ̵kó׬þhîÜ êééuµó”´]UUÕ' æ³MY¿\§ñ·vuxÕüe}_S^·wÏ>.—K£Ñ (éSB)‰vïÚu`ÿþ½k~˜2rd'~f£¤¼|â’Å&ó·-[¬­­ ¶½£œ¨ù%D¼ô; aééôéÓcGøàø -{½¦Œ™zî|Ü­[Sßy÷Ù³gB¡P"‘ ¢Dg}W‹ì•ŸŸÿλS<û¹¼¸SË^o×èà…žý\¦¼3%??þ¼¸);QàZo$‰P(|öìÙ´wß»u+õÜy-{½¬ÌÌ?1" pìèѧOŸ‹Å°¢Ø¥`•CÃ30|'Ôg(‹·lÞ|ñܹS›·ùø¨zŒ=¿<°ùÈ‘Ý{öÒét2™L£ÑðÎŽ·ü œ½àib±¸¨¨hÒä‰ó—ÏùäË;åB´¬ÿê·ÿˆ777×ÓÓƒ[Ðub†÷k@ދʼn‰‰ æÏÿ|Öì}ÔkÁß iiï~ñyÔ¤IŸñ¼A„Cr IDATõ(j|w¢îš5kT=†®Î^°ÇI"‘Ô×ׯ\¾<5!áÁ±ãÎvvªc‰D ëÛÏËÑéƒO—ØÙÙÙa?&\/ ©©ém¢½`r——7hРU›WÎY2£3.B‹ÿaà°sã…-:d(Ü+`CƒvøÃ{á-W®\ùìÓOnøùÃI“48Âv¬ÌÌfGMX»esRrrø AÈX𱦦¦·4Ÿ:Cc30{Añ. ?úðC¦®îÙ­Û˜ †ªÇ¨!¸Ÿ’öþô;wŽ=šN§Ã{-a/@‡ó0´¥b/±X\\\<í½©ãÞ‹üöçe~ZŽì>¾sÓ'NZ[[CSÂ<ìmz:pöB5üóçÎmøé§wïÑ–@: ¡ÐuT$›Ë=wþ<“ÉÄS1 ÎÃ4–ÀPS)b¯†††)“'›\ß G/ý©†ÈÌÍí7eòš5k¦¼óƒÁÀ9¬Ë ¥ðд¥H$ªªªš5{VÄø+ZÚEW¡`ã·[£/Ý;røˆ±±±žžZú-†ùFŸ†–4Dì% ¯\¾¼xÉ’Ìÿ.kÞb†ª…B¡ˆüøc ìýã‹Eà0ìéÐÀºs‹¹—H$Z¹|¹nc£–½ºNN 'OmÚ¸1&&ötÀ€¥hÞÙä> ±~Ë×Ï7é«e¯®ÆÊŸ–zø»ìÙ»Ýê Ña;Ø+&&fõªU÷Ó²W§CWW÷ê¾} ’Î×+WŠD"±X ïÔD»Ai^º¢†–7ÄõûÆŸ.}ñâÁ±ãZöê"x»º^ؾcåŠÉÉÉ"‘>4‰Õþ؇ïŠî4¿sçλw–­U÷í45kÿæâ¥‹wïÞE÷É"#¾‘ñžCØ.Ÿœœ¼rÅŠ Ûwh× è"èêêžûý÷âüüM7âM‰Šæ•óT=ÀN†¦¾ *¸GGG_»r%úàŸ ==UP“֯ߵ?®X¶ŒÇã¡ÅЮÖíQèL¶È!Ç[½fÕo2dtÃUhaÈ6ØüçúïW}í ¡hÞièìo<‡ÿ <oŲe\Ö¯_7\E¯CO/æÏCW/_ŽŽŽÆ×XéX9DÍ¡Q]ˆÈg Û@ÑWQQ±hÁ‚Cë~ÒøÍPÔRÅ'' 3ÿh >€uµµh>tÏì»Ù±s‡…£É‚esºã´ààl—•ž“–’„–‹E›w¼v& ßÖðÁÆ , Ùß}òI÷\BoJõqqýìûïÇŽK§Óñ6U±s Q˜ò܉D"Ù¸aØðAÃCCU=ºÞ‚Ý߯ºyóæƒàï ÚïMP¿5ŸÏ?{öÌ¢¯ævÛø;±X nßbòvŸ©Z,újî¹sgkjjàx2™ 7PoD›<à÷? ‹Àà—÷¯]Ëa³»gðZv~÷ÝÃRRR`7’’ 9Zj4‡ÀèCn#‰Ž>¼tÆL•ªêѽ $õ‰ªÇðf3x°B*½wïJÂ`àk[¼£Ð’QB¡ðì¹3_¬Y؃ hx@6M,HËμõ\$#ž$¯|¼Ò·_dÔês·²=¢ÆÏhÏ¢VdÇ…óGú€¸}¿¿ï>ìó«;ôÕ݃ÏW/|¸pú{ª‚c«g“<¢6=äÞà ¢|?Ø’Õ’³Ô—>Ý»e…¯‡¯AÀÇñ‚7{¯jA"‘¾ÿdÁá?ÿ„ÒyNå Bï EEEuõõÞþžÝ<~ ¼"›wf7ÏD…;²^=Eœó­éÔ¿Ò2ÿŸ‚ä›6ÍjÙŽO¦…Îÿüàãô„»ëCÈܺÌçók¯æWíøêî‚·¿gCCCaa!2"ÞÍÑâ[ð.*yó6ÙGúnþ'j6ïÒ–+Õg7ð%M˜ýãÉ{¥-ù—8ïß¡÷—pïÀ ’‡ûçÿæuçèÛ‰ïM‹ÏËËCu`”CkF¦9†”º÷ëä‰KÞŸÁbªÛ^®ŠúñdÓ h€ÉÙÙiñÏ…ÄIyüù “?Ùw) ¸Íøx´1¹ýïU Ì?¾¬´433‰÷¶=‡pó2ô·ØØØÁ#ÂTø†7s& ¹꤯þÌòÛk—ÿˆú6-æó¾vÌ7üx²ÕÀI§KlýlwÌ+µÄ×}u÷D"…%„¿Ö¦3q‰Ò茌ŒÒ’’™QQÝ>ü¶Ñ–+QØ._‹Ùñ«Ö̳ò‹:”Á#¼Y&æß ­Æ€Iò¢n¾€ö€ÅÔ_òþŒS'O»ú`Wp§/Ó¬BhÐfQpúäQJʨðªš2 ü¾*±#Â]^ €YÿþØÿ›Ã€¯9Y—yñèçShí}¯š€D"  yðà |m/pŽ,ˆnJ¥)’GLÚíc–5À˜04ôw1Äþ*Ï~C6ÁçþœÉméír~ÞùM[æLX4g¢%ó7¬ù|õ«…Ä“,ûÿý)à׈¿KÚýÕÝŒ†¦@Õ'È^ååå¥eeÁ>¾ª] `èÜì™@×ÈÐðŠÄ–WÜ›ºü$`Û‰¸õc}Yoò^µÂ˜ðAÉ øÆÍ­yÞ€ƒ‘Çã™[šª`èX ^tÿùn7€9¡àzÂçþø_ÓÎÌø{upKÓ^‚¬k‘œÑ‹Wî½v1º0?úܾÃl=y5§^ùLîÐÙ›gö^M©kçWw3,¬ÌªyÕP¼ã­Û­¾çÀ’Æ„‡«`è¯Ãk]‰Ì´ýà«Ãw—EÞùôh)þ7]º>¾ö, L@Öi[u.úûú–”••——ŒØÎ[úÔB`„z©T7"4T=×Ý0°´˜1†æ_, J.ÀeêËyÃ÷ªF‡‡?JKC«r $ ´ûÐä?jùåñx&æÆª;t{'K¨È¹v¶V&øVÝ¥×ÿŽÀmÔ`ÛÞ(/üÅã³LB¾Þ–"ʺù8+ãá·€V¦±˜aQ³WcóÛ÷ÕÝ scÄ{Í8¸ Aç‹D¢Ô´´QÕ‘ÀÚéJ?Z½Ö €ì_¹…QÓÈ€4€ce pµQÓ»ìuuuG„†Þ¿F¼™^K`j¤û‡ÉåòÊÊJssU­eØ-z~m·'À|/úzÁlLb×¥o=˜ºkFË«´õ^5“Á R(|>ŸûZìã@†–oËå5üUe`m¡žŸ“°æ²ZXõù©¢ÖZ?ÒŒdF[M°\o7@Ü…,AW õ­aniÊçñQé Ù¨ÅØ‡N7o`Äçó©ŠzîüÐnW2]ºi=`ëá{üÿÑrUôõ‚‰Î–ݘç×b· 6Õ¶•••(6¢^*-© Õ'™LÆçñ,MÔ/öAÐ œl-¡$7±´µãü¿Ä.}|÷>roMv·þ^5„‰§¢¢‚°’Mkú/à H¥Q B•Œ¼-PàãÅi)«ª+®|ûõ°vNMJj‰ jAƒF£Á¨‡—žÚÈ¡ñ‰ÌÊÊJc#u­´Û•X®Kñws0•a„ÞBã8ÙZÒ»v¬oK>Ÿ*ùx¸§£ÇîHÈÇ Y››©p`ÃË‚çcõMw6¬ÌÍ***{µÝÁÔ=¢:C6»²\éF)•C€´§¼fµêž^Ð(ØkÂÎC r@MëO ²¼šÍ6D´„lÚìã@V^^n­®…7×7ÿ¢îµ§ª!¬ÍÌùÕÕ-ÞÖÓ“°O`@©:…J­¨gU¦-0ŒŒžö&ªHç ®¡J¥"k£…^Ä­i`Àª|Y©‚q· –Q@qu½r.¤"*M¾òNløµ«NÏŒꭖͤ òe¥¡!aò²í ¬©y))¹\N¥RëT0îN†¢¢XÕCx Ô ¨4R!mLE÷8h!M×qP(L}ý²Jõ‹}¯ƒ_È(èy#o•ÕÕ, /.½¶÷ ?ÁÜÔüijV·Œô`9èý`²¯ÜVêŒ437À­+OðÎþ᪋ð/¥“u±BÃlºl´o…ôG™æ¦ÿ«d´Óv¸¡Y,VEµúåÐo ]SkUá-𲪊ÁdBI,¨mâP/ Ï466”ö@3·÷äWµUtêA¨àñØl6·Úã6pÁlÏëcºxŒÏÔ逿Þÿá>ñ_Œ°=‹5«nÄŹ¹º@ "ó¡LZÕ£{[hA ‡AÛºyxýç’ªÇõæ0xn×lÀÊÃ矼WÙ3k‰U|~Ò“'^^^pØ×ú ®B þ “É ÅÃÃJ¦^>w½[GßN¹~“~'ú×y3‚AZü­‚öÌ\Ê‹®žÌn“–~{.3áà÷CU¸ÎaÛ¸|î:•Lõðð P(ÐÈ: }v„Îèåå•ôäIŸßâùê 1/ç÷Õ“GmÀíâ®zhgðÑ.¹º»+oʬêqu4„À²@áRWW744ô^rrzNŽªG÷ÆpòuÚ¶ù€}kæ™ú¹OX±?·§Ñغ={úèëë£\Š"ÎGÊQ|¤R©ÃÂ7~»M.WÏEÉÎCÇ®9z¸¤)ëô§^í8Ÿ93&«¤éâö-3ƒÝÕ·#@.—oüv[Xè@*•Šl콌ðܸȎºººúúú?îÞ­’ éÄ¥÷æ¥:þ³SÙDœþïèxKõÌ“_ƒôœœØää°°0”~áy˜ªG× Ð„kÀÝz | #$4tíî]ª`GÐgÄç²û—ÿ^6{ˆ¸øÏ£ZõŒÞ­€_[»ÿÌé!C‡R©T<ê!H8¾‚”| •J¥R©4Íßß__µnù/ª¸”^ŠuËÑ×cõíÛ—F£AC BBõÃíC$®E¨Têà!Cœ=Óƒ&¤e ¥ûâ³}‚ÇoûåïŠôSÕWj´÷ìÊ`0AqR3ò°O`x샆«ÅÐÐÐk÷ïgææªz˜™ã8ý£¯c.d5eîìÛ£ÚŸÖïÛëééijj • |x Š|ö ¾‹J¥Òétø8~ÜøS‡Î'Æ¥tÿµôB$Æ¥œ:t~ü¸ñè÷‡æ P(øL˜òqCO„ï255õôô\¿oo÷_KÇÀrÚ”™õøÐ¦OÇö3QÇõÀÛ…ÌÜÜ«±÷BCCñª´K*¤g¡ÇÀ܆D"QšÅ»‘‘Qä¨QQ‹J¥RU³·à^RÒsçÆŽM€,‚Z|*Í#gƒog0t:Ãá 6bÑ{ËjkzäZ>=uµõ §~9|؇C§Ó LÂ(l{5à »Ã·7îÀ¹s÷’’ºùrz-¤RéøE #G222B„ÀëUªæÛ¢Ç_ûPõ‰N§Óéô   º¾þ·¿oSõ{Bá{˾5z4r$Þ¡îÍÆR~/*Ðã„N§3™L&“àâè2!tzC½,M¤¦4ÆõŸêêìv:އ¿Ö&ÀfV¼ŒêÀFFF£ÇŒ™¶ìKPýVgÖD|ûû6=}ý   èDx©U± 9† ÐÙ {éééÑh´ÈÑ£ÿ8}úNB‚ª‡©ùøä‡5Æff¾¾¾ôfÀ$ •žÚx:ž^3 FDÄ0}=ƒYc>ÑæÓ]©TêÊêgÈdGD c0è—W6âk%Áˆ>>>&ff ÖþÐý—ÖÛp'!aÿéÓ#GB5 :%*æk L]€¦ŽñêÊÀ˜L¦……Å”wÞ·paâ“'ª¬&ã³õ?Ŧ¦ŽŠb00ÂØ‡‡¿6¤A…@ êééÁT@__ŸÉdŽ3–W^ã@ó EÝ|uš ‘P4!ôý°±cÇÁ_þàЈÐ¯}xd/¤Bà¿Äø¨¨{-ݰ¾›¯®W!þñãñ‹Nš2ÅÒÒæÐø,&jÆÑŒ$LwÍš5ªCç_ `[«À¥˜L&SŸùÖÍQC‡špÔtáƒQóæÞŒæL‹Åb±˜L&쀂.„f[ÓïøS|ŸR€³³ ¿†÷×þ“c&`0Õq§Ä‡ªŠêÉá3I:‘#" õõõ¡!‡1™L|¬s'p_|w•ÆÆF‰dgoÿ÷éÓR©l`@@7\ZoCÆóç}'OÕ§OhG¤EP/"T“š‘„iBw`CõÅ;ƒÁ€¾¾¾!aažcÇÜNˆWõ`5 ëvï¾;söl.—‹~pX»€2§®6Üï&E¥`hG}}}HŠúúúQã'±¸#ü'ôä].ÔEÅ#ü'êEŸ^ø¨¯¯OH¿ðîµì ˆ20øÏÿ+¸\î»Ó¦}»uKÈ{Óºó2{žäd{7eòd___ôƒÃ4VAð{!T=ØÎ†d`$‰°N%Z߆ŠËåšš˜üôûïý}}í­zò jƒ¦¦¦O×ÿtèÂ…çÌ155500 ¤_zzz„fú¶# PZi”°L3|jme­)~^õ›©¥‰—¯{W^¢&ãÌÑ‹MXÜÏ?`àÀ(ñb±XP¹CâA±•Ûùáø>¥ø+ ÅÏÏïNlì‹ÒÒQj@ ¸?rî܈ˆÿ¾}¡‘5ñi0˜~iÌÌB`O ‘HøFБ ÙlC÷nuspðprRÑH5©tÞªU×>xgêTSSSû`øƒ†:éߨs¿I™Êø MMM&&&&Æ&‡÷ý›48r Þê–ðZ(£¶¦nÑ{_ž:x!rd¤··7d/ø {Á&˜@ãk©´ñ±“Á >èäì|éêÕ»‰‰"†‘[¹¹B‹vâÜëS¿øbä¨Q~þþ¸)QfÒHˆhÆÐ$ƒÑ /RAŸ4†›ššØl¶…¥å¯{÷æ¾(6`…Ü#‰Q9ÒsrÏšY^W7aâD‡£¯¯ohhˆ õqà‹8´Çmu¡3Ñ1”ÈÊ:::L&ÓÍÕ-ãIÖ–u;}¼l´Yu»óprøLÝ&ʸ±ã,-- š뇨Œ¦¾Ú/Û ¶Ã 𝱱‘L&;9;?LJÚqäÈ `S.· /Xs!‹­ýaãÁƒ&NtqqA"Íe";¢*ˆÆ¤_@“ ´$ØAK;ß4551™L'gç{ñ·üùç €@ “ºP§Ê°ùÏ?g|µÒÛÇghDzl6…?4†î>y#·ÁIÝC†/"'>mll˜ æ®ßöÝyØ·¿¯‡Ý5­ Èþbñôe· I F=CCCh>”:ãìõFÙ3.%qöBÕÑÑillÔÑÑqtrˆD?lÛF§PøûwíÅked œ9£¼¶v|T”••òD4[ E$!‡ÖöF`¸`Ç_ÄÿJ"‘(н½¢©ií¶m]rPŸ>­-¡ŽÂÒÒIŸ.¹;>*ÊÕÍ ÷Û ðE¤Þ苉PZ.›Ívw÷(,(þõ‡­Õ¼þáp#M-DBѺ忬øx•±‘Ù¨ÈQÖÖÖxÉÚ–› íà” >sÙþ¢¡BpIÄa𩱉‰½½ý±óçÿ½ukHP!‹ÕU?A&“ýöçŸ~ûM߀€°ŒŒ aM}Aö‚"Í~iFñBÓ us}Àû£ð”±±±££ãéÿÛzø««½½jǯÎ…«·oŸýõWSÓÈQ£¸\. ¥':Žnûï€Û(‡<Äaøþ,èžYØöfaaáìäüð^Âæµ;är¹§Ÿ;Fí¢_£¡¾®aï¯?™úEmeý¨ÈÑnnnh® ŸíGæCì…:;Ör]çÕ­œ¡XDnH§Ó]\]ó WoÝZ/ ðõ¥jõGëøïöíóæ¦dgŠrvvÆû5ÂæCXÃG+HiRñBÓ ´NZÈ âF£¹¸ºèR(;þ÷öíP?®QOÜyµkqäÂ…Q\\]9z´Wóœ?tBøC'P¿¿¥Ûò0øàÎað€L&ÓétGG33ó;7bY½•Ï«ñðqcê÷¨µ;/+[³cñôe/ «ÂBÃúõ €õ%|ž…}Û³_—†àIÊÓ#»O\8þŸ‹‹³Ÿ¯?—ËÅ×å‚\…нp¥ 8饼sÊ[š¶B7”Édb±z"ô;@ÐÐÐÐÐÐàŸòóóã<0b±V/\8qØpÍ »@v~Þ»w_Œ‰ñ÷÷ïÛ¯´ºÓ ¹!¼{ÝÀ‡»¡FþŒK` yœÃ$‰X,†Ñ B¡P"‘ÔÔÔ$(ÑÚåø²‡šÍ^@ã 4>€L&S(H"çAÆ>$áá9OŸ>Í}ö¬¦¦fæø¨O¦NõrqQõu Ãì<~,îñV/ IDATÑ#'''O//+++|=VûЯèN/´Ôa±2%^NÄ %(ÕÕÕýõWEEETT‡Ã‘H$ ;;»¤´¸¸¨Ø/Ègü´Ñ#Ƶ´6ïÜ¡vÊJʯ]Œ¾târjÂk++Kk777¸t!ŸÏ¿xñ¢‰‰Éûï¿ollŒŠ‡hm'|eÜv ³Ù ‚ÀaÐvb±X*•ÂwCä‰Ðš‰¤¤¤$ãéÓÜÜÜÿEïM×lAùôÙ³='O½t‘Íf;¹¸xyyAc6g@B„ "áüeW5„æPrT‹‡.ãaúH$xNUUUVfæógϬÍÍç¿ûîø!Cí¬¬T}Y…B÷èÑÙ×?Ïf³œœÜÝÝÑ ¼0÷BB¼è„ï–‚"`§Lœ´TN„+5#ED="3‘H·cÇŽþýû3F¡P@[CΓJ¥B¡°   ¸¤¨ðE¡¥­Å€ÁA¡Cƒ ⚨õZÏÕ•¼‡wc£>¸PRXfggkmecoofìÑ>jººº—/_~ðàÁ¢E‹BCCñÍPºŒ2f•Øé”@£‚0ª1B7„Þ* ³²²òsskjj>˜8qòð!þþs÷Ë‹’’‹11ûNŸ*~ùÒÙÅÅÝÃÃØØJCä†Ê™h»/|¥¨®‘ê†^A` uçA†ÊM8‡¡×QàËÍÍ}QPðâÅ “wFŒœ8|X€wœ$ŠD×bcO^½råî]}}}K++7wwccc|BÜ[ðä3¨Ûà3]ê6È”KÅdÍ€–ª­­Ý´iÓƒ–/_îì쌌ÿŠ€þ JJJJËJyüê’âR® gÀ ÀC‚<ú¸ºy»ª|…*±X’ž“ù$çáíÄ¸Û Õ•ÉHÍzYZaljÌ1âZYY™šš"Å€ï~o!€ä„$9|”Ëå¿ýö[rrò¶mÛú÷ïßEXš¡«© ‡r)Ò>7K‹b% l[*•* ———WV\\V^îçá1"$dpPP_?:M­ÆÌÌͽ—œt=.înR‰D²²¶¶µ³³±±KøÃGänø&·P×(̤qêê ìzA å}¡ó@ÿ´„zÛð2ê]Äé}…BQUUU\\\]YùòåK©Tҷ侮°>®n~îî¶Š×4jjjzþâÅã쬤ô§×îÇ>}öÌÜÌŒkllnaammÍd2a­ÍúBÇÀõãÒ›×…B}†„E†ºßgðT šR,¯_¿þðáÃ7n6l(H|àöE=ðE9´“\eeeuuu5¯Z$ÖÕ××ðø:::ÖæÖöVöN6\SÇØÈˆË††F†d ™J¥P¨*•B¥QÉd²\.—IeR©L*‘J¥2…\QëáW×ðªøð±º‚W[T\PRVRÞ¨P°9F,–žƒËár¹\ccc¸2"-D](ñBDú¸èèè•+WΘ1ã»ï¾ƒFtS m‡ôüýQ6†fÈðZrF܂РAqqñ˲²êªª—åå^..#BC½½}\ÝœíìT>Ä«©IÍÊz’“}%66.%…J¥š™™›šZ[[C7„ ˆHø/ÿâöE7< ˆæÝªÜ6zVjP¨š„jø„ t¼ŽÏAâÐÚÚÚÒÒÒÊòòºÚÚ²òr¦žž·«k€—w?/O;K+{++KSÓ®‹©´ ¤8¿¸$¯¨(þIZJFFv~>‹É4ærYl¶……lÊÐÑÑ¡R©ð’Œq¸~‡@ŒE¨;é6£ÛJOmY333sÖ¬Yfff»víâü_{××äµþOÈ„@¶Lq C†¸œH[÷ª­»Zkë¨Z{»§ZíºöÚÖÛ:êmµZ½­«jëÖ:Á-"Ã,‘ üþxnžßáM@P ƒ÷ûñ“Ïkx“œ7ß<Ï÷{žsÞs<<€ðéè94–@Sô7L¸555UUUpß’N¯ÕhµZ­R«ÕjøAéõz½N¯ÕêŒÄÈ!.kJ5<+ …"¡@ ðù<._$Á‚„‰D,£!àÖšÌwæÅCZÌèà%eeeóæÍËÏÏß´iSdd¤GLa`Tƒi=Ð}hxf <¤ÂÂÂ*¹¼´¬¬J¡èÒ®kçÈøè˜öAAíB…Í6)ßh4<|x/??§ ÿRFæùôk×oÞTÔÔøùúJ¤Ro__©TŠûV§8–Œ•CÚP"h×£~RÄÚah-´F@ä dÌÀ¬ƒF|„‚¨C!Ôétð†r¹¼¤¤¤´´´ºªªZ¡WVÖÔÔ´ñöö÷ïÔ¶­¯§§·‡‡—ÌÝS&ó”ɼÜÝ|>üƒ @ 0Ðq€GV[]SS"//)//•ËKåò¢ÒÒü¢¢›÷ïçV(îR©T"uq»I$^^^>>>¸™$ýs§í]¯CH'Gz]([‹£Ñ¸bÅŠ¥K—~öÙg/¿ü2­:˜ÔЪCN„L”hDèR$þ$€_C5švÆŠ4‘^¯§›gÏž‰Dqqq¤ö✌µ”p\1Ãá W ‰£»_˜ø £q¹\¼“žA³B áºuëÞÿý>úèõ×_·îÌe ãˆ6XA颫út7ßúvjµº¸¸¸¸¸¸ª²²FQ]QYQ^Q!uu ôóëØÆ××ÓcÐKæîâìü¿äó|¾H(äp8Sb$B –ÈËKåòâ²²¢ÒÒ99÷ »¸¸È$±««‹««——————L&ÃÏ0Ž€_4Fú·PÌ ÎOÏ»Áú1-ÖÕÚÐzŒ˜Õ  1¡ŒÑ!D×é*"ÊžéN :>ò \.¯ªªªªªR*•`µPQ«u¦†ƒ^o$„grj\''.'44žI^\\\pU'HD‹6ïh÷ठÂ…ŠÖ3_óL%ÛZ=//oÚ´iJ¥ò—_~i×®Ñøòáû7 xýHWW!ð> axSöÌŒÔ6ª„°ãÇ ‚ÄÄDb¶®#~\juGzY,z~ Åâ!üW@-ÕÊx„÷ÁwÆ5œîÝ»7eÊ¡P¸qãÆ   «‘g‚ùø4ÍŽSÒŠE ü‚ûp´ÿ #(ƒ>4¬Å£Ñht¦·‚wÖétzXÕëu:‡'.—‡Dp¹<zF|/àóø|gggXÕI&“ñ©es‘ˆ¬ÑÄ¡ ÁÑe FÚ>ÒÒÅ1­'i;‘h´ê­°0ž1ÝÀÏÂ`0À£V« … Z"‘ˆŽi6Ý c=š‚e(™LFç>Fâ#–ö!µÍ;ý“¥å„vd6(]tØÀ±Ð„bF‹Cºœ¨Ut‰Íؽ-[¶,X°à7Þx÷ÝwQà[…½^Tòx<½^/ u¦ÉUÑ™†Óè!1ZÀPÏŒf ¦.¾‹‹ —Ë•ÉdNµW³EЬ¡€Ñô999ñ©ÍàþÖ*>µ€!¤KZ „víÚžCk]€¢=`]æXŠü™âìX.µ¬-1š«cxÐÏà&AÚ¼ãçÚˆt•••Í™3çÚµk[¶léÒ¥‹ù ($t‡ >ÊÝÁ2˜ò·šéMëj2ÄB"V¤=°Ý»wÆÑ£GK+ë›Á³óL«¯Ò0¤•ÏçÃiŒ.êýžø¡3ÝÕ«W'OžñÃ?xxØÄ pðMbÁ–îFc4Ñ%_:égÌ5Œá?h‰©LkX=aXW7š®`˜¡^ð$ÎzgŒSÒ]m†ƒ´èEZ9ZuŒvÅŒF£““üŽœœ ŸÏG%ÃÛ´žatÁp ¦<ÌtðЃ(tâ£]<Ý6üÉÒÆpî˜ã芎ü×eÛ!ZÐÂCà1’ MÌf̘1nܸŸþYXÇ„il0Ý!3`êQÉŒ¦ù¨x€»ÎŒÊ!]BDé‚w ƒpìêêªÑh¼¼¼Å#1õ3Hm£yd Dá1¼˜¢u yCX‹½xñâ‡~µnݺÁƒ71UP‘Ýh°F£Q Бˆié¤;Ó +‰CÝ á˜PêÕ0äPƒ—,tµ–î1£/ Ñr¢†ÄøÔ­ØÙB–iiS‘hu°V (cp@Ç–2 àwO—˜Ðž£¤ái(`ðhžf±aÄlkGF鉿{ó-T'˜yÔ¶ O‚-‰ššš·ß~{ïÞ½›6mJJJjÈKSbÚÙ• ¾v>Ÿ\Ð,ºâdBˆN§#Ôæ)¬ººÚÓÓ“ÑÊ£n¤³¤iâPÝn5*Ig؆|?B¡ð_ÿú׈#¦N:tèÐåË—»¸¸4œ‘f²Æ0@ Ç£ V†ÑPÒý6UBÔjµ„F)Õ«!‘ˆß¶¹ù@‚xÔ< $Z̸Ôô>þ1Þ¤ÉAË1Ì ¦±1(FÚvèò/-Zæ%: 1ÀIíâ3±‰ôW Ʊ®0„(#„ðjOå0?v¢:p´nÛ C›+`õ:è‰)åa.£Wð¿Xž2Ô®T`àfõCøhFí‚ÑÌe„ '³Z<>r©q2ú˜cVt"60:îÓO?]µjÕêÕ«ÇŽû„ïÆ  ¡ ö±èþ–Ñ4WÞ"k³8pvvæñxnnn4‰pÀð ø_®i†=¡úd„*62´ª©ø’H$6lعsçÈ‘#gÍšµpáBH¾V‡E¾<-#T•ØüÑb<’Ú&’4, Ñ|˜Ç#Ý-£åŠCYOÆùæ2É¢ØÄÔöQOj—ÑÄÑÑBëã%õ˜÷ºšádšFAg4 b !†°Ñ©ÿDjG£mLvvö”)S¼¼¼ÒÒÒÚ´iÊeãéK¦}7T‰iB1ë%ÓÉŽPiŽ–:€³³³“““X,ÆO$ÔDÆ7Ï4®i™ZdÊü%MŽ1cÆ$&&¾ôÒKñññ›7o·¥m‘aHAóa®FŒN3Æ#1Í× ã‰~ŒHÄc†ž1Ê$ðHLC׿/±ñ0´M°Ö8X !RÛ¸é©yÕ?„J‚$ø<¾?#!ÒŸKj{@óà!”¤‘ÚæCM ö Z£Ñ¸jÕªE‹}úé§³gÏnÖÏb|èTHmIcd·ºò>#‰8޳³3±TÜc8R›R›ñcÊ××wß¾}k×®íÓ§ÏÂ… çÏŸok?sçJ?rCíi5Œn4ã˜a"ñ=IÂÔ¾!ŽJ|žÑofœOšß‘86X{L0Bˆ~¤%PÕ B-ÿanÞiI«ëIíYìô3ëQÄžC¥  `úôér¹<%%¥cÇŽ-üéæß’yRÃŒi‘5xR$ @`ñ;§õ‰ñ¤Õ9š9sfrrò /¼ðÇlذ!00Ðºí© õˆSÆ:ª¾æfógÌ?Ñ< icÔHHm_bÑ °x<°Ö`üz†æ˜rѦa1r,šwBM©'õšw‹ï`ËØ¶mÛüùóçÏŸÿÁpmcçz¾Æz’ŸÏ7u &Ù8):t8yòä?ÿùÏ®]»®X±bâĉÖnÑ#P—­$fQÉCb‰Ä†G¢Å0$µ3ö†¶VÀšæ¿T‹æÝâ±Ågê7ïÄεŠ¹\þꫯ^ºt鯿þêÖ­›µ›Ó Ôó…Ã,ûe„Ëå~ðÁC† ™²®cûåÝ^`«*8<°¼@ÏMªôm"xr= §0ÙuÌ9r$**ÊÛÛûÊ•+ö¢^õƒÇãÁÝv¸¸¸K—.ùùùEEE.^¼Ø¥K—âââôôtGR/â@HJJºvíZEEEllìùóç­Ý­¬€±°&ôzý§Ÿ~:dÈO>ùdË–-2kïaÝäpŒ" ©TºiÓ¦Ï?ÿ|ذaŸ|ò‰ƒ] û+`,¬†[·nõîÝûĉW®\?~¼µ›Ó,p°â¹çžKKK;{ölbbâ7¬Ý­¬€±°Ö¬YÓ«W¯)S¦8pÀßßßÚÍi.8ª€BÚ´i³ÿþéÓ§'&&®\¹ÒÚÍaÑÁNâ`ÑÒxðàÁôéÓKJJNŸ>fíæ4/¯„ÈÀœ9sžzê©)S¦ìÞ½{Æ ìEXØ Ø‹ÅöíÛcbbâããÏž=ëðêEº† =sæLß¾}»té²mÛ6k7‡E+ÛcÑB¨¨¨˜?~JJʾ}ûzôèaíæ´Zƒ€B¸\îÇRÍŠ‚‚‚€€‰DB1 NNN:.,,ìÒ¥KÖnZK£  `Ú´i•••¿üòKhh¨µ›Ã¡Àz"MŒü±gÏžãÇ?|øpëT/Bˆ¿¿·nÝ*+++++ Eee%—Ë}çw¬Ý.+ÀßßÿСCS§NMHHX³fµ›Ã¡ÀöÀX4>|8cÆŒüüüÍ›7GDDX»9VÆæÍ›gÏž­P(à¿"‘¨¬¬¬–R7nܘ>þûï¿—J¥Ön ;ÛcñD8yòdTT”P(¼zõ*«^ Ì›7O(B¸\nRR’µ›c+èÑ£ÇÕ«W¥Rittô±cǬÝv VÀlÆÆÀÚý4Í;ï¼3nܸ5kÖ¬Y³F,[»EÖƒ©˜˜˜ÀÀ@.—;uêT‡c›ÇçóÝ$™L&sww÷ðpww÷ôôôòò ‰Dæ<â3Ç£]Àh4~÷ÝwK–,yýõ×?ÿüs¥Réìì|áÂ…ÈÈÈú_Åð4q„¢ŒPÌj4š¼¼¼œœœâââòòòÒÒRyYYyyyeEEee¥V«ÕêtjµZ«Õj4£ÑÈãñþGŸ/àóEÎÎ2™ÌÝÃCæ±èéááâææFDqrrbG3K…>«€°ÆÁ<ÙÁR­ ð¤ÑhT*•ééé7nÜÈÍÉÉËË»Ÿ›«ÑhB‚‚ÚxH¥Þîî^2™§Læ)“y»{ø|€/ä àÀY(Òéõj4­V£Õ¨5ZEMuIyy©\^\V^R!/‘ËKÊËoß¿_ð௯op```PPpHHçΣ¢¢Ú¶mËãñ0`¸\.­j\.—SŒ‹Õjµ;w¾uë\²@ 8zôhïÞ½[ö+o4G8P©TYYYééé7²³ï›xTªT!!žî2O©ÔÇÝÝS&ó”¹{{¸ ù€/àóá@$ê Vk¢R£Ñj«k”Ååe¥ryIyy‰¼¢¸¼¼¸¼ü^~^~a¡§‡GpPðÕ¾}û†óHì¼N•’’Ò¿FCáp8;v¼~ý:ŸÏ§Ï1W,¤¥ÿ«ÓérrrÒÓÓ322rîÞÍËͽŸ—WTTäߦM‡à`/ww/™Ì[æîå.ó”ɼÜÝ]]Ä>_Àç 8àóx*µšŠD­Z£úJåò¹¼¸¼¼¬¢ân~þ½Ü\@Ô¶m§N¢¢¢"""\\\8TG(BðIV̬€5˜ï0BИà¿ÕÕÕçÏŸ?î\fFFfffÎýÜÐv!]ÂÃãÂÃýüCÚz¹»7G õz}îƒÂ»yy÷òóïäå]¸~ýÚòÊʈ°°ˆÈȨ˜˜ÄÄݰ0'''H‚´%4¡·ß~{ÕªU555ðà©§žÚ·o_s´¿eÐ@•Jå¥K—RRR2ÓÓ³²³ïܽۡmÛØðð.ÂB€GŸæ™º¢×ëó‹ŠL<æ^Ì̼vãFqii8ðÁãñ0ñ¡žÕÅ£}aذa‡#„¸¸¸Ì;wÙ²e¤¶n!_x ¢¥×ë Cvvö™3gÒÓÒ2322³³eIt§N]#";}AmüpT²iQR^~/?ïn^þý‚ËYYW²²nÝ»Ù92"2²GÏž=zô‹ÅhAt›Ø-}- VÀê#ßÑ},ƒÁP^^ž’’’röì¹ÔÔôŒŒÎC“zöˆéѾ=Ã9¶0Ê+*Ò²³Ónd_ÌÈ G~Ý{ÚðZ‹5JåÙ+WN\8üÂ…KׯÇFG?3dÈ!C à]jÔ0{4"-VÀj¶ê4t:ä»k×®ý±{÷ÁJJJF$%8pPŸ¾B«ÚóÇCÞƒ;ÚuìXê•+½âãŸ4hôèÑ^^^6Ï=÷ÜáÇy<^TTÔðáÓ““ždBs ã‘<Þ¸qc率¼Ÿ›;l@Ò˜äCûõw‰¬ÝðF£¨¤dבÃ;=}éb×.]ž¼wïÞôôt''§¾}ûnß¾,HIIÉ®]»8zî\ÏØØÑIIcžzÚ–E«.¨5š§NîŸOzÌÌ^l°ö?Ð)®KÀ piiéo¿ýöÛ¶m%ÅÅSG9 )>6Ö16è«T(þ:qb×Ñ£{˜”4~âĤ¤¤ÜÜ܇öêÕËÅÅżFoí&ׇzxÔëõr¹|ûöíÿݺ5''xìÓ­[3…´0ªkjœ:µûØÑ‡÷NLœ0iÒÓO? ÕE€½ðh>6YSS“’’âããtüøñ­[¶=vlø€¤Ñé×Oâêjí&7 CêÕ«?öóîÝ^ÞÞÏ7nÜ8T2ºFBX30f•  Õjáñï¿ÿÞ¼iÓÑcdžôë÷ò³cŸJLt Ý2GyEÅæ½{~Ú±ãaYÙØçž{qúô   :~l<ý1椡t F“’’²iãÏHNHxùÙ±Cúõs Ý2GUµbÛŸýgûïwóóŸ{î¹i/¾Ø¾}{»à‘!]è<´Zmnnî†õë·ÿþ»·»ÇËcŸ<|„u‡µšƒáð™3?íÜñçßLJšü ýû÷çóùNNNðHVÆZ»€áD&½^ã[z½^£ÑüñÇ«¾ÿ^§VÏ?ÞÆiÙÙëvîØ°cÇ ÁƒçΛ‘ÃåréÁ›J4˜ûÀ‚ìß¿åwß••”¼:aÂÔQ£›i¨ "ûîõ;wþ°m[ÿþýç½öZtt´@ °MÒ1ôeee­üþûû÷¿øì³/y6&,̺Mm1€¡\½mO(|uÞ¼‘#G äzÕ8õÔÚµZ¯€aÌ€[×ét6ÕÕÕ[·nýaõj7·fÍÕZ·À(¯¨ønËæï6mêѳ眹s{öìÉçó!lèÒ¼Õ=`]<*•ÊíÛ·¯^µŠÏá|4sÖóƒ·Î8¯ªV¬þuë×?oìܹóœ¹sûöíkS<2ŠÀ^¯×jµçÎ[½råùsçæ¿ðÂüI“[ƒd`÷‘#Ÿþ°¦¬ªjÖœ9&L‹ÅÀ܈s=¬îB¬‚Ö(`cF§Ói4šÝ»w¶tiDûö¾2³ÏžÖn©õQ£TþøûoË7nŒˆŒüháÂN:aúÑkyÀºx„^×gK—úyz~8sæ >}[¾m¶µF³q×ί֯÷ \ôÉ'‘‘‘B¡ÐÉÉ ŠŠô„·–l•ºï¡Õj³³³?[º43#ãÍiÓ^~îy[žÙÛbøûܹÏþ³6óÎ?þxÔ¨Q¸³bE´:£+ìï `xùòåÅ VWV®Y¸¨O·nÖn¦mA§Ó}µnݲu?7þ7ßðððàñx dô|ß– ìx¡n µZ‘‘ñÉ¢E¹¹+?úø™>}Z¬=v£ÑøïM›>Y½jĈo½ýv›6mx&´0t¿‚Q«Õêtº²²²¯—ýÛ·½ýÒŒ·_z‰Çã5wKì §.^œ½ä±D²xÉ’¸¸8,*ÒótZ•†µ¢¢ íõ Ð¤Ñh4MAAÁü¹s§N™òÒði;w±êe÷þÌ™™{öjJJz'&nX¿^©TªT*X³ÄÃ`Zß¶¹QÅÅÅï¼õÖócÇŽéÛ7sï>V½ÌÁápLzë¯ýbn@ÿþ+¿ÿ¾¦¦ÆœGƒiáÇf=Ö‹ ªT*¥R¹aýúÞ‰‰š’’Œ={ߟ9“U/sôéÖ-mç®—†˜:eʼW_-((€?VÎÁ´žnIkéÑŽȆUVÿþûï7^}üàÁŸÌ›ïóq›—32¦ô¡o@ÀWË—ûúúB)ƒžÞÖ¬e(šG´í&55uÁüùƒ{þúëž­f𯓠ãÖ­W/⊜—óuPPP(lQ#iÿQTTôö›oåç¯ÿô³¸z—îe¨T(}ÿݶýû¿þö[˜¦Èçó‘ÁÖ3*Æ]¼x±µÛÐì`xv.¹\þùgŸ}»|ùÏŸ1wÒd{¼Ù*ðóö~yìs×23ÞúðÃö:à¦*¸þžÑhl¦Z~{Æ v¼¤ðöð˜>zLNîýï½ؾ}{üÐ×ä<š›F£V«:ôÂäÉOõèñÛ×ßøú6ÕÇ96„Áà>}£;†Î|ãEE]»våóùto¤•L²wücjµN§S©T9993^z©}¿ Ÿ}ÆöÇÃñs©“Þ~g؈á/\èììŒ×MoÚà1¯ªÕê‚‚‚—_zIæì¼ùŸËü||šðãZR¯^ðö[ñ _þóŸ...´—oBé1K,(•Ê¥K–ìÛ³wËWËôŒòOi…(-/ñÃï<(üiݺ¶mÛŠD"ì‡á+k·±áàF×+À°«Õê+W®Ì˜>ýÃY³æMšlíÚ7ä••#çÍuóôüfÅ ‰D[—Ñë¹5Uð0FûÁ¼gdd¼ôâ‹3Ç>÷Á¬YŽ¥Í Euõø7ߨ6V­YãááåD¼ùïÉyDóã^jµº²²ò T•–þñýJ™DÒT×Ò:ñÝæ_>_»v݆ °¸3¸zŽ•µØ\päIôX1 u*•ʃ¾0eÊŠ÷ÞgÕëÉ!“Hÿø“³‘Lš0¡¢¢B¥Rº`¶j{ÄP/àñÔ©S'Løxæ¬gÏvàøl¸ŠÅ{V­îàãûüsÏ•••!M2)€V/x[•JUTT4iÂg#9üãO¬z=9æOž²â½÷§Lštþüy¥R‰3;pA5k7°¹à°=0ÌzôL§‹/Ž3æøÆŸÙ{¼šF£Ñ·Oïâ²²+W®øøø`?¬IŠ˜þh³²²žyæ™=«VOJj aÑmì³—22Î;çïïeá'áÑ|øY­VWTTDDDÌ™8qåÇ YóфزwÏä·ß^¿~}rr²H$‚ý£é{$¬ÝÀ¦‡c 60P¬R©Îž=;a„›~éÛ½»µ耘÷éÒ3ׯÿ²y³T*…܇EŒÇÖ0 ^W®\9räÞÕk† ÐÔÁ‚|¼bÅoGüºu«=´ùw¬Ó“n ï¥T*+**&OœXZ\|ÿè±æ»ŠV‹3—/xõÕUkÖ$$$ˆD"¡P÷Š9êx˜–éû”ѳgddÌ3gϪլz5¾ûð£ð€ÀùóæUWWÓ5(½oì2x„ÒÓíÛ·_™1cóW_±êÕLXº`ÁÀnÝçÌž]QQ¡T*áFàWúoè9‡H_uuõ¼WçF·Í9r´Y¯¢Õ"1®ë–¯¾š;gNFFÞá‡¥àæ¾Ã¯åáhÓèqy!\J­VçççOž8ñû?óôÓÖn Ã‚ÃáŒNNþmß¾[÷îuïуódÛÛcºÄk*•ª¤¤dò¤I‹fÏ™6fL³] 2´_¿£§Ï\ÏÎîѳ'‡Ú“4†GF÷ ª ?þ¸{‡ß¼ûnë\—²eÐ1¸mûÀ 9o¿5tØ0±XL¯[ïxsëígĸÉ_­V+•ʯ–-Ú·ïóƒ[»u.—»éË/·mÝzêÔ)¥R©V«Áýá’w +ÆÐ¤¿ß~Û5,üåçŸo¾K`Aáp8?.Y²ç?öï߯R©ƒGz‘C ÃS§N9|xÞÄ‰Žº‘íà¹Aƒ†ôéûÕ²e°bNË/—Óbp(£ÃîR©T‡:Ÿšúõ»ïZ»u­2ÙOK–~ðþûr¹\­VÃT(¨`4¼ÅèFãæ¾={~X´¨¹/!Dìâ²é‹/—,^\TT„°<ÒûaD.—øþû?.Yâ!“µØU´f|ûÞ{çΞ=tèXÜ¡¦±VÒÆá8%Dó°¢Óì™3ÿæÛÁm­ÝÀÖ‚NíÚeÞ¾ý÷Ù³}úôÑcBHÃ÷ßcÌ[+**f¾üòúÏ>‹n5ÛAYmŠËÊvþõgrr2c©ßúyÄ*ȬsøÅçŸG½õÒK-y ­ !6öÕ÷ß5j”H$ÂIVHtœÚv\¦A­VïØ¾½[d焸8k·îI ®ªV[» ÃÒùó÷îÝ[XX,Ðî¯0äüû¾}û}|ØQZÍž}âĉ;wî X‰ª‡GóÞ³Z­.,,Ü»wïÒùó[¸ýOÝ9ââºGvÞ±};†á#é³;8ˆ€™‡F£Q(?oܸpÎk·Žê-‹¦q"F-K)#e)£GŠ}ñ›,KÁRUpý‡oÞ‰ˆ•tŸ™Zݸ×Zm¼½Ç²éçŸq¥á%xF÷ ê‡ë×­ûx¶½òØÔ¯m9H\]g·þ§ŸàÞØ†ÜÚl>­R©6ýüó¸ÁCÚx{·pûëE}Teü*éË=mé¶“–xQÝÙ;0"= ®?%%%*44Øß¿…[þ(ÔGÈ¿×çËVj/\?-žìéc¿_«#æ‰kÀð„20:¤ùÛü8˜>zÌßÇŽA!'ã8Ì=aŽ `hÛÑúÁ¸ñÅK—žéÝÛÚ­³WBHXˆ—˜pÝ# ! m¾uOŽ{!dÅÖ3ŸukÌkm Ãúõ;sú4FNCªOôÍCRSS‡Ø\÷‹'ãÂŽxÞ¯_ÊÙ³ûÐÂ[Ì€ôô‘gNŸÖ¯ŸUZ^?IOüâ{O¼•LyþµMô߸" !1±!n„H|:BˆVßBín$õésáâEœOO«—ôÃAÀˆ)÷a÷K«Õ^¾|9ØÏÏ×ËËÚM³‰ !ÄWL‘¶!„ĆRº¨ÿ\ùJ!Iom~-Ö£‘¯µ- îÓ÷â… Œbýå ôïX?ÌÊÊðùÚµkÉ–7âB—•²÷ƒEs¾8wô;ïüãË/f}¹é¶º¯µ! îÓ–ˆÅáL ’˜e@ÆÍËÀàÅ Ûäì›RÐwÆ¢%a„dÿë«c”„‰ÝÛ’&ñ „xxB:Ùè’Ä>žžmýý/_¾Œ¹Q§Ó9̘#¬…h4q¥µšš…BQSSóóÏ?«ŠŠÖ~²ÄÚ­³uåí"…O°¿!Å÷kD¾m=þW"$•ÆO>FÆg^ù$\ØÈ×Ú„1Ñ{öîõôôtssssssvv†¥~-.-Š<ªÕêêêj…BQ]]½cÇŽ›—/ÿöÍ·Viÿ#PÕ¿9éùÙ„F²³ !„$§\X/~äkm¾}z¿zuHHˆT*uuuuvv‰D qÕ(¸m¹ªªªªªª´´tÄðáê´kÖm¿e4˜‚ª;$£> ñŸ”m"W^p¿^¢.»]¤ öµXˉY‹ |¼§N*‹]]]]\\pµR{ŸLï=0zÙ¡6ž¶Øý"„¡¤C°?Ô½ýƒé°)¸zâ!13‡XV¯z_kƒðpw/..†îND¬ëdøcGII‰»…ž¨M n.nü÷ó³ ‰ß¼ý„q×ncæ¹5É„ÂoÀkm2YII ðRO ‘˜‚NÓjµÅÅÅ6»alƒ)pëÔýuBHê‰Õÿÿ¤;¾DèÑÁ†Õ‹ÒÆË«¤¤„1Ø1†Áì^À°Iþët:yYY›¬Ö÷nBÚy¹=òL»€¯§WQQ½Ž1 •EÐé¼HYii€¯½mµ¬¿³lÁFBȚݫ&EBã¹6-PB/¯‡B)˜6"Œú Žx•_ݽ ÛzÍyb<,+“H$F ¤*ñO@º››ÛÃÒÒ–nn“C_zõ!$9¾­N5¬‚€ÑV’Øý8†€èÐ2 ‰¤ Øþú1þ±ñI„¤­ýëší-,ÔX¨5š¥R,ªÌK6Œ,éææVðÐÎxt†×9óPG)ÎØ;`Âg„BÄ„Wß mF£±´¼ÜÍÍ^K¥éò”X,V©Õj¦ÛÛô¨º}á[BH|?;- çK¥RŒ>Ç(GÀ@Oddäþ'ì'IìëÓÂÙ¶à§‹ÖnÊ“âàéSBCœœËmðÃÃÃO]¼`_矰"Œr$¹ÿŒYïLóûVÚÿþ’}§ÈþŒÉ©‹}}|ÀˆÔóÛœœœB;vÝ‚ím2¨Ênü{ÑØ!ߥ¶{Õ‹v:3xÿÉSBC¹±VÒöáF¨¬aÃãñ¸\nï>}¾Þ°^¥¶?èô~ÚŠY„µ‹_ñé>úoÛÛEì×Þ^]ÈOÛ õBÒ¨¢ˆ-Ã5=°ÆÄ[ßþý¿øÏìôŽžGûI3Þ?º+˘¹²«]M:~.µD.‹‹C.@ŠR» û^|>_ p¹Ü¾ýû­øùg{ìLÛ5®fe]»y3>>^(¢€Ñ},†€‘Úôñx<øtíÚµ¸¼üø¹Të]JãàÖi¼13ëê†e¯ ïæÍµvkƒá‹ÿü§oÿþÀpaèUD»0mÛù&ˆD¢ÐÐPOÏ÷–/·v[j”Ê)ï¼óô AB¡N|àÜqv†9èîœÏãñP( n߱㼥K[øZZ3´Zíø7þ109Y,ƒ“ 5Ì"ø<2Îãñàgðô ASÞy§Fi‹»>:*Þ[¾ÜÃÓ344V^¦Ýä#‹ùö‡¸''xäšÀçó…B¡@ ‰D#Fúá·ÿžKK{äû°hüãË/|ýý£££!` ñù|ºÆkñ…ô8zF'‰„BáÐaÃv=røÌ™¾œV‹…ß}Ç ãããÁFti×ü%“#M=ŸÏŽŽöõ÷ÿÇ—_´ü…´NœKK[ûÛGŒ%‰À}X !¦Ìi×°û 1Ø `žžžO?ó̤·ß²¯{‰ìÇÏ¥þ~ðàÐaÜ]\\ xÖÔ]¸€ g"ƒ ¥Ré¡C_xïݪjEË^SkÄ¥ë×WoÛ:|äH‘Häìì û§#¨^KˆŒB0ûw 6lû¡CÇRS¬vU­jfÒÛo=õÌ3žžž`åaX—±;8‚€1"ì„ ½RRçÎÅb±X,¦;aX€zä4zè„ádì‡A'à™Áƒ•zýs ØéÄÛGáÇý§¾Ð3>>&&ÆÙÙÝòˆÞbúÉT`%±û?‰ÈÈÈœ>=·°°å/­•`謙ù¥%Ð{€táÔ6‡™‚HIÀèÚ…@ €ìéêê ›ººº>;vì‰Ë—§ð¾µë€(|ø0tð ˜.±qqqÎ`¤Q¾öï`A€JäqĨQ™9÷ž?ßñÖű:ÊärÿþýB:tè•àââþy¤3 ±Ä£ÅZˆP(¤qqqQ1Ñ]ÆŒ.´Ãµ¶mSÞyûï F?û, ½3j=ØÞá8†µ H|ð¹ ‘H&Lœ¸q×®ØÑ£ØZbâæ½{=Æ=?0))!1Ñ•¤?œþD×à‘žŒƒÝ/è ¸¸¸H¥Ò±Ï?üÂù€þýÙqÍ&DnaaqÏ'ôê5 )I,»¹¹!þ%D‹oBß“ÁJ"z÷éÓ¥kWÿþý²îÜiákt`ètºÞ}çøÅ‹¯¿þºT*żþ³¢#ÝFá.^¼ØÚmh2p8Æ{ŒÍ÷8NllìõÌÌ݇M6ŒçØÖŹ´´þS_ˆíÚµWB‚ÄtBŒa°¾3ðEoÏ›tp8œ¨¨¨û÷ïÿ²kפaÃAs^b«Àõ›7{MœÖÀ777 ÑÍÍÍÍÍ ó Íc]¦Œâääd¾œÑhôññ …Kÿ½b`||€¯oK_­ÃA­Ñ zyFfNÎègŸ•ÉdÀ ˆ0ó*¢µ[ÝpC>0ñ¡˜aúƒgÚµo=;{Í–-ƒz÷qˆíb­†M»wO|ëÍvíÚDK"‘¸™Ã`p+øêO<èM€\аà¶mïåæ~³î§§z%øxz6ße:rdä€$gç&¿^GÅ匌ÄIåJåÐáÃGL‚8Ž.äñÒÒW×ÂEb±¸cÇŽi™™Ÿ¯Z•ìç×´×èÀ¨T(FÏ›ûë_ 6¬sçÎh;d2ÖðÅb1=þ‘½g»ƒC ©íþ`?=Æ“˜ûœœœœ;††fݾ½ä»ï¼Ý=º„‡;Œ1i&—•Í[ºôã¯HìÛ·{¨Xtá‚ÎzPµ€)× ô ›ÂápœÛwè“—·hÅ·®ÎÎÝ:wv¤mÈ++ß\öÏ7þùe·ž=!åÑu'º “ •þh¹‚ˆÃWÑæƒ˜n] tvqùbå÷ÙwïõŽ‹³.¤^Æ ;w›5“/2ÄÇÇYCõà ŽÇ®‚Ø8MÀŒbºÙþËãñdîî¿ìÜñÓï¿w g= EhµÚ¯7¬»à55!Ï D—Úxã$f=\êñ>—¶ð˜=‘>|g.—ëçççíãóûŸû¾ÿesçÚ5ÝÕ;ôzýê_9÷Õ •ê™ÁƒCBBè²!£rˆC_8{­á<š»Fäï!s¢ •J;tìxñÚµOþ½‚ÇåöŒŽvŒ¥"š§.^:kæþ3§ûö‹‹Ãé6PÃÝBÿA߽ǩc#»† ÝÍ"f[…9™6 ÿëêêÚ©“R£YþãΧ]ëÞ¹3;¹a4÷?þôŒ—®Þº•”œ vèxaá§«ÑóK_7 æ‰Þòš“iYE: ºººvèØÑÀ!ÿ^¿îø¹sÝ"#½=<šü ±_:}zðÌWN]¹ÒoÀ€Ø.]GƸÞ„Î0ïÁ#c< (Íò(‚‚‚üþ8thùºŸ:µ q°„û$¸}ÿþ+üÅÖ†FDôëß:^´z¡€Ñ#—8íÐñÔ‹ba€Á1Cýz½^¯×ët:F£R©ÔjuuuµR©T(ÕÕÕøXSS£T*kjjjjj.^¸™™™Ü«×â¹óºDDXû:¬ N·eïÞOV­Tj4qݺuìØQ(‚DÁÌ4˜¢¸æ®ºÖ$% œAªÕjGµZ­R©€, x¬©©Q(ð'¥RyéâÅëׯ'v‰[Ñ«s' ÎãÙå~’M…+™™‹W~$%%""¢[÷îX¥§×j€G¸cVÀlâ ‡0bIà xT*•R©ÄÈA=ƒ?A\¥]½š••öék úvïníKii¨5šÕ¿þúùÚµbWqdTT‡pQ \Á¸_’^w£I î Ójµ aÀ¦?0`N¨®®N¿v-3#³cpЧ¯-xºwï'oŒ}A«Õ®Û±céêUN<^dTThh(ÜÝT¢€aîÃ¥7hŸD½¨a†À ZÆêÚP*•À¬Z­¾}ûvFzzµ¢úƒ™3çLœØ gZ¼pᣯ¸š‹]+CT,0dî:wxõ"Ž-`Ä,÷ét:Hmþ ÙAÁ1¦E8¸~ýzvf¦›‹Ëœ ¦ÓêQç¯][³mÛoöûµiÓ9::00ÖÂ Õ rCÍÝ çª5áp±9Ð¥ sÇä³²²²22ø\î¬qã^zv¬ŸOS5Ìf‘–½fëÖ-ûözyyuŽŽÆUëÒvl lâÕ´<¢†éõzÐ0•J¥Ñh èÐGB¢†Á9yyyׯ]+|ðàùAƒgß#:úÉÛcã(.+Û¸kçê­[«”ʰððÎ;q¸((„ЇÓmpåC\Ö!ǽh8¸€*÷aC§Ó¿ÃrÄ &>œ Óérrrnݸy÷ÞÝ={Ι0aø€$›ÉC)“Ë×íØ¾zëÖ …¢]ûöaáá^^^¸†&;Úîa±Ôë gmÔšG0àzÕ´YH‚jµZ«ÕæææÞºyóÎ;ñ11s'Mü”ã¦*Š»v®üõ×¢ÒÒvíÚ…GDxyyáÂÖÈ#2˜ø°Ý<â’ aèBè¢vË01 KJJ²³²îÞ¹#uu=~üŒ±ÏyÈdMÕ6Á`Ø÷÷ñU¿þzüܹv!í:v †å¸è%%i Îz]`>è¯c«i FÁûÿÁjM@ !Ä0Ì}jµZ§Ó)ŠìììÜœ¹\>¨OŸñC† êÝÇU,¶öÅ=îäæî<|xÛþ¿ÒoÜiÒ!´c`` d1ˆ:ëá&Az­Þ–©WXL‚Ø«¦û^4›À#œ¯P(nÞ¼yÿÞ½’’’§Ç <´©›[35¸ep¿ `÷Ñ#[ÿüórffpppû‚ƒƒq+5ºl¬¡nѶ±çró¹¬ê#}PQDçÃ` úT*Ôóòònß¼u/ç^T§NãóÔSö>ãTQ]}àô©mýuàÔ)©TæêêŠûYÓ%0š>ÆžË8eñՋ´йOgZxzxŒñÁ£Õj+**îܹSTXXPXØ3&fÊðýztk×ÞÚ××P¨5šÔ«Wÿ ö hÛ¶-ðHsDs‡F'>z™¨ææ{ÒÈÌì@úÑG‡!œ£Ñhôz}uuõýû÷óóòrss½ÜÝÇ <´_¿øØX;'˾{çÄù ›÷îMM»êïççëç×¾}{©TJ/GN‡!ã˜ÅŽWs›ÛD+0bVNÔét`äA™PÌè( ‚Ó0ýiµZ¥RyïÞ½EEEz½¾w×®ƒz÷îÛ­{\d¤µ/”‰êšš“/?—zèÌÙô›7|¼½½¼½ƒÛ¶mÓ¦ ŒvàŽ…3øˆ¦þŠw(C™‚±ÃaËdšG¤’Á#£{ $ªM yT©T999…ùù>T©T qqƒz÷î×½G÷¨([3•Z} x<{öJf¦·§§—O`PP@@òˆ¶Ríß>¤X`B óˆœ@ V1ia ”L­V?xðà~NNIqñÃââ¨ÐNO%$$ÅÇ÷íÖMìâÒ|Wñx¸’™yâÂù§OŸ¾t‰Ëåúúú¶ñ÷ °‚:<š9}ôNå¸ÄWë)Òh]FÌ‚‡¶ØÍ¢Í ]HÄrN¦ÒjµƒA£ÑTVVæåå••––WU)BÛ…t‹ìÜ#ªsLXXL§°–¯4æ¦eg_ÎÊ<íÚ•¬¬¢’¿6m¤îî~~~~~~ð»‡;o0fP½h £ë„¸-Æ íøZ8f<•8QÝÍ#pG{8yÔjµUUUyyy%ÅÅ¥%%òŠŠÐ¶mã"#{FEÇ„…ņ‡K\][ò !…^Íξ’•yþZúåÌŒ‚‡}}|dîî~þþ~~~ BÈ#íÜáO8²…鉯rÍcK®3d†8¿ Âê"ÃС Áa¨V« Ü»•6tñyÄqJF§¹åM¤ Õ €aá!xP–èÎÖ.0÷¡ÇÇó!ð ÁB—””TWUUTT=|èíáØÆ¯CPPX»víCÚyÊdO¸z©Ñh¬¨ªzXZz;7÷^~þÍœœ9÷îåçß/,äp8Þžžb77©Læåååéé AÂápÀ©¡tá¾ïtØÐÀ55è‚!=EÍŠ1Có_>*V ±[F§?Zä`n*öà­t:ò¨¨¬¬¬¨(*.v—Jƒüü:……„´ èì!•>ùŒUUÅee·sïßËÏ¿››}÷î¼¼¼t:·7òèåå…ƒÈ#ÝFQ½ðO@µ³:]Ò¼ Œ1èCÓ¡C¦Õja¶ªV«----))©Ë««ªŠKK z}Û€€€€NmCBÛ¶ èäãé)“HžðBTju©\~7/ïn^Þ¼¼ì»woçææ>(,)+óõñ‘J¥b77///oooèiÁŽ}_ FœÊ‹„î+Ó¸ãQ»c·ªŽ¢• ·˜Ò›I9Þ³B[BÈ}˜"qJ¦?Œ"L…r¹¼²²²²²²ººZ£RÕÔÔTVU) '''©Dâî&ñI}<=|¾Ï …"¡P$ˆ5­J£Qk4JµZ­Õ¨5EMMqYY™\.¯ªªT(DB¡›««›««ÈÅE(ÁJ¬R©T,;99á&´S£SF Ý cChÑï@»u[ˆz«0ð"È#MƒDZ½vyÔét0Zï\YYYQQQYYY­PhÔêšêêʪ*Euµ‘©««‡Læ!•úxz àQ(8 …."‘N¯W©Õ*µF­Ñ¨´•Z]­Tþ?UUÀU,–¸Iœ]œµyÄ5à,+-“W”WUÊ++ƒ«««ÄÕÕE,ˆD°9ƒD"‘Édô÷Œ [cù掶 ñ¯¸¬núÚÂýf[C«0By@ÚÅÓë> „ aíþÐþÃKh]„@"„À“ø‰ÓÌè ˆâ#ü4ágŠ?},î‰D"óå”à¶S<Ÿvëtß‹Ž º¦D÷ɸ¦}uÑëa(ÚZ̘ó9 y4 t²óΠA–þF¯×3¡Ûg°ù òÆnQÀá ZH¸¦}«1CáÜ ºj„®‚Ñ»Âc¥ËvxÄÝÂð«/‚îîoÕŒt? ÑÓàÛ¢×À'âLxOƒF£‘ž_#Ö÷`³súÀpÐJC³€“iq²ŒÈ5VPÎÃL¤µÐÚ PWúÃ,FO¾‡8½Á¹ð ]ŠÄ÷¡Ó#rpk+8ÆÆÐŒÕäHíÕa+&Ðaƒ¼ð»§e‰–+Ú ÒR‡®ŸcZƒÕvRž9êâ'z›h8h‰ Å“éŽü· y$¦iá¿yd¤?‹™;Ù(uy´ÁÜGËÎT«‡²„AGw²éBˆZ­Æ.8€›„†˜kZÒXú>’î$¡c KØÆ š¶~EÐÎ *¬tÑ`ìÿ¿`LL?´ÇàÑ›nE¢+tù‚Ì€tâÃGbŠƒi÷a#µ‡¶Ð‰ZÖÖÉ´Ã0žh£Mg=u“# Ï4‰v÷éxf³rmVºh4œG6FÇë‘<Ò#7æIXâ‘PTÒöòæ/s¨J‘E/oÑpÐÿÅ߀cðhш˜+™ùõ/|žAЋ‘ˆYº ÏÐý]ô‘æ¶ùâ›îÀãQSu¸ÔضÝ9–+`þ”önZÓœC½©pOÇ ý: bXÒÆøDŽYÁ‘øµ3³˜ уctÁŸ! Ý¢ßßßws¡!<Òæƒæ‘îºék—žàLBñH:vXeðˆYCMÞ¡„:Ç['Žšøè¯—¡d„š>t™€:³‘KZÏH½ô*éGZ½ˆIÕè¤yDúÐdÐôѶƒ¦Ø³óh°ÖPXÌ€tH©Z‡y©Q6ÄÄG«—yäêÉ}´ä˜*NÔ3ÚÖ¡OÄ0㘠é;|´4ŠGsîÌy$µ;y¤n Å1㑘xáPåDšGF6„ó9TÙª•ðh¬ ;ÄÔW£‹%x&}H"ÄÌ| ‘ˆF¨¦éÈbDÝ9æÔ3cuëñÀ Øã߆Úå#FRc˜>#U©€éP¹þ8Ú÷3óNÇ’ÅÀpkOÔ&Ôö¸­6ZË£ù9¤1<’Ú_µEéDFçA|!Z«~$­G†!„ÐUA8Fca‘D|-CÀH"‘á<è'ÍÃ9bˆ>’ÖG_“€°'ý+7Ô® B´“dœÆP2:rH‰> } x—šòNÿ•~!-ˆ–瑘õÆÌKRÄTWÄç~…°<š`Î-Tð_ðxýWb©×Õ(úÌÕˆ˜è#NT½‘˜yS+`M ‹¹Ì<¢ˆY²«?ëFê­G1@Ÿßî`h,Ä’a$Ä’—gy|r0"«º#±áô‘º½ˆ9­„¥¯IÁ X3ÂÜЙ‡JCÒŸÅ”GÌêQu=Ó,×Öš`‘GR7ƒ,6…úé3æ1è#uˆ™ù_Y4-XkiÔoñê§Ã< q¢ÅÀòh輻ÁÆÒGX­VÀX°`Á‚…]¦W”aÁ‚ ,ê+`,X°`ÁÂ.Á  ,X°°K°Æ‚ ,쬀±`Á‚ »+`,X°`ÁÂ.Á  ,X°°K°Æ‚ ,쬀±`Á‚ »+`,X°`ÁÂ.Á  ,X°°K°Æ‚ ,쬀±`Á‚ »Äÿ 9ÑCÞä•IEND®B`‚treetop-1.4.14/doc/site/images/pivotal.gif0000644000004100000410000000747212157663062020460 0ustar www-datawww-dataGIF89a=s÷ÿÿÿüýþþûüýúûùûü÷úüöùûü÷÷üøøüööõøûòöúûóôïôùïôøúòóìò÷ñððêñöéðöøëíçïõæîõ÷éêãìóâëóßêòàêòõäæßéòõâäÜçñôàãÙåïóÞáããâ×äï×äîââáÖãîÑàìñØÛÒàíÐßëÏßëÏÞëÐÞëÎÝêÎÝëÌÜêÕÙÝÇÙèÆØçíÍÑÅ×çÔÓÒÔÔÓÂÕæÁÕåÀÔå¿Ôå¿Óä¾ÒäêÅÊÌÎÏ»Ñã¹Ïâ·Îá¸Îâè¿ÄèÀÅ´Ëà²Ëß²Êß°ÊÞ°ÉÞÆÅįÉÞ¯ÈÞÅÄÄæ¹¿«ÆÜ©ÅܵÃϧÃÛ§ÃÚ¥ÂÚ¥ÁÚ£ÀÙ¡¿Øâ®´ ¾ØŸ¾×Ÿ½×½Ö¼Ö··¶·¶µ«·ÂšºÕ™¹Õ—¸Ô•·Ó“µÒ§¯·³Ñ³ÑÝŸ§Üœ¤‹°ÏŠ¯Ï‰¯ÎŸª´©¨§¨§¦‡­Í†­Í…«ÌØ“›¡¢£€¨Ê¨Êw£Çx£Çs Åš™˜yŸ¿yŸ¾š˜—pžÃpÄoÃҊшr–´r–³Ñ~ˆÐ|†s’«d•¾Ïyƒa“¾`“½_’¼ŒŠ‰‹Šˆl¨lŒ§Ís}W¹k‡ŸÊlwf„Qˆ¶Pˆ¶eƒœÉiuO‡¶Éhs}|zM…µ}{yÇco_z‘Æ_k@}°Å\i?|¯ÃYeomk8w¬Yq…ÂVcnljÂTaÁS`0r©ÀN\/q©Rhz'l¥&k¥`^\¼DR`][ g¢L_nº>L·7F]œ·5ERPM\œQOMµ2ACOY Yšµ0?´/??LWV˜³,<³+;HIJ³*:Q•±%5;EN°$4CA?8CLC@>)ŸB_R©É›xR4Á™s´&•xä)hD lbŸÕI¥•E9ÐAƒ^F€™8^XP`²¶P”ÐCsä!jFúØ{•66#™ƒS§Ÿ†ÿ*ꬳªa*dú¥J¦™Ú×R- Ñ­Ä›Ç ·>và.²ši (+¬±Ô;GÉ>Fiˆ4ñšéI;lµäËC¶È¢IÎf Fâ–+oµ×¢ë˜Š8¾ikÅ;ï¿äžk/b6âʾ¾&ÔÁ N”ðÃòr1ðc&xÄuà¡q&½88ॠ; ñÈò61ñcN–ÇàòË.¯ÐHÇÒA¸pÃ$ç,¯Ÿì˜–ÍeÌD¿¼&­å¢Š&mèì4¹j QªÏ =aõÕX{„õmm‚B@ ÇØSæÂE§ýò‹üÇ&pÇ-÷Üp“·%RgtÖœÿ´7×(™`uF[_½Ñ‘£x(a ÄÎãGÎŽ9¡|‘äý¹- ™¹y©`@Ú<ðÀië°Ç¿˜Hîºë#9i9'Ùž’í€[ôúãæDÒwמ»n׿».Çå‘S‡äÃFäÚäÕÂè/#`)ÎŒãý6Æ\Rƒ0ëÀzò¿?´ã®³ÜEl÷8ù}„~ IEäTH‘Ç¥‚ 8ÄaЧ"Ä dGÿ "Ãh´#rüE4^g6"Ÿˆ\ $¶cRJ™l³"cå£ÇXŽ]ˆfWëD9r•ˆ®KEFXÈz†1ÁãZñ¸Oä‘8ˆ ÙáGˆDQˆ‰ƒ@" ‚˜`ëŸïž8‘HN’éCä ÙŽä@V(ÃD%—¥€â £*ËWxàeJ Yä¾AÂ&˜° Ut:¢W:Ú±#xì$Í©ã4ˆÙñ>ˆÓ Œ4Èo÷GÈY„Žr,Hñ'OªX^€*±ÊUn£0ÙÃfY.*° !Ã|$0âËÜ=$X`+Úñÿ?v(²"K&4™‘g$šá#ä†PJNäy, !×rÑàe?à9ʹJfpàe3;åΈlóAœ=ãgOv€¢€[ *PGÚ° óáA!×È‚Lƒ¥“´¦ERêOXua‘[E¹ ð2Ol”£«\ÃË* RÈÑ’V%•D…>ê ïùÏÍ´¡x\ï$Ѓ¤µŽ9ä/x¹ÓÇõT 7À…äFPM²V’ìx­Ö¹t”K 0SÆS¡JFV€b#Íjæ ×ĉ>®™a¥æüüÊ‘é±cyYf6'ÒV‚ Adobe Fireworks CS3 2007-11-06T02:20:42Z 2007-11-06T05:17:23Z image/png EDg¨ºIDATxœíÙ±‘ƒ@ÁÕíAn$BŠä·è½wUu%UwãÏkß÷w|PUQUqßwTUŒ1⺮cÄyžqÇÓ‰ðoÛ¶X×5zï±,KôÞ#3£µ™™ùt"ðÚÓðŒ6˜`´À£ &m0Áh€ FL0Ú`‚Ñþ±^Ef{¸IEND®B`‚treetop-1.4.14/doc/site/images/bottom_background.png0000644000004100000410000000317612157663062022521 0ustar www-datawww-data‰PNG  IHDRÚ '“ºsBIT|dˆ pHYs  ÒÝ~ütEXtSoftwareAdobe Fireworks CS3˜ÖFtEXtXML:com.adobe.xmp Adobe Fireworks CS3 2007-11-06T02:20:42Z 2007-11-06T05:17:23Z image/png EDg¨ÛIDATxœíÝQŽê @QZêòüvnÐåÙÂû¢aÎØi}É9 ©©šô“p‡ëõšÀRJaY–õº,K˜ç9Ìóî÷{¸Ýnï~DXÏçp:Â4Maš¦c 1Æ0ŽãzØËŒxÚ0 Ýa‘€O3ŽãÃù+ÀQ¬Š›•Å ‹|ªv®jÎ ¼‚ÐüJ½›ÍŽ6>M™§úaðJÓ»øôŽŒÌ9 m|œÚzGHEh6iÿ—-çbŒo~*ø*ÆØmGÚ€§”E‰œswWÛår ˲„”RH)…œóz­ìÕ;i¡>Ö¼Žl½ÿjÜ€£mÀ&õE}ddY°¨C›ÈÀ«´±­mípl$ð*B°IYœÇ1¤”º±­ìrëE6Á €=êXö(¶ÕÑ­¾'´GÚ€§´GG†ð5¶•ÝlÃ0¬1­ŽlGêÙÆ¶^dÜ€# mÀ&%¤Õ±­5‘ €¿ô]lkGýy€£mÀÓêÈVǶú½^\Úx…v>Z®^·ßØKh6éŶö^Ñ l¢{ôBÙ£àöÝ=€#ü’Z¼-ðý¶”IEND®B`‚treetop-1.4.14/doc/site/using_in_ruby.html0000644000004100000410000001317312157663062020603 0ustar www-datawww-data

Using Treetop Grammars in Ruby

Using the Command Line Compiler

You can compile .treetop files into Ruby source code with the tt command line script. tt takes an list of files with a .treetop extension and compiles them into .rb files of the same name. You can then require these files like any other Ruby script. Alternately, you can supply just one .treetop file and a -o flag to name specify the name of the output file. Improvements to this compilation script are welcome.

tt foo.treetop bar.treetop
tt foo.treetop -o foogrammar.rb

Loading A Grammar Directly

The Polyglot gem makes it possible to load .treetop or .tt files directly with require. This will invoke Treetop.load, which automatically compiles the grammar to Ruby and then evaluates the Ruby source. If you are getting errors in methods you define on the syntax tree, try using the command line compiler for better stack trace feedback. A better solution to this issue is in the works.

In order to use Polyglot dynamic loading of .treetop or .tt files though, you need to require the Polyglot gem before you require the Treetop gem as Treetop will only create hooks into Polyglot for the treetop files if Polyglot is already loaded. So you need to use:

require 'polyglot'
require 'treetop'

in order to use Polyglot auto loading with Treetop in Ruby.

Instantiating and Using Parsers

If a grammar by the name of Foo is defined, the compiled Ruby source will define a FooParser class. To parse input, create an instance and call its parse method with a string. The parser will return the syntax tree of the match or nil if there is a failure. Note that by default, the parser will fail unless all input is consumed.

Treetop.load "arithmetic"

parser = ArithmeticParser.new
if parser.parse('1+1')
  puts 'success'
else
  puts 'failure'
end

Parser Options

A Treetop parser has several options you may set. Some are settable permanently by methods on the parser, but all may be passed in as options to the parse method.

parser = ArithmeticParser.new
input = 'x = 2; y = x+3;'

# Temporarily override an option:
result1 = parser.parse(input, :consume_all_input => false)
puts "consumed #{parser.index} characters"

parser.consume_all_input = false
result1 = parser.parse(input)
puts "consumed #{parser.index} characters"

# Continue the parse with the next character:
result2 = parser.parse(input, :index => parser.index)

# Parse, but match rule `variable` instead of the normal root rule:
parser.parse(input, :root => :variable)
parser.root = :variable # Permanent setting

If you have a statement-oriented language, you can save memory by parsing just one statement at a time, and discarding the parse tree after each statement.

Learning From Failure

If a parse fails, it returns nil. In this case, you can ask the parser for an explanation. The failure reasons include the terminal nodes which were tried at the furthermost point the parse reached.

parser = ArithmeticParser.new
result = parser.parse('4+=3')

if !result
  puts parser.failure_reason
  puts parser.failure_line
  puts parser.failure_column
end

=>
Expected one of (, - at line 1, column 3 (byte 3) after +
1
3

Using Parse Results

Please don't try to walk down the syntax tree yourself, and please don't use the tree as your own convenient data structure. It contains many more nodes than your application needs, often even more than one for every character of input.

parser = ArithmeticParser.new
p parser.parse('2+3')

=>
SyntaxNode+Additive1 offset=0, "2+3" (multitive):
  SyntaxNode+Multitive1 offset=0, "2" (primary):
    SyntaxNode+Number0 offset=0, "2":
      SyntaxNode offset=0, ""
      SyntaxNode offset=0, "2"
      SyntaxNode offset=1, ""
    SyntaxNode offset=1, ""
  SyntaxNode offset=1, "+3":
    SyntaxNode+Additive0 offset=1, "+3" (multitive):
      SyntaxNode offset=1, "+"
      SyntaxNode+Multitive1 offset=2, "3" (primary):
        SyntaxNode+Number0 offset=2, "3":
          SyntaxNode offset=2, ""
          SyntaxNode offset=2, "3"
          SyntaxNode offset=3, ""
        SyntaxNode offset=3, ""

Instead, add methods to the root rule which return the information you require in a sensible form. Each rule can call its sub-rules, and this method of walking the syntax tree is much preferable to attempting to walk it from the outside.

treetop-1.4.14/doc/site/contribute.html0000644000004100000410000001434312157663062020105 0ustar www-datawww-data

Google Group

I've created a Google Group as a better place to organize discussion and development. treetop-dev@google-groups.com

Contributing

Visit the Treetop repository page on GitHub in your browser for more information about checking out the source code.

I like to try Rubinius's policy regarding commit rights. If you submit one patch worth integrating, I'll give you commit rights. We'll see how this goes, but I think it's a good policy.

Getting Started with the Code

Treetop compiler is interesting in that it is implemented in itself. Its functionality revolves around metagrammar.treetop, which specifies the grammar for Treetop grammars. I took a hybrid approach with regard to definition of methods on syntax nodes in the metagrammar. Methods that are more syntactic in nature, like those that provide access to elements of the syntax tree, are often defined inline, directly in the grammar. More semantic methods are defined in custom node classes.

Iterating on the metagrammar is tricky. The current testing strategy uses the last stable version of Treetop to parse the version under test. Then the version under test is used to parse and functionally test the various pieces of syntax it should recognize and translate to Ruby. As you change metagrammar.treetop and its associated node classes, note that the node classes you are changing are also used to support the previous stable version of the metagrammar, so must be kept backward compatible until such time as a new stable version can be produced to replace it.

Tests

Most of the compiler's tests are functional in nature. The grammar under test is used to parse and compile piece of sample code. Then I attempt to parse input with the compiled output and test its results.

What Needs to be Done

Small Stuff

  • Improve the tt command line tool to allow .treetop extensions to be elided in its arguments.
  • Generate and load temp files with Treetop.load rather than evaluating strings to improve stack trace readability.
  • Allow do/end style blocks as well as curly brace blocks. This was originally omitted because I thought it would be confusing. It probably isn't.

Big Stuff

Transient Expressions

Currently, every parsing expression instantiates a syntax node. This includes even very simple parsing expressions, like single characters. It is probably unnecessary for every single expression in the parse to correspond to its own syntax node, so much savings could be garnered from a transient declaration that instructs the parser only to attempt a match without instantiating nodes.

Generate Rule Implementations in C

Parsing expressions are currently compiled into simple Ruby source code that comprises the body of parsing rules, which are translated into Ruby methods. The generator could produce C instead of Ruby in the body of these method implementations.

Global Parsing State and Semantic Backtrack Triggering

Some programming language grammars are not entirely context-free, requiring that global state dictate the behavior of the parser in certain circumstances. Treetop does not currently expose explicit parser control to the grammar writer, and instead automatically constructs the syntax tree for them. A means of semantic parser control compatible with this approach would involve callback methods defined on parsing nodes. Each time a node is successfully parsed it will be given an opportunity to set global state and optionally trigger a parse failure on extrasyntactic grounds. Nodes will probably need to define an additional method that undoes their changes to global state when there is a parse failure and they are backtracked.

Here is a sketch of the potential utility of such mechanisms. Consider the structure of YAML, which uses indentation to indicate block structure.

level_1:
  level_2a:
  level_2b:
    level_3a:
  level_2c:    

Imagine a grammar like the following:

rule yaml_element
  name ':' block
  /
  name ':' value
end

rule block
  indent yaml_elements outdent
end

rule yaml_elements
  yaml_element (samedent yaml_element)*
end

rule samedent
  newline spaces {
    def after_success(parser_state)
      spaces.length == parser_state.indent_level
    end
  }
end

rule indent
  newline spaces {
    def after_success(parser_state)
      if spaces.length == parser_state.indent_level + 2
        parser_state.indent_level += 2
        true
      else
        false # fail the parse on extrasyntactic grounds
      end
    end

    def undo_success(parser_state)
      parser_state.indent_level -= 2
    end
  }
end

rule outdent
  newline spaces {
    def after_success(parser_state)
      if spaces.length == parser_state.indent_level - 2
        parser_state.indent_level -= 2
        true
      else
        false # fail the parse on extrasyntactic grounds
      end
    end

    def undo_success(parser_state)
      parser_state.indent_level += 2
    end
  }
end

In this case a block will be detected only if a change in indentation warrants it. Note that this change in the state of indentation must be undone if a subsequent failure causes this node not to ultimately be incorporated into a successful result.

I am by no means sure that the above sketch is free of problems, or even that this overall strategy is sound, but it seems like a promising path.

treetop-1.4.14/doc/syntactic_recognition.markdown0000644000004100000410000001750512157663062022245 0ustar www-datawww-data#Syntactic Recognition Treetop grammars are written in a custom language based on parsing expression grammars. Literature on the subject of parsing expression grammars (PEGs) is useful in writing Treetop grammars. PEGs have no separate lexical analyser (since the algorithm has the same time-complexity guarantees as the best lexical analysers) so all whitespace and other lexical niceties (like comments) must be explicitly handled in the grammar. A further benefit is that multiple PEG grammars may be seamlessly composed into a single parser. #Grammar Structure Treetop grammars look like this: require "my_stuff" grammar GrammarName include Module::Submodule rule rule_name ... end rule rule_name ... end ... end The main keywords are: * `grammar` : This introduces a new grammar. It is followed by a constant name to which the grammar will be bound when it is loaded. * `include`: This causes the generated parser to include the referenced Ruby module (which may be another parser) * `require`: This must be at the start of the file, and is passed through to the emitted Ruby grammar * `rule` : This defines a parsing rule within the grammar. It is followed by a name by which this rule can be referenced within other rules. It is then followed by a parsing expression defining the rule. A grammar may be surrounded by one or more nested `module` statements, which provides a namespace for the generated Ruby parser. Treetop will emit a module called `GrammarName` and a parser class called `GrammarNameParser` (in the module namespace, if specified). #Parsing Expressions Each rule associates a name with a _parsing expression_. Parsing expressions are a generalization of vanilla regular expressions. Their key feature is the ability to reference other expressions in the grammar by name. ##Terminal Symbols ###Strings Strings are surrounded in double or single quotes and must be matched exactly. * `"foo"` * `'foo'` ###Character Classes Character classes are surrounded by brackets. Their semantics are identical to those used in Ruby's regular expressions. * `[a-zA-Z]` * `[0-9]` ###The Anything Symbol The anything symbol is represented by a dot (`.`) and matches any single character. ###Ellipsis An empty string matches at any position and consumes no input. It's useful when you wish to treat a single symbol as part of a sequence, for example when an alternate rule will be processed using shared code.
    rule alts
      ( foo bar / baz '' )
      {
        def value
          elements.map{|e| e.text_value }
        end
      }
    end
##Nonterminal Symbols Nonterminal symbols are unquoted references to other named rules. They are equivalent to an inline substitution of the named expression. rule foo "the dog " bar end rule bar "jumped" end The above grammar is equivalent to: rule foo "the dog jumped" end ##Ordered Choice Parsers attempt to match ordered choices in left-to-right order, and stop after the first successful match. "foobar" / "foo" / "bar" Note that if `"foo"` in the above expression came first, `"foobar"` would never be matched. Note also that the above rule will match `"bar"` as a prefix of `"barbie"`. Care is required when it's desired to match language keywords exactly. ##Sequences Sequences are a space-separated list of parsing expressions. They have higher precedence than choices, so choices must be parenthesized to be used as the elements of a sequence. "foo" "bar" ("baz" / "bop") ##Zero or More Parsers will greedily match an expression zero or more times if it is followed by the star (`*`) symbol. * `'foo'*` matches the empty string, `"foo"`, `"foofoo"`, etc. ##One or More Parsers will greedily match an expression one or more times if it is followed by the plus (`+`) symbol. * `'foo'+` does not match the empty string, but matches `"foo"`, `"foofoo"`, etc. ##Optional Expressions An expression can be declared optional by following it with a question mark (`?`). * `'foo'?` matches `"foo"` or the empty string. ##Repetition count A generalised repetition count (minimum, maximum) is also available. * `'foo' 2..` matches `'foo'` two or more times * `'foo' 3..5` matches `'foo'` from three to five times * `'foo' ..4` matches `'foo'` from zero to four times ##Lookahead Assertions Lookahead assertions can be used to make parsing expressions context-sensitive. The parser will look ahead into the buffer and attempt to match an expression without consuming input. ###Positive Lookahead Assertion Preceding an expression with an ampersand `(&)` indicates that it must match, but no input will be consumed in the process of determining whether this is true. * `"foo" &"bar"` matches `"foobar"` but only consumes up to the end `"foo"`. It will not match `"foobaz"`. ###Negative Lookahead Assertion Preceding an expression with a bang `(!)` indicates that the expression must not match, but no input will be consumed in the process of determining whether this is true. * `"foo" !"bar"` matches `"foobaz"` but only consumes up to the end `"foo"`. It will not match `"foobar"`. Note that a lookahead assertion may be used on any rule, not just a string terminal. rule things thing (!(disallowed / ',') following)* end Here's a common use case: rule word [a-zA-Z]+ end rule conjunction primitive ('and' ' '+ primitive)* end rule primitive (!'and' word ' '+)* end Here's the easiest way to handle C-style comments: rule c_comment '/*' ( !'*/' (. / "\n") )* '*/' end ##Semantic predicates (positive and negative) Sometimes you must execute Ruby code during parsing in order to decide how to proceed. This is an advanced feature, and must be used with great care, because it can change the way a Treetop parser backtracks in a way that breaks the parsing algorithm. See the notes below on how to use this feature safely. The code block is the body of a Ruby lambda block, and should return true or false, to cause this parse rule to continue or fail (for positive sempreds), fail or continue (for negative sempreds). * `&{ ... }` Evaluate the block and fail this rule if the result is false or nil * `!{ ... }` Evaluate the block and fail this rule if the result is not false or nil The lambda is passed a single argument which is the array of syntax nodes matched so far in the current sequence. Note that because the current rule has not yet succeeded, no syntax node has yet been constructed, and so the lambda block is being run in a context where the `names` of the preceding rules (or as assigned by labels) are not available to access the sub-rules. rule id [a-zA-Z][a-zA-Z0-9]* { def is_reserved ReservedSymbols.include? text_value end } end rule foo_rule foo id &{|seq| seq[1].is_reserved } baz end Match "foo id baz" only if `id.is_reserved`. Note that `id` cannot be referenced by name from `foo_rule`, since that rule has not yet succeeded, but `id` has completed and so its added methods are available. rule test_it foo bar &{|s| debugger; true } baz end Match `foo` then `bar`, stop to enter the debugger (make sure you have said `require "ruby-debug"` somewhere), then continue by trying to match `baz`. Treetop, like other PEG parsers, achieves its performance guarantee by remembering which rules it has tried at which locations in the input, and what the result was. This process, called memoization, requires that the rule would produce the same result (if run again) as it produced the first time when the result was remembered. If you violate this principle in your semantic predicates, be prepared to fight Cerberus before you're allowed out of Hades again. treetop-1.4.14/doc/contributing_and_planned_features.markdown0000644000004100000410000001306712157663062024573 0ustar www-datawww-data#Google Group I've created a Google Group as a better place to organize discussion and development. treetop-dev@google-groups.com #Contributing Visit the Treetop repository page on GitHub in your browser for more information about checking out the source code. I like to try Rubinius's policy regarding commit rights. If you submit one patch worth integrating, I'll give you commit rights. We'll see how this goes, but I think it's a good policy. ##Getting Started with the Code Treetop compiler is interesting in that it is implemented in itself. Its functionality revolves around `metagrammar.treetop`, which specifies the grammar for Treetop grammars. I took a hybrid approach with regard to definition of methods on syntax nodes in the metagrammar. Methods that are more syntactic in nature, like those that provide access to elements of the syntax tree, are often defined inline, directly in the grammar. More semantic methods are defined in custom node classes. Iterating on the metagrammar is tricky. The current testing strategy uses the last stable version of Treetop to parse the version under test. Then the version under test is used to parse and functionally test the various pieces of syntax it should recognize and translate to Ruby. As you change `metagrammar.treetop` and its associated node classes, note that the node classes you are changing are also used to support the previous stable version of the metagrammar, so must be kept backward compatible until such time as a new stable version can be produced to replace it. ##Tests Most of the compiler's tests are functional in nature. The grammar under test is used to parse and compile piece of sample code. Then I attempt to parse input with the compiled output and test its results. #What Needs to be Done ##Small Stuff * Improve the `tt` command line tool to allow `.treetop` extensions to be elided in its arguments. * Generate and load temp files with `Treetop.load` rather than evaluating strings to improve stack trace readability. * Allow `do/end` style blocks as well as curly brace blocks. This was originally omitted because I thought it would be confusing. It probably isn't. ##Big Stuff ####Transient Expressions Currently, every parsing expression instantiates a syntax node. This includes even very simple parsing expressions, like single characters. It is probably unnecessary for every single expression in the parse to correspond to its own syntax node, so much savings could be garnered from a transient declaration that instructs the parser only to attempt a match without instantiating nodes. ###Generate Rule Implementations in C Parsing expressions are currently compiled into simple Ruby source code that comprises the body of parsing rules, which are translated into Ruby methods. The generator could produce C instead of Ruby in the body of these method implementations. ###Global Parsing State and Semantic Backtrack Triggering Some programming language grammars are not entirely context-free, requiring that global state dictate the behavior of the parser in certain circumstances. Treetop does not currently expose explicit parser control to the grammar writer, and instead automatically constructs the syntax tree for them. A means of semantic parser control compatible with this approach would involve callback methods defined on parsing nodes. Each time a node is successfully parsed it will be given an opportunity to set global state and optionally trigger a parse failure on _extrasyntactic_ grounds. Nodes will probably need to define an additional method that undoes their changes to global state when there is a parse failure and they are backtracked. Here is a sketch of the potential utility of such mechanisms. Consider the structure of YAML, which uses indentation to indicate block structure. level_1: level_2a: level_2b: level_3a: level_2c: Imagine a grammar like the following: rule yaml_element name ':' block / name ':' value end rule block indent yaml_elements outdent end rule yaml_elements yaml_element (samedent yaml_element)* end rule samedent newline spaces { def after_success(parser_state) spaces.length == parser_state.indent_level end } end rule indent newline spaces { def after_success(parser_state) if spaces.length == parser_state.indent_level + 2 parser_state.indent_level += 2 true else false # fail the parse on extrasyntactic grounds end end def undo_success(parser_state) parser_state.indent_level -= 2 end } end rule outdent newline spaces { def after_success(parser_state) if spaces.length == parser_state.indent_level - 2 parser_state.indent_level -= 2 true else false # fail the parse on extrasyntactic grounds end end def undo_success(parser_state) parser_state.indent_level += 2 end } end In this case a block will be detected only if a change in indentation warrants it. Note that this change in the state of indentation must be undone if a subsequent failure causes this node not to ultimately be incorporated into a successful result. I am by no means sure that the above sketch is free of problems, or even that this overall strategy is sound, but it seems like a promising path. treetop-1.4.14/examples/0000755000004100000410000000000012157663062015141 5ustar www-datawww-datatreetop-1.4.14/examples/lambda_calculus/0000755000004100000410000000000012157663062020254 5ustar www-datawww-datatreetop-1.4.14/examples/lambda_calculus/arithmetic.rb0000644000004100000410000002322212157663062022733 0ustar www-datawww-datamodule Arithmetic include Treetop::Runtime def root @root || :expression end def _nt_expression start_index = index cached = node_cache[:expression][index] if cached @index = cached.interval.end return cached end i0 = index r1 = _nt_comparative if r1.success? r0 = r1 else r2 = _nt_additive if r2.success? r0 = r2 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:expression][start_index] = r0 return r0 end module Comparative0 def operand_1 elements[0] end def space elements[1] end def operator elements[2] end def space elements[3] end def operand_2 elements[4] end end def _nt_comparative start_index = index cached = node_cache[:comparative][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] r1 = _nt_additive s0 << r1 if r1.success? r2 = _nt_space s0 << r2 if r2.success? r3 = _nt_equality_op s0 << r3 if r3.success? r4 = _nt_space s0 << r4 if r4.success? r5 = _nt_additive s0 << r5 end end end end if s0.last.success? r0 = (BinaryOperation).new(input, i0...index, s0) r0.extend(Comparative0) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:comparative][start_index] = r0 return r0 end module EqualityOp0 def apply(a, b) a == b end end def _nt_equality_op start_index = index cached = node_cache[:equality_op][index] if cached @index = cached.interval.end return cached end r0 = parse_terminal('==', SyntaxNode, EqualityOp0) node_cache[:equality_op][start_index] = r0 return r0 end module Additive0 def operand_1 elements[0] end def space elements[1] end def operator elements[2] end def space elements[3] end def operand_2 elements[4] end end def _nt_additive start_index = index cached = node_cache[:additive][index] if cached @index = cached.interval.end return cached end i0 = index i1, s1 = index, [] r2 = _nt_multitive s1 << r2 if r2.success? r3 = _nt_space s1 << r3 if r3.success? r4 = _nt_additive_op s1 << r4 if r4.success? r5 = _nt_space s1 << r5 if r5.success? r6 = _nt_additive s1 << r6 end end end end if s1.last.success? r1 = (BinaryOperation).new(input, i1...index, s1) r1.extend(Additive0) else self.index = i1 r1 = ParseFailure.new(input, i1) end if r1.success? r0 = r1 else r7 = _nt_multitive if r7.success? r0 = r7 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:additive][start_index] = r0 return r0 end module AdditiveOp0 def apply(a, b) a + b end end module AdditiveOp1 def apply(a, b) a - b end end def _nt_additive_op start_index = index cached = node_cache[:additive_op][index] if cached @index = cached.interval.end return cached end i0 = index r1 = parse_terminal('+', SyntaxNode, AdditiveOp0) if r1.success? r0 = r1 else r2 = parse_terminal('-', SyntaxNode, AdditiveOp1) if r2.success? r0 = r2 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:additive_op][start_index] = r0 return r0 end module Multitive0 def operand_1 elements[0] end def space elements[1] end def operator elements[2] end def space elements[3] end def operand_2 elements[4] end end def _nt_multitive start_index = index cached = node_cache[:multitive][index] if cached @index = cached.interval.end return cached end i0 = index i1, s1 = index, [] r2 = _nt_primary s1 << r2 if r2.success? r3 = _nt_space s1 << r3 if r3.success? r4 = _nt_multitive_op s1 << r4 if r4.success? r5 = _nt_space s1 << r5 if r5.success? r6 = _nt_multitive s1 << r6 end end end end if s1.last.success? r1 = (BinaryOperation).new(input, i1...index, s1) r1.extend(Multitive0) else self.index = i1 r1 = ParseFailure.new(input, i1) end if r1.success? r0 = r1 else r7 = _nt_primary if r7.success? r0 = r7 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:multitive][start_index] = r0 return r0 end module MultitiveOp0 def apply(a, b) a * b end end module MultitiveOp1 def apply(a, b) a / b end end def _nt_multitive_op start_index = index cached = node_cache[:multitive_op][index] if cached @index = cached.interval.end return cached end i0 = index r1 = parse_terminal('*', SyntaxNode, MultitiveOp0) if r1.success? r0 = r1 else r2 = parse_terminal('/', SyntaxNode, MultitiveOp1) if r2.success? r0 = r2 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:multitive_op][start_index] = r0 return r0 end module Primary0 def space elements[1] end def expression elements[2] end def space elements[3] end end module Primary1 def eval(env={}) expression.eval(env) end end def _nt_primary start_index = index cached = node_cache[:primary][index] if cached @index = cached.interval.end return cached end i0 = index r1 = _nt_variable if r1.success? r0 = r1 else r2 = _nt_number if r2.success? r0 = r2 else i3, s3 = index, [] r4 = parse_terminal('(', SyntaxNode) s3 << r4 if r4.success? r5 = _nt_space s3 << r5 if r5.success? r6 = _nt_expression s3 << r6 if r6.success? r7 = _nt_space s3 << r7 if r7.success? r8 = parse_terminal(')', SyntaxNode) s3 << r8 end end end end if s3.last.success? r3 = (SyntaxNode).new(input, i3...index, s3) r3.extend(Primary0) r3.extend(Primary1) else self.index = i3 r3 = ParseFailure.new(input, i3) end if r3.success? r0 = r3 else self.index = i0 r0 = ParseFailure.new(input, i0) end end end node_cache[:primary][start_index] = r0 return r0 end module Variable0 def eval(env={}) env[name] end def name text_value end end def _nt_variable start_index = index cached = node_cache[:variable][index] if cached @index = cached.interval.end return cached end s0, i0 = [], index loop do r1 = parse_char_class(/[a-z]/, 'a-z', SyntaxNode) if r1.success? s0 << r1 else break end end if s0.empty? self.index = i0 r0 = ParseFailure.new(input, i0) else r0 = SyntaxNode.new(input, i0...index, s0) r0.extend(Variable0) end node_cache[:variable][start_index] = r0 return r0 end module Number0 end module Number1 def eval(env={}) text_value.to_i end end def _nt_number start_index = index cached = node_cache[:number][index] if cached @index = cached.interval.end return cached end i0 = index i1, s1 = index, [] r2 = parse_char_class(/[1-9]/, '1-9', SyntaxNode) s1 << r2 if r2.success? s3, i3 = [], index loop do r4 = parse_char_class(/[0-9]/, '0-9', SyntaxNode) if r4.success? s3 << r4 else break end end r3 = SyntaxNode.new(input, i3...index, s3) s1 << r3 end if s1.last.success? r1 = (SyntaxNode).new(input, i1...index, s1) r1.extend(Number0) else self.index = i1 r1 = ParseFailure.new(input, i1) end if r1.success? r0 = r1 r0.extend(Number1) else r5 = parse_terminal('0', SyntaxNode) if r5.success? r0 = r5 r0.extend(Number1) else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:number][start_index] = r0 return r0 end def _nt_space start_index = index cached = node_cache[:space][index] if cached @index = cached.interval.end return cached end s0, i0 = [], index loop do r1 = parse_terminal(' ', SyntaxNode) if r1.success? s0 << r1 else break end end r0 = SyntaxNode.new(input, i0...index, s0) node_cache[:space][start_index] = r0 return r0 end end class ArithmeticParser < Treetop::Runtime::CompiledParser include Arithmetic end treetop-1.4.14/examples/lambda_calculus/lambda_calculus_node_classes.rb0000644000004100000410000000012712157663062026436 0ustar www-datawww-datamodule LambdaCalculus class Application < Treetop::Runtime::SyntaxNode end endtreetop-1.4.14/examples/lambda_calculus/lambda_calculus.treetop0000644000004100000410000000516512157663062025002 0ustar www-datawww-datagrammar LambdaCalculus include Arithmetic rule program expression more_expressions:(';' space expression)* { def eval(env={}) env = env.clone last_eval = nil expressions.each do |exp| last_eval = exp.eval(env) end last_eval end def expressions [expression] + more_expressions.elements.map {|elt| elt.expression} end } end rule expression definition / conditional / application / function / super end rule definition 'def' space variable space expression { def eval(env) env[variable.name] = expression.eval(env) end } end rule conditional 'if' space '(' space condition:expression space ')' space true_case:expression space 'else' space false_case:expression { def eval(env) if condition.eval(env) true_case.eval(env) else false_case.eval(env) end end } end rule primary application / super end rule application operator space expression { def eval(env={}) left_associative_apply(operator.eval(env), env) end def left_associative_apply(operator, env) if expression.instance_of?(Application) expression.left_associative_apply(operator.apply(expression.operator.eval(env)), env) else operator.apply(expression.eval(env)) end end def to_s(env={}) operator.to_s(env) + ' ' + expression.to_s(env) end } end rule operator function / variable end rule non_application function / variable end rule function '\\' param:variable '(' body:expression ')' { class Closure attr_reader :env, :function def initialize(function, env) @function = function @env = env end def apply(arg) function.body.eval(function.param.bind(arg, env)) end def to_s(other_env={}) "\\#{function.param.to_s}(#{function.body.to_s(other_env.merge(env))})" end end def eval(env={}) Closure.new(self, env) end def to_s(env={}) eval(env).to_s end } end rule variable !keyword ( super { def bind(value, env) env.merge(name => value) end def to_s(env={}) env.has_key?(name) ? env[name].to_s : name end } ) end rule keyword ('if' / 'else') !non_space_char end rule non_space_char ![ \n] . end rule space [ \n]* end endtreetop-1.4.14/examples/lambda_calculus/lambda_calculus.rb0000644000004100000410000003313512157663062023721 0ustar www-datawww-datamodule LambdaCalculus include Treetop::Runtime def root @root || :program end include Arithmetic module Program0 def space elements[1] end def expression elements[2] end end module Program1 def expression elements[0] end def more_expressions elements[1] end end module Program2 def eval(env={}) env = env.clone last_eval = nil expressions.each do |exp| last_eval = exp.eval(env) end last_eval end def expressions [expression] + more_expressions.elements.map {|elt| elt.expression} end end def _nt_program start_index = index cached = node_cache[:program][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] r1 = _nt_expression s0 << r1 if r1.success? s2, i2 = [], index loop do i3, s3 = index, [] r4 = parse_terminal(';', SyntaxNode) s3 << r4 if r4.success? r5 = _nt_space s3 << r5 if r5.success? r6 = _nt_expression s3 << r6 end end if s3.last.success? r3 = (SyntaxNode).new(input, i3...index, s3) r3.extend(Program0) else self.index = i3 r3 = ParseFailure.new(input, i3) end if r3.success? s2 << r3 else break end end r2 = SyntaxNode.new(input, i2...index, s2) s0 << r2 end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(Program1) r0.extend(Program2) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:program][start_index] = r0 return r0 end def _nt_expression start_index = index cached = node_cache[:expression][index] if cached @index = cached.interval.end return cached end i0 = index r1 = _nt_definition if r1.success? r0 = r1 else r2 = _nt_conditional if r2.success? r0 = r2 else r3 = _nt_application if r3.success? r0 = r3 else r4 = _nt_function if r4.success? r0 = r4 else r5 = super if r5.success? r0 = r5 else self.index = i0 r0 = ParseFailure.new(input, i0) end end end end end node_cache[:expression][start_index] = r0 return r0 end module Definition0 def space elements[1] end def variable elements[2] end def space elements[3] end def expression elements[4] end end module Definition1 def eval(env) env[variable.name] = expression.eval(env) end end def _nt_definition start_index = index cached = node_cache[:definition][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] r1 = parse_terminal('def', SyntaxNode) s0 << r1 if r1.success? r2 = _nt_space s0 << r2 if r2.success? r3 = _nt_variable s0 << r3 if r3.success? r4 = _nt_space s0 << r4 if r4.success? r5 = _nt_expression s0 << r5 end end end end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(Definition0) r0.extend(Definition1) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:definition][start_index] = r0 return r0 end module Conditional0 def space elements[1] end def space elements[3] end def condition elements[4] end def space elements[5] end def space elements[7] end def true_case elements[8] end def space elements[9] end def space elements[11] end def false_case elements[12] end end module Conditional1 def eval(env) if condition.eval(env) true_case.eval(env) else false_case.eval(env) end end end def _nt_conditional start_index = index cached = node_cache[:conditional][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] r1 = parse_terminal('if', SyntaxNode) s0 << r1 if r1.success? r2 = _nt_space s0 << r2 if r2.success? r3 = parse_terminal('(', SyntaxNode) s0 << r3 if r3.success? r4 = _nt_space s0 << r4 if r4.success? r5 = _nt_expression s0 << r5 if r5.success? r6 = _nt_space s0 << r6 if r6.success? r7 = parse_terminal(')', SyntaxNode) s0 << r7 if r7.success? r8 = _nt_space s0 << r8 if r8.success? r9 = _nt_expression s0 << r9 if r9.success? r10 = _nt_space s0 << r10 if r10.success? r11 = parse_terminal('else', SyntaxNode) s0 << r11 if r11.success? r12 = _nt_space s0 << r12 if r12.success? r13 = _nt_expression s0 << r13 end end end end end end end end end end end end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(Conditional0) r0.extend(Conditional1) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:conditional][start_index] = r0 return r0 end def _nt_primary start_index = index cached = node_cache[:primary][index] if cached @index = cached.interval.end return cached end i0 = index r1 = _nt_application if r1.success? r0 = r1 else r2 = super if r2.success? r0 = r2 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:primary][start_index] = r0 return r0 end module Application0 def operator elements[0] end def space elements[1] end def expression elements[2] end end module Application1 def eval(env={}) left_associative_apply(operator.eval(env), env) end def left_associative_apply(operator, env) if expression.instance_of?(Application) expression.left_associative_apply(operator.apply(expression.operator.eval(env)), env) else operator.apply(expression.eval(env)) end end def to_s(env={}) operator.to_s(env) + ' ' + expression.to_s(env) end end def _nt_application start_index = index cached = node_cache[:application][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] r1 = _nt_operator s0 << r1 if r1.success? r2 = _nt_space s0 << r2 if r2.success? r3 = _nt_expression s0 << r3 end end if s0.last.success? r0 = (Application).new(input, i0...index, s0) r0.extend(Application0) r0.extend(Application1) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:application][start_index] = r0 return r0 end def _nt_operator start_index = index cached = node_cache[:operator][index] if cached @index = cached.interval.end return cached end i0 = index r1 = _nt_function if r1.success? r0 = r1 else r2 = _nt_variable if r2.success? r0 = r2 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:operator][start_index] = r0 return r0 end def _nt_non_application start_index = index cached = node_cache[:non_application][index] if cached @index = cached.interval.end return cached end i0 = index r1 = _nt_function if r1.success? r0 = r1 else r2 = _nt_variable if r2.success? r0 = r2 else self.index = i0 r0 = ParseFailure.new(input, i0) end end node_cache[:non_application][start_index] = r0 return r0 end module Function0 def param elements[1] end def body elements[3] end end module Function1 class Closure attr_reader :env, :function def initialize(function, env) @function = function @env = env end def apply(arg) function.body.eval(function.param.bind(arg, env)) end def to_s(other_env={}) "\\#{function.param.to_s}(#{function.body.to_s(other_env.merge(env))})" end end def eval(env={}) Closure.new(self, env) end def to_s(env={}) eval(env).to_s end end def _nt_function start_index = index cached = node_cache[:function][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] r1 = parse_terminal('\\', SyntaxNode) s0 << r1 if r1.success? r2 = _nt_variable s0 << r2 if r2.success? r3 = parse_terminal('(', SyntaxNode) s0 << r3 if r3.success? r4 = _nt_expression s0 << r4 if r4.success? r5 = parse_terminal(')', SyntaxNode) s0 << r5 end end end end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(Function0) r0.extend(Function1) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:function][start_index] = r0 return r0 end module Variable0 def bind(value, env) env.merge(name => value) end def to_s(env={}) env.has_key?(name) ? env[name].to_s : name end end module Variable1 end def _nt_variable start_index = index cached = node_cache[:variable][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] i1 = index r2 = _nt_keyword if r2.success? r1 = ParseFailure.new(input, i1) else self.index = i1 r1 = SyntaxNode.new(input, index...index) end s0 << r1 if r1.success? r3 = super r3.extend(Variable0) s0 << r3 end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(Variable1) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:variable][start_index] = r0 return r0 end module Keyword0 end def _nt_keyword start_index = index cached = node_cache[:keyword][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] i1 = index r2 = parse_terminal('if', SyntaxNode) if r2.success? r1 = r2 else r3 = parse_terminal('else', SyntaxNode) if r3.success? r1 = r3 else self.index = i1 r1 = ParseFailure.new(input, i1) end end s0 << r1 if r1.success? i4 = index r5 = _nt_non_space_char if r5.success? r4 = ParseFailure.new(input, i4) else self.index = i4 r4 = SyntaxNode.new(input, index...index) end s0 << r4 end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(Keyword0) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:keyword][start_index] = r0 return r0 end module NonSpaceChar0 end def _nt_non_space_char start_index = index cached = node_cache[:non_space_char][index] if cached @index = cached.interval.end return cached end i0, s0 = index, [] i1 = index r2 = parse_char_class(/[ \n]/, ' \n', SyntaxNode) if r2.success? r1 = ParseFailure.new(input, i1) else self.index = i1 r1 = SyntaxNode.new(input, index...index) end s0 << r1 if r1.success? r3 = parse_anything(SyntaxNode) s0 << r3 end if s0.last.success? r0 = (SyntaxNode).new(input, i0...index, s0) r0.extend(NonSpaceChar0) else self.index = i0 r0 = ParseFailure.new(input, i0) end node_cache[:non_space_char][start_index] = r0 return r0 end def _nt_space start_index = index cached = node_cache[:space][index] if cached @index = cached.interval.end return cached end s0, i0 = [], index loop do r1 = parse_char_class(/[ \n]/, ' \n', SyntaxNode) if r1.success? s0 << r1 else break end end r0 = SyntaxNode.new(input, i0...index, s0) node_cache[:space][start_index] = r0 return r0 end end class LambdaCalculusParser < Treetop::Runtime::CompiledParser include LambdaCalculus end treetop-1.4.14/examples/lambda_calculus/lambda_calculus0000644000004100000410000000000012157663062023300 0ustar www-datawww-datatreetop-1.4.14/examples/lambda_calculus/test_helper.rb0000644000004100000410000000051212157663062023115 0ustar www-datawww-datarequire 'test/unit' require 'rubygems' require 'treetop' module ParserTestHelper def assert_evals_to_self(input) assert_evals_to(input, input) end def parse(input) result = @parser.parse(input) unless result puts @parser.terminal_failures.join("\n") end assert !result.nil? result end endtreetop-1.4.14/examples/lambda_calculus/arithmetic.treetop0000644000004100000410000000250512157663062024013 0ustar www-datawww-datagrammar Arithmetic rule expression comparative / additive end rule comparative head:additive tail:( space operator:equality_op space operand:additive)* end rule equality_op '==' { def apply(a, b) a == b end } end rule additive head:multitive tail:( space operator:additive_op space operand:multitive)* end rule additive_op '+' { def apply(a, b) a + b end } / '-' { def apply(a, b) a - b end } end rule multitive head:primary tail:( space operator:multitive_op space operand:primary)* end rule multitive_op '*' { def apply(a, b) a * b end } / '/' { def apply(a, b) a / b end } end rule primary variable / number / '(' space expression space ')' { def eval(env={}) expression.eval(env) end } end rule variable [a-z]+ { def eval(env={}) env[name] end def name text_value end } end rule number ([1-9] [0-9]* / '0') { def eval(env={}) text_value.to_i end } end rule space ' '* end end treetop-1.4.14/examples/lambda_calculus/arithmetic_node_classes.rb0000644000004100000410000000037212157663062025456 0ustar www-datawww-datamodule Arithmetic class BinaryOperation < Treetop::Runtime::SyntaxNode def eval(env={}) tail.elements.inject(head.eval(env)) do |value, element| element.operator.apply(value, element.operand.eval(env)) end end end end treetop-1.4.14/examples/lambda_calculus/arithmetic_test.rb0000644000004100000410000000245612157663062024000 0ustar www-datawww-datadir = File.dirname(__FILE__) require File.expand_path("#{dir}/test_helper") require File.expand_path("#{dir}/arithmetic_node_classes") Treetop.load File.expand_path("#{dir}/arithmetic") class ArithmeticParserTest < Test::Unit::TestCase include ParserTestHelper def setup @parser = ArithmeticParser.new end def test_number assert_equal 0, parse('0').eval assert_equal 1, parse('1').eval assert_equal 123, parse('123').eval end def test_variable assert_equal 0, parse('x').eval('x' => 0) assert_equal 3, parse('x').eval('x' => 3) assert_equal 10, parse('y').eval('y' => 10) end def test_addition assert_equal 10, parse('x + 5').eval('x' => 5) end def test_subtraction assert_equal 0, parse('x - 5').eval('x' => 5) end def test_multiplication assert_equal 6, parse('x * 2').eval('x' => 3) end def test_division assert_equal 3, parse('x / 2').eval('x' => 6) end def test_order_of_operations assert_equal 11, parse('1 + 2 * 3 + 4').eval end def test_left_to_right assert_equal 2, parse('5 - 2 - 1').eval end def test_parentheses assert_equal 25, parse('(5 + x) * (10 - y)').eval('x' => 0, 'y' => 5) end def test_equality assert parse('4 == 4').eval assert !parse('4 == 3').eval end end treetop-1.4.14/examples/lambda_calculus/lambda_calculus_test.rb0000644000004100000410000000464212157663062024761 0ustar www-datawww-datadir = File.dirname(__FILE__) require File.expand_path("#{dir}/test_helper") require File.expand_path("#{dir}/arithmetic_node_classes") require File.expand_path("#{dir}/lambda_calculus_node_classes") Treetop.load File.expand_path("#{dir}/arithmetic") Treetop.load File.expand_path("#{dir}/lambda_calculus") class Treetop::Runtime::SyntaxNode def method_missing(method, *args) raise "Node representing #{text_value} does not respond to #{method}" end end class LambdaCalculusParserTest < Test::Unit::TestCase include ParserTestHelper def setup @parser = LambdaCalculusParser.new end def test_free_variable assert_equal 'x', parse('x').eval.to_s end def test_variable_binding variable = parse('x').eval env = variable.bind(1, {}) assert_equal 1, env['x'] end def test_bound_variable_evaluation assert_equal 1, parse('x').eval({'x' => 1}) end def test_identity_function assert_equal '\x(x)', parse('\x(x)').eval.to_s end def test_function_returning_constant_function assert_equal '\x(\y(x))', parse('\x(\y(x))').eval.to_s end def test_identity_function_application assert_equal 1, parse('\x(x) 1').eval assert_equal '\y(y)', parse('\x(x) \y(y)').eval.to_s end def test_constant_function_construction assert_equal '\y(1)', parse('\x(\y(x)) 1').eval.to_s end def test_multiple_argument_application_is_left_associative assert_equal '\b(b)', parse('\x(\y(x y)) \a(a) \b(b)').eval.to_s end def test_parentheses_override_application_order assert_equal '\y(\b(b) y)', parse('\x(\y(x y)) (\a(a) \b(b))').eval.to_s end def test_arithmetic_in_function_body assert_equal 10, parse('\x(x + 5) 5').eval end def test_addition_of_function_results assert_equal 20, parse('\x(x + 5) 5 + \x(15 - x) 5').eval end def test_conditional result = parse('if (x) 1 else 2') assert_equal 1, result.eval({'x' => true}) assert_equal 2, result.eval({'x' => false}) end def test_keyword assert @parser.parse('if').failure? assert @parser.parse('else').failure? assert parse('elsee').success? assert parse('iff').success? end def test_program result = parse('def fact \x(if (x == 0) 1 else x * fact (x - 1)); fact(5)').eval assert_equal 5 * 4 * 3 * 2, result end end treetop-1.4.14/LICENSE0000644000004100000410000000204012157663062014324 0ustar www-datawww-dataCopyright (c) 2007 Nathan Sobo. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. treetop-1.4.14/README.md0000644000004100000410000002600412157663062014604 0ustar www-datawww-dataSupport ======= Support for Treetop is provided through the mailing list you can join or browse here: http://groups.google.com/group/treetop-dev Tutorial ======== Languages can be split into two components, their *syntax* and their *semantics*. It's your understanding of English syntax that tells you the stream of words "Sleep furiously green ideas colorless" is not a valid sentence. Semantics is deeper. Even if we rearrange the above sentence to be "Colorless green ideas sleep furiously", which is syntactically correct, it remains nonsensical on a semantic level. With Treetop, you'll be dealing with languages that are much simpler than English, but these basic concepts apply. Your programs will need to address both the syntax and the semantics of the languages they interpret. Treetop equips you with powerful tools for each of these two aspects of interpreter writing. You'll describe the syntax of your language with a *parsing expression grammar*. From this description, Treetop will generate a Ruby parser that transforms streams of characters written into your language into *abstract syntax trees* representing their structure. You'll then describe the semantics of your language in Ruby by defining methods on the syntax trees the parser generates. Parsing Expression Grammars, The Basics ======================================= The first step in using Treetop is defining a grammar in a file with the `.treetop` extension. Here's a grammar that's useless because it's empty: # my_grammar.treetop grammar MyGrammar end Next, you start filling your grammar with rules. Each rule associates a name with a parsing expression, like the following: # my_grammar.treetop # You can use a .tt extension instead if you wish grammar MyGrammar rule hello 'hello chomsky' end end The first rule becomes the *root* of the grammar, causing its expression to be matched when a parser for the grammar is fed a string. The above grammar can now be used in a Ruby program. Notice how a string matching the first rule parses successfully, but a second nonmatching string does not. # use_grammar.rb require 'rubygems' require 'treetop' Treetop.load 'my_grammar' # or just: # require 'my_grammar' # This works because Polyglot hooks "require" to find and load Treetop files parser = MyGrammarParser.new puts parser.parse('hello chomsky') # => Treetop::Runtime::SyntaxNode puts parser.parse('silly generativists!') # => nil Users of *regular expressions* will find parsing expressions familiar. They share the same basic purpose, matching strings against patterns. However, parsing expressions can recognize a broader category of languages than their less expressive brethren. Before we get into demonstrating that, lets cover some basics. At first parsing expressions won't seem much different. Trust that they are. Terminal Symbols ---------------- The expression in the grammar above is a terminal symbol. It will only match a string that matches it exactly. There are two other kinds of terminal symbols, which we'll revisit later. Terminals are called *atomic expressions* because they aren't composed of smaller expressions. Ordered Choices --------------- Ordered choices are *composite expressions*, which allow for any of several subexpressions to be matched. These should be familiar from regular expressions, but in parsing expressions, they are delimited by the `/` character. Its important to note that the choices are prioritized in the order they appear. If an earlier expression is matched, no subsequent expressions are tried. Here's an example: # my_grammar.treetop grammar MyGrammar rule hello 'hello chomsky' / 'hello lambek' end end # fragment of use_grammar.rb puts parser.parse('hello chomsky') # => Treetop::Runtime::SyntaxNode puts parser.parse('hello lambek') # => Treetop::Runtime::SyntaxNode puts parser.parse('silly generativists!') # => nil Note that once a choice rule has matched the text using a particular alternative at a particular location in the input and hence has succeeded, that choice will never be reconsidered, even if the chosen alternative causes another rule to fail where a later alternative wouldn't have. It's always a later alternative, since the first to succeed is final - why keep looking when you've found what you wanted? This is a feature of PEG parsers that you need to understand if you're going to succeed in using Treetop. In order to memoize success and failures, such decisions cannot be reversed. Luckily Treetop provides a variety of clever ways you can tell it to avoid making the wrong decisions. But more on that later. Sequences --------- Sequences are composed of other parsing expressions separated by spaces. Using sequences, we can tighten up the above grammar. # my_grammar.treetop grammar MyGrammar rule hello 'hello ' ('chomsky' / 'lambek') end end Note the use of parentheses to override the default precedence rules, which bind sequences more tightly than choices. Once the whole sequence has been matched, the result is memoized and the details of the match will not be reconsidered for that location in the input. Nonterminal Symbols ------------------- Here we leave regular expressions behind. Nonterminals allow expressions to refer to other expressions by name. A trivial use of this facility would allow us to make the above grammar more readable should the list of names grow longer. # my_grammar.treetop grammar MyGrammar rule hello 'hello ' linguist end rule linguist 'chomsky' / 'lambek' / 'jacobsen' / 'frege' end end The true power of this facility, however, is unleashed when writing *recursive expressions*. Here is a self-referential expression that can match any number of open parentheses followed by any number of closed parentheses. This is theoretically impossible with regular expressions due to the *pumping lemma*. # parentheses.treetop grammar Parentheses rule parens '(' parens ')' / '' end end The `parens` expression simply states that a `parens` is a set of parentheses surrounding another `parens` expression or, if that doesn't match, the empty string. If you are uncomfortable with recursion, its time to get comfortable, because it is the basis of language. Here's a tip: Don't try and imagine the parser circling round and round through the same rule. Instead, imagine the rule is *already* defined while you are defining it. If you imagine that `parens` already matches a string of matching parentheses, then its easy to think of `parens` as an open and closing parentheses around another set of matching parentheses, which conveniently, you happen to be defining. You know that `parens` is supposed to represent a string of matched parentheses, so trust in that meaning, even if you haven't fully implemented it yet. Repetition ---------- Any item in a rule may be followed by a '+' or a '*' character, signifying one-or-more and zero-or-more occurrences of that item. Beware though; the match is greedy, and if it matches too many items and causes subsequent items in the sequence to fail, the number matched will never be reconsidered. Here's a simple example of a rule that will never succeed: # toogreedy.treetop grammar TooGreedy rule a_s 'a'* 'a' end end The 'a'* will always eat up any 'a's that follow, and the subsequent 'a' will find none there, so the whole rule will fail. You might need to use lookahead to avoid matching too much. Alternatively, you can use an occurrence range: # toogreedy.treetop grammar TooGreedy rule two_to_four_as 'a' 2..4 end end In an occurrence range, you may omit either the minimum count or the maximum count, so that "0.. " works like "*" and "1.. " works like '+'. Negative Lookahead ------------------ When you need to ensure that the following item *doesn't* match in some case where it might otherwise, you can use negat!ve lookahead, which is an item preceeded by a ! - here's an example: # postcondition.treetop grammar PostCondition rule conditional_sentence ( !conditional_keyword word )+ conditional_keyword [ \t]+ word* end rule word ([a-zA-Z]+ [ \t]+) end rule conditional_keyword 'if' / 'while' / 'until' end end Even though the rule `word` would match any of the conditional keywords, the first words of a conditional_sentence must not be conditional_keywords. The negative lookahead prevents that matching, and prevents the repetition from matching too much input. Note that the lookahead may be a grammar rule of any complexity, including one that isn't used elsewhere in your grammar. Positive lookahead ------------------ Sometimes you want an item to match, but only if the *following* text would match some pattern. You don't want to consume that following text, but if it's not there, you want this rule to fail. You can append a positive lookahead like this to a rule by appending the lookahead rule preceeded by an & character. Semantic predicates ------------------- Warning: This is an advanced feature. You need to understand the way a packrat parser operates to use it correctly. The result of computing a rule containing a semantic predicate will be memoized, even if the same rule, applied later at the same location in the input, would work differently due to a semantic predicate returning a different value. If you don't understand the previous sentence yet still use this feature, you're on your own, so test carefully! Sometimes, you need to run external Ruby code to decide whether this syntax rule should continue or should fail. You can do this using either positive or negative semantic predicates. These are Ruby code blocks (lambdas) which are called when the parser reaches that location. For this rule to succeed, the value must be true for a positive predicate (a block like &{ ... }), or false for a negative predicate (a block like !{ ... }). The block is called with one argument, the array containing the preceding syntax nodes in the current sequence. Within the block, you cannot use node names or labels for the preceding nodes, as the node for the current rule does not yet exist. You must refer to preceding nodes using their position in the sequence. grammar Keywords rule sequence_of_reserved_and_nonreserved_words ( reserved / word )* end rule reserved word &{ |s| symbol_reserved?(s[0].text_value) } end rule word ([a-zA-Z]+ [ \t]+) end end One case where it is always safe to use a semantic predicate is to invoke the Ruby debugger, but don't forget to return true so the rule succeeds! Assuming you have required the 'ruby-debug' module somewhere, it looks like this: rule problems word &{ |s| debugger; true } end When the debugger stops here, you can inspect the contents of the SyntaxNode for "word" by looking at s[0], and the stack trace will show how you got there. treetop-1.4.14/Rakefile0000644000004100000410000000356312157663062014777 0ustar www-datawww-datarequire 'rubygems' require 'bundler' Bundler.setup(:default, :development) require 'rake' require 'jeweler' require 'rspec/core/rake_task' require File.expand_path("../lib/treetop/version", __FILE__) Jeweler::Tasks.new do |gem| gem.name = "treetop" gem.version = Treetop::VERSION::STRING gem.author = ["Nathan Sobo", "Clifford Heath"] gem.license = "MIT" gem.email = "cliffordheath@gmail.com" gem.homepage = "https://github.com/cjheath/treetop" gem.platform = Gem::Platform::RUBY gem.summary = "A Ruby-based text parsing and interpretation DSL" gem.files = ["LICENSE", "README.md", "Rakefile", "treetop.gemspec", "{spec,lib,bin,doc,examples}/**/*"].map{|p| Dir[p]}.flatten gem.bindir = "bin" gem.executables = ["tt"] gem.require_path = "lib" gem.autorequire = "treetop" gem.has_rdoc = false gem.add_dependency "polyglot", ">= 0.3.1" end Jeweler::RubygemsDotOrgTasks.new task :default => :spec RSpec::Core::RakeTask.new do |t| t.pattern = 'spec/**/*spec.rb' # t.libs << 'spec' # @todo not sure what this did in the original rspec 1.3 end task :spec => 'lib/treetop/compiler/metagrammar.treetop' file 'lib/treetop/compiler/metagrammar.treetop' do |t| unless $bootstrapped_gen_1_metagrammar load File.expand_path('../lib/treetop/bootstrap_gen_1_metagrammar.rb', __FILE__) end Treetop::Compiler::GrammarCompiler.new.compile(METAGRAMMAR_PATH) end task :version do puts RUBY_VERSION end desc 'Generate website files' task :website_generate do `cd doc; ruby ./site.rb` end desc 'Upload website files' task :website_upload do rubyforge_config_file = "#{ENV['HOME']}/.rubyforge/user-config.yml" rubyforge_config = YAML.load_file(rubyforge_config_file) `rsync -aCv doc/site/ #{rubyforge_config['username']}@rubyforge.org:/var/www/gforge-projects/treetop/` end desc 'Generate and upload website files' task :website => [:website_generate, :website_upload] treetop-1.4.14/spec/0000755000004100000410000000000012157663062014255 5ustar www-datawww-datatreetop-1.4.14/spec/ruby_extensions/0000755000004100000410000000000012157663062017515 5ustar www-datawww-datatreetop-1.4.14/spec/ruby_extensions/string_spec.rb0000644000004100000410000000142512157663062022364 0ustar www-datawww-datarequire 'spec_helper' describe String do before do @string = %{ 0123456789 012345 01234567 0123 }.tabto(0).strip end it "can translate indices to column numbers" do @string.column_of(0).should == 1 @string.column_of(5).should == 6 @string.column_of(10).should == 11 @string.column_of(11).should == 1 @string.column_of(17).should == 7 @string.column_of(18).should == 1 @string.column_of(24).should == 7 end it "can translate indices to line numbers" do @string.line_of(0).should == 1 @string.line_of(5).should == 1 @string.line_of(10).should == 1 @string.line_of(11).should == 2 @string.line_of(17).should == 2 @string.line_of(18).should == 3 @string.line_of(24).should == 3 end end treetop-1.4.14/spec/compiler/0000755000004100000410000000000012157663062016067 5ustar www-datawww-datatreetop-1.4.14/spec/compiler/zero_or_more_spec.rb0000644000004100000410000000342512157663062022133 0ustar www-datawww-datarequire 'spec_helper' module ZeroOrMoreSpec class Foo < Treetop::Runtime::SyntaxNode end describe "zero or more of a terminal symbol followed by a node class declaration and a block" do testing_expression '"foo"* { def a_method; end }' it "successfully parses epsilon, returning an instance declared node class and recording a terminal failure" do parse('') do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "successfully parses two of that terminal in a row, returning an instance of the declared node class and recording a failure representing the third attempt " do parse("foofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 6 failure.expected_string.should == 'foo' end end end describe "Zero or more of a sequence" do testing_expression '("foo" "bar")*' it "resets the index appropriately following partially matcing input" do parse('foobarfoo', :consume_all_input => false) do |result| result.should_not be_nil result.interval.should == (0...6) end end end describe "Zero or more of a choice" do testing_expression '("a" / "b")*' it "successfully parses matching input" do parse('abba').should_not be_nil end end end treetop-1.4.14/spec/compiler/grammar_compiler_spec.rb0000644000004100000410000000672412157663062022757 0ustar www-datawww-datarequire 'spec_helper' require 'tmpdir' describe Compiler::GrammarCompiler do attr_reader :compiler, :source_path_with_treetop_extension, :source_path_with_tt_extension, :target_path, :alternate_target_path before do @compiler = Compiler::GrammarCompiler.new dir = File.dirname(__FILE__) @tmpdir = Dir.tmpdir @source_path_with_treetop_extension = "#{dir}/test_grammar.treetop" @source_path_with_do = "#{dir}/test_grammar_do.treetop" @source_path_with_tt_extension = "#{dir}/test_grammar.tt" @target_path = "#{@tmpdir}/test_grammar.rb" @target_path_with_do = "#{@tmpdir}/test_grammar_do.rb" @alternate_target_path = "#{@tmpdir}/test_grammar_alt.rb" delete_target_files end after do delete_target_files Object.class_eval do remove_const(:Test) if const_defined?(:Test) end end specify "compilation of a single file to a default file name" do src_copy = "#{@tmpdir}/test_grammar.treetop" File.open(source_path_with_treetop_extension) { |f| File.open(src_copy,'w'){|o|o.write(f.read)} } File.exists?(target_path).should be_false compiler.compile(src_copy) File.exists?(target_path).should be_true require target_path Test::GrammarParser.new.parse('foo').should_not be_nil end specify "compilation of a single file to an explicit file name" do File.exists?(alternate_target_path).should be_false compiler.compile(source_path_with_treetop_extension, alternate_target_path) File.exists?(alternate_target_path).should be_true require alternate_target_path Test::GrammarParser.new.parse('foo').should_not be_nil end specify "compilation of a single file without writing it to an output file" do compiler.ruby_source(source_path_with_treetop_extension).should_not be_nil end specify "ruby_source_from_string compiles a grammar stored in string" do compiler.ruby_source_from_string(File.read(source_path_with_treetop_extension)).should_not be_nil end specify "Treetop.load_from_string compiles and evaluates a source grammar stored in string" do Treetop.load_from_string File.read(source_path_with_treetop_extension) Test::GrammarParser.new.parse('foo').should_not be_nil end specify "Treetop.load compiles and evaluates a source grammar with a .treetop extension" do Treetop.load source_path_with_treetop_extension Test::GrammarParser.new.parse('foo').should_not be_nil end specify "Treetop.load compiles and evaluates a source grammar with a .tt extension" do path_without_extension = source_path_with_tt_extension Treetop.load path_without_extension Test::GrammarParser.new.parse('foo').should_not be_nil end specify "Treetop.load compiles and evaluates source grammar with no extension" do path_without_extension = source_path_with_treetop_extension.gsub(/\.treetop\Z/, '') Treetop.load path_without_extension Test::GrammarParser.new.parse('foo').should_not be_nil end specify "grammars with 'do' compile" do src_copy = "#{@tmpdir}/test_grammar_do.treetop" File.open(@source_path_with_do) { |f| File.open(src_copy,'w'){|o|o.write(f.read)} } compiler.compile(src_copy) require @target_path_with_do Test::GrammarParser.new.parse('foo').should_not be_nil end def delete_target_files File.delete(target_path) if File.exists?(target_path) File.delete(@target_path_with_do) if File.exists?(@target_path_with_do) File.delete(alternate_target_path) if File.exists?(alternate_target_path) end end treetop-1.4.14/spec/compiler/multibyte_chars_spec.rb0000644000004100000410000000253212157663062022626 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' module MultibyteCharsSpec describe "an anything symbol", :multibyte => true do testing_expression '.' it "matches an UTF-8 character" do parse_multibyte("ø").should_not be_nil end end describe "A character class containing UTF-8 characters", :multibyte => true do testing_expression "[æøå]" it "recognizes the UTF-8 characters" do parse_multibyte("ø").should_not be_nil end end describe( "a character class repetition containing UTF-8 characters mixed with other expressions", :multibyte => true ) do testing_expression '[æøå]+ "a"' it "lazily instantiates a node for the character" do result = parse_multibyte('æøåa') pending "Multibyte support is not supported in Ruby 1.8.6" if RUBY_VERSION =~ /^1\.8.6/ result.elements[0].instance_variable_get("@elements").should include(true) result.elements[0].elements.should_not include(true) result.elements[0].elements.size.should == 3 result.elements.size.should == 2 result.elements[0].text_value.should == "æøå" result.elements[0].elements[0].text_value.should == "æ" result.elements[0].elements[1].text_value.should == "ø" result.elements[0].elements[2].text_value.should == "å" result.elements[1].text_value == "a" end end end treetop-1.4.14/spec/compiler/failure_propagation_functional_spec.rb0000644000004100000410000000127012157663062025702 0ustar www-datawww-datarequire 'spec_helper' describe "An expression for braces surrounding zero or more letters followed by semicolons" do testing_expression "'{' ([a-z] ';')* '}'" it "parses matching input successfully" do parse('{a;b;c;}').should_not be_nil end it "fails to parse input with an expression that is missing a semicolon, reporting the terminal failure occurring at the maximum index" do parse('{a;b;c}') do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures[0] failure.index.should == 6 failure.expected_string.should == ';' end end end treetop-1.4.14/spec/compiler/occurrence_range_spec.rb0000644000004100000410000001513512157663062022737 0ustar www-datawww-datarequire 'spec_helper' module OccurrenceRangeSpec class Foo < Treetop::Runtime::SyntaxNode end describe "zero to two of a terminal symbol followed by a node class declaration and a block" do testing_expression '"foo"..2 { def a_method; end }' it "successfully parses epsilon, reporting a failure" do parse('') do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "successfully parses epsilon, returning an instance declared node class and recording a terminal failure" do parse('') do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "successfully parses one of that terminal, returning an instance of the declared node class and recording a terminal failure" do parse("foo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 3 failure.expected_string.should == 'foo' end end it "successfully parses two of that terminal, returning an instance of the declared node class and reporting no failure" do parse("foofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end it "fails to parses three of that terminal, returning an instance of the declared node class and reporting no failure" do parse("foofoofoo") do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end end describe "two to four of a terminal symbol followed by a node class declaration and a block" do testing_expression '"foo" 2..4 { def a_method; end }' it "fails to parse epsilon, reporting a failure" do parse('') do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "fails to parse one of that terminal, returning an instance of the declared node class and recording a terminal failure" do parse("foo") do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 3 failure.expected_string.should == 'foo' end end it "successfully parses two of that terminal, returning an instance of the declared node class and reporting no failure" do parse("foofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 6 failure.expected_string.should == 'foo' end end it "successfully parses four of that terminal, returning an instance of the declared node class and reporting no failure" do parse("foofoofoofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end it "fails to parses five of that terminal, returning an instance of the declared node class and reporting no failure" do parse("foofoofoofoofoo") do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end end describe "two to any number of a terminal symbol followed by a node class declaration and a block" do testing_expression '"foo" 2.. { def a_method; end }' it "fails to parse epsilon, reporting a failure" do parse('') do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "fails to parse one of that terminal, returning an instance of the declared node class and recording a terminal failure" do parse("foo") do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 3 failure.expected_string.should == 'foo' end end it "successfully parses two of that terminal, returning an instance of the declared node class and reporting no failure" do parse("foofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 6 failure.expected_string.should == 'foo' end end it "successfully parses four of that terminal, returning an instance of the declared node class and reporting a failure on the fifth" do parse("foofoofoofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 12 failure.expected_string.should == 'foo' end end end end treetop-1.4.14/spec/compiler/character_class_spec.rb0000644000004100000410000002330712157663062022554 0ustar www-datawww-datarequire 'spec_helper' module CharacterClassSpec class Foo < Treetop::Runtime::SyntaxNode end describe "a character class followed by a node class declaration and a block" do testing_expression "[A-Z] { def a_method; end }" it "matches single characters within that range, returning instances of the declared node class that respond to the method defined in the inline module" do result = parse('A') result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result = parse('N') result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result = parse('Z') result.should be_an_instance_of(Foo) result.should respond_to(:a_method) end it "does not match single characters outside of that range" do parse('8').should be_nil parse('a').should be_nil end it "matches a single character within that range at index 1" do parse(' A', :index => 1).should_not be_nil end it "fails to match a single character out of that range at index 1" do parse(' 1', :index => 1).should be_nil end end module ModFoo end describe "a character class followed by a node module declaration and a block" do testing_expression "[A-Z] { def a_method; end }" it "matches single characters within that range, returning instances of SyntaxNode extended by the specified module" do result = parse('A') result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result = parse('N') result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result = parse('Z') result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) end it "does not match single characters outside of that range" do parse('8').should be_nil parse('a').should be_nil end it "matches a single character within that range at index 1" do parse(' A', :index => 1).should_not be_nil end it "fails to match a single character out of that range at index 1" do parse(' 1', :index => 1).should be_nil end end describe "a character class with a POSIX bracket expression" do testing_expression "[[:digit:]]" it "matches a single character within the class" do parse('1').should_not be_nil end it "does not match a single character outside the class" do parse('a').should be_nil parse('-').should be_nil end testing_expression "[[:digit:][:space:]]+" it "matches a string with a mix of two character classes" do parse('1 4 9').should_not be_nil end end describe "a character class with a negated POSIX bracket expression" do testing_expression "[[:^space:]]" it "matches a character outside the negated class" do parse('a').should_not be_nil end it "doesn't match a character within the negated class" do parse(' ').should be_nil end end describe "a character class followed by a node class declaration and a block" do testing_expression "[A-Z] " it "actively generates nodes for the character when it is the primary node" do result = parse('A') result.should be_a(Treetop::Runtime::SyntaxNode) result.elements.should be_nil end end describe "A character class containing quotes" do testing_expression "[\"']" it "matches a quote" do parse("'").should_not be_nil end it "matches a double-quote" do parse('"').should_not be_nil end end describe "A character class containing a special character" do testing_expression "[\t]" it "matches that character only" do parse("\t").should_not be_nil parse('t').should be_nil end end describe "A character class containing an escaped backslash" do slash = "\\" # Make it explicit that there are *two* backslashes here testing_expression "[#{slash}#{slash}]" it "matches a backslash only" do parse("\\").should_not be_nil parse('t').should be_nil end end describe "A character class containing a hex escape" do slash = "\\" testing_expression "[#{slash}x41]" it "matches that character only" do parse('A').should_not be_nil parse('\\').should be_nil parse('x').should be_nil parse('4').should be_nil parse('1').should be_nil end end describe "A character class containing an octal escape" do slash = "\\" testing_expression "[#{slash}101]" it "matches that character only" do parse('A').should_not be_nil parse('\\').should be_nil parse('1').should be_nil parse('0').should be_nil end end describe "A character class containing a \\c control-char escape" do slash = "\\" testing_expression "[#{slash}cC]" it "matches that character only" do parse("\003").should_not be_nil parse('\\').should be_nil parse('c').should be_nil parse('C').should be_nil end end describe "A character class containing a \\C- control-char escape" do slash = "\\" testing_expression "[#{slash}C-C]" it "matches that character only" do parse("\003").should_not be_nil parse('\\').should be_nil parse('C').should be_nil parse('-').should be_nil end end if RUBY_VERSION =~ /\A1\.8\./ describe "A character class containing a \\M- meta-char escape" do slash = "\\" testing_expression "[#{slash}M- ]" it "matches that character only" do parse("\240").should_not be_nil parse('\\').should be_nil parse('M').should be_nil parse('-').should be_nil parse(' ').should be_nil end end end describe "A character class containing an escaped non-special character" do slash = "\\" testing_expression "[#{slash}y]" it "matches that character only" do parse("y").should_not be_nil parse('\\').should be_nil end end describe "A character class containing an \#{...} insertion" do testing_expression "[\#{raise 'error'}]" it "doesn't evaluate the insertion" do x = true lambda{ x = parse("y") }.should_not raise_error x.should be_nil parse('#').should_not be_nil parse("'").should_not be_nil parse("0").should be_nil end end describe "a character class" do testing_expression "[A-Z]" it "actively generates a node for the character because it is the primary node" do result = parse('A') result.should be_a(Treetop::Runtime::SyntaxNode) result.elements.should be_nil end end describe "a character class mixed with other expressions" do testing_expression '[A-Z] "a"' it "lazily instantiates a node for the character" do result = parse('Aa') result.instance_variable_get("@elements").should include(true) result.elements.should_not include(true) result.elements.size.should == 2 end end describe "a character class with a node class declaration mixed with other expressions" do testing_expression '([A-Z] ) "a"' it "actively generates a node for the character because it has a node class declared" do result = parse('Aa') result.instance_variable_get("@elements").should_not include(true) result.elements.should_not include(true) result.elements.size.should == 2 end end describe "a character class with a node module declaration mixed with other expressions" do testing_expression '([A-Z] ) "a"' it "actively generates a node for the character because it has a node module declared" do result = parse('Aa') result.instance_variable_get("@elements").should_not include(true) result.elements.should_not include(true) result.elements.size.should == 2 end end describe "a character class with an inline block mixed with other expressions" do testing_expression '([A-Z] { def a_method; end }) "a"' it "actively generates a node for the character because it has an inline block" do result = parse('Aa') result.instance_variable_get("@elements").should_not include(true) result.elements.should_not include(true) result.elements.size.should == 2 end end describe "a character class with a label mixed with other expressions" do testing_expression 'upper:([A-Z]) "b"' it "returns the correct element for the labeled expression" do result = parse('Ab') result.upper.text_value.should == "A" result.elements.size.should == 2 end end describe "a character class repetition mixed with other expressions" do testing_expression '[A-Z]+ "a"' it "lazily instantiates a node for the character" do result = parse('ABCa') result.elements[0].instance_variable_get("@elements").should include(true) result.elements[0].elements.should_not include(true) result.elements[0].elements.size.should == 3 result.elements.size.should == 2 result.elements.inspect.should == %Q{[SyntaxNode offset=0, "ABC":\n SyntaxNode offset=0, "A"\n SyntaxNode offset=1, "B"\n SyntaxNode offset=2, "C", SyntaxNode offset=3, "a"]} end end describe "a character class that gets cached because of a choice" do testing_expression "[A-Z] 'a' / [A-Z]" it "generates a node for the lazily-instantiated character when it is the primary node" do result = parse('A') result.should be_a(Treetop::Runtime::SyntaxNode) result.elements.should be_nil end end end treetop-1.4.14/spec/compiler/sequence_spec.rb0000644000004100000410000001121212157663062021233 0ustar www-datawww-datarequire 'spec_helper' module SequenceSpec class Foo < Treetop::Runtime::SyntaxNode end describe "a sequence of labeled terminal symbols followed by a node class declaration and a block" do testing_expression 'foo:"foo" bar:"bar" baz:"baz" { def a_method; end }' it "upon successfully matching input, instantiates an instance of the declared node class with element accessor methods and the method from the inline module" do parse('foobarbaz') do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.foo.text_value.should == 'foo' result.bar.text_value.should == 'bar' result.baz.text_value.should == 'baz' end end it "successfully matches at a non-zero index" do parse('---foobarbaz', :index => 3) do |result| result.should_not be_nil result.should be_nonterminal (result.elements.map {|elt| elt.text_value}).join.should == 'foobarbaz' end end it "fails to match non-matching input, recording the parse failure of first non-matching terminal" do parse('---foobazbaz', :index => 3) do |result| result.should be_nil parser.index.should == 3 terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 6 failure.expected_string.should == 'bar' end end end module ModFoo def mod_method; end end describe "a sequence of labeled terminal symbols followed by a node module declaration and a block" do testing_expression 'foo:"foo" bar:"bar" baz:"baz" { def a_method; end }' it "upon successfully matching input, instantiates a syntax node and extends it with the declared module, element accessor methods, and the method from the inline module" do parse('foobarbaz') do |result| result.should_not be_nil result.should respond_to(:mod_method) result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result.foo.text_value.should == 'foo' result.bar.text_value.should == 'bar' result.baz.text_value.should == 'baz' end end end describe "a labeled single element sequence followed by a node module declaration and a block" do testing_expression 'foo:"foo"+ { def a_method; end }' it "upon successfully matching input, instantiates a syntax node and extends it with the declared module, element accessor methods, and the method from the inline module" do parse('foofoofoo') do |result| result.should_not be_nil result.should respond_to(:mod_method) result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result.foo.text_value.should == 'foofoofoo' end end end describe "a sequence of non-terminals" do testing_grammar %{ grammar TestGrammar rule sequence foo bar baz { def baz 'override' + super.text_value end } end rule foo 'foo' end rule bar 'bar' end rule baz 'baz' end end } it "defines accessors for non-terminals automatically that can be overridden in the inline block" do parse('foobarbaz') do |result| result.foo.text_value.should == 'foo' result.bar.text_value.should == 'bar' result.baz.should == 'overridebaz' end end end describe "Compiling a sequence containing various white-space errors" do it "should succeed on a valid sequence" do compiling_expression('foo:"foo" "bar" { def a_method; end }').should_not raise_error end it "rejects space after a label" do compiling_expression('foo :"foo" "bar"').should raise_error(RuntimeError) end it "rejects space after label's colon" do compiling_expression('foo: "foo" "bar"').should raise_error(RuntimeError) end it "rejects missing space after a primary" do compiling_expression('foo:"foo""bar"').should raise_error(RuntimeError) end it "rejects missing space before node class declaration" do compiling_expression('foo:"foo" "bar"').should raise_error(RuntimeError) end it "rejects missing space before inline module" do compiling_expression('foo:"foo" "bar" {def a_method; end}').should raise_error(RuntimeError) end end end treetop-1.4.14/spec/compiler/optional_spec.rb0000644000004100000410000000213212157663062021251 0ustar www-datawww-datarequire 'spec_helper' module OptionalSpec describe "An optional terminal symbol" do testing_expression '"foo"?' it "parses input matching the terminal" do parse('foo').should_not be_nil end it "parses epsilon, recording a failure" do parse('') do |result| result.should_not be_nil result.interval.should == (0...0) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "parses input not matching the terminal, returning an epsilon result and recording a failure" do parse('bar', :consume_all_input => false) do |result| result.should_not be_nil result.interval.should == (0...0) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end end end treetop-1.4.14/spec/compiler/test_grammar.tt0000644000004100000410000000011012157663062021115 0ustar www-datawww-datamodule Test grammar Grammar rule foo 'foo' end end endtreetop-1.4.14/spec/compiler/anything_symbol_spec.rb0000644000004100000410000000272512157663062022642 0ustar www-datawww-datarequire 'spec_helper' module AnythingSymbolSpec class Foo < Treetop::Runtime::SyntaxNode end describe "an anything symbol followed by a node class declaration and a block" do testing_expression '. { def a_method; end }' it "matches any single character in a big range, returning an instance of the declared node class that responds to methods defined in the inline module" do (33..127).each do |digit| parse(digit.chr) do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (0...1) end end end it "fails to parse epsilon" do parse('').should be_nil end end module ModFoo end describe "an anything symbol followed by a module declaration and a block" do testing_expression '. { def a_method; end }' it "matches any single character in a big range, returning an instance of SyntaxNode extended by the declared module that responds to methods defined in the inline module" do (33..127).each do |digit| parse(digit.chr) do |result| result.should_not be_nil result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result.interval.should == (0...1) end end end end end treetop-1.4.14/spec/compiler/circular_compilation_spec.rb0000644000004100000410000000156712157663062023641 0ustar www-datawww-datarequire 'spec_helper' BENCHMARK = false METAGRAMMAR_PATH = File.expand_path('../../../lib/treetop/compiler/metagrammar.treetop', __FILE__) module CircularCompilationSpec describe "a parser for the metagrammar" do attr_reader :parser before do @parser = Treetop::Compiler::MetagrammarParser.new end it "can parse the metagrammar.treetop whence it was generated" do File.open(METAGRAMMAR_PATH, 'r') do |f| metagrammar_source = f.read result = parser.parse(metagrammar_source) result.should_not be_nil # generated_parser = result.compile # Object.class_eval(generated_parser) # parser_2 = Treetop::Compiler::MetagrammarParser.new # optionally_benchmark do # result = parser_2.parse(metagrammar_source) # result.should_not be_nil # end end end end end treetop-1.4.14/spec/compiler/choice_spec.rb0000644000004100000410000000500112157663062020654 0ustar www-datawww-datarequire 'spec_helper' module ChoiceSpec describe "A choice between terminal symbols" do testing_expression '"foo" { def foo_method; end } / "bar" { def bar_method; end } / "baz" { def baz_method; end }' it "successfully parses input matching any of the alternatives, returning a node that responds to methods defined in its respective inline module" do result = parse('foo') result.should_not be_nil result.should respond_to(:foo_method) result = parse('bar') result.should_not be_nil result.should respond_to(:bar_method) result = parse('baz') result.should_not be_nil result.should respond_to(:baz_method) end it "upon parsing a string matching the second alternative, records the failure of the first terminal" do result = parse('bar') terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures[0] failure.expected_string.should == 'foo' failure.index.should == 0 end it "upon parsing a string matching the third alternative, records the failure of the first two terminals" do result = parse('baz') terminal_failures = parser.terminal_failures terminal_failures.size.should == 2 failure_1 = terminal_failures[0] failure_1.expected_string == 'foo' failure_1.index.should == 0 failure_2 = terminal_failures[1] failure_2.expected_string == 'bar' failure_2.index.should == 0 end end describe "A choice between sequences" do testing_expression "'foo' 'bar' 'baz'\n/\n'bing' 'bang' 'boom'" it "successfully parses input matching any of the alternatives" do parse('foobarbaz').should_not be_nil parse('bingbangboom').should_not be_nil end end describe "A choice between terminals followed by a block" do testing_expression "('a'/ 'b' / 'c') { def a_method; end }" it "extends a match of any of its subexpressions with a module created from the block" do ['a', 'b', 'c'].each do |letter| parse(letter).should respond_to(:a_method) end end end module TestModule def a_method end end describe "a choice followed by a declared module" do testing_expression "('a'/ 'b' / 'c') " it "extends a match of any of its subexpressions with a module created from the block" do ['a', 'b', 'c'].each do |letter| parse(letter).should respond_to(:a_method) end end end end treetop-1.4.14/spec/compiler/parenthesized_expression_spec.rb0000644000004100000410000000065412157663062024557 0ustar www-datawww-datarequire 'spec_helper' module ParenthesizedExpressionSpec describe "An unadorned expression inside of parentheses" do testing_expression '("foo")' it "should behave as normal" do parse('foo').should_not be_nil end end describe "A prefixed-expression inside of parentheses" do testing_expression '(!"foo")' it "should behave as normal" do parse('foo').should be_nil end end end treetop-1.4.14/spec/compiler/nonterminal_symbol_spec.rb0000644000004100000410000000176012157663062023345 0ustar www-datawww-datarequire 'spec_helper' module NonterminalSymbolSpec describe "A nonterminal symbol followed by a block" do testing_expression 'foo { def a_method; end }' parser_class_under_test.class_eval do def _nt_foo '_nt_foo called' end end it "compiles to a method call, extending its results with the anonymous module for the block" do result = parse('') result.should == '_nt_foo called' result.should respond_to(:a_method) end end module TestModule def a_method end end describe "a non-terminal followed by a module declaration" do testing_expression 'foo ' parser_class_under_test.class_eval do def _nt_foo '_nt_foo called' end end it "compiles to a method call, extending its results with the anonymous module for the block" do result = parse('') result.should == '_nt_foo called' result.should respond_to(:a_method) end end end treetop-1.4.14/spec/compiler/test_grammar.treetop0000644000004100000410000000011012157663062022150 0ustar www-datawww-datamodule Test grammar Grammar rule foo 'foo' end end endtreetop-1.4.14/spec/compiler/grammar_spec.rb0000644000004100000410000000144112157663062021054 0ustar www-datawww-datarequire 'spec_helper' module GrammarSpec module Bar end describe "a grammar" do testing_grammar %{ grammar Foo # This comment should not cause a syntax error, nor should the following empty one # include GrammarSpec::Bar rule foo bar / baz end rule bar 'bar' 'bar' end rule baz 'baz' 'baz' end end } it "parses matching input" do parse('barbar').should_not be_nil parse('bazbaz').should_not be_nil end it "fails if it does not parse all input" do parse('barbarbazbaz').should be_nil end it "mixes in included modules" do self.class.const_get(:Foo).ancestors.should include(GrammarSpec::Bar) end end end treetop-1.4.14/spec/compiler/test_grammar_do.treetop0000644000004100000410000000011712157663062022641 0ustar www-datawww-datamodule Test grammar Grammar do rule foo do 'foo' end end end treetop-1.4.14/spec/compiler/namespace_spec.rb0000644000004100000410000000153112157663062021362 0ustar www-datawww-datarequire 'spec_helper' module NamespaceSpec describe "a grammar" do class_eval("module Foo; end") testing_grammar %{ module Foo::Bar module Baz grammar Bat rule foo bar / baz end rule bar 'bar' 'bar' end rule baz 'baz' 'baz' end end end end } it "parses matching input" do parse('barbar').should_not be_nil parse('bazbaz').should_not be_nil end it "mixes in included modules" do foo = self.class.const_get(:Foo) bar = foo.const_get(:Bar) baz = bar.const_get(:Baz) baz.class.should == Module bat = baz.const_get(:Bat) bat.class.should == Module baz.const_get(:BatParser).class.should == Class end end end treetop-1.4.14/spec/compiler/not_predicate_spec.rb0000644000004100000410000000207212157663062022247 0ustar www-datawww-datarequire 'spec_helper' module NotPredicateSpec describe "A !-predicated terminal symbol" do testing_expression '!"foo"' it "fails to parse input matching the terminal symbol" do parse('foo').should be_nil end end describe "A sequence of a terminal and an and another !-predicated terminal" do testing_expression '"foo" !"bar"' it "fails to match input matching both terminals" do parse('foobar').should be_nil end it "successfully parses input matching the first terminal and not the second, reporting the parse failure of the second terminal" do parse('foo') do |result| result.should_not be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 3 failure.expected_string.should == 'bar' end end end describe "A !-predicated sequence" do testing_expression '!("a" "b" "c")' it "fails to parse matching input" do parse('abc').should be_nil end end end treetop-1.4.14/spec/compiler/semantic_predicate_spec.rb0000644000004100000410000001337612157663062023263 0ustar www-datawww-datarequire 'spec_helper' module SemanticPredicateSpec describe "An &-predicate block" do testing_expression '& {|| $ok_to_succeed}' it "succeeds if it returns true, returning an epsilon syntax node" do $ok_to_succeed = true parse('foo', :consume_all_input => false) do |result| result.should_not be_nil result.interval.should == (0...0) end end it "fails if it returns false" do $ok_to_succeed = false parse('foo', :consume_all_input => false) do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end end describe "A sequence of a terminal and an &-predicate block" do testing_expression '"prior " &{|s| $value = s[0].text_value; $ok_to_succeed }' it "matches the input terminal and consumes it if the block returns true, seeing the terminal in the sequence" do $ok_to_succeed = true $value = nil parse('prior foo', :consume_all_input => false) do |result| result.should_not be_nil result.elements[0].text_value.should == "prior " result.text_value.should == 'prior ' $value.should == 'prior ' end end it "fails if the block returns false, but sees the terminal in the sequence" do $ok_to_succeed = false $value = nil parse('prior foo', :consume_all_input => false) do |result| result.should be_nil $value.should == 'prior ' terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end end describe "A sequence of an optional terminal and an &-predicate block" do testing_expression '"prior "? &{|s| $value = s[0].text_value; $ok_to_succeed}' it "matches the input terminal and consumes it if the block returns true" do $ok_to_succeed = true parse('prior foo', :consume_all_input => false) do |result| result.should_not be_nil result.elements[0].text_value.should == "prior " result.text_value.should == 'prior ' $value.should == 'prior ' end end it "fails with no terminal_failures if the block returns false" do $ok_to_succeed = false parse('prior foo', :consume_all_input => false) do |result| result.should be_nil $value.should == 'prior ' terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end it "fail and return the expected optional preceeding terminal as expected input if the block returns false" do $ok_to_succeed = false parse('foo', :consume_all_input => false) do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures[0] failure.index.should == 0 failure.expected_string.should == 'prior ' end end end describe "A !-predicate block" do testing_expression '! {|| $ok_to_succeed}' it "succeeds if it returns false, returning an epsilon syntax node" do $ok_to_succeed = false parse('foo', :consume_all_input => false) do |result| result.should_not be_nil result.interval.should == (0...0) end end it "fails if it returns true" do $ok_to_succeed = true parse('foo', :consume_all_input => false) do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end end describe "A sequence of a terminal and an !-predicate block" do testing_expression '"prior " !{|s| $value = s[0].text_value; $ok_to_succeed }' it "matches the input terminal and consumes it if the block returns false, seeing the terminal in the sequence" do $ok_to_succeed = false $value = nil parse('prior foo', :consume_all_input => false) do |result| result.should_not be_nil result.elements[0].text_value.should == "prior " result.text_value.should == 'prior ' $value.should == 'prior ' end end it "fails if the block returns true, but sees the terminal in the sequence" do $ok_to_succeed = true $value = nil parse('prior foo', :consume_all_input => false) do |result| result.should be_nil $value.should == 'prior ' terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end end describe "A sequence of an optional terminal and an !-predicate block" do testing_expression '"prior "? !{|s| $value = s[0].text_value; $ok_to_succeed}' it "matches the input terminal and consumes it if the block returns false" do $ok_to_succeed = false parse('prior foo', :consume_all_input => false) do |result| result.should_not be_nil result.elements[0].text_value.should == "prior " result.text_value.should == 'prior ' $value.should == 'prior ' end end it "fails with no terminal_failures if the block returns true" do $ok_to_succeed = true parse('prior foo', :consume_all_input => false) do |result| result.should be_nil $value.should == 'prior ' terminal_failures = parser.terminal_failures terminal_failures.size.should == 0 end end it "fail and return the expected optional preceeding terminal as expected input if the block returns true" do $ok_to_succeed = true parse('foo', :consume_all_input => false) do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures[0] failure.index.should == 0 failure.expected_string.should == 'prior ' end end end end treetop-1.4.14/spec/compiler/and_predicate_spec.rb0000644000004100000410000000221412157663062022207 0ustar www-datawww-datarequire 'spec_helper' module AndPredicateSpec describe "An &-predicated terminal symbol" do testing_expression '&"foo"' it "successfully parses input matching the terminal symbol, returning an epsilon syntax node" do parse('foo', :consume_all_input => false) do |result| result.should_not be_nil result.interval.should == (0...0) end end end describe "A sequence of a terminal and an and another &-predicated terminal" do testing_expression '"foo" &"bar"' it "matches input matching both terminals, but only consumes the first" do parse('foobar', :consume_all_input => false) do |result| result.should_not be_nil result.text_value.should == 'foo' end end it "fails to parse input matching only the first terminal, with a terminal failure recorded at index 3" do parse('foo') do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures[0] failure.index.should == 3 failure.expected_string.should == 'bar' end end end end treetop-1.4.14/spec/compiler/one_or_more_spec.rb0000644000004100000410000000225712157663062021737 0ustar www-datawww-datarequire 'spec_helper' module OneOrMoreSpec class Foo < Treetop::Runtime::SyntaxNode end describe "one or more of a terminal symbol followed by a node class declaration and a block" do testing_expression '"foo"+ { def a_method; end }' it "fails to parse epsilon, reporting a failure" do parse('') do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'foo' end end it "successfully parses two of that terminal in a row, returning an instance of the declared node class and reporting the failure the third parsing attempt" do parse("foofoo") do |result| result.should_not be_nil result.should be_an_instance_of(Foo) result.should respond_to(:a_method) terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 6 failure.expected_string.should == 'foo' end end end end treetop-1.4.14/spec/compiler/tt_compiler_spec.rb0000644000004100000410000001676012157663062021761 0ustar www-datawww-datarequire 'digest/sha1' require 'tmpdir' # ensure the Kernel.system and Kernel.open's always use the correct tt and # Treetop library versions, not a previously installed gem ENV['PATH'] = File.expand_path(File.dirname(__FILE__) + '../../../bin' + File::PATH_SEPARATOR + ENV['PATH']) $LOAD_PATH.unshift(File.expand_path('../../../../lib', __FILE__)) describe "The 'tt' comand line compiler" do before(:each) do @tmpdir = Dir.tmpdir end context 'when processing a single grammar file' do before(:each) do # create a fresh but dumb grammar file for each example @test_base = "dumb-#{rand(1000)}" @test_path = "#{@tmpdir}/#{@test_base}" @test_grammar = "#{@test_path}.tt" @test_ruby = "#{@test_path}.rb" File.open(@test_grammar, 'w+') do |f| f.print("# Encoding: UTF-8\n") f.print("grammar Dumb\n") f.print("end\n") end unless File.exists?(@test_grammar) end after(:each) do # cleanup test grammar and parser output files File.delete(@test_grammar) if File.exists?(@test_grammar) File.delete(@test_ruby) if File.exists?(@test_ruby) end it 'can compile a grammar file' do # puts %q{emulate 'tt dumb.tt'} system("ruby -S tt #{@test_grammar}").should be_true File.exists?(@test_ruby).should be_true File.zero?(@test_ruby).should_not be_true end it 'can compile a relative pathed grammar file' do dir = File.basename(File.expand_path(File.dirname(@test_grammar))) # puts %q{emulate 'tt "..//dumb.tt"'} system("cd #{@tmpdir}/..; ruby -S tt \"./#{dir}/#{@test_base}.tt\"").should be_true File.exists?(@test_ruby).should be_true File.zero?(@test_ruby).should_not be_true end it 'can compile an absolute pathed grammar file' do # puts %q{emulate 'tt "/path/to/dumb.tt"'} system("ruby -S tt \"#{File.expand_path(@test_grammar)}\"").should be_true File.exists?(@test_ruby).should be_true File.zero?(@test_ruby).should_not be_true end it 'can compile without explicit file extensions' do # puts %q{emulate 'tt dumb'} system("ruby -S tt #{@test_path}").should be_true File.exists?(@test_ruby).should be_true File.zero?(@test_ruby).should_not be_true end it 'skips nonexistent grammar file without failing or creating bogus output' do # puts %q{emulate 'tt dumb.bad'} Kernel.open("|ruby -S tt #{@test_base}.bad") do |io| (io.read =~ /ERROR.*?not exist.*?continuing/).should_not be_nil end File.exists?("#{@test_base}.rb").should be_false end it 'can compile to a specified parser source file' do # puts %q{emulate 'tt -o my_dumb_test_parser.rb dumb'} pf = "#{@tmpdir}/my_dumb_test_parser.rb" begin system("ruby -S tt -o #{pf} #{@test_path}").should be_true File.exists?(pf).should be_true File.zero?(pf).should_not be_true ensure File.delete(pf) if File.exists?(pf) end end it 'by default, does not overwrite an existing file without an autogenerated header' do # puts %q{emulate 'tt -o must_save_parser.rb dumb'} pf = "#{@tmpdir}/must_save_parser.rb" begin system("ruby -S tt -o #{pf} #{@test_path}").should be_true File.exists?(pf).should be_true File.zero?(pf).should_not be_true # Check that the magic comment is preserved: written = File.open(pf, "r") { |f| s = f.read } written.should =~ /\A# Encoding: UTF-8/ # Modify the file's auto-generated comment and make sure it doesn't get overwritten: written.sub!(/generated/, 'broken'); File.open(pf, "w") { |f| f.write(written) } # File.open(pf, "r+") { |f| s = f.read; s.sub!(/generated/, 'broken'); f.rewind; f.write(s) } orig_file_hash = Digest::SHA1.hexdigest(File.read(pf)) Kernel.open("|ruby -S tt -o #{pf} #{@test_path}") do |io| (io.read =~ /ERROR.*?already exists.*?skipping/).should_not be_nil end Digest::SHA1.hexdigest(File.read(pf)).should == orig_file_hash ensure File.delete(pf) if File.exists?(pf) end end it 'by default, overwrites a changed file with an intact autogenerated header' do # puts %q{emulate 'tt -o must_save_parser.rb dumb'} pf = "#{@tmpdir}/must_save_parser.rb" begin system("ruby -S tt -o #{pf} #{@test_path}").should be_true File.exists?(pf).should be_true File.zero?(pf).should_not be_true orig_file_hash = Digest::SHA1.hexdigest(File.read(pf)) # Modify the file and make sure it gets reverted: File.open(pf, "r+") { |f| f.gets; f.write("#") } system("ruby -S tt -o #{pf} #{@test_path}").should be_true Digest::SHA1.hexdigest(File.read(pf)).should == orig_file_hash ensure File.delete(pf) if File.exists?(pf) end end it 'can be forced to overwrite existing file #{@test_path}' do pf = "#{@test_path}.rb" system("echo some junk >#{pf}").should be_true File.exists?(pf).should be_true File.zero?(pf).should_not be_true orig_file_hash = Digest::SHA1.hexdigest(File.read(pf)) system("ruby -S tt -f #{@test_path}").should be_true Digest::SHA1.hexdigest(File.read(pf)).should_not == orig_file_hash end end context 'when processing multiple grammar files' do before(:each) do # provide fresh but dumb grammar files for each test @test_bases = [] @test_grammars = [] %w[dumb1 dumb2].each do |e| base = "#{@tmpdir}/#{e}-#{rand(1000)}" grammar_file = "#{base}.tt" @test_bases << base @test_grammars << grammar_file File.open(grammar_file, 'w+') do |f| f.print("grammar #{e.capitalize}\n") f.print("end\n") end unless File.exists?(grammar_file) end end after(:each) do # cleanup test grammar and output parser files @test_grammars.each { |f| File.delete(f) if File.exists?(f) } @test_bases.each { |f| File.delete("#{f}.rb") if File.exists?("#{f}.rb") } end it 'can compile them in one invocation' do # puts %q{emulate 'tt dumb1.tt dumb2.tt'} system("ruby -S tt #{@test_grammars.join(' ')}").should be_true @test_bases.each do |f| pf = "#{f}.rb" File.exists?(pf).should be_true File.zero?(pf).should_not be_true end end it 'can compile them without explicit file extenstions' do # puts %q{emulate 'tt dumb1 dumb2'} system("ruby -S tt #{@test_bases.join(' ')}").should be_true @test_bases.each do |f| pf = "#{f}.rb" File.exists?(pf).should be_true File.zero?(pf).should_not be_true end end it 'can skip nonexistent and invalid extension named grammar files' do # puts %q{emulate 'tt not_here bad_ext.ttg dumb1 dumb2'} system("ruby -S tt not_here bad_ext.ttg #{@test_bases.join(' ')} >/dev/null 2>&1").should be_true File.exists?('not_here.rb').should_not be_true File.exists?('bad_ext.rb').should_not be_true @test_bases.each do |f| pf = "#{f}.rb" File.exists?(pf).should be_true File.zero?(pf).should_not be_true end end it 'can not specify an output file' do # puts %q{emulate 'tt -o my_bogus_test_parser.rb dumb1 dumb2'} pf = 'my_bogus_test_parser.rb' system("ruby -S tt -o #{pf} #{@test_bases.join(' ')} >/dev/null 2>&1").should be_false File.exists?(pf).should be_false end end end treetop-1.4.14/spec/compiler/repeated_subrule_spec.rb0000644000004100000410000000124712157663062022764 0ustar www-datawww-datarequire 'spec_helper' module RepeatedSubruleSpec describe "a repeated subrule" do testing_grammar %{ grammar Foo rule foo a:'a' space b:'b' space 'c' end rule space ' ' end end } it "should produce a parser having sequence-numbered node accessor methods" do parse("a b c") do |result| result.should_not be_nil result.should respond_to(:space1) result.should respond_to(:space2) result.should_not respond_to(:space) result.should respond_to(:a) result.should respond_to(:b) result.should_not respond_to(:c) end end end end treetop-1.4.14/spec/compiler/terminal_symbol_spec.rb0000644000004100000410000000240612157663062022630 0ustar www-datawww-datarequire 'spec_helper' module TerminalSymbolSpec class Foo < Treetop::Runtime::SyntaxNode end describe "a terminal symbol followed by a node class declaration and a block" do testing_expression "'foo' { def a_method; end }" it "correctly parses matching input prefixes at various indices, returning an instance of the declared class that can respond to methods defined in the inline module" do parse "foo", :index => 0 do |result| result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (0...3) result.text_value.should == 'foo' end parse "xfoo", :index => 1 do |result| result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (1...4) result.text_value.should == 'foo' end parse "---foo", :index => 3 do |result| result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (3...6) result.text_value.should == 'foo' end end it "fails to parse nonmatching input at the index even if a match occurs later" do parse(" foo", :index => 0).should be_nil end end end treetop-1.4.14/spec/compiler/terminal_spec.rb0000644000004100000410000000560312157663062021245 0ustar www-datawww-datarequire 'spec_helper' module TerminalSymbolSpec class Foo < Treetop::Runtime::SyntaxNode end describe "a terminal symbol followed by a node class declaration and a block" do testing_expression "'foo' { def a_method; end }" it "correctly parses matching input prefixes at various indices, returning an instance of the declared class that can respond to methods defined in the inline module" do parse "foo", :index => 0 do |result| result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (0...3) result.text_value.should == 'foo' end parse "xfoo", :index => 1 do |result| result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (1...4) result.text_value.should == 'foo' end parse "---foo", :index => 3 do |result| result.should be_an_instance_of(Foo) result.should respond_to(:a_method) result.interval.should == (3...6) result.text_value.should == 'foo' end end it "fails to parse nonmatching input at the index even if a match occurs later" do parse(" foo", :index => 0).should be_nil end end module ModFoo end describe "a terminal symbol followed by a node class declaration and a block" do testing_expression "'foo' { def a_method; end }" it "correctly parses matching input prefixes at various indices, returning an instance of SyntaxNode extended with the declared module that can respond to methods defined in the inline module" do parse "foo", :index => 0 do |result| result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result.interval.should == (0...3) result.text_value.should == 'foo' end parse "xfoo", :index => 1 do |result| result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result.interval.should == (1...4) result.text_value.should == 'foo' end parse "---foo", :index => 3 do |result| result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) result.should be_a_kind_of(ModFoo) result.should respond_to(:a_method) result.interval.should == (3...6) result.text_value.should == 'foo' end end end describe "a transient terminal symbol" do testing_expression "~'foo'" it "returns true upon parsing matching input prefixes at various indices" do pending "transient terminal expressions" parse("foo", :index => 0).should be_true parse("-foo", :index => 1).should be_true parse("---foo", :index => 3).should be_true end end end treetop-1.4.14/spec/compiler/parsing_rule_spec.rb0000644000004100000410000000266612157663062022132 0ustar www-datawww-datarequire 'spec_helper' module ParsingRuleSpec describe "a grammar with one parsing rule" do testing_grammar %{ grammar Foo rule bar "baz" end end } it "stores and retrieves nodes in its node cache" do parser = self.class.const_get(:FooParser).new parser.send(:prepare_to_parse, 'baz') node_cache = parser.send(:node_cache) node_cache[:bar][0].should be_nil parser._nt_bar cached_node = node_cache[:bar][0] cached_node.should be_an_instance_of(Runtime::SyntaxNode) cached_node.text_value.should == 'baz' parser.instance_eval { @index = 0 } parser._nt_bar.should equal(cached_node) parser.index.should == cached_node.interval.end end end describe "a grammar with choice that uses the cache and has a subsequent expression" do testing_grammar %{ grammar Logic rule expression value_plus / value end rule value_plus value "something else" end rule value [a-z] / "foobar" # the subsequent expression that needs cached.interval.end end end } it "parses a single-character value and generates a node from the cache" do result = parse('a') result.should be_a(Treetop::Runtime::SyntaxNode) result.elements.should be_nil end end end treetop-1.4.14/spec/composition/0000755000004100000410000000000012157663062016620 5ustar www-datawww-datatreetop-1.4.14/spec/composition/c.treetop0000644000004100000410000000014312157663062020444 0ustar www-datawww-datamodule Test grammar C include A include B rule c a b 'c' end end endtreetop-1.4.14/spec/composition/grammar_composition_spec.rb0000644000004100000410000000201612157663062024227 0ustar www-datawww-datarequire 'spec_helper' module GrammarCompositionSpec describe "several composed grammars" do before do dir = File.dirname(__FILE__) Treetop.load File.join(dir, 'a') Treetop.load File.join(dir, 'b') Treetop.load File.join(dir, 'c') # Check that polyglot finds d.treetop and loads it: $: << dir require 'd' @c = ::Test::CParser.new @d = ::Test::DParser.new end specify "rules in C have access to rules defined in A and B" do @c.parse('abc').should_not be_nil end specify "rules in C can override rules in A and B with super semantics" do @d.parse('superkeywordworks').should_not be_nil end end describe "composed grammar chaining with require" do before do # Load f with polyglot without using the load path: require File.dirname(__FILE__) + '/f' @f = ::Test::FParser.new end specify "rules in F have access to rule defined in E" do @f.parse('abcef').should_not be_nil end end end treetop-1.4.14/spec/composition/d.treetop0000644000004100000410000000015712157663062020452 0ustar www-datawww-datamodule Test grammar D include A include B rule inherit super 'works' end end endtreetop-1.4.14/spec/composition/b.treetop0000644000004100000410000000016212157663062020444 0ustar www-datawww-datamodule Test grammar B rule b 'b' end rule inherit super 'keyword' end end endtreetop-1.4.14/spec/composition/f.treetop0000644000004100000410000000034212157663062020450 0ustar www-datawww-data require "a" require File.dirname(__FILE__) + "/b" require File.dirname(__FILE__) + "/subfolder/e_includes_c" module Test grammar F include A include B include E rule f c e 'f' end end end treetop-1.4.14/spec/composition/a.treetop0000644000004100000410000000015212157663062020442 0ustar www-datawww-datamodule Test grammar A rule a 'a' end rule inherit 'super' end end endtreetop-1.4.14/spec/composition/subfolder/0000755000004100000410000000000012157663062020605 5ustar www-datawww-datatreetop-1.4.14/spec/composition/subfolder/e_includes_c.treetop0000644000004100000410000000025012157663062024622 0ustar www-datawww-datarequire File.dirname(__FILE__) + "/../c" module Test grammar E include C rule e 'e' end rule inherit 'super' end end end treetop-1.4.14/spec/runtime/0000755000004100000410000000000012157663062015740 5ustar www-datawww-datatreetop-1.4.14/spec/runtime/interval_skip_list/0000755000004100000410000000000012157663062021645 5ustar www-datawww-datatreetop-1.4.14/spec/runtime/interval_skip_list/palindromic_fixture_spec.rb0000644000004100000410000000757212157663062027266 0ustar www-datawww-datarequire 'runtime/interval_skip_list/spec_helper' describe "The palindromic fixture", :palindromic => true do include PalindromicFixtureSharedContext describe " #nodes" do describe "[0]" do before do @node = list.nodes[0] end it "has a key of 1 and a height of 3" do node.key.should == 1 node.height.should == 3 end it "has :c, :d, :e, and :f as its only forward markers at level 2" do node.forward_markers[2].should have_markers(:c, :d, :e, :f) end it "has :a, :b as its only forward markers at level 1" do node.forward_markers[1].should have_markers(:a, :b) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has no markers" do node.markers.should be_empty end end describe "[1]" do before do @node = list.nodes[1] end it "has a key of 3 and a height of 2" do node.key.should == 3 node.height.should == 2 end it "has no forward markers at level 1" do node.forward_markers[1].should be_empty end it "has :b as its only forward marker at level 0" do node.forward_markers[0].should have_marker(:b) end it "has :a and :b as its only markers" do node.markers.should have_markers(:a, :b) end end describe "[2]" do before do @node = list.nodes[2] end it "has a key of 5 and a height of 1" do node.key.should == 5 node.height.should == 1 end it "has :g as its only forward marker at level 0" do node.forward_markers[0].should have_marker(:g) end it "has :b as its only marker" do node.markers.should have_marker(:b) end end describe "[3]" do before do @node = list.nodes[3] end it "has a key of 7 and a height of 3" do node.key.should == 7 node.height.should == 3 end it "has :f and :g as its only forward markers at level 2" do node.forward_markers[2].should have_markers(:f, :g) end it "has :e as its only forward markers at level 1" do node.forward_markers[1].should have_marker(:e) end it "has :d as its only forward marker at level 0" do node.forward_markers[0].should have_markers(:d) end it "has :c, :d, :e, :f and :g as its only markers" do node.markers.should have_markers(:c, :d, :e, :f, :g) end end describe "[4]" do before do @node = list.nodes[4] end it "has a key of 9 and a height of 1" do node.key.should == 9 node.height.should == 1 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty end it "has :d as its only marker" do node.markers.should have_markers(:d) end end describe "[5]" do before do @node = list.nodes[5] end it "has a key of 11 and a height of 2" do node.key.should == 11 node.height.should == 2 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty end it "has :e as its only marker" do node.markers.should have_markers(:e) end end describe "[6]" do before do @node = list.nodes[6] end it "has a key of 13 and a height of 3" do node.key.should == 13 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :f and :g as its only markers" do node.markers.should have_markers(:f, :g) end end end end treetop-1.4.14/spec/runtime/interval_skip_list/delete_spec.rb0000644000004100000410000000672712157663062024462 0ustar www-datawww-datarequire 'runtime/interval_skip_list/spec_helper' class IntervalSkipList public :insert_node, :delete_node, :head, :nodes end describe IntervalSkipList, :palindromic => true do include PalindromicFixtureSharedContext describe " when :c is deleted" do before do list.delete(:c) end describe "[0]" do before do @node = list.nodes[0] end it "has a key of 1 and a height of 3" do node.key.should == 1 node.height.should == 3 end it "has :f as its only forward marker at level 2" do node.forward_markers[2].should have_markers(:f) end it "has :a, :b, :d, and :e as its only forward markers at level 1" do node.forward_markers[1].should have_markers(:a, :b, :d, :e) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has no markers" do node.markers.should be_empty end end describe "[1]" do before do @node = list.nodes[1] end it "has a key of 3 and a height of 2" do node.key.should == 3 node.height.should == 2 end it "has :e as its only forward marker at level 1" do node.forward_markers[1].should have_markers(:e) end it "has :b and :d as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:b, :d) end it "has :a, :b, :d, and :e as its only markers" do node.markers.should have_markers(:a, :b, :d, :e) end end describe "[2]" do before do @node = list.nodes[2] end it "has a key of 5 and a height of 1" do node.key.should == 5 node.height.should == 1 end it "has :d and :g as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:d, :g) end it "has :b and :d as its only markers" do node.markers.should have_markers(:b, :d) end end describe "[3]" do before do @node = list.nodes[3] end it "has a key of 9 and a height of 1" do node.key.should == 9 node.height.should == 1 end it "has :g as its only forward marker at level 0" do node.forward_markers[0].should have_markers(:g) end it "has :d and :g as its only markers" do node.markers.should have_markers(:d, :g) end end describe "[4]" do before do @node = list.nodes[4] end it "has a key of 11 and a height of 2" do node.key.should == 11 node.height.should == 2 end it "has :g as its only forward marker at level 1" do node.forward_markers[1].should have_markers(:g) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :e and :g as its only markers" do node.markers.should have_markers(:e, :g) end end describe "[5]" do before do @node = list.nodes[5] end it "has a key of 13 and a height of 3" do node.key.should == 13 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :f and :g as its only markers" do node.markers.should have_markers(:f, :g) end end end end treetop-1.4.14/spec/runtime/interval_skip_list/palindromic_fixture.rb0000644000004100000410000000144212157663062026242 0ustar www-datawww-datamodule PalindromicFixtureSharedContext extend RSpec::Core::SharedContext include IntervalSkipListSpecHelper attr_reader :list, :node def construct_interval_skip_list @list = IntervalSkipList.new end def expected_node_heights [3, 2, 1, 3, 1, 2, 3] end def populate_interval_skip_list @list.insert(1..3, :a) @list.insert(1..5, :b) @list.insert(1..7, :c) @list.insert(1..9, :d) @list.insert(1..11, :e) @list.insert(1..13, :f) @list.insert(5..13, :g) end def make_it_determinisitic extend NextNodeHeightIsDeterministicSharedContext # use the method without getting the filter next_node_height_is_deterministic end before :each do construct_interval_skip_list make_it_determinisitic populate_interval_skip_list end end treetop-1.4.14/spec/runtime/interval_skip_list/insert_and_delete_node_spec.rb0000644000004100000410000002240612157663062027665 0ustar www-datawww-datarequire 'runtime/interval_skip_list/spec_helper' shared_examples_for "it is non-empty" do specify "#empty? returns false" do list.should_not be_empty end end shared_examples_for "#nodes is an array of the three inserted nodes in key order" do specify "#nodes is an array of the three inserted nodes in key order" do list.nodes.should == inserted_nodes.sort_by(&:key) end end shared_examples_for "it has nil forward pointers" do it "has nil forward pointers" do inserted_node.forward.each do |next_pointer| next_pointer.should be_nil end end end describe IntervalSkipList do attr_reader :list before do @list = IntervalSkipList.new end describe " when nothing has been inserted" do specify "#empty? returns true" do list.should be_empty end specify "#nodes returns an empty array" do list.nodes.should == [] end describe "#head" do attr_reader :head before do @head = list.head end it "#has a height of #max_height" do head.height.should == list.max_height end it "has nil forward pointers" do 0.upto(list.max_height - 1) do |i| head.forward[i].should be_nil end end end end describe " when 1 has been inserted", :deterministic => true do attr_reader :inserted_node, :inserted_nodes def expected_node_heights [1] end include NextNodeHeightIsDeterministicSharedContext before do @inserted_node = list.insert_node(1) @inserted_nodes = [@inserted_node] end it_should_behave_like "it is non-empty" it_should_behave_like "#nodes is an array of the three inserted nodes in key order" describe "#head" do attr_reader :head before do @head = list.head end it "has inserted_node.height forward pointers pointing at the inserted node" do 0.upto(inserted_node.height - 1) do |i| head.forward[i].should == inserted_node end end it "has the rest of its forward pointers pointing at nil" do inserted_node.height.upto(list.max_height - 1) do |i| head.forward[i].should == nil end end end describe "the inserted node" do it_should_behave_like "it has nil forward pointers" it "has a height of the expected_node_heights.first" do inserted_node.height.should == expected_node_heights.first end it "has a key of 1" do inserted_node.key.should == 1 end end describe "and subsequently deleted" do before do list.delete_node(1) end specify "#empty? returns true" do list.should be_empty end end end describe " when 1 and 3 have been inserted in order", :deterministic => true do attr_reader :inserted_nodes def expected_node_heights [1, 2] end include NextNodeHeightIsDeterministicSharedContext before do @inserted_nodes = [] inserted_nodes << list.insert_node(1) inserted_nodes << list.insert_node(3) end it_should_behave_like "it is non-empty" it_should_behave_like "#nodes is an array of the three inserted nodes in key order" describe "the first inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[0] end it "has a key of 1" do inserted_node.key.should == 1 end it "has a height of the first expected node height" do inserted_node.height.should == expected_node_heights[0] end it "has its single forward pointer pointing at the second inserted node" do inserted_node.forward[0].should == inserted_nodes[1] end end describe "the second inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[1] end it_should_behave_like "it has nil forward pointers" it "has a key of 3" do inserted_node.key.should == 3 end it "has a height of the second expected node height" do inserted_node.height.should == expected_node_heights[1] end end describe "and 1 is subsequently deleted" do before do list.delete_node(1) end describe "the remaining node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[1] end it "is the first node in the list" do inserted_node.should == list.nodes[0] end it_should_behave_like "it has nil forward pointers" end end describe "and 3 is subsequently deleted" do before do list.delete_node(3) end describe "the remaining node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[0] end it "is the first node in the list" do inserted_node.should == list.nodes[0] end it_should_behave_like "it has nil forward pointers" end end end describe " when 1, 3 and 7 have been inserted in order", :deterministic => true do attr_reader :inserted_nodes def expected_node_heights [1, 2, 1] end include NextNodeHeightIsDeterministicSharedContext before do @inserted_nodes = [] inserted_nodes << list.insert_node(1) inserted_nodes << list.insert_node(3) inserted_nodes << list.insert_node(7) end it_should_behave_like "it is non-empty" it_should_behave_like "#nodes is an array of the three inserted nodes in key order" describe "the first inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[0] end it "has a key of 1" do inserted_node.key.should == 1 end it "has a height of the first expected node height" do inserted_node.height.should == expected_node_heights[0] end it "has its single forward pointer pointing at the second inserted node" do inserted_node.forward[0].should == inserted_nodes[1] end end describe "the second inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[1] end it "has a key of 3" do inserted_node.key.should == 3 end it "has a height of the second expected node height" do inserted_node.height.should == expected_node_heights[1] end it "has a forward pointer at level 0 pointing to the third inserted node" do inserted_node.forward[0].should == inserted_nodes[2] end it "has nil forward pointer at level 1" do inserted_node.forward[1].should be_nil end end describe "the third inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[2] end it_should_behave_like "it has nil forward pointers" it "has a key of 3" do inserted_node.key.should == 7 end it "has a height of the third expected node height" do inserted_node.height.should == expected_node_heights[2] end end describe "and 3 is subsequently deleted" do before do list.delete_node(3) end specify "#head points at nil at levels 1 and 2" do list.head.forward[1].should be_nil list.head.forward[2].should be_nil end specify "#nodes contains the remaining nodes in order" do list.nodes.should == [inserted_nodes[0], inserted_nodes[2]] end end end describe " when 7, 1 and 3 have been inserted in order", :deterministic => true do attr_reader :inserted_nodes def expected_node_heights [1, 1, 2] end include NextNodeHeightIsDeterministicSharedContext before do @inserted_nodes = [] inserted_nodes << list.insert_node(7) inserted_nodes << list.insert_node(1) inserted_nodes << list.insert_node(3) end it_should_behave_like "it is non-empty" it_should_behave_like "#nodes is an array of the three inserted nodes in key order" describe "the first inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[0] end it_should_behave_like "it has nil forward pointers" it "has a key of 7" do inserted_node.key.should == 7 end it "has a height of the first expected node height" do inserted_node.height.should == expected_node_heights[0] end end describe "the second inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[1] end it "has a key of 1" do inserted_node.key.should == 1 end it "has a height of the second expected node height" do inserted_node.height.should == expected_node_heights[1] end it "has a forward pointer at level 0 pointing to the second node in the list" do inserted_node.forward[0].should == list.nodes[1] end end describe "the third inserted node" do attr_reader :inserted_node before do @inserted_node = inserted_nodes[2] end it "has a key of 3" do inserted_node.key.should == 3 end it "has a height of the third expected node height" do inserted_node.height.should == expected_node_heights[2] end end end endtreetop-1.4.14/spec/runtime/interval_skip_list/interval_skip_list_spec.rb0000644000004100000410000000345412157663062027117 0ustar www-datawww-data#require 'runtime/interval_skip_list/spec_helper' # #MAX_INTERVAL = 100000 # #describe IntervalSkipList do # describe "#next_node_height" do # attr_reader :list # # before do # @list = IntervalSkipList.new # end # # it "returns a number between 1 and the max_height of the list" do # height = list.next_node_height # height.should be <= list.max_height # height.should be > 0 # end # end # # describe "a list with 1000 random intervals" do # attr_reader :list, :inserted_ranges # # before do # @list = IntervalSkipList.new # @inserted_ranges = [] # # 0.upto(10) do |i| # first, last = [rand(MAX_INTERVAL), rand(MAX_INTERVAL)].sort # range = first..last # list.insert(range, i) # inserted_ranges.push(range) # end # end # # it "functions correctly for stabbing queries" do # 10000.times do # n = rand(MAX_INTERVAL) # ranges = list.containing(n).sort # # expected_ranges = [] # inserted_ranges.each_with_index do |range,i| # expected_ranges.push(i) if n > range.first && n < range.last # end # expected_ranges.sort! # unless ranges == expected_ranges # puts "N = #{n}" # puts "Expected: " + expected_ranges.inspect # puts "Actual: " + ranges.inspect # expected_ranges.size.should be <= ranges.size # puts "Missing containers: #{(expected_ranges.map {|o| o.object_id} - ranges.map {|o| o.object_id}).inspect}" # puts "Unexpected containers: #{(ranges.map {|o| o.object_id} - expected_ranges.map {|o| o.object_id}).inspect}" # puts "Inserted Ranges: #{inserted_ranges.inspect}" # puts "Expected Ranges: #{expected_ranges.map {|i| inserted_ranges[i]}.inspect}" # end # end # end # end #end treetop-1.4.14/spec/runtime/interval_skip_list/interval_skip_list_spec.graffle0000644000004100000410000044417112157663062030127 0ustar www-datawww-data CreationDate 2008-01-23 19:21:27 -0800 Creator pivotal GraphDocumentVersion 5 GuidesLocked NO GuidesVisible YES ImageCounter 1 LinksVisible NO MagnetsVisible NO MasterSheets ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 in = 1 in GraphicsList Bounds {{676.1, 164.06}, {24, 14}} Class ShapedGraphic FitText YES Flow Resize ID 209 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 13} Wrap NO Bounds {{566.114, 164.06}, {23, 14}} Class ShapedGraphic FitText YES Flow Resize ID 207 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 11} Wrap NO Bounds {{463.723, 164.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 206 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 9} Wrap NO Bounds {{359.775, 164.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 205 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 7} Wrap NO Bounds {{264.057, 164.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 204 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 5} Wrap NO Bounds {{160.599, 164.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 203 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 3} Wrap NO Bounds {{51.8613, 164.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 202 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 1} Wrap NO Bounds {{311.301, 122.432}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 100 Line ID 45 Position 0.49750059843063354 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 g} Bounds {{411.092, 122.432}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 91 Line ID 46 Position 0.4975009560585022 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 d} Bounds {{461.295, 81.4593}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 90 Line ID 40 Position 0.48428341746330261 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 e} Bounds {{501.164, 40.4863}, {24, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 89 Line ID 36 Position 0.44795909523963928 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 f g} Bounds {{194.113, 40.4863}, {43, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 88 Line ID 35 Position 0.50672364234924316 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 c d e f} Bounds {{212.329, 122.432}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 86 Line ID 44 Position 0.49750003218650818 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b} Bounds {{97.2116, 81.4594}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 85 Line ID 37 Position 0.43750011920928955 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b} Class LineGraphic Head ID 32 ID 48 Points {598.785, 129.432} {667.238, 129.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 30 Class LineGraphic Head ID 30 ID 47 Points {493.394, 129.432} {556.752, 129.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 16 Class LineGraphic Head ID 16 ID 46 Points {388.138, 129.432} {451.361, 129.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 25 Class LineGraphic Head ID 25 ID 45 Points {293.698, 129.432} {346.165, 129.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 6 Class LineGraphic Head ID 6 ID 44 Points {190.24, 129.432} {251.725, 129.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 19 Class LineGraphic Head ID 19 ID 42 Points {81.5016, 129.432} {148.267, 129.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 21 Class LineGraphic Head ID 33 ID 41 Points {598.785, 88.4593} {667.238, 88.4593} Style stroke HeadArrow 0 TailArrow 0 Tail ID 29 Class LineGraphic Head ID 29 ID 40 Points {388.138, 88.4593} {556.752, 88.4593} Style stroke HeadArrow 0 TailArrow 0 Tail ID 26 Class LineGraphic Head ID 26 ID 38 Points {190.24, 88.4593} {346.165, 88.4593} Style stroke HeadArrow 0 TailArrow 0 Tail ID 18 Class LineGraphic Head ID 18 ID 37 Points {81.5016, 88.4594} {148.267, 88.4594} Style stroke HeadArrow 0 TailArrow 0 Tail ID 22 Class LineGraphic Head ID 34 ID 36 Points {388.138, 47.4863} {667.238, 47.4863} Style stroke HeadArrow 0 TailArrow 0 Tail ID 27 Class LineGraphic Head ID 27 ID 35 Points {81.5016, 47.4863} {346.165, 47.4863} Style stroke HeadArrow 0 TailArrow 0 Tail ID 23 Bounds {{451.861, 108.946}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 16 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 d} Class Group Graphics Bounds {{557.252, 67.973}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 29 Shape Rectangle Bounds {{557.252, 108.946}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 30 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 e} ID 28 Class Group Graphics Bounds {{667.738, 108.946}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 32 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 f g} Bounds {{667.738, 67.973}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 33 Shape Rectangle Bounds {{667.738, 27}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 34 Shape Rectangle ID 31 Class Group Graphics Bounds {{346.665, 108.946}, {40.9727, 40.9726}} Class ShapedGraphic ID 25 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 c d e f g} Bounds {{346.665, 67.973}, {40.9727, 40.9726}} Class ShapedGraphic ID 26 Shape Rectangle Bounds {{346.665, 27}, {40.9727, 40.9726}} Class ShapedGraphic ID 27 Shape Rectangle ID 24 Bounds {{252.225, 108.946}, {40.9727, 40.9726}} Class ShapedGraphic ID 6 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b} Class Group Graphics Bounds {{148.767, 67.973}, {40.9727, 40.9727}} Class ShapedGraphic ID 18 Shape Rectangle Bounds {{148.767, 108.946}, {40.9727, 40.9727}} Class ShapedGraphic ID 19 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b} ID 17 Class Group Graphics Bounds {{40.0289, 108.946}, {40.9727, 40.9727}} Class ShapedGraphic ID 21 Shape Rectangle Bounds {{40.0289, 67.973}, {40.9727, 40.9727}} Class ShapedGraphic ID 22 Shape Rectangle Bounds {{40.0289, 27}, {40.9727, 40.9727}} Class ShapedGraphic ID 23 Shape Rectangle ID 20 GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle Master 1 UniqueID 1 VPages 1 ModificationDate 2008-01-25 12:52:43 -0800 Modifier pivotal NotesVisible NO OriginVisible NO PageBreaks YES PrintInfo NSBottomMargin float 0 NSLeftMargin float 0 NSOrientation int 1 NSPaperSize size {792, 612} NSRightMargin float 0 NSTopMargin float 0 ReadOnly NO Sheets ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 in = 1 in GraphicsList Bounds {{337.9, 223.864}, {73, 18}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 15 ID 210 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs30 \cf0 delete(:c)} Wrap NO Bounds {{617.836, 328.64}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 103 Line ID 74 Position 0.49193865060806274 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 g} Bounds {{509.836, 369.613}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 101 Line ID 79 Position 0.49032312631607056 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 g} Bounds {{356.356, 369.613}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 99 Line ID 83 Position 0.52189022302627563 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 d g} Bounds {{360.246, 328.64}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 96 Line ID 82 Position 0.50374859571456909 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 e} Bounds {{360.548, 287.667}, {14, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 95 Line ID 81 Position 0.49880927801132202 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 f} Bounds {{201.204, 369.613}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 94 Line ID 76 Position 0.4975002110004425 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b d} Bounds {{84.0915, 328.64}, {47, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 93 Line ID 71 Position 0.4825001060962677 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b d e} Class LineGraphic Head ID 68 ID 83 Points {287.573, 376.612} {445.237, 376.613} Style stroke HeadArrow 0 TailArrow 0 Tail ID 56 Class LineGraphic Head ID 66 ID 82 Points {184.115, 335.64} {550.629, 335.64} Style stroke HeadArrow 0 TailArrow 0 Tail ID 54 Class LineGraphic Head ID 64 ID 81 Points {75.3772, 294.667} {661.114, 294.667} Style stroke HeadArrow 0 TailArrow 0 Tail ID 52 Class LineGraphic Head ID 62 ID 80 Points {592.661, 376.612} {661.114, 376.612} Style stroke HeadArrow 0 TailArrow 0 Tail ID 67 Class LineGraphic Head ID 67 ID 79 Points {487.269, 376.613} {550.629, 376.612} Style stroke HeadArrow 0 TailArrow 0 Tail ID 68 Class LineGraphic Head ID 56 ID 76 Points {184.115, 376.613} {245.601, 376.612} Style stroke HeadArrow 0 TailArrow 0 Tail ID 55 Class LineGraphic Head ID 55 ID 75 Points {75.3772, 376.612} {142.143, 376.613} Style stroke HeadArrow 0 TailArrow 0 Tail ID 50 Class LineGraphic Head ID 63 ID 74 Points {592.661, 335.64} {661.114, 335.64} Style stroke HeadArrow 0 TailArrow 0 Tail ID 66 Class LineGraphic Head ID 54 ID 71 Points {75.3772, 335.639} {142.143, 335.64} Style stroke HeadArrow 0 TailArrow 0 Tail ID 51 Bounds {{445.737, 356.127}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 68 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 d g} Class Group Graphics Bounds {{551.129, 315.154}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 66 Shape Rectangle Bounds {{551.129, 356.126}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 67 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 e g} ID 65 Class Group Graphics Bounds {{661.614, 356.126}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 62 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 f g} Bounds {{661.614, 315.154}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 63 Shape Rectangle Bounds {{661.614, 274.181}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 64 Shape Rectangle ID 61 Bounds {{246.101, 356.126}, {40.9727, 40.9726}} Class ShapedGraphic ID 56 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b d} Class Group Graphics Bounds {{142.643, 315.154}, {40.9727, 40.9726}} Class ShapedGraphic ID 54 Shape Rectangle Bounds {{142.643, 356.127}, {40.9727, 40.9726}} Class ShapedGraphic ID 55 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b e d} ID 53 Class Group Graphics Bounds {{33.9045, 356.126}, {40.9727, 40.9726}} Class ShapedGraphic ID 50 Shape Rectangle Bounds {{33.9045, 315.153}, {40.9727, 40.9726}} Class ShapedGraphic ID 51 Shape Rectangle Bounds {{33.9045, 274.181}, {40.9727, 40.9726}} Class ShapedGraphic ID 52 Shape Rectangle ID 49 GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo MasterSheet Master 1 Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle delete(:c) UniqueID 1 VPages 1 ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 in = 1 in GraphicsList Bounds {{183.062, 227}, {128, 23}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 18 ID 206 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs38 \cf0 expire(7..7, 0)} Wrap NO Bounds {{265.352, 437.939}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 204 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 5} Wrap NO Bounds {{161.894, 437.939}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 203 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 3} Wrap NO Bounds {{53.1566, 437.939}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 202 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 1} Wrap NO Bounds {{212.329, 383.432}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 195 Line ID 189 Position 0.49750003218650818 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b} Bounds {{97.2119, 342.459}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 194 Line ID 184 Position 0.43750011920928955 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b} Class LineGraphic Head ID 169 ID 189 Points {190.24, 390.432} {251.725, 390.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 168 Class LineGraphic Head ID 168 ID 188 Points {81.5021, 390.432} {148.267, 390.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 163 Class LineGraphic Head ID 167 ID 184 Points {81.5021, 349.459} {148.267, 349.459} Style stroke HeadArrow 0 TailArrow 0 Tail ID 164 Bounds {{252.225, 369.946}, {40.9727, 40.9726}} Class ShapedGraphic ID 169 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b} Class Group Graphics Bounds {{148.767, 328.973}, {40.9727, 40.9727}} Class ShapedGraphic ID 167 Shape Rectangle Bounds {{148.767, 369.946}, {40.9727, 40.9727}} Class ShapedGraphic ID 168 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b} ID 166 Class Group Graphics Bounds {{40.0294, 369.946}, {40.9727, 40.9727}} Class ShapedGraphic ID 163 Shape Rectangle Bounds {{40.0294, 328.973}, {40.9727, 40.9727}} Class ShapedGraphic ID 164 Shape Rectangle Bounds {{40.0294, 288}, {40.9727, 40.9727}} Class ShapedGraphic ID 165 Shape Rectangle ID 162 GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo MasterSheet Master 1 Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle expire(7..7, 0) UniqueID 2 VPages 1 ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 in = 1 in GraphicsList Bounds {{265.638, 219.932}, {122, 22}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 17 ID 272 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs36 \cf0 expire(4..4, 2)} Wrap NO Class LineGraphic Head ID 224 ID 271 Points {190.24, 291.459} {667.238, 291.459} Style stroke HeadArrow 0 TailArrow 0 Tail ID 215 Bounds {{483.529, 325.432}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 270 Line ID 269 Position 0.46961680054664612 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 g} Class LineGraphic Head ID 223 ID 269 Points {336.894, 332.432} {667.238, 332.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 217 Bounds {{666.254, 363}, {44, 14}} Class ShapedGraphic FitText YES Flow Resize ID 255 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 13 + 2} Wrap NO Bounds {{296.907, 363}, {38, 14}} Class ShapedGraphic FitText YES Flow Resize ID 251 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 5 + 2} Wrap NO Bounds {{160.753, 363}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 250 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 3} Wrap NO Bounds {{52.0152, 363}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 249 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 1} Wrap NO Bounds {{102.211, 284.459}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica-Oblique Size 12 ID 242 Line ID 232 Position 0.43750011920928955 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a} Class LineGraphic FontInfo Font Helvetica Size 12 Head ID 217 ID 237 Points {190.24, 332.432} {294.921, 332.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 216 Class LineGraphic FontInfo Font Helvetica Size 12 Head ID 216 ID 236 Points {81.5016, 332.432} {148.267, 332.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 211 Class LineGraphic FontInfo Font Helvetica Size 12 Head ID 215 ID 232 Points {81.5016, 291.459} {148.267, 291.459} Style stroke HeadArrow 0 TailArrow 0 Tail ID 212 Class Group Graphics Bounds {{667.738, 311.946}, {41.0327, 40.9726}} Class ShapedGraphic FontInfo Font Helvetica Size 12 HFlip YES ID 223 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 g} Bounds {{667.738, 270.973}, {41.0327, 40.9726}} Class ShapedGraphic FontInfo Font Helvetica Size 12 HFlip YES ID 224 Shape Rectangle Bounds {{667.738, 230}, {41.0327, 40.9726}} Class ShapedGraphic FontInfo Font Helvetica Size 12 HFlip YES ID 225 Shape Rectangle ID 222 Bounds {{295.421, 311.946}, {40.9727, 40.9726}} Class ShapedGraphic FontInfo Font Helvetica Size 12 ID 217 Shape Rectangle Class Group Graphics Bounds {{148.767, 270.973}, {40.9727, 40.9727}} Class ShapedGraphic FontInfo Font Helvetica Size 12 ID 215 Shape Rectangle Bounds {{148.767, 311.946}, {40.9727, 40.9727}} Class ShapedGraphic FontInfo Font Helvetica Size 12 ID 216 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a} ID 214 Class Group Graphics Bounds {{40.0289, 311.946}, {40.9727, 40.9727}} Class ShapedGraphic FontInfo Font Helvetica Size 12 ID 211 Shape Rectangle Bounds {{40.0289, 270.973}, {40.9727, 40.9727}} Class ShapedGraphic FontInfo Font Helvetica Size 12 ID 212 Shape Rectangle Bounds {{40.0289, 230}, {40.9727, 40.9727}} Class ShapedGraphic FontInfo Font Helvetica Size 12 ID 213 Shape Rectangle ID 210 GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo MasterSheet Master 1 Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle expire(4..4, 2) UniqueID 3 VPages 1 ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 in = 1 in GraphicsList Bounds {{468.5, 194}, {111, 18}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 14 ID 269 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs30 \cf0 insert(9..13, :z)} Wrap NO Class LineGraphic Head ID 227 ID 268 Points {190.24, 479.459} {667.238, 479.459} Style stroke HeadArrow 0 TailArrow 0 Tail ID 218 Class LineGraphic Head ID 228 ID 267 Points {81.502, 438.486} {667.238, 438.486} Style stroke HeadArrow 0 TailArrow 0 Tail ID 216 Class LineGraphic Head ID 232 ID 266 Points {190.24, 520.432} {451.361, 520.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 219 Bounds {{570, 513.432}, {16, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 265 Line ID 264 Position 0.48667857050895691 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 z} Class LineGraphic Head ID 226 ID 264 Points {493.394, 520.432} {667.238, 520.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 232 Bounds {{623, 274.12}, {16, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 261 Line ID 41 Position 0.47061088681221008 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 z} Bounds {{516, 315.093}, {16, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 260 Line ID 47 Position 0.48306027054786682 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 z} Bounds {{313.152, 395}, {108, 18}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 14 ID 259 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs30 \cf0 expire(4..8, -3)} Wrap NO Bounds {{667.6, 555.06}, {41, 14}} Class ShapedGraphic FitText YES Flow Resize ID 258 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 13 - 3} Wrap NO Bounds {{454.723, 555.06}, {35, 14}} Class ShapedGraphic FitText YES Flow Resize ID 256 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 9 - 3} Wrap NO Bounds {{160.599, 555.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 253 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 3} Wrap NO Bounds {{51.8617, 555.06}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 252 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 1} Wrap NO Bounds {{102.212, 472.459}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 245 Line ID 235 Position 0.43750011920928955 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a} Class LineGraphic Head ID 219 ID 239 Points {81.502, 520.432} {148.267, 520.432} Style stroke HeadArrow 0 TailArrow 0 Tail ID 214 Class LineGraphic Head ID 218 ID 235 Points {81.502, 479.459} {148.267, 479.459} Style stroke HeadArrow 0 TailArrow 0 Tail ID 215 Bounds {{451.861, 499.946}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 232 Shape Rectangle Class Group Graphics Bounds {{667.738, 499.946}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 226 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 z} Bounds {{667.738, 458.973}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 227 Shape Rectangle Bounds {{667.738, 418}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 228 Shape Rectangle ID 225 Class Group Graphics Bounds {{148.767, 458.973}, {40.9727, 40.9727}} Class ShapedGraphic ID 218 Shape Rectangle Bounds {{148.767, 499.946}, {40.9727, 40.9727}} Class ShapedGraphic ID 219 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a} ID 217 Class Group Graphics Bounds {{40.0293, 499.946}, {40.9727, 40.9727}} Class ShapedGraphic ID 214 Shape Rectangle Bounds {{40.0293, 458.973}, {40.9727, 40.9727}} Class ShapedGraphic ID 215 Shape Rectangle Bounds {{40.0293, 418}, {40.9727, 40.9727}} Class ShapedGraphic ID 216 Shape Rectangle ID 213 Bounds {{311.301, 194}, {109, 18}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 14 ID 212 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs30 \cf0 insert(7..11, :y)} Wrap NO Bounds {{145.062, 194}, {102, 18}} Class ShapedGraphic FitText YES Flow Resize FontInfo Font Helvetica Size 14 ID 211 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs30 \cf0 insert(1..5, :x)} Wrap NO Bounds {{676.1, 354.579}, {24, 14}} Class ShapedGraphic FitText YES Flow Resize ID 209 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 13} Wrap NO Bounds {{566.114, 354.579}, {23, 14}} Class ShapedGraphic FitText YES Flow Resize ID 207 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 11} Wrap NO Bounds {{463.723, 354.579}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 206 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 9} Wrap NO Bounds {{359.775, 354.579}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 205 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 7} Wrap NO Bounds {{264.057, 354.579}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 204 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 5} Wrap NO Bounds {{160.599, 354.579}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 203 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 3} Wrap NO Bounds {{51.8617, 354.579}, {17, 14}} Class ShapedGraphic FitText YES Flow Resize ID 202 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 1} Wrap NO Bounds {{311.301, 315.093}, {17, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 100 Line ID 45 Position 0.49750059843063354 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 g} Bounds {{406.092, 315.093}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 91 Line ID 46 Position 0.4975009560585022 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 d y} Bounds {{456.295, 274.12}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 90 Line ID 40 Position 0.48428341746330261 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 e y} Bounds {{501.164, 233.147}, {24, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 89 Line ID 36 Position 0.44795909523963928 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 f g} Bounds {{194.113, 233.147}, {43, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 88 Line ID 35 Position 0.50672364234924316 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 c d e f} Bounds {{207.329, 315.093}, {27, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 86 Line ID 44 Position 0.49750003218650818 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b x} Bounds {{92.2119, 274.12}, {37, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 85 Line ID 37 Position 0.43750011920928955 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b x} Class LineGraphic Head ID 32 ID 48 Points {598.785, 322.093} {667.238, 322.093} Style stroke HeadArrow 0 TailArrow 0 Tail ID 30 Class LineGraphic Head ID 30 ID 47 Points {493.394, 322.093} {556.752, 322.093} Style stroke HeadArrow 0 TailArrow 0 Tail ID 16 Class LineGraphic Head ID 16 ID 46 Points {388.138, 322.093} {451.361, 322.093} Style stroke HeadArrow 0 TailArrow 0 Tail ID 25 Class LineGraphic Head ID 25 ID 45 Points {293.698, 322.093} {346.165, 322.093} Style stroke HeadArrow 0 TailArrow 0 Tail ID 6 Class LineGraphic Head ID 6 ID 44 Points {190.24, 322.093} {251.725, 322.093} Style stroke HeadArrow 0 TailArrow 0 Tail ID 19 Class LineGraphic Head ID 19 ID 42 Points {81.502, 322.093} {148.267, 322.093} Style stroke HeadArrow 0 TailArrow 0 Tail ID 21 Class LineGraphic Head ID 33 ID 41 Points {598.785, 281.12} {667.238, 281.12} Style stroke HeadArrow 0 TailArrow 0 Tail ID 29 Class LineGraphic Head ID 29 ID 40 Points {388.138, 281.12} {556.752, 281.12} Style stroke HeadArrow 0 TailArrow 0 Tail ID 26 Class LineGraphic Head ID 26 ID 38 Points {190.24, 281.12} {346.165, 281.12} Style stroke HeadArrow 0 TailArrow 0 Tail ID 18 Class LineGraphic Head ID 18 ID 37 Points {81.502, 281.12} {148.267, 281.12} Style stroke HeadArrow 0 TailArrow 0 Tail ID 22 Class LineGraphic Head ID 34 ID 36 Points {388.138, 240.147} {667.238, 240.147} Style stroke HeadArrow 0 TailArrow 0 Tail ID 27 Class LineGraphic Head ID 27 ID 35 Points {81.502, 240.147} {346.165, 240.147} Style stroke HeadArrow 0 TailArrow 0 Tail ID 23 Bounds {{451.861, 301.607}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 16 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 d} Class Group Graphics Bounds {{557.252, 260.634}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 29 Shape Rectangle Bounds {{557.252, 301.607}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 30 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 e y z} ID 28 Class Group Graphics Bounds {{667.738, 301.607}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 32 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 f g z} Bounds {{667.738, 260.634}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 33 Shape Rectangle Bounds {{667.738, 219.661}, {41.0327, 40.9726}} Class ShapedGraphic HFlip YES ID 34 Shape Rectangle ID 31 Class Group Graphics Bounds {{346.665, 301.607}, {40.9727, 40.9726}} Class ShapedGraphic ID 25 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 c d e f g} Bounds {{346.665, 260.634}, {40.9727, 40.9726}} Class ShapedGraphic ID 26 Shape Rectangle Bounds {{346.665, 219.661}, {40.9727, 40.9726}} Class ShapedGraphic ID 27 Shape Rectangle ID 24 Bounds {{252.225, 301.607}, {40.9727, 40.9726}} Class ShapedGraphic ID 6 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 b x} Class Group Graphics Bounds {{148.767, 260.634}, {40.9727, 40.9727}} Class ShapedGraphic ID 18 Shape Rectangle Bounds {{148.767, 301.607}, {40.9727, 40.9727}} Class ShapedGraphic ID 19 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf440 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 a b x} ID 17 Class Group Graphics Bounds {{40.0293, 301.607}, {40.9727, 40.9727}} Class ShapedGraphic ID 21 Shape Rectangle Bounds {{40.0293, 260.634}, {40.9727, 40.9727}} Class ShapedGraphic ID 22 Shape Rectangle Bounds {{40.0293, 219.661}, {40.9727, 40.9727}} Class ShapedGraphic ID 23 Shape Rectangle ID 20 GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo MasterSheet Master 1 Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle expire(4..8, -3) UniqueID 4 VPages 1 SmartAlignmentGuidesActive YES SmartDistanceGuidesActive YES UseEntirePage WindowInfo CurrentSheet 3 DrawerOpen DrawerTab Canvases DrawerWidth 209 FitInWindow Frame {{294, 134}, {1014, 944}} ShowRuler ShowStatusBar VisibleRegion {{-125, -118}, {999, 830}} Zoom 1 treetop-1.4.14/spec/runtime/interval_skip_list/insert_spec.rb0000644000004100000410000004371012157663062024515 0ustar www-datawww-datarequire 'runtime/interval_skip_list/spec_helper' describe IntervalSkipList, " when #next_node_height returns 1, 3, 2, 3, 1 in order", :deterministic => true do include IntervalSkipListSpecHelper attr_reader :list, :node before do @list = IntervalSkipList.new end include NextNodeHeightIsDeterministicSharedContext def expected_node_heights [1, 3, 2, 3, 1] end describe ", when :a is inserted on 1..7" do before do list.insert(1..7, :a) end describe ", #containing" do it "returns only :a from 2 through 6" do (2..6).should contain_marker(:a) end it "returns nothing at 1 and 7" do list.containing(1).should be_empty list.containing(7).should be_empty end end describe " #nodes[0]" do before do @node = list.nodes[0] end it "has a key of 1 and height of 1" do node.key.should == 1 node.height.should == 1 end it "has :a as its only marker at level 0" do node.forward_markers[0].should have_marker(:a) end it "has no markers" do node.markers.should be_empty end it "is an endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end describe " #nodes[1]" do before do @node = list.nodes[1] end it "has a key of 7 and height of 3" do node.key.should == 7 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :a as its only marker" do node.markers.should have_marker(:a) end it "is an endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end describe ", and then :b is inserted on 1..5" do before do list.insert(1..5, :b) end describe ", #containing" do it "returns only :a and :b from 2 through 4" do (2..4).should contain_markers(:a, :b) end it "returns only :a from 5 through 6" do (5..6).should contain_marker(:a) end it "returns nothing at 1 and 7" do list.containing(1).should be_empty list.containing(7).should be_empty end end describe " #nodes[0]" do before do @node = list.nodes[0] end it "has a key of 1 and height of 1" do node.key.should == 1 node.height.should == 1 end it "has :a and :b as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:a, :b) end it "has no markers" do node.markers.should be_empty end it "is an endpoint of only :a and :b" do node.endpoint_of.should have_markers(:a, :b) end end describe " #nodes[1]" do before do @node = list.nodes[1] end it "has a key of 5 and height of 2" do node.key.should == 5 node.height.should == 2 end it "has :a as its only forward marker at level 1" do node.forward_markers[1].should have_marker(:a) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :a and :b as its only markers" do node.markers.should have_markers(:a, :b) end it "is an endpoint of only :b" do node.endpoint_of.should have_marker(:b) end end describe " #nodes[2]" do before do @node = list.nodes[2] end it "has a key of 7 and height of 3" do node.key.should == 7 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :a its only marker" do node.markers.should have_marker(:a) end it "is an endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end describe ", and then :c is inserted on 1..3" do before do list.insert(1..3, :c) end describe ", #containing" do it "returns only :a, :b, and :c for 2" do (2..2).should contain_markers(:a, :b, :c) end it "returns only :a, :b from 3..4" do (3..4).should contain_markers(:a, :b) end it "returns only :a from 5..6" do (5..6).should contain_markers(:a) end it "returns nothing at 1 and 7" do list.containing(1).should be_empty list.containing(7).should be_empty end end describe " #nodes[0]" do before do @node = list.nodes[0] end it "has a key of 1 and height of 1" do node.key.should == 1 node.height.should == 1 end it "has :a, :b, :c as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:a, :b, :c) end it "has no markers" do node.markers.should be_empty end it "is an endpoint of only :a, :b, :c" do node.endpoint_of.should have_markers(:a, :b, :c) end end describe " #nodes[1]" do before do @node = list.nodes[1] end it "has a key of 3 and height of 3" do node.key.should == 3 node.height.should == 3 end it "has :a as its only forward marker at level 2" do node.forward_markers[2].should have_marker(:a) end it "has :b as its only forward marker at level 1" do node.forward_markers[1].should have_marker(:b) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :a, :b, and :c as its only markers" do node.markers.should have_markers(:a, :b, :c) end it "is an endpoint of only :c" do node.endpoint_of.should have_marker(:c) end end describe " #nodes[2]" do before do @node = list.nodes[2] end it "has a key of 5 and height of 2" do node.key.should == 5 node.height.should == 2 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty end it "has :b as its only markers" do node.markers.should have_marker(:b) end it "is an endpoint of only :b" do node.endpoint_of.should have_marker(:b) end end describe " #nodes[3]" do before do @node = list.nodes[3] end it "has a key of 7 and height of 3" do node.key.should == 7 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :a as its only marker" do node.markers.should have_marker(:a) end it "is an endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end describe ", and then :d is inserted on 1..9" do before do list.insert(1..9, :d) end describe ", #containing" do it "returns only :a, :b, :c, and :d for 2" do (2..2).should contain_markers(:a, :b, :c, :d) end it "returns only :a, :b from 3..4" do (3..4).should contain_markers(:a, :b, :d) end it "returns only :a from 5..6" do (5..6).should contain_markers(:a, :d) end it "returns only :a from 7..8" do (7..8).should contain_markers(:d) end it "returns nothing at 1 and 9" do list.containing(1).should be_empty list.containing(9).should be_empty end it "returns nothing for -1, 0, and 10" do list.containing(-1).should be_empty list.containing(0).should be_empty list.containing(10).should be_empty end end describe " #nodes[0]" do before do @node = list.nodes[0] end it "has a key of 1 and height of 1" do node.key.should == 1 node.height.should == 1 end it "has :a, :b, :c, :d as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:a, :b, :c, :d) end it "has no markers" do node.markers.should be_empty end it "is an endpoint of only :a, :b, :c, and :d" do node.endpoint_of.should have_markers(:a, :b, :c, :d) end end describe " #nodes[1]" do before do @node = list.nodes[1] end it "has a key of 3 and height of 3" do node.key.should == 3 node.height.should == 3 end it "has :a and :d as its only forward markers at level 2" do node.forward_markers[2].should have_markers(:a, :d) end it "has :b as its only marker at level 1" do node.forward_markers[1].should have_marker(:b) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :a, :b, :c, :d as its only markers" do node.markers.should have_markers(:a, :b, :c, :d) end it "is an endpoint of only :c" do node.endpoint_of.should have_marker(:c) end end describe " #nodes[2]" do before do @node = list.nodes[2] end it "has a key of 5 and height of 2" do node.key.should == 5 node.height.should == 2 end it "has no markers on any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty end it "has :b as its only marker" do node.markers.should have_marker(:b) end it "is an endpoint of only :b" do node.endpoint_of.should have_marker(:b) end end describe " #nodes[3]" do before do @node = list.nodes[3] end it "has a key of 7 and height of 3" do node.key.should == 7 node.height.should == 3 end it "has :d as its only marker at level 0" do node.forward_markers[0].should have_marker(:d) end it "has no forward markers at levels 1 and 2" do node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :a, :d as its only markers" do node.markers.should have_markers(:a, :d) end it "is an endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end describe " #nodes[4]" do before do @node = list.nodes[4] end it "has a key of 9 and height of 1" do node.key.should == 9 node.height.should == 1 end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :d as its only marker" do node.markers.should have_marker(:d) end it "is an endpoint of only :d" do node.endpoint_of.should have_marker(:d) end end describe ", and then :d is deleted" do before do list.delete(:d) end it "has only 4 nodes" do list.nodes.size.should == 4 end describe " #nodes[0]" do before do @node = list.nodes[0] end it "has a key of 1 and height of 1" do node.key.should == 1 node.height.should == 1 end it "has :a, :b, and :c as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:a, :b, :c) end end describe " #nodes[1]" do before do @node = list.nodes[1] end it "has a key of 3 and height of 3" do node.key.should == 3 node.height.should == 3 end it "has :a as its only forward marker at level 2" do node.forward_markers[2].should have_marker(:a) end it "has :b as its only forward marker at level 1" do node.forward_markers[1].should have_marker(:b) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :a, :b, and :c as its only markers" do node.markers.should have_markers(:a, :b, :c) end it "is the endpoint of only :c" do node.endpoint_of.should have_marker(:c) end end describe " #nodes[2]" do before do @node = list.nodes[2] end it "has a key of 5 and height of 2" do node.key.should == 5 node.height.should == 2 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty end it "has :b as its only marker" do node.markers.should have_marker(:b) end it "is the endpoint of only :b" do node.endpoint_of.should have_marker(:b) end end describe " #nodes[3]" do before do @node = list.nodes[3] end it "has a key of 7 and height of 3" do node.key.should == 7 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :a as its only marker" do node.markers.should have_marker(:a) end it "is the endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end describe ", and then :c is deleted" do before do list.delete(:c) end it "has only 3 nodes" do list.nodes.size.should == 3 end describe " #nodes[0]" do before do @node = list.nodes[0] end it "has a key of 1 and height of 1" do node.key.should == 1 node.height.should == 1 end it "has :a and :b as its only forward markers at level 0" do node.forward_markers[0].should have_markers(:a, :b) end it "has no markers" do node.markers.should be_empty end it "is an endpoint of only :a and :b" do node.endpoint_of.should have_markers(:a, :b) end end describe " #nodes[1]" do before do @node = list.nodes[1] end it "has a key of 5 and height of 2" do node.key.should == 5 node.height.should == 2 end it "has :a as its only forward marker at level 1" do node.forward_markers[1].should have_marker(:a) end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :a and :b as its only markers" do node.markers.should have_markers(:a, :b) end it "is an endpoint of only :b" do node.endpoint_of.should have_marker(:b) end end describe " #nodes[2]" do before do @node = list.nodes[2] end it "has a key of 7 and height of 3" do node.key.should == 7 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :a its only marker" do node.markers.should have_marker(:a) end it "is an endpoint of only :a" do node.endpoint_of.should have_marker(:a) end end end end end end end end end treetop-1.4.14/spec/runtime/interval_skip_list/spec_helper.rb0000644000004100000410000000431312157663062024464 0ustar www-datawww-datarequire 'spec_helper' class IntervalSkipList public :insert_node, :delete_node, :nodes, :head, :next_node_height end module NextNodeHeightIsDeterministicSharedContext extend RSpec::Core::SharedContext before :each do next_node_height_is_deterministic end # @todo we call this in one place other than here. cleanup? def next_node_height_is_deterministic node_heights = expected_node_heights.dup stub(list).next_node_height { node_heights.shift } end end module IntervalSkipListSpecHelper def contain_marker(marker) ContainMarkers.new(list, [marker]) end def contain_markers(*markers) ContainMarkers.new(list, markers) end class ContainMarkers attr_reader :failure_message def initialize(list, expected_markers) @list = list @expected_markers = expected_markers end def matches?(target_range) @target_range = target_range @target_range.each do |i| markers = @list.containing(i) @expected_markers.each do |expected_marker| unless markers.include?(expected_marker) @failure_message = "Expected #{expected_marker.inspect} to contain #{i}, but it doesn't. #{i} is contained by: #{markers.inspect}." return false end end markers.each do |marker| unless @expected_markers.include?(marker) @failure_message = "Did not expect #{marker.inspect} to contain #{i}. Only expected #{@expected_markers.inspect}." return false end end end true end end def have_markers(*markers) HaveMarkers.new(markers) end def have_marker(marker) HaveMarkers.new([marker]) end class HaveMarkers def initialize(expected_markers) @expected_markers = expected_markers end def matches?(target) @target = target return false unless @target.size == @expected_markers.size @expected_markers.each do |expected_marker| return false unless @target.include?(expected_marker) end true end def failure_message "Expected #{@target.inspect} to include only #{@expected_markers.inspect}" end end end require 'runtime/interval_skip_list/palindromic_fixture' treetop-1.4.14/spec/runtime/interval_skip_list/expire_range_spec.rb0000644000004100000410000002051012157663062025652 0ustar www-datawww-datarequire 'runtime/interval_skip_list/spec_helper' describe IntervalSkipList, :palindromic => true do include PalindromicFixtureSharedContext describe "#overlapping" do it "returns intervals :d, :e, :f, and :g for 7..9" do list.overlapping(7..9)[0].should have_markers(:d, :e, :f, :g) end it "returns intervals :b, :c, :d, :e, :f, and :g for 3..7" do list.overlapping(3..7)[0].should have_markers(:b, :c, :d, :e, :f, :g ) end it "returns intervals :b, :c, :d, :e, :f, and :g for 3..6" do list.overlapping(3..6)[0].should have_markers(:b, :c, :d, :e, :f, :g ) end describe ", when :x is inserted on 3..7" do before do list.insert(3..7, :x) end it "returns intervals :b, :c, :d, :e, :f, :x for 3..5" do list.overlapping(3..5)[0].should have_markers(:b, :c, :d, :e, :f, :x) end end end describe "when 7..7 is expired with a length change of 0" do before do list.expire(7..7, 0) end describe " #nodes" do attr_reader :nodes, :node before do @nodes = list.nodes end it "has a size of 4" do nodes.size.should == 4 end describe "[0]" do before do @node = nodes[0] end it "has a key of 1 and a height of 3" do node.key.should == 1 node.height.should == 3 end it "has no forward markers at level 0" do node.forward_markers[0].should be_empty end it "has :a and :b as its only forward markers on level 1" do node.forward_markers[1].should have_markers(:a, :b) end it "has :c as its only forward marker on level 2" do node.forward_markers[2].should have_markers(:c) end it "has no markers" do node.markers.should be_empty end end describe "[1]" do before do @node = nodes[1] end it "has a key of 3 and a height of 2" do node.key.should == 3 node.height.should == 2 end it "has :b as its only forward marker on level 0" do node.forward_markers[0].should have_markers(:b) end it "has no forward markers on level 1" do node.forward_markers[1].should be_empty end it "has :a and :b as its only markers" do node.markers.should have_markers(:a, :b) end end describe "[2]" do before do @node = nodes[2] end it "has a key of 5 and a height of 1" do node.key.should == 5 node.height.should == 1 end it "has no forward markers on level 0" do node.forward_markers[0].should be_empty end it "has :b as its only marker" do node.markers.should have_markers(:b) end end describe "[3]" do before do @node = nodes[3] end it "has a key of 7 and a height of 3" do node.key.should == 7 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :c as its only marker" do node.markers.should have_markers(:c) end end end end describe "when 4..4 is expired with a length change of 2" do before do list.expire(4..4, 2) end describe " #nodes" do attr_reader :nodes, :node before do @nodes = list.nodes end it "has a size of 4" do nodes.size.should == 4 end describe "[0]" do before do @node = nodes[0] end it "has a key of 1 and a height of 3" do node.key.should == 1 node.height.should == 3 end it "has no forward markers at level 0 and 2" do node.forward_markers[0].should be_empty node.forward_markers[2].should be_empty end it "has :a as its only forward marker on level 1" do node.forward_markers[1].should have_markers(:a) end it "has no markers" do node.markers.should be_empty end end describe "[1]" do before do @node = nodes[1] end it "has a key of 3 and a height of 2" do node.key.should == 3 node.height.should == 2 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty end it "has :a as its only marker" do node.markers.should have_markers(:a) end end describe "[2]" do before do @node = nodes[2] end it "has a key of 7 and a height of 1" do node.key.should == 7 node.height.should == 1 end it "has :g as its only forward marker at level 0" do node.forward_markers[0].should have_markers(:g) end it "has no markers" do node.markers.should be_empty end end describe "[3]" do before do @node = nodes[3] end it "has a key of 15 and a height of 3" do node.key.should == 15 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :g as its only marker" do node.markers.should have_markers(:g) end end end end describe "when :x is inserted on 1..5, :y on 7..11, and :z on 9..13" do before do list.insert(1..5, :x) list.insert(7..11, :y) list.insert(9..13, :z) end describe "when 4..8 is expired with a length change of -3" do before do list.expire(4..8, -3) end describe "#nodes" do attr_reader :nodes, :node before do @nodes = list.nodes end it "has a size of 4" do nodes.size.should == 4 end describe "[0]" do before do @node = nodes[0] end it "has a key of 1 and height of 3" do node.key.should == 1 node.height.should == 3 end it "has :a as its only forward marker on level 1" do node.forward_markers[1].should have_markers(:a) end it "has no forward markers at level 0 and 2" do node.forward_markers[0].should be_empty node.forward_markers[2].should be_empty end it "has no markers" do node.markers.should be_empty end end describe "[1]" do before do @node = nodes[1] end it "has a key of 3 and height of 2" do node.key.should == 3 node.height.should == 2 end it "has no forward markers" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty end it "has :a as its only marker" do node.markers.should have_markers(:a) end end describe "[2]" do before do @node = nodes[2] end it "has a key of 6 and a height of 1" do node.key.should == 6 node.height.should == 1 end it "has :z as its only forward marker at level 0" do node.forward_markers[0].should have_markers(:z) end it "has no markers" do node.markers.should be_empty end end describe "[3]" do before do @node = nodes[3] end it "has a key of 10 and height of 3" do node.key.should == 10 node.height.should == 3 end it "has no forward markers at any level" do node.forward_markers[0].should be_empty node.forward_markers[1].should be_empty node.forward_markers[2].should be_empty end it "has :z as its only marker" do node.markers.should have_markers(:z) end end end end end end treetop-1.4.14/spec/runtime/compiled_parser_spec.rb0000644000004100000410000000627412157663062022460 0ustar www-datawww-datarequire 'spec_helper' module CompiledParserSpec describe Runtime::CompiledParser, "for a grammar with two rules" do attr_reader :parser testing_grammar %{ grammar TwoRules rule a 'a' end rule b 'b' end end } before do @parser = parser_class_under_test.new end it "allows its root to be specified" do parser.parse('a').should_not be_nil parser.parse('b').should be_nil # Check that the temporary-override works: parser.parse('b', :root => :b).should_not be_nil parser.parse('a', :root => :b).should be_nil # Check that the temporary-override isn't sticky: parser.parse('a').should_not be_nil # Try a permanent override: parser.root = :b parser.parse('b').should_not be_nil parser.parse('a').should be_nil end it "allows the requirement that all input be consumed to be disabled" do parser.parse('ab').should be_nil # Try a temporary override, and check it's not sticky: result = parser.parse('ab', :consume_all_input => false) result.should_not be_nil result.interval.should == (0...1) parser.parse('ab').should be_nil # Now a permanent override: parser.consume_all_input = false result = parser.parse('ab') result.should_not be_nil result.interval.should == (0...1) end it "allows input to be parsed at a given index" do parser.parse('ba').should be_nil parser.parse('ba', :index => 1).should_not be_nil # Check that the index defaults again to zero: parser.parse('a').should_not be_nil result = parser.parse('ba', :consume_all_input => false, :index => 1) result.should_not be_nil result.interval.should == (1...2) end end describe Runtime::CompiledParser, "for a grammar with a choice between terminals" do attr_reader :parser testing_grammar %{ grammar Choice rule choice 'a' / 'b' / 'c' end end } before do @parser = parser_class_under_test.new end it "provides #failure_reason, #failure_column, and #failure_line when there is a parse failure" do parser.parse('z').should be_nil parser.failure_reason.should == "Expected one of a, b, c at line 1, column 1 (byte 1) after " parser.failure_line.should == 1 parser.failure_column.should == 1 end end describe Runtime::CompiledParser, "#terminal_failures" do attr_reader:parser testing_grammar %{ grammar SequenceOfTerminals rule foo 'a' 'b' 'c' end end } before do @parser = parser_class_under_test.new end it "is reset between parses" do parser.parse('ac') terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 1 failure.expected_string.should == 'b' parser.parse('b') terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 failure = terminal_failures.first failure.index.should == 0 failure.expected_string.should == 'a' end end end treetop-1.4.14/spec/runtime/syntax_node_spec.rb0000644000004100000410000000417512157663062021641 0ustar www-datawww-datarequire 'spec_helper' module SyntaxNodeSpec describe "A new terminal syntax node" do attr_reader :node before do @node = Runtime::SyntaxNode.new("input", 0...3) end it "reports itself as terminal" do node.should be_terminal node.should_not be_nonterminal end it "has a text value based on the input and the interval" do node.text_value.should == "inp" end it "has itself as its only element" do node.elements.should be_nil end end describe "A new nonterminal syntax node" do attr_reader :node before do @elements = [Runtime::SyntaxNode.new('input', 0...3)] @node = Runtime::SyntaxNode.new('input', 0...3, @elements) end it "reports itself as nonterminal" do node.should be_nonterminal node.should_not be_terminal end it "has a text value based on the input and the interval" do node.text_value.should == "inp" end it "has the elements with which it was instantiated" do node.elements.should == @elements end it "sets itself as the parent of its elements" do node.elements.each do |element| element.parent.should == node end end end describe "A new nonterminal syntax node with all children lazily instantiated" do attr_reader :node it "should lazily instantiate its child nodes" do @node = Runtime::SyntaxNode.new('input', 0...3, [true, true, true]) node.elements.size.should == 3 node.elements.first.interval.should == (0...1) node.elements.first.parent.should == node end it "should lazily replace stand-in child nodes around real ones" do @input = "input" child1 = Runtime::SyntaxNode.new(@input, 1...2) child2 = Runtime::SyntaxNode.new(@input, 3...4) @node = Runtime::SyntaxNode.new(@input, 0...5, [true, child1, true, child2, true]) node.elements.size.should == 5 node.elements[0].interval.should == (0...1) node.elements[0].parent.should == node 0.upto(4) do |index| node.elements[index].text_value.should == @input[index, 1] end end end end treetop-1.4.14/spec/spec_helper.rb0000644000004100000410000000550212157663062017075 0ustar www-datawww-datarequire 'rubygems' require 'benchmark' require 'rspec' require 'rspec/core/shared_context' require 'polyglot' $LOAD_PATH.unshift File.expand_path('../../lib') require 'treetop' include Treetop module Treetop module ExampleGroupInstanceMethods module ClassMethods attr_accessor :parser_class_under_test def testing_expression(expression_under_test) testing_grammar(%{ grammar Test rule expression_under_test }+expression_under_test+%{ end end }.tabto(0)) end def testing_grammar(grammar_under_test) grammar_node = parse_with_metagrammar(grammar_under_test.strip, :module_or_grammar) parser_code = grammar_node.compile class_eval(parser_code) self.parser_class_under_test = class_eval(grammar_node.parser_name) end def parse_with_metagrammar(input, root) parser = Treetop::Compiler::MetagrammarParser.new parser.root = root node = parser.parse(input) raise parser.failure_reason unless node node end end attr_reader :parser def parse_with_metagrammar(input, root) self.class.parse_with_metagrammar(input, root) end def parser_class_under_test self.class.parser_class_under_test end def parse(input, options = {}) @parser = parser_class_under_test.new unless options[:consume_all_input].nil? parser.consume_all_input = options.delete(:consume_all_input) end result = parser.parse(input, options) yield result if block_given? result end def parse_multibyte(input, options = {}) require 'active_support/all' if RUBY_VERSION !~ /^1.9/ && 'NONE' == $KCODE then $KCODE = 'UTF8' end # rspec 1.3 used to do something similar (set it to 'u') that we need # for activerecord multibyte wrapper to kick in (1.8 only? @todo) parse(input.mb_chars, options) end def compiling_grammar(grammar_under_test) lambda { grammar_node = parse_with_metagrammar(grammar_under_test.strip, :grammar) parser_code = grammar_node.compile [grammar_node, parser_code] } end def compiling_expression(expression_under_test) compiling_grammar(%{ grammar Test rule expression_under_test #{expression_under_test} end end }.tabto(0)) end def optionally_benchmark(&block) if BENCHMARK Benchmark.bm do |x| x.report(&block) end else yield end end end end RSpec.configure do |c| c.mock_with :rr c.extend Treetop::ExampleGroupInstanceMethods::ClassMethods c.include Treetop::ExampleGroupInstanceMethods end class Symbol def to_proc lambda do |x| x.send(self) end end unless method_defined?(:to_proc) end treetop-1.4.14/bin/0000755000004100000410000000000012157663062014073 5ustar www-datawww-datatreetop-1.4.14/bin/tt0000755000004100000410000000671112157663062014455 0ustar www-datawww-data#!/usr/bin/env ruby require 'optparse' require 'rubygems' $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib")) require 'treetop' require 'treetop/version' require 'treetop/polyglot' options = {} parser = OptionParser.new do |opts| exts = Treetop::Polyglot::VALID_GRAMMAR_EXT.collect { |i| '.' + i } opts.banner = "Treetop Parsing Expression Grammar (PEG) Comand Line Compiler" opts.define_head "Usage: tt [options] grammar_file[#{exts.join('|')}] ..." opts.separator '' opts.separator 'Examples:' opts.separator ' tt foo.tt # 1 grammar -> 1 parser source' opts.separator ' tt foo bar.treetop # 2 grammars -> 2 separate parsers' opts.separator ' tt -o alt_name.rb foo # alternately named output file' opts.separator '' opts.separator '' opts.separator 'NOTE: while treetop grammar files *must* have one of the following' opts.separator 'filename extensions, the extension name is not required when calling' opts.separator 'the compiler with grammar file names.' opts.separator '' opts.separator " Valid extensions: #{exts.join(', ')}" opts.separator '' opts.separator '' opts.separator 'Options:' opts.on('-o', '--output FILENAME', 'Write parser source to FILENAME') do |fn| options[:out_file] = fn end opts.on('-f', '--force', 'Overwrite existing output file(s)') do options[:force] = true end opts.on_tail('-v', '--version', 'Show Treetop version') do puts "Treetop v#{Treetop::VERSION::STRING}" exit end opts.on_tail('-h', '--help', 'Show this help message') do puts opts exit end end file_list = parser.parse! # check options and arg constraints if file_list.empty? || (options[:out_file] && file_list.size > 1) puts parser exit 1 end def grammar_exist?(filename) if File.extname(filename).empty? Treetop::Polyglot::VALID_GRAMMAR_EXT.each do |ext| fn_ext = "#{filename}.#{ext}" return true if File.exist?(fn_ext) && !File.zero?(fn_ext) end end File.exist?(filename) && !File.zero?(filename) end def full_grammar_filename(filename) return filename if !File.extname(filename).empty? Treetop::Polyglot::VALID_GRAMMAR_EXT.each do |ext| fn_ext = "#{filename}.#{ext}" return fn_ext if File.exist?(fn_ext) && !File.zero?(fn_ext) end end def protect_output?(filename, forced=false) if !forced and File.exist?(filename) and File.open(filename) { |f| ![(f.gets rescue ''), (f.gets rescue '')].include? Treetop::Compiler::AUTOGENERATED } puts "ERROR: '#{filename}' output already exists; skipping compilation...\n" return true end false end compiler = Treetop::Compiler::GrammarCompiler.new while !file_list.empty? treetop_file = file_list.shift # handle nonexistent and existent grammar files mixed together if !grammar_exist?(treetop_file) puts "ERROR: input grammar file '#{treetop_file}' does not exist; continuing...\n" next end # try to compile treetop_file = full_grammar_filename(treetop_file) std_output_file = treetop_file.gsub(Treetop::Polyglot::VALID_GRAMMAR_EXT_REGEXP, '.rb') if options[:out_file] # explicit output file name option; never overwrite unless forced next if protect_output?(options[:out_file], options[:force]) compiler.compile(treetop_file, options[:out_file]) else # compile one input file from input file list option; never overwrite unless forced next if protect_output?(std_output_file, options[:force]) compiler.compile(treetop_file) end end treetop-1.4.14/metadata.yml0000644000004100000410000002207012157663062015627 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: treetop version: !ruby/object:Gem::Version version: 1.4.14 prerelease: platform: ruby authors: - Nathan Sobo - Clifford Heath autorequire: treetop bindir: bin cert_chain: [] date: 2013-06-04 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: polyglot requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: jeweler requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: activesupport requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: i18n requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 0.5.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 0.5.0 - !ruby/object:Gem::Dependency name: rr requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: '1.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: '1.0' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 2.0.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 2.0.0 - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: polyglot requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 0.3.1 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 0.3.1 description: email: cliffordheath@gmail.com executables: - tt extensions: [] extra_rdoc_files: - LICENSE - README.md files: - LICENSE - README.md - Rakefile - bin/tt - doc/contributing_and_planned_features.markdown - doc/grammar_composition.markdown - doc/index.markdown - doc/pitfalls_and_advanced_techniques.markdown - doc/semantic_interpretation.markdown - doc/site.rb - doc/site/contribute.html - doc/site/images/bottom_background.png - doc/site/images/middle_background.png - doc/site/images/paren_language_output.png - doc/site/images/pivotal.gif - doc/site/images/top_background.png - doc/site/index.html - doc/site/pitfalls_and_advanced_techniques.html - doc/site/robots.txt - doc/site/screen.css - doc/site/semantic_interpretation.html - doc/site/syntactic_recognition.html - doc/site/using_in_ruby.html - doc/sitegen.rb - doc/syntactic_recognition.markdown - doc/using_in_ruby.markdown - examples/lambda_calculus/arithmetic.rb - examples/lambda_calculus/arithmetic.treetop - examples/lambda_calculus/arithmetic_node_classes.rb - examples/lambda_calculus/arithmetic_test.rb - examples/lambda_calculus/lambda_calculus - examples/lambda_calculus/lambda_calculus.rb - examples/lambda_calculus/lambda_calculus.treetop - examples/lambda_calculus/lambda_calculus_node_classes.rb - examples/lambda_calculus/lambda_calculus_test.rb - examples/lambda_calculus/test_helper.rb - lib/treetop.rb - lib/treetop/bootstrap_gen_1_metagrammar.rb - lib/treetop/compiler.rb - lib/treetop/compiler/grammar_compiler.rb - lib/treetop/compiler/lexical_address_space.rb - lib/treetop/compiler/metagrammar.rb - lib/treetop/compiler/metagrammar.treetop - lib/treetop/compiler/node_classes.rb - lib/treetop/compiler/node_classes/anything_symbol.rb - lib/treetop/compiler/node_classes/atomic_expression.rb - lib/treetop/compiler/node_classes/character_class.rb - lib/treetop/compiler/node_classes/choice.rb - lib/treetop/compiler/node_classes/declaration_sequence.rb - lib/treetop/compiler/node_classes/grammar.rb - lib/treetop/compiler/node_classes/inline_module.rb - lib/treetop/compiler/node_classes/nonterminal.rb - lib/treetop/compiler/node_classes/optional.rb - lib/treetop/compiler/node_classes/parenthesized_expression.rb - lib/treetop/compiler/node_classes/parsing_expression.rb - lib/treetop/compiler/node_classes/parsing_rule.rb - lib/treetop/compiler/node_classes/predicate.rb - lib/treetop/compiler/node_classes/predicate_block.rb - lib/treetop/compiler/node_classes/repetition.rb - lib/treetop/compiler/node_classes/sequence.rb - lib/treetop/compiler/node_classes/terminal.rb - lib/treetop/compiler/node_classes/transient_prefix.rb - lib/treetop/compiler/node_classes/treetop_file.rb - lib/treetop/compiler/ruby_builder.rb - lib/treetop/polyglot.rb - lib/treetop/ruby_extensions.rb - lib/treetop/ruby_extensions/string.rb - lib/treetop/runtime.rb - lib/treetop/runtime/compiled_parser.rb - lib/treetop/runtime/interval_skip_list.rb - lib/treetop/runtime/interval_skip_list/head_node.rb - lib/treetop/runtime/interval_skip_list/interval_skip_list.rb - lib/treetop/runtime/interval_skip_list/node.rb - lib/treetop/runtime/syntax_node.rb - lib/treetop/runtime/terminal_parse_failure.rb - lib/treetop/runtime/terminal_syntax_node.rb - lib/treetop/version.rb - spec/compiler/and_predicate_spec.rb - spec/compiler/anything_symbol_spec.rb - spec/compiler/character_class_spec.rb - spec/compiler/choice_spec.rb - spec/compiler/circular_compilation_spec.rb - spec/compiler/failure_propagation_functional_spec.rb - spec/compiler/grammar_compiler_spec.rb - spec/compiler/grammar_spec.rb - spec/compiler/multibyte_chars_spec.rb - spec/compiler/namespace_spec.rb - spec/compiler/nonterminal_symbol_spec.rb - spec/compiler/not_predicate_spec.rb - spec/compiler/occurrence_range_spec.rb - spec/compiler/one_or_more_spec.rb - spec/compiler/optional_spec.rb - spec/compiler/parenthesized_expression_spec.rb - spec/compiler/parsing_rule_spec.rb - spec/compiler/repeated_subrule_spec.rb - spec/compiler/semantic_predicate_spec.rb - spec/compiler/sequence_spec.rb - spec/compiler/terminal_spec.rb - spec/compiler/terminal_symbol_spec.rb - spec/compiler/test_grammar.treetop - spec/compiler/test_grammar.tt - spec/compiler/test_grammar_do.treetop - spec/compiler/tt_compiler_spec.rb - spec/compiler/zero_or_more_spec.rb - spec/composition/a.treetop - spec/composition/b.treetop - spec/composition/c.treetop - spec/composition/d.treetop - spec/composition/f.treetop - spec/composition/grammar_composition_spec.rb - spec/composition/subfolder/e_includes_c.treetop - spec/ruby_extensions/string_spec.rb - spec/runtime/compiled_parser_spec.rb - spec/runtime/interval_skip_list/delete_spec.rb - spec/runtime/interval_skip_list/expire_range_spec.rb - spec/runtime/interval_skip_list/insert_and_delete_node_spec.rb - spec/runtime/interval_skip_list/insert_spec.rb - spec/runtime/interval_skip_list/interval_skip_list_spec.graffle - spec/runtime/interval_skip_list/interval_skip_list_spec.rb - spec/runtime/interval_skip_list/palindromic_fixture.rb - spec/runtime/interval_skip_list/palindromic_fixture_spec.rb - spec/runtime/interval_skip_list/spec_helper.rb - spec/runtime/syntax_node_spec.rb - spec/spec_helper.rb - treetop.gemspec homepage: https://github.com/cjheath/treetop licenses: - MIT post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' segments: - 0 hash: 622706517614693275 required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 1.8.24 signing_key: specification_version: 3 summary: A Ruby-based text parsing and interpretation DSL test_files: [] treetop-1.4.14/lib/0000755000004100000410000000000012157663062014071 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/0000755000004100000410000000000012157663062015553 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/ruby_extensions/0000755000004100000410000000000012157663062021013 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/ruby_extensions/string.rb0000644000004100000410000000140212157663062022643 0ustar www-datawww-dataclass String def column_of(index) return 1 if index == 0 newline_index = rindex("\n", index - 1) if newline_index index - newline_index else index + 1 end end def line_of(index) self[0...index].count("\n") + 1 end unless method_defined?(:blank?) def blank? self == "" end end # The following methods are lifted from Facets 2.0.2 def tabto(n) if self =~ /^( *)\S/ indent(n - $1.length) else self end end unless method_defined?(:indent) def indent(n) if n >= 0 gsub(/^/, ' ' * n) else gsub(/^ {0,#{-n}}/, "") end end end def treetop_camelize to_s.gsub(/\/(.?)/){ "::" + $1.upcase }.gsub(/(^|_)(.)/){ $2.upcase } end endtreetop-1.4.14/lib/treetop/compiler/0000755000004100000410000000000012157663062017365 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/compiler/node_classes/0000755000004100000410000000000012157663062022027 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/compiler/node_classes/character_class.rb0000644000004100000410000000156712157663062025506 0ustar www-datawww-datamodule Treetop module Compiler class CharacterClass < AtomicExpression def compile(address, builder, parent_expression = nil) super builder.if__ "has_terminal?(#{grounded_regexp(text_value)}, true, index)" do if address == 0 || decorated? assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))" extend_result_with_inline_module else assign_lazily_instantiated_node end builder << "@index += 1" end builder.else_ do # "terminal_parse_failure(#{single_quote(characters)})" assign_result 'nil' end end def grounded_regexp(string) # Double any backslashes, then backslash any single-quotes: "'\\G#{string.gsub(/\\/) { '\\\\' }.gsub(/'/) { "\\'"}}'" end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/transient_prefix.rb0000644000004100000410000000035112157663062025737 0ustar www-datawww-datamodule Treetop module Compiler class TransientPrefix < ParsingExpression def compile(address, builder, parent_expression) parent_expression.prefixed_expression.compile(address, builder) end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/choice.rb0000644000004100000410000000160112157663062023604 0ustar www-datawww-datamodule Treetop module Compiler class Choice < ParsingExpression def compile(address, builder, parent_expression = nil) super begin_comment(self) use_vars :result, :start_index compile_alternatives(alternatives) end_comment(self) end def compile_alternatives(alternatives) obtain_new_subexpression_address alternatives.first.compile(subexpression_address, builder) builder.if__ subexpression_success? do assign_result subexpression_result_var extend_result_with_declared_module extend_result_with_inline_module end builder.else_ do if alternatives.size == 1 reset_index assign_failure start_index_var else compile_alternatives(alternatives[1..-1]) end end end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/grammar.rb0000644000004100000410000000144512157663062024006 0ustar www-datawww-datamodule Treetop module Compiler class Grammar < Runtime::SyntaxNode def compile builder = RubyBuilder.new builder.module_declaration "#{grammar_name.text_value}" do builder.in(indent_level) # account for initial indentation of grammar declaration builder << "include Treetop::Runtime" builder.newline declaration_sequence.compile(builder) end builder.newline builder.class_declaration "#{parser_name} < Treetop::Runtime::CompiledParser" do builder << "include #{grammar_name.text_value}" end end def indent_level input.column_of(interval.begin) - 1 end def parser_name grammar_name.text_value + 'Parser' end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/repetition.rb0000644000004100000410000000442212157663062024540 0ustar www-datawww-datamodule Treetop module Compiler class Repetition < ParsingExpression def compile(address, builder, parent_expression) super repeated_expression = parent_expression.atomic begin_comment(parent_expression) use_vars :result, :accumulator, :start_index builder.loop do obtain_new_subexpression_address repeated_expression.compile(subexpression_address, builder) builder.if__ subexpression_success? do accumulate_subexpression_result end builder.else_ do builder.break end if max && !max.empty? builder.if_ "#{accumulator_var}.size == #{max.text_value}" do builder.break end end end end def inline_module_name parent_expression.inline_module_name end def assign_and_extend_result assign_result "instantiate_node(#{node_class_name},input, #{start_index_var}...index, #{accumulator_var})" extend_result_with_inline_module end end class ZeroOrMore < Repetition def compile(address, builder, parent_expression) super assign_and_extend_result end_comment(parent_expression) end def max nil end end class OneOrMore < Repetition def compile(address, builder, parent_expression) super builder.if__ "#{accumulator_var}.empty?" do reset_index assign_failure start_index_var end builder.else_ do assign_and_extend_result end end_comment(parent_expression) end def max nil end end class OccurrenceRange < Repetition def compile(address, builder, parent_expression) super if min.empty? || min.text_value.to_i == 0 assign_and_extend_result else # We got some, but fewer than we wanted. There'll be a failure reported already builder.if__ "#{accumulator_var}.size < #{min.text_value}" do reset_index assign_failure start_index_var end builder.else_ do assign_and_extend_result end end end_comment(parent_expression) end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/terminal.rb0000644000004100000410000000120212157663062024162 0ustar www-datawww-datamodule Treetop module Compiler class Terminal < AtomicExpression def compile(address, builder, parent_expression = nil) super string_length = eval(text_value).length builder.if__ "has_terminal?(#{text_value}, false, index)" do assign_result "instantiate_node(#{node_class_name},input, index...(index + #{string_length}))" extend_result_with_inline_module builder << "@index += #{string_length}" end builder.else_ do builder << "terminal_parse_failure(#{text_value})" assign_result 'nil' end end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/atomic_expression.rb0000644000004100000410000000046512157663062026114 0ustar www-datawww-datamodule Treetop module Compiler class AtomicExpression < ParsingExpression def inline_modules [] end def single_quote(string) # Double any backslashes, then backslash any single-quotes: "'#{string.gsub(/\\/) { '\\\\' }.gsub(/'/) { "\\'"}}'" end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/declaration_sequence.rb0000644000004100000410000000107212157663062026531 0ustar www-datawww-datamodule Treetop module Compiler class DeclarationSequence < Runtime::SyntaxNode def compile(builder) unless rules.empty? builder.method_declaration("root") do builder << "@root ||= :#{rules.first.name}" end builder.newline end declarations.each do |declaration| declaration.compile(builder) builder.newline end end def rules declarations.select { |declaration| declaration.instance_of?(ParsingRule) } end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/nonterminal.rb0000644000004100000410000000055512157663062024707 0ustar www-datawww-datamodule Treetop module Compiler class Nonterminal < AtomicExpression def compile(address, builder, parent_expression = nil) super use_vars :result assign_result text_value == 'super' ? 'super' : "_nt_#{text_value}" extend_result_with_declared_module extend_result_with_inline_module end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/predicate_block.rb0000644000004100000410000000117712157663062025474 0ustar www-datawww-datamodule Treetop module Compiler class PredicateBlock < ParsingExpression def compile(index, builder, parent_expression = nil) super # REVISIT: This is distinctly dodgey, but since we can only be called from # two contexts, and it works in both those, I'm going with it for now, as # opposed to doing the major refactor of providing a proper way of accessing # the parent's accumulator variable. p = parent p = p.parent while p && !p.respond_to?(:accumulator_var) assign_result "lambda #{text_value}.call(#{p ? p.accumulator_var : ""})" end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/optional.rb0000644000004100000410000000076212157663062024206 0ustar www-datawww-datamodule Treetop module Compiler class Optional < ParsingExpression def compile(address, builder, parent_expression) super use_vars :result obtain_new_subexpression_address parent_expression.atomic.compile(subexpression_address, builder) builder.if__ subexpression_success? do assign_result subexpression_result_var end builder.else_ do assign_result epsilon_node end end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/treetop_file.rb0000644000004100000410000000025212157663062025034 0ustar www-datawww-datamodule Treetop module Compiler class TreetopFile < Runtime::SyntaxNode def compile (elements.map {|elt| elt.compile}).join end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/sequence.rb0000644000004100000410000000466412157663062024176 0ustar www-datawww-datamodule Treetop module Compiler class Sequence < ParsingExpression def compile(address, builder, parent_expression = nil) super begin_comment(self) use_vars :result, :start_index, :accumulator compile_sequence_elements(sequence_elements) builder.if__ "#{accumulator_var}.last" do assign_result "instantiate_node(#{node_class_name},input, #{start_index_var}...index, #{accumulator_var})" extend_result sequence_element_accessor_module_name if sequence_element_accessor_module_name extend_result_with_inline_module end builder.else_ do reset_index assign_failure start_index_var end end_comment(self) end def node_class_name node_class_declarations.node_class_name || 'SyntaxNode' end def compile_sequence_elements(elements) obtain_new_subexpression_address elements.first.compile(subexpression_address, builder) accumulate_subexpression_result if elements.size > 1 builder.if_ subexpression_success? do compile_sequence_elements(elements[1..-1]) end end end def sequence_element_accessor_module @sequence_element_accessor_module ||= SequenceElementAccessorModule.new(sequence_elements) end def sequence_element_accessor_module_name sequence_element_accessor_module.module_name end end class SequenceElementAccessorModule include InlineModuleMixin attr_reader :sequence_elements def initialize(sequence_elements) @sequence_elements = sequence_elements end def compile(idx, builder, rule) super builder.module_declaration(module_name) do elements_by_name = sequence_elements.inject({}){|h,e| (h[e.label_name.to_s] ||= []) << e; h} sequence_elements.each_with_index do |element, index| if element.label_name repetitions = elements_by_name[element.label_name.to_s] label_name = element.label_name + (repetitions.size > 1 ? (repetitions.index(element)+1).to_s : "") builder.method_declaration(label_name) do builder << "elements[#{index}]" end builder.newline unless index == sequence_elements.size - 1 end end end end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/parsing_rule.rb0000644000004100000410000000333512157663062025052 0ustar www-datawww-datamodule Treetop module Compiler class ParsingRule < Runtime::SyntaxNode def compile(builder) compile_inline_module_declarations(builder) generate_method_definition(builder) end def compile_inline_module_declarations(builder) parsing_expression.inline_modules.each_with_index do |inline_module, i| inline_module.compile(i, builder, self) builder.newline end end def generate_method_definition(builder) builder.reset_addresses expression_address = builder.next_address result_var = "r#{expression_address}" builder.method_declaration(method_name) do builder.assign 'start_index', 'index' generate_cache_lookup(builder) builder.newline parsing_expression.compile(expression_address, builder) builder.newline generate_cache_storage(builder, result_var) builder.newline builder << result_var end end def generate_cache_lookup(builder) builder.if_ "node_cache[:#{name}].has_key?(index)" do builder.assign 'cached', "node_cache[:#{name}][index]" builder.if_ "cached" do builder << 'cached = SyntaxNode.new(input, index...(index + 1)) if cached == true' builder << '@index = cached.interval.end' end builder << 'return cached' end end def generate_cache_storage(builder, result_var) builder.assign "node_cache[:#{name}][start_index]", result_var end def method_name "_nt_#{name}" end def name nonterminal.text_value end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/predicate.rb0000644000004100000410000000176612157663062024326 0ustar www-datawww-datamodule Treetop module Compiler class Predicate < ParsingExpression def compile(address, builder, parent_expression) super begin_comment(parent_expression) use_vars :result, :start_index obtain_new_subexpression_address parent_expression.prefixed_expression.compile(subexpression_address, builder) builder.if__(subexpression_success?) { when_success } builder.else_ { when_failure } end_comment(parent_expression) end def assign_failure super(start_index_var) end def assign_success reset_index assign_result epsilon_node end end class AndPredicate < Predicate def when_success assign_success end def when_failure assign_failure end end class NotPredicate < Predicate def when_success assign_failure end def when_failure assign_success end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/anything_symbol.rb0000644000004100000410000000103412157663062025560 0ustar www-datawww-datamodule Treetop module Compiler class AnythingSymbol < AtomicExpression def compile(address, builder, parent_expression = nil) super builder.if__ "index < input_length" do assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))" extend_result_with_inline_module builder << "@index += 1" end builder.else_ do builder << 'terminal_parse_failure("any character")' assign_result 'nil' end end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/parenthesized_expression.rb0000644000004100000410000000036412157663062027503 0ustar www-datawww-datamodule Treetop module Compiler class ParenthesizedExpression < ParsingExpression def compile(address, builder, parent_expression = nil) elements[2].compile(address, builder, parent_expression) end end end endtreetop-1.4.14/lib/treetop/compiler/node_classes/inline_module.rb0000644000004100000410000000110312157663062025172 0ustar www-datawww-datamodule Treetop module Compiler module InlineModuleMixin attr_reader :module_name def compile(index, builder, rule) @module_name = "#{rule.name.treetop_camelize}#{index}" end end class InlineModule < Runtime::SyntaxNode include InlineModuleMixin def compile(index, builder, rule) super builder.module_declaration(module_name) do builder << ruby_code.gsub(/\A\n/, '').rstrip end end def ruby_code elements[1].text_value end end end end treetop-1.4.14/lib/treetop/compiler/node_classes/parsing_expression.rb0000644000004100000410000000707412157663062026306 0ustar www-datawww-datamodule Treetop module Compiler class ParsingExpression < Runtime::SyntaxNode attr_reader :address, :builder, :subexpression_address, :var_symbols, :parent_expression def compile(address, builder, parent_expression) @address = address @builder = builder @parent_expression = parent_expression end def node_class_name parent_expression && parent_expression.node_class_name || 'SyntaxNode' end def declared_module_name parent_expression && parent_expression.node_class_name end def inline_module_name parent_expression && parent_expression.inline_module_name end def decorated? parent_expression && (parent_expression.node_class_name || parent_expression.node_class_name || parent_expression.inline_module_name) end def optional_arg(arg) if arg ", #{arg}" else '' end end def use_vars(*var_symbols) @var_symbols = var_symbols builder << var_initialization end def result_var var(:result) end def accumulator_var var(:accumulator) end def start_index_var var(:start_index) end def subexpression_result_var "r#{subexpression_address}" end def subexpression_success? subexpression_result_var end def obtain_new_subexpression_address @subexpression_address = builder.next_address end def accumulate_subexpression_result builder.accumulate accumulator_var, subexpression_result_var end def assign_result(value_ruby) builder.assign result_var, value_ruby end def extend_result(module_name) builder.extend result_var, module_name end def extend_result_with_declared_module extend_result declared_module_name if declared_module_name end def extend_result_with_inline_module extend_result inline_module_name if inline_module_name end def reset_index builder.assign '@index', start_index_var end def epsilon_node "instantiate_node(SyntaxNode,input, index...index)" end def assign_failure(start_index_var) assign_result("nil") end def assign_lazily_instantiated_node assign_result("true") end def var_initialization left, right = [], [] var_symbols.each do |symbol| if init_value(symbol) left << var(symbol) right << init_value(symbol) end end if left.empty? "" else left.join(', ') + ' = ' + right.join(', ') end end def var(var_symbol) case var_symbol when :result then "r#{address}" when :accumulator then "s#{address}" when :start_index then "i#{address}" else raise "Unknown var symbol #{var_symbol}." end end def init_value(var_symbol) case var_symbol when :accumulator then '[]' when :start_index then 'index' else nil end end def begin_comment(expression) #builder << "# begin #{on_one_line(expression)}" end def end_comment(expression) #builder << "# end #{on_one_line(expression)}" end def on_one_line(expression) expression.text_value.tr("\n", ' ') end end end end treetop-1.4.14/lib/treetop/compiler/grammar_compiler.rb0000644000004100000410000000276212157663062023241 0ustar www-datawww-datamodule Treetop module Compiler AUTOGENERATED = "# Autogenerated from a Treetop grammar. Edits may be lost.\n" class GrammarCompiler def compile(source_path, target_path = source_path.gsub(/\.(treetop|tt)\Z/, '.rb')) File.open(target_path, 'w') do |target_file| ruby = ruby_source(source_path) if ruby =~ /\A#.*\n/ ruby.sub!(/\n/, "\n"+AUTOGENERATED+"\n\n") else ruby = AUTOGENERATED+"\n\n"+ruby end target_file.write(ruby) end end # compile a treetop file into ruby def ruby_source(source_path) ruby_source_from_string(File.read(source_path)) end # compile a string containing treetop source into ruby def ruby_source_from_string(s) parser = MetagrammarParser.new result = parser.parse(s) unless result raise RuntimeError.new(parser.failure_reason) end result.compile end end end # compile a treetop source file and load it def self.load(path) adjusted_path = path =~ /\.(treetop|tt)\Z/ ? path : path + '.treetop' File.open(adjusted_path) do |source_file| source = source_file.read source.gsub!(/\b__FILE__\b/, %Q{"#{adjusted_path}"}) load_from_string(source) end end # compile a treetop source string and load it def self.load_from_string(s) compiler = Treetop::Compiler::GrammarCompiler.new Object.class_eval(compiler.ruby_source_from_string(s)) end end treetop-1.4.14/lib/treetop/compiler/node_classes.rb0000644000004100000410000000177712157663062022370 0ustar www-datawww-datarequire 'treetop/compiler/node_classes/parsing_expression' require 'treetop/compiler/node_classes/atomic_expression' require 'treetop/compiler/node_classes/inline_module' require 'treetop/compiler/node_classes/predicate_block' require 'treetop/compiler/node_classes/treetop_file' require 'treetop/compiler/node_classes/grammar' require 'treetop/compiler/node_classes/declaration_sequence' require 'treetop/compiler/node_classes/parsing_rule' require 'treetop/compiler/node_classes/parenthesized_expression' require 'treetop/compiler/node_classes/nonterminal' require 'treetop/compiler/node_classes/terminal' require 'treetop/compiler/node_classes/anything_symbol' require 'treetop/compiler/node_classes/character_class' require 'treetop/compiler/node_classes/sequence' require 'treetop/compiler/node_classes/choice' require 'treetop/compiler/node_classes/repetition' require 'treetop/compiler/node_classes/optional' require 'treetop/compiler/node_classes/predicate' require 'treetop/compiler/node_classes/transient_prefix' treetop-1.4.14/lib/treetop/compiler/metagrammar.treetop0000644000004100000410000002635312157663062023277 0ustar www-datawww-datamodule Treetop module Compiler grammar Metagrammar rule treetop_file requires:(space? require_statement)* prefix:space? module_or_grammar suffix:space? { def compile requires.text_value + prefix.text_value + module_or_grammar.compile + suffix.text_value end } end rule require_statement prefix:space? "require" [ \t]+ [^\n\r]+ [\n\r] end rule module_or_grammar module_declaration / grammar end rule module_declaration prefix:('module' space name:([A-Z] alphanumeric_char* ('::' [A-Z] alphanumeric_char*)*) space) module_contents:(module_declaration / grammar) suffix:(space 'end') { def compile prefix.text_value + module_contents.compile + suffix.text_value end def parser_name prefix.name.text_value+'::'+module_contents.parser_name end } end rule grammar 'grammar' space grammar_name space ('do' space)? declaration_sequence space? 'end' end rule grammar_name ([A-Z] alphanumeric_char*) end rule declaration_sequence head:declaration tail:(space declaration)* { def declarations [head] + tail end def tail super.elements.map { |elt| elt.declaration } end } / '' { def compile(builder) end } end rule declaration parsing_rule / include_declaration end rule include_declaration 'include' space [A-Z] (alphanumeric_char / '::')* { def compile(builder) builder << text_value end } end rule parsing_rule 'rule' space nonterminal space ('do' space)? parsing_expression space 'end' end rule parsing_expression choice / sequence / primary end rule choice head:alternative tail:(space? '/' space? alternative)+ { def alternatives [head] + tail end def tail super.elements.map {|elt| elt.alternative} end def inline_modules (alternatives.map {|alt| alt.inline_modules }).flatten end } end rule sequence sequence_body node_class_declarations { def sequence_elements [sequence_body.head] + tail end def tail sequence_body.tail end def inline_modules (sequence_elements.map {|elt| elt.inline_modules}).flatten + [sequence_element_accessor_module] + node_class_declarations.inline_modules end def inline_module_name node_class_declarations.inline_module_name end } end rule sequence_body variable_length_sequence_body / labeled_expression_sequence_body end rule variable_length_sequence_body head:optionally_labeled_sequence_primary tail:(space optionally_labeled_sequence_primary)+ { def tail super.elements.map {|elt| elt.optionally_labeled_sequence_primary } end } end rule labeled_expression_sequence_body labeled_sequence_primary { def head self end def tail [] end } end rule alternative sequence / primary end rule primary prefix atomic { def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression atomic end def inline_modules atomic.inline_modules end def inline_module_name nil end } / prefix space? predicate_block { def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression predicate_block end def inline_modules [] end } / atomic suffix node_class_declarations { def compile(address, builder, parent_expression=nil) suffix.compile(address, builder, self) end def optional_expression atomic end def node_class_name node_class_declarations.node_class_name end def inline_modules atomic.inline_modules + node_class_declarations.inline_modules end def inline_module_name node_class_declarations.inline_module_name end } / atomic node_class_declarations { def compile(address, builder, parent_expression=nil) atomic.compile(address, builder, self) end def node_class_name node_class_declarations.node_class_name end def inline_modules atomic.inline_modules + node_class_declarations.inline_modules end def inline_module_name node_class_declarations.inline_module_name end } end rule optionally_labeled_sequence_primary labeled_sequence_primary / unlabeled_sequence_primary end rule labeled_sequence_primary named_label sequence_primary { def compile(lexical_address, builder) sequence_primary.compile(lexical_address, builder) end def inline_modules sequence_primary.inline_modules end def label_name named_label.name end } end rule unlabeled_sequence_primary null_label sequence_primary { def compile(lexical_address, builder) sequence_primary.compile(lexical_address, builder) end def inline_modules sequence_primary.inline_modules end def label_name if sequence_primary.instance_of?(Nonterminal) sequence_primary.text_value else nil end end } end rule label named_label / null_label end rule named_label (alpha_char alphanumeric_char*) ':' { def name elements[0].text_value end } end rule null_label '' { def name nil end } end rule sequence_primary prefix atomic { def compile(lexical_address, builder) prefix.compile(lexical_address, builder, self) end def prefixed_expression elements[1] end def inline_modules atomic.inline_modules end def inline_module_name nil end } / prefix space? predicate_block { def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression predicate_block end def inline_modules [] end } / atomic suffix { def compile(lexical_address, builder) suffix.compile(lexical_address, builder, self) end def node_class_name nil end def inline_modules atomic.inline_modules end def inline_module_name nil end } / atomic end rule suffix repetition_suffix / optional_suffix end rule optional_suffix '?' end rule node_class_declarations node_class_expression trailing_inline_module { def node_class_name node_class_expression.node_class_name end def inline_modules trailing_inline_module.inline_modules end def inline_module trailing_inline_module.inline_module end def inline_module_name inline_module.module_name if inline_module end } end rule repetition_suffix '+' / '*' / occurrence_range end rule occurrence_range space? min:([0-9])* '..' max:([0-9])* end rule prefix '&' / '!' / '~' end rule atomic terminal / nonterminal / parenthesized_expression end rule parenthesized_expression '(' space? parsing_expression space? ')' { def inline_modules parsing_expression.inline_modules end } end rule nonterminal !keyword_inside_grammar (alpha_char alphanumeric_char*) end rule terminal quoted_string / character_class / anything_symbol end rule quoted_string (single_quoted_string / double_quoted_string) { def string super.text_value end } end rule double_quoted_string '"' string:(!'"' ("\\\\" / '\"' / .))* '"' end rule single_quoted_string "'" string:(!"'" ("\\\\" / "\\'" / .))* "'" end rule character_class '[' characters:(!']' ('\\' . / bracket_expression / !'\\' .))+ ']' { def characters super.text_value end } end rule bracket_expression '[:' '^'? ( 'alnum' / 'alpha' / 'blank' / 'cntrl' / 'digit' / 'graph' / 'lower' / 'print' / 'punct' / 'space' / 'upper' / 'xdigit' / 'word' ) ':]' end rule anything_symbol '.' end rule node_class_expression space '<' (!'>' .)+ '>' { def node_class_name elements[2].text_value end } / '' { def node_class_name nil end } end rule trailing_inline_module space inline_module { def inline_modules [inline_module] end def inline_module_name inline_module.module_name end } / '' { def inline_modules [] end def inline_module nil end def inline_module_name nil end } end rule predicate_block '' inline_module end rule inline_module '{' (inline_module / ![{}] .)* '}' end rule keyword_inside_grammar ('rule' / 'end') !non_space_char end rule non_space_char !space . end rule alpha_char [A-Za-z_] end rule alphanumeric_char alpha_char / [0-9] end rule space (white / comment_to_eol)+ end rule comment_to_eol '#' (!"\n" .)* end rule white [ \t\n\r] end end end end treetop-1.4.14/lib/treetop/compiler/lexical_address_space.rb0000644000004100000410000000042012157663062024207 0ustar www-datawww-datamodule Treetop module Compiler class LexicalAddressSpace def initialize reset_addresses end def next_address @next_address += 1 end def reset_addresses @next_address = -1 end end end endtreetop-1.4.14/lib/treetop/compiler/metagrammar.rb0000644000004100000410000030631612157663062022220 0ustar www-datawww-data# Autogenerated from a Treetop grammar. Edits may be lost. module Treetop module Compiler module Metagrammar include Treetop::Runtime def root @root ||= :treetop_file end module TreetopFile0 def require_statement elements[1] end end module TreetopFile1 def requires elements[0] end def prefix elements[1] end def module_or_grammar elements[2] end def suffix elements[3] end end module TreetopFile2 def compile requires.text_value + prefix.text_value + module_or_grammar.compile + suffix.text_value end end def _nt_treetop_file start_index = index if node_cache[:treetop_file].has_key?(index) cached = node_cache[:treetop_file][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] s1, i1 = [], index loop do i2, s2 = index, [] r4 = _nt_space if r4 r3 = r4 else r3 = instantiate_node(SyntaxNode,input, index...index) end s2 << r3 if r3 r5 = _nt_require_statement s2 << r5 end if s2.last r2 = instantiate_node(SyntaxNode,input, i2...index, s2) r2.extend(TreetopFile0) else @index = i2 r2 = nil end if r2 s1 << r2 else break end end r1 = instantiate_node(SyntaxNode,input, i1...index, s1) s0 << r1 if r1 r7 = _nt_space if r7 r6 = r7 else r6 = instantiate_node(SyntaxNode,input, index...index) end s0 << r6 if r6 r8 = _nt_module_or_grammar s0 << r8 if r8 r10 = _nt_space if r10 r9 = r10 else r9 = instantiate_node(SyntaxNode,input, index...index) end s0 << r9 end end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(TreetopFile1) r0.extend(TreetopFile2) else @index = i0 r0 = nil end node_cache[:treetop_file][start_index] = r0 r0 end module RequireStatement0 def prefix elements[0] end end def _nt_require_statement start_index = index if node_cache[:require_statement].has_key?(index) cached = node_cache[:require_statement][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r2 = _nt_space if r2 r1 = r2 else r1 = instantiate_node(SyntaxNode,input, index...index) end s0 << r1 if r1 if has_terminal?("require", false, index) r3 = instantiate_node(SyntaxNode,input, index...(index + 7)) @index += 7 else terminal_parse_failure("require") r3 = nil end s0 << r3 if r3 s4, i4 = [], index loop do if has_terminal?('\G[ \\t]', true, index) r5 = true @index += 1 else r5 = nil end if r5 s4 << r5 else break end end if s4.empty? @index = i4 r4 = nil else r4 = instantiate_node(SyntaxNode,input, i4...index, s4) end s0 << r4 if r4 s6, i6 = [], index loop do if has_terminal?('\G[^\\n\\r]', true, index) r7 = true @index += 1 else r7 = nil end if r7 s6 << r7 else break end end if s6.empty? @index = i6 r6 = nil else r6 = instantiate_node(SyntaxNode,input, i6...index, s6) end s0 << r6 if r6 if has_terminal?('\G[\\n\\r]', true, index) r8 = true @index += 1 else r8 = nil end s0 << r8 end end end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(RequireStatement0) else @index = i0 r0 = nil end node_cache[:require_statement][start_index] = r0 r0 end def _nt_module_or_grammar start_index = index if node_cache[:module_or_grammar].has_key?(index) cached = node_cache[:module_or_grammar][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_module_declaration if r1 r0 = r1 else r2 = _nt_grammar if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:module_or_grammar][start_index] = r0 r0 end module ModuleDeclaration0 end module ModuleDeclaration1 end module ModuleDeclaration2 def space1 elements[1] end def name elements[2] end def space2 elements[3] end end module ModuleDeclaration3 def space elements[0] end end module ModuleDeclaration4 def prefix elements[0] end def module_contents elements[1] end def suffix elements[2] end end module ModuleDeclaration5 def compile prefix.text_value + module_contents.compile + suffix.text_value end def parser_name prefix.name.text_value+'::'+module_contents.parser_name end end def _nt_module_declaration start_index = index if node_cache[:module_declaration].has_key?(index) cached = node_cache[:module_declaration][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1, s1 = index, [] if has_terminal?('module', false, index) r2 = instantiate_node(SyntaxNode,input, index...(index + 6)) @index += 6 else terminal_parse_failure('module') r2 = nil end s1 << r2 if r2 r3 = _nt_space s1 << r3 if r3 i4, s4 = index, [] if has_terminal?('\G[A-Z]', true, index) r5 = true @index += 1 else r5 = nil end s4 << r5 if r5 s6, i6 = [], index loop do r7 = _nt_alphanumeric_char if r7 s6 << r7 else break end end r6 = instantiate_node(SyntaxNode,input, i6...index, s6) s4 << r6 if r6 s8, i8 = [], index loop do i9, s9 = index, [] if has_terminal?('::', false, index) r10 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('::') r10 = nil end s9 << r10 if r10 if has_terminal?('\G[A-Z]', true, index) r11 = true @index += 1 else r11 = nil end s9 << r11 if r11 s12, i12 = [], index loop do r13 = _nt_alphanumeric_char if r13 s12 << r13 else break end end r12 = instantiate_node(SyntaxNode,input, i12...index, s12) s9 << r12 end end if s9.last r9 = instantiate_node(SyntaxNode,input, i9...index, s9) r9.extend(ModuleDeclaration0) else @index = i9 r9 = nil end if r9 s8 << r9 else break end end r8 = instantiate_node(SyntaxNode,input, i8...index, s8) s4 << r8 end end if s4.last r4 = instantiate_node(SyntaxNode,input, i4...index, s4) r4.extend(ModuleDeclaration1) else @index = i4 r4 = nil end s1 << r4 if r4 r14 = _nt_space s1 << r14 end end end if s1.last r1 = instantiate_node(SyntaxNode,input, i1...index, s1) r1.extend(ModuleDeclaration2) else @index = i1 r1 = nil end s0 << r1 if r1 i15 = index r16 = _nt_module_declaration if r16 r15 = r16 else r17 = _nt_grammar if r17 r15 = r17 else @index = i15 r15 = nil end end s0 << r15 if r15 i18, s18 = index, [] r19 = _nt_space s18 << r19 if r19 if has_terminal?('end', false, index) r20 = instantiate_node(SyntaxNode,input, index...(index + 3)) @index += 3 else terminal_parse_failure('end') r20 = nil end s18 << r20 end if s18.last r18 = instantiate_node(SyntaxNode,input, i18...index, s18) r18.extend(ModuleDeclaration3) else @index = i18 r18 = nil end s0 << r18 end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(ModuleDeclaration4) r0.extend(ModuleDeclaration5) else @index = i0 r0 = nil end node_cache[:module_declaration][start_index] = r0 r0 end module Grammar0 def space elements[1] end end module Grammar1 def space1 elements[1] end def grammar_name elements[2] end def space2 elements[3] end def declaration_sequence elements[5] end end def _nt_grammar start_index = index if node_cache[:grammar].has_key?(index) cached = node_cache[:grammar][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('grammar', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 7)) @index += 7 else terminal_parse_failure('grammar') r1 = nil end s0 << r1 if r1 r2 = _nt_space s0 << r2 if r2 r3 = _nt_grammar_name s0 << r3 if r3 r4 = _nt_space s0 << r4 if r4 i6, s6 = index, [] if has_terminal?('do', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('do') r7 = nil end s6 << r7 if r7 r8 = _nt_space s6 << r8 end if s6.last r6 = instantiate_node(SyntaxNode,input, i6...index, s6) r6.extend(Grammar0) else @index = i6 r6 = nil end if r6 r5 = r6 else r5 = instantiate_node(SyntaxNode,input, index...index) end s0 << r5 if r5 r9 = _nt_declaration_sequence s0 << r9 if r9 r11 = _nt_space if r11 r10 = r11 else r10 = instantiate_node(SyntaxNode,input, index...index) end s0 << r10 if r10 if has_terminal?('end', false, index) r12 = instantiate_node(SyntaxNode,input, index...(index + 3)) @index += 3 else terminal_parse_failure('end') r12 = nil end s0 << r12 end end end end end end end if s0.last r0 = instantiate_node(Grammar,input, i0...index, s0) r0.extend(Grammar1) else @index = i0 r0 = nil end node_cache[:grammar][start_index] = r0 r0 end module GrammarName0 end def _nt_grammar_name start_index = index if node_cache[:grammar_name].has_key?(index) cached = node_cache[:grammar_name][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('\G[A-Z]', true, index) r1 = true @index += 1 else r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do r3 = _nt_alphanumeric_char if r3 s2 << r3 else break end end r2 = instantiate_node(SyntaxNode,input, i2...index, s2) s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(GrammarName0) else @index = i0 r0 = nil end node_cache[:grammar_name][start_index] = r0 r0 end module DeclarationSequence0 def space elements[0] end def declaration elements[1] end end module DeclarationSequence1 def head elements[0] end def tail elements[1] end end module DeclarationSequence2 def declarations [head] + tail end def tail super.elements.map { |elt| elt.declaration } end end module DeclarationSequence3 def compile(builder) end end def _nt_declaration_sequence start_index = index if node_cache[:declaration_sequence].has_key?(index) cached = node_cache[:declaration_sequence][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index i1, s1 = index, [] r2 = _nt_declaration s1 << r2 if r2 s3, i3 = [], index loop do i4, s4 = index, [] r5 = _nt_space s4 << r5 if r5 r6 = _nt_declaration s4 << r6 end if s4.last r4 = instantiate_node(SyntaxNode,input, i4...index, s4) r4.extend(DeclarationSequence0) else @index = i4 r4 = nil end if r4 s3 << r4 else break end end r3 = instantiate_node(SyntaxNode,input, i3...index, s3) s1 << r3 end if s1.last r1 = instantiate_node(DeclarationSequence,input, i1...index, s1) r1.extend(DeclarationSequence1) r1.extend(DeclarationSequence2) else @index = i1 r1 = nil end if r1 r0 = r1 else if has_terminal?('', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 0)) r7.extend(DeclarationSequence3) @index += 0 else terminal_parse_failure('') r7 = nil end if r7 r0 = r7 else @index = i0 r0 = nil end end node_cache[:declaration_sequence][start_index] = r0 r0 end def _nt_declaration start_index = index if node_cache[:declaration].has_key?(index) cached = node_cache[:declaration][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_parsing_rule if r1 r0 = r1 else r2 = _nt_include_declaration if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:declaration][start_index] = r0 r0 end module IncludeDeclaration0 def space elements[1] end end module IncludeDeclaration1 def compile(builder) builder << text_value end end def _nt_include_declaration start_index = index if node_cache[:include_declaration].has_key?(index) cached = node_cache[:include_declaration][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('include', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 7)) @index += 7 else terminal_parse_failure('include') r1 = nil end s0 << r1 if r1 r2 = _nt_space s0 << r2 if r2 if has_terminal?('\G[A-Z]', true, index) r3 = true @index += 1 else r3 = nil end s0 << r3 if r3 s4, i4 = [], index loop do i5 = index r6 = _nt_alphanumeric_char if r6 r5 = r6 else if has_terminal?('::', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('::') r7 = nil end if r7 r5 = r7 else @index = i5 r5 = nil end end if r5 s4 << r5 else break end end r4 = instantiate_node(SyntaxNode,input, i4...index, s4) s0 << r4 end end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(IncludeDeclaration0) r0.extend(IncludeDeclaration1) else @index = i0 r0 = nil end node_cache[:include_declaration][start_index] = r0 r0 end module ParsingRule0 def space elements[1] end end module ParsingRule1 def space1 elements[1] end def nonterminal elements[2] end def space2 elements[3] end def parsing_expression elements[5] end def space3 elements[6] end end def _nt_parsing_rule start_index = index if node_cache[:parsing_rule].has_key?(index) cached = node_cache[:parsing_rule][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('rule', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 4)) @index += 4 else terminal_parse_failure('rule') r1 = nil end s0 << r1 if r1 r2 = _nt_space s0 << r2 if r2 r3 = _nt_nonterminal s0 << r3 if r3 r4 = _nt_space s0 << r4 if r4 i6, s6 = index, [] if has_terminal?('do', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('do') r7 = nil end s6 << r7 if r7 r8 = _nt_space s6 << r8 end if s6.last r6 = instantiate_node(SyntaxNode,input, i6...index, s6) r6.extend(ParsingRule0) else @index = i6 r6 = nil end if r6 r5 = r6 else r5 = instantiate_node(SyntaxNode,input, index...index) end s0 << r5 if r5 r9 = _nt_parsing_expression s0 << r9 if r9 r10 = _nt_space s0 << r10 if r10 if has_terminal?('end', false, index) r11 = instantiate_node(SyntaxNode,input, index...(index + 3)) @index += 3 else terminal_parse_failure('end') r11 = nil end s0 << r11 end end end end end end end if s0.last r0 = instantiate_node(ParsingRule,input, i0...index, s0) r0.extend(ParsingRule1) else @index = i0 r0 = nil end node_cache[:parsing_rule][start_index] = r0 r0 end def _nt_parsing_expression start_index = index if node_cache[:parsing_expression].has_key?(index) cached = node_cache[:parsing_expression][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_choice if r1 r0 = r1 else r2 = _nt_sequence if r2 r0 = r2 else r3 = _nt_primary if r3 r0 = r3 else @index = i0 r0 = nil end end end node_cache[:parsing_expression][start_index] = r0 r0 end module Choice0 def alternative elements[3] end end module Choice1 def head elements[0] end def tail elements[1] end end module Choice2 def alternatives [head] + tail end def tail super.elements.map {|elt| elt.alternative} end def inline_modules (alternatives.map {|alt| alt.inline_modules }).flatten end end def _nt_choice start_index = index if node_cache[:choice].has_key?(index) cached = node_cache[:choice][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_alternative s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] r5 = _nt_space if r5 r4 = r5 else r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 if has_terminal?('/', false, index) r6 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('/') r6 = nil end s3 << r6 if r6 r8 = _nt_space if r8 r7 = r8 else r7 = instantiate_node(SyntaxNode,input, index...index) end s3 << r7 if r7 r9 = _nt_alternative s3 << r9 end end end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(Choice0) else @index = i3 r3 = nil end if r3 s2 << r3 else break end end if s2.empty? @index = i2 r2 = nil else r2 = instantiate_node(SyntaxNode,input, i2...index, s2) end s0 << r2 end if s0.last r0 = instantiate_node(Choice,input, i0...index, s0) r0.extend(Choice1) r0.extend(Choice2) else @index = i0 r0 = nil end node_cache[:choice][start_index] = r0 r0 end module Sequence0 def sequence_body elements[0] end def node_class_declarations elements[1] end end module Sequence1 def sequence_elements [sequence_body.head] + tail end def tail sequence_body.tail end def inline_modules (sequence_elements.map {|elt| elt.inline_modules}).flatten + [sequence_element_accessor_module] + node_class_declarations.inline_modules end def inline_module_name node_class_declarations.inline_module_name end end def _nt_sequence start_index = index if node_cache[:sequence].has_key?(index) cached = node_cache[:sequence][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_sequence_body s0 << r1 if r1 r2 = _nt_node_class_declarations s0 << r2 end if s0.last r0 = instantiate_node(Sequence,input, i0...index, s0) r0.extend(Sequence0) r0.extend(Sequence1) else @index = i0 r0 = nil end node_cache[:sequence][start_index] = r0 r0 end def _nt_sequence_body start_index = index if node_cache[:sequence_body].has_key?(index) cached = node_cache[:sequence_body][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_variable_length_sequence_body if r1 r0 = r1 else r2 = _nt_labeled_expression_sequence_body if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:sequence_body][start_index] = r0 r0 end module VariableLengthSequenceBody0 def space elements[0] end def optionally_labeled_sequence_primary elements[1] end end module VariableLengthSequenceBody1 def head elements[0] end def tail elements[1] end end module VariableLengthSequenceBody2 def tail super.elements.map {|elt| elt.optionally_labeled_sequence_primary } end end def _nt_variable_length_sequence_body start_index = index if node_cache[:variable_length_sequence_body].has_key?(index) cached = node_cache[:variable_length_sequence_body][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_optionally_labeled_sequence_primary s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] r4 = _nt_space s3 << r4 if r4 r5 = _nt_optionally_labeled_sequence_primary s3 << r5 end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(VariableLengthSequenceBody0) else @index = i3 r3 = nil end if r3 s2 << r3 else break end end if s2.empty? @index = i2 r2 = nil else r2 = instantiate_node(SyntaxNode,input, i2...index, s2) end s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(VariableLengthSequenceBody1) r0.extend(VariableLengthSequenceBody2) else @index = i0 r0 = nil end node_cache[:variable_length_sequence_body][start_index] = r0 r0 end module LabeledExpressionSequenceBody0 def head self end def tail [] end end def _nt_labeled_expression_sequence_body start_index = index if node_cache[:labeled_expression_sequence_body].has_key?(index) cached = node_cache[:labeled_expression_sequence_body][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end r0 = _nt_labeled_sequence_primary r0.extend(LabeledExpressionSequenceBody0) node_cache[:labeled_expression_sequence_body][start_index] = r0 r0 end def _nt_alternative start_index = index if node_cache[:alternative].has_key?(index) cached = node_cache[:alternative][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_sequence if r1 r0 = r1 else r2 = _nt_primary if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:alternative][start_index] = r0 r0 end module Primary0 def prefix elements[0] end def atomic elements[1] end end module Primary1 def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression atomic end def inline_modules atomic.inline_modules end def inline_module_name nil end end module Primary2 def prefix elements[0] end def predicate_block elements[2] end end module Primary3 def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression predicate_block end def inline_modules [] end end module Primary4 def atomic elements[0] end def suffix elements[1] end def node_class_declarations elements[2] end end module Primary5 def compile(address, builder, parent_expression=nil) suffix.compile(address, builder, self) end def optional_expression atomic end def node_class_name node_class_declarations.node_class_name end def inline_modules atomic.inline_modules + node_class_declarations.inline_modules end def inline_module_name node_class_declarations.inline_module_name end end module Primary6 def atomic elements[0] end def node_class_declarations elements[1] end end module Primary7 def compile(address, builder, parent_expression=nil) atomic.compile(address, builder, self) end def node_class_name node_class_declarations.node_class_name end def inline_modules atomic.inline_modules + node_class_declarations.inline_modules end def inline_module_name node_class_declarations.inline_module_name end end def _nt_primary start_index = index if node_cache[:primary].has_key?(index) cached = node_cache[:primary][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index i1, s1 = index, [] r2 = _nt_prefix s1 << r2 if r2 r3 = _nt_atomic s1 << r3 end if s1.last r1 = instantiate_node(SyntaxNode,input, i1...index, s1) r1.extend(Primary0) r1.extend(Primary1) else @index = i1 r1 = nil end if r1 r0 = r1 else i4, s4 = index, [] r5 = _nt_prefix s4 << r5 if r5 r7 = _nt_space if r7 r6 = r7 else r6 = instantiate_node(SyntaxNode,input, index...index) end s4 << r6 if r6 r8 = _nt_predicate_block s4 << r8 end end if s4.last r4 = instantiate_node(SyntaxNode,input, i4...index, s4) r4.extend(Primary2) r4.extend(Primary3) else @index = i4 r4 = nil end if r4 r0 = r4 else i9, s9 = index, [] r10 = _nt_atomic s9 << r10 if r10 r11 = _nt_suffix s9 << r11 if r11 r12 = _nt_node_class_declarations s9 << r12 end end if s9.last r9 = instantiate_node(SyntaxNode,input, i9...index, s9) r9.extend(Primary4) r9.extend(Primary5) else @index = i9 r9 = nil end if r9 r0 = r9 else i13, s13 = index, [] r14 = _nt_atomic s13 << r14 if r14 r15 = _nt_node_class_declarations s13 << r15 end if s13.last r13 = instantiate_node(SyntaxNode,input, i13...index, s13) r13.extend(Primary6) r13.extend(Primary7) else @index = i13 r13 = nil end if r13 r0 = r13 else @index = i0 r0 = nil end end end end node_cache[:primary][start_index] = r0 r0 end def _nt_optionally_labeled_sequence_primary start_index = index if node_cache[:optionally_labeled_sequence_primary].has_key?(index) cached = node_cache[:optionally_labeled_sequence_primary][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_labeled_sequence_primary if r1 r0 = r1 else r2 = _nt_unlabeled_sequence_primary if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:optionally_labeled_sequence_primary][start_index] = r0 r0 end module LabeledSequencePrimary0 def named_label elements[0] end def sequence_primary elements[1] end end module LabeledSequencePrimary1 def compile(lexical_address, builder) sequence_primary.compile(lexical_address, builder) end def inline_modules sequence_primary.inline_modules end def label_name named_label.name end end def _nt_labeled_sequence_primary start_index = index if node_cache[:labeled_sequence_primary].has_key?(index) cached = node_cache[:labeled_sequence_primary][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_named_label s0 << r1 if r1 r2 = _nt_sequence_primary s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(LabeledSequencePrimary0) r0.extend(LabeledSequencePrimary1) else @index = i0 r0 = nil end node_cache[:labeled_sequence_primary][start_index] = r0 r0 end module UnlabeledSequencePrimary0 def null_label elements[0] end def sequence_primary elements[1] end end module UnlabeledSequencePrimary1 def compile(lexical_address, builder) sequence_primary.compile(lexical_address, builder) end def inline_modules sequence_primary.inline_modules end def label_name if sequence_primary.instance_of?(Nonterminal) sequence_primary.text_value else nil end end end def _nt_unlabeled_sequence_primary start_index = index if node_cache[:unlabeled_sequence_primary].has_key?(index) cached = node_cache[:unlabeled_sequence_primary][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_null_label s0 << r1 if r1 r2 = _nt_sequence_primary s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(UnlabeledSequencePrimary0) r0.extend(UnlabeledSequencePrimary1) else @index = i0 r0 = nil end node_cache[:unlabeled_sequence_primary][start_index] = r0 r0 end def _nt_label start_index = index if node_cache[:label].has_key?(index) cached = node_cache[:label][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_named_label if r1 r0 = r1 else r2 = _nt_null_label if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:label][start_index] = r0 r0 end module NamedLabel0 def alpha_char elements[0] end end module NamedLabel1 end module NamedLabel2 def name elements[0].text_value end end def _nt_named_label start_index = index if node_cache[:named_label].has_key?(index) cached = node_cache[:named_label][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1, s1 = index, [] r2 = _nt_alpha_char s1 << r2 if r2 s3, i3 = [], index loop do r4 = _nt_alphanumeric_char if r4 s3 << r4 else break end end r3 = instantiate_node(SyntaxNode,input, i3...index, s3) s1 << r3 end if s1.last r1 = instantiate_node(SyntaxNode,input, i1...index, s1) r1.extend(NamedLabel0) else @index = i1 r1 = nil end s0 << r1 if r1 if has_terminal?(':', false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure(':') r5 = nil end s0 << r5 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(NamedLabel1) r0.extend(NamedLabel2) else @index = i0 r0 = nil end node_cache[:named_label][start_index] = r0 r0 end module NullLabel0 def name nil end end def _nt_null_label start_index = index if node_cache[:null_label].has_key?(index) cached = node_cache[:null_label][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?('', false, index) r0 = instantiate_node(SyntaxNode,input, index...(index + 0)) r0.extend(NullLabel0) @index += 0 else terminal_parse_failure('') r0 = nil end node_cache[:null_label][start_index] = r0 r0 end module SequencePrimary0 def prefix elements[0] end def atomic elements[1] end end module SequencePrimary1 def compile(lexical_address, builder) prefix.compile(lexical_address, builder, self) end def prefixed_expression elements[1] end def inline_modules atomic.inline_modules end def inline_module_name nil end end module SequencePrimary2 def prefix elements[0] end def predicate_block elements[2] end end module SequencePrimary3 def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression predicate_block end def inline_modules [] end end module SequencePrimary4 def atomic elements[0] end def suffix elements[1] end end module SequencePrimary5 def compile(lexical_address, builder) suffix.compile(lexical_address, builder, self) end def node_class_name nil end def inline_modules atomic.inline_modules end def inline_module_name nil end end def _nt_sequence_primary start_index = index if node_cache[:sequence_primary].has_key?(index) cached = node_cache[:sequence_primary][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index i1, s1 = index, [] r2 = _nt_prefix s1 << r2 if r2 r3 = _nt_atomic s1 << r3 end if s1.last r1 = instantiate_node(SyntaxNode,input, i1...index, s1) r1.extend(SequencePrimary0) r1.extend(SequencePrimary1) else @index = i1 r1 = nil end if r1 r0 = r1 else i4, s4 = index, [] r5 = _nt_prefix s4 << r5 if r5 r7 = _nt_space if r7 r6 = r7 else r6 = instantiate_node(SyntaxNode,input, index...index) end s4 << r6 if r6 r8 = _nt_predicate_block s4 << r8 end end if s4.last r4 = instantiate_node(SyntaxNode,input, i4...index, s4) r4.extend(SequencePrimary2) r4.extend(SequencePrimary3) else @index = i4 r4 = nil end if r4 r0 = r4 else i9, s9 = index, [] r10 = _nt_atomic s9 << r10 if r10 r11 = _nt_suffix s9 << r11 end if s9.last r9 = instantiate_node(SyntaxNode,input, i9...index, s9) r9.extend(SequencePrimary4) r9.extend(SequencePrimary5) else @index = i9 r9 = nil end if r9 r0 = r9 else r12 = _nt_atomic if r12 r0 = r12 else @index = i0 r0 = nil end end end end node_cache[:sequence_primary][start_index] = r0 r0 end def _nt_suffix start_index = index if node_cache[:suffix].has_key?(index) cached = node_cache[:suffix][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_repetition_suffix if r1 r0 = r1 else r2 = _nt_optional_suffix if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:suffix][start_index] = r0 r0 end def _nt_optional_suffix start_index = index if node_cache[:optional_suffix].has_key?(index) cached = node_cache[:optional_suffix][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?('?', false, index) r0 = instantiate_node(Optional,input, index...(index + 1)) @index += 1 else terminal_parse_failure('?') r0 = nil end node_cache[:optional_suffix][start_index] = r0 r0 end module NodeClassDeclarations0 def node_class_expression elements[0] end def trailing_inline_module elements[1] end end module NodeClassDeclarations1 def node_class_name node_class_expression.node_class_name end def inline_modules trailing_inline_module.inline_modules end def inline_module trailing_inline_module.inline_module end def inline_module_name inline_module.module_name if inline_module end end def _nt_node_class_declarations start_index = index if node_cache[:node_class_declarations].has_key?(index) cached = node_cache[:node_class_declarations][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_node_class_expression s0 << r1 if r1 r2 = _nt_trailing_inline_module s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(NodeClassDeclarations0) r0.extend(NodeClassDeclarations1) else @index = i0 r0 = nil end node_cache[:node_class_declarations][start_index] = r0 r0 end def _nt_repetition_suffix start_index = index if node_cache[:repetition_suffix].has_key?(index) cached = node_cache[:repetition_suffix][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index if has_terminal?('+', false, index) r1 = instantiate_node(OneOrMore,input, index...(index + 1)) @index += 1 else terminal_parse_failure('+') r1 = nil end if r1 r0 = r1 else if has_terminal?('*', false, index) r2 = instantiate_node(ZeroOrMore,input, index...(index + 1)) @index += 1 else terminal_parse_failure('*') r2 = nil end if r2 r0 = r2 else r3 = _nt_occurrence_range if r3 r0 = r3 else @index = i0 r0 = nil end end end node_cache[:repetition_suffix][start_index] = r0 r0 end module OccurrenceRange0 def min elements[1] end def max elements[3] end end def _nt_occurrence_range start_index = index if node_cache[:occurrence_range].has_key?(index) cached = node_cache[:occurrence_range][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r2 = _nt_space if r2 r1 = r2 else r1 = instantiate_node(SyntaxNode,input, index...index) end s0 << r1 if r1 s3, i3 = [], index loop do if has_terminal?('\G[0-9]', true, index) r4 = true @index += 1 else r4 = nil end if r4 s3 << r4 else break end end r3 = instantiate_node(SyntaxNode,input, i3...index, s3) s0 << r3 if r3 if has_terminal?('..', false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('..') r5 = nil end s0 << r5 if r5 s6, i6 = [], index loop do if has_terminal?('\G[0-9]', true, index) r7 = true @index += 1 else r7 = nil end if r7 s6 << r7 else break end end r6 = instantiate_node(SyntaxNode,input, i6...index, s6) s0 << r6 end end end if s0.last r0 = instantiate_node(OccurrenceRange,input, i0...index, s0) r0.extend(OccurrenceRange0) else @index = i0 r0 = nil end node_cache[:occurrence_range][start_index] = r0 r0 end def _nt_prefix start_index = index if node_cache[:prefix].has_key?(index) cached = node_cache[:prefix][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index if has_terminal?('&', false, index) r1 = instantiate_node(AndPredicate,input, index...(index + 1)) @index += 1 else terminal_parse_failure('&') r1 = nil end if r1 r0 = r1 else if has_terminal?('!', false, index) r2 = instantiate_node(NotPredicate,input, index...(index + 1)) @index += 1 else terminal_parse_failure('!') r2 = nil end if r2 r0 = r2 else if has_terminal?('~', false, index) r3 = instantiate_node(TransientPrefix,input, index...(index + 1)) @index += 1 else terminal_parse_failure('~') r3 = nil end if r3 r0 = r3 else @index = i0 r0 = nil end end end node_cache[:prefix][start_index] = r0 r0 end def _nt_atomic start_index = index if node_cache[:atomic].has_key?(index) cached = node_cache[:atomic][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_terminal if r1 r0 = r1 else r2 = _nt_nonterminal if r2 r0 = r2 else r3 = _nt_parenthesized_expression if r3 r0 = r3 else @index = i0 r0 = nil end end end node_cache[:atomic][start_index] = r0 r0 end module ParenthesizedExpression0 def parsing_expression elements[2] end end module ParenthesizedExpression1 def inline_modules parsing_expression.inline_modules end end def _nt_parenthesized_expression start_index = index if node_cache[:parenthesized_expression].has_key?(index) cached = node_cache[:parenthesized_expression][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('(', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('(') r1 = nil end s0 << r1 if r1 r3 = _nt_space if r3 r2 = r3 else r2 = instantiate_node(SyntaxNode,input, index...index) end s0 << r2 if r2 r4 = _nt_parsing_expression s0 << r4 if r4 r6 = _nt_space if r6 r5 = r6 else r5 = instantiate_node(SyntaxNode,input, index...index) end s0 << r5 if r5 if has_terminal?(')', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure(')') r7 = nil end s0 << r7 end end end end if s0.last r0 = instantiate_node(ParenthesizedExpression,input, i0...index, s0) r0.extend(ParenthesizedExpression0) r0.extend(ParenthesizedExpression1) else @index = i0 r0 = nil end node_cache[:parenthesized_expression][start_index] = r0 r0 end module Nonterminal0 def alpha_char elements[0] end end module Nonterminal1 end def _nt_nonterminal start_index = index if node_cache[:nonterminal].has_key?(index) cached = node_cache[:nonterminal][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1 = index r2 = _nt_keyword_inside_grammar if r2 r1 = nil else @index = i1 r1 = instantiate_node(SyntaxNode,input, index...index) end s0 << r1 if r1 i3, s3 = index, [] r4 = _nt_alpha_char s3 << r4 if r4 s5, i5 = [], index loop do r6 = _nt_alphanumeric_char if r6 s5 << r6 else break end end r5 = instantiate_node(SyntaxNode,input, i5...index, s5) s3 << r5 end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(Nonterminal0) else @index = i3 r3 = nil end s0 << r3 end if s0.last r0 = instantiate_node(Nonterminal,input, i0...index, s0) r0.extend(Nonterminal1) else @index = i0 r0 = nil end node_cache[:nonterminal][start_index] = r0 r0 end def _nt_terminal start_index = index if node_cache[:terminal].has_key?(index) cached = node_cache[:terminal][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_quoted_string if r1 r0 = r1 else r2 = _nt_character_class if r2 r0 = r2 else r3 = _nt_anything_symbol if r3 r0 = r3 else @index = i0 r0 = nil end end end node_cache[:terminal][start_index] = r0 r0 end module QuotedString0 def string super.text_value end end def _nt_quoted_string start_index = index if node_cache[:quoted_string].has_key?(index) cached = node_cache[:quoted_string][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_single_quoted_string if r1 r0 = r1 r0.extend(QuotedString0) else r2 = _nt_double_quoted_string if r2 r0 = r2 r0.extend(QuotedString0) else @index = i0 r0 = nil end end node_cache[:quoted_string][start_index] = r0 r0 end module DoubleQuotedString0 end module DoubleQuotedString1 def string elements[1] end end def _nt_double_quoted_string start_index = index if node_cache[:double_quoted_string].has_key?(index) cached = node_cache[:double_quoted_string][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('"', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('"') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if has_terminal?('"', false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('"') r5 = nil end if r5 r4 = nil else @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 i6 = index if has_terminal?("\\\\", false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure("\\\\") r7 = nil end if r7 r6 = r7 else if has_terminal?('\"', false, index) r8 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('\"') r8 = nil end if r8 r6 = r8 else if index < input_length r9 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r9 = nil end if r9 r6 = r9 else @index = i6 r6 = nil end end end s3 << r6 end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(DoubleQuotedString0) else @index = i3 r3 = nil end if r3 s2 << r3 else break end end r2 = instantiate_node(SyntaxNode,input, i2...index, s2) s0 << r2 if r2 if has_terminal?('"', false, index) r10 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('"') r10 = nil end s0 << r10 end end if s0.last r0 = instantiate_node(Terminal,input, i0...index, s0) r0.extend(DoubleQuotedString1) else @index = i0 r0 = nil end node_cache[:double_quoted_string][start_index] = r0 r0 end module SingleQuotedString0 end module SingleQuotedString1 def string elements[1] end end def _nt_single_quoted_string start_index = index if node_cache[:single_quoted_string].has_key?(index) cached = node_cache[:single_quoted_string][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?("'", false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("'") r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if has_terminal?("'", false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("'") r5 = nil end if r5 r4 = nil else @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 i6 = index if has_terminal?("\\\\", false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure("\\\\") r7 = nil end if r7 r6 = r7 else if has_terminal?("\\'", false, index) r8 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure("\\'") r8 = nil end if r8 r6 = r8 else if index < input_length r9 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r9 = nil end if r9 r6 = r9 else @index = i6 r6 = nil end end end s3 << r6 end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(SingleQuotedString0) else @index = i3 r3 = nil end if r3 s2 << r3 else break end end r2 = instantiate_node(SyntaxNode,input, i2...index, s2) s0 << r2 if r2 if has_terminal?("'", false, index) r10 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("'") r10 = nil end s0 << r10 end end if s0.last r0 = instantiate_node(Terminal,input, i0...index, s0) r0.extend(SingleQuotedString1) else @index = i0 r0 = nil end node_cache[:single_quoted_string][start_index] = r0 r0 end module CharacterClass0 end module CharacterClass1 end module CharacterClass2 end module CharacterClass3 def characters elements[1] end end module CharacterClass4 def characters super.text_value end end def _nt_character_class start_index = index if node_cache[:character_class].has_key?(index) cached = node_cache[:character_class][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('[', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('[') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if has_terminal?(']', false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure(']') r5 = nil end if r5 r4 = nil else @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 i6 = index i7, s7 = index, [] if has_terminal?('\\', false, index) r8 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('\\') r8 = nil end s7 << r8 if r8 if index < input_length r9 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r9 = nil end s7 << r9 end if s7.last r7 = instantiate_node(SyntaxNode,input, i7...index, s7) r7.extend(CharacterClass0) else @index = i7 r7 = nil end if r7 r6 = r7 else r10 = _nt_bracket_expression if r10 r6 = r10 else i11, s11 = index, [] i12 = index if has_terminal?('\\', false, index) r13 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('\\') r13 = nil end if r13 r12 = nil else @index = i12 r12 = instantiate_node(SyntaxNode,input, index...index) end s11 << r12 if r12 if index < input_length r14 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r14 = nil end s11 << r14 end if s11.last r11 = instantiate_node(SyntaxNode,input, i11...index, s11) r11.extend(CharacterClass1) else @index = i11 r11 = nil end if r11 r6 = r11 else @index = i6 r6 = nil end end end s3 << r6 end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(CharacterClass2) else @index = i3 r3 = nil end if r3 s2 << r3 else break end end if s2.empty? @index = i2 r2 = nil else r2 = instantiate_node(SyntaxNode,input, i2...index, s2) end s0 << r2 if r2 if has_terminal?(']', false, index) r15 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure(']') r15 = nil end s0 << r15 end end if s0.last r0 = instantiate_node(CharacterClass,input, i0...index, s0) r0.extend(CharacterClass3) r0.extend(CharacterClass4) else @index = i0 r0 = nil end node_cache[:character_class][start_index] = r0 r0 end module BracketExpression0 end def _nt_bracket_expression start_index = index if node_cache[:bracket_expression].has_key?(index) cached = node_cache[:bracket_expression][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('[:', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure('[:') r1 = nil end s0 << r1 if r1 if has_terminal?('^', false, index) r3 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('^') r3 = nil end if r3 r2 = r3 else r2 = instantiate_node(SyntaxNode,input, index...index) end s0 << r2 if r2 i4 = index if has_terminal?('alnum', false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('alnum') r5 = nil end if r5 r4 = r5 else if has_terminal?('alpha', false, index) r6 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('alpha') r6 = nil end if r6 r4 = r6 else if has_terminal?('blank', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('blank') r7 = nil end if r7 r4 = r7 else if has_terminal?('cntrl', false, index) r8 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('cntrl') r8 = nil end if r8 r4 = r8 else if has_terminal?('digit', false, index) r9 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('digit') r9 = nil end if r9 r4 = r9 else if has_terminal?('graph', false, index) r10 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('graph') r10 = nil end if r10 r4 = r10 else if has_terminal?('lower', false, index) r11 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('lower') r11 = nil end if r11 r4 = r11 else if has_terminal?('print', false, index) r12 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('print') r12 = nil end if r12 r4 = r12 else if has_terminal?('punct', false, index) r13 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('punct') r13 = nil end if r13 r4 = r13 else if has_terminal?('space', false, index) r14 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('space') r14 = nil end if r14 r4 = r14 else if has_terminal?('upper', false, index) r15 = instantiate_node(SyntaxNode,input, index...(index + 5)) @index += 5 else terminal_parse_failure('upper') r15 = nil end if r15 r4 = r15 else if has_terminal?('xdigit', false, index) r16 = instantiate_node(SyntaxNode,input, index...(index + 6)) @index += 6 else terminal_parse_failure('xdigit') r16 = nil end if r16 r4 = r16 else if has_terminal?('word', false, index) r17 = instantiate_node(SyntaxNode,input, index...(index + 4)) @index += 4 else terminal_parse_failure('word') r17 = nil end if r17 r4 = r17 else @index = i4 r4 = nil end end end end end end end end end end end end end s0 << r4 if r4 if has_terminal?(':]', false, index) r18 = instantiate_node(SyntaxNode,input, index...(index + 2)) @index += 2 else terminal_parse_failure(':]') r18 = nil end s0 << r18 end end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(BracketExpression0) else @index = i0 r0 = nil end node_cache[:bracket_expression][start_index] = r0 r0 end def _nt_anything_symbol start_index = index if node_cache[:anything_symbol].has_key?(index) cached = node_cache[:anything_symbol][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?('.', false, index) r0 = instantiate_node(AnythingSymbol,input, index...(index + 1)) @index += 1 else terminal_parse_failure('.') r0 = nil end node_cache[:anything_symbol][start_index] = r0 r0 end module NodeClassExpression0 end module NodeClassExpression1 def space elements[0] end end module NodeClassExpression2 def node_class_name elements[2].text_value end end module NodeClassExpression3 def node_class_name nil end end def _nt_node_class_expression start_index = index if node_cache[:node_class_expression].has_key?(index) cached = node_cache[:node_class_expression][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index i1, s1 = index, [] r2 = _nt_space s1 << r2 if r2 if has_terminal?('<', false, index) r3 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('<') r3 = nil end s1 << r3 if r3 s4, i4 = [], index loop do i5, s5 = index, [] i6 = index if has_terminal?('>', false, index) r7 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('>') r7 = nil end if r7 r6 = nil else @index = i6 r6 = instantiate_node(SyntaxNode,input, index...index) end s5 << r6 if r6 if index < input_length r8 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r8 = nil end s5 << r8 end if s5.last r5 = instantiate_node(SyntaxNode,input, i5...index, s5) r5.extend(NodeClassExpression0) else @index = i5 r5 = nil end if r5 s4 << r5 else break end end if s4.empty? @index = i4 r4 = nil else r4 = instantiate_node(SyntaxNode,input, i4...index, s4) end s1 << r4 if r4 if has_terminal?('>', false, index) r9 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('>') r9 = nil end s1 << r9 end end end if s1.last r1 = instantiate_node(SyntaxNode,input, i1...index, s1) r1.extend(NodeClassExpression1) r1.extend(NodeClassExpression2) else @index = i1 r1 = nil end if r1 r0 = r1 else if has_terminal?('', false, index) r10 = instantiate_node(SyntaxNode,input, index...(index + 0)) r10.extend(NodeClassExpression3) @index += 0 else terminal_parse_failure('') r10 = nil end if r10 r0 = r10 else @index = i0 r0 = nil end end node_cache[:node_class_expression][start_index] = r0 r0 end module TrailingInlineModule0 def space elements[0] end def inline_module elements[1] end end module TrailingInlineModule1 def inline_modules [inline_module] end def inline_module_name inline_module.module_name end end module TrailingInlineModule2 def inline_modules [] end def inline_module nil end def inline_module_name nil end end def _nt_trailing_inline_module start_index = index if node_cache[:trailing_inline_module].has_key?(index) cached = node_cache[:trailing_inline_module][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index i1, s1 = index, [] r2 = _nt_space s1 << r2 if r2 r3 = _nt_inline_module s1 << r3 end if s1.last r1 = instantiate_node(SyntaxNode,input, i1...index, s1) r1.extend(TrailingInlineModule0) r1.extend(TrailingInlineModule1) else @index = i1 r1 = nil end if r1 r0 = r1 else if has_terminal?('', false, index) r4 = instantiate_node(SyntaxNode,input, index...(index + 0)) r4.extend(TrailingInlineModule2) @index += 0 else terminal_parse_failure('') r4 = nil end if r4 r0 = r4 else @index = i0 r0 = nil end end node_cache[:trailing_inline_module][start_index] = r0 r0 end module PredicateBlock0 def inline_module elements[1] end end def _nt_predicate_block start_index = index if node_cache[:predicate_block].has_key?(index) cached = node_cache[:predicate_block][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 0)) @index += 0 else terminal_parse_failure('') r1 = nil end s0 << r1 if r1 r2 = _nt_inline_module s0 << r2 end if s0.last r0 = instantiate_node(PredicateBlock,input, i0...index, s0) r0.extend(PredicateBlock0) else @index = i0 r0 = nil end node_cache[:predicate_block][start_index] = r0 r0 end module InlineModule0 end module InlineModule1 end def _nt_inline_module start_index = index if node_cache[:inline_module].has_key?(index) cached = node_cache[:inline_module][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('{', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('{') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3 = index r4 = _nt_inline_module if r4 r3 = r4 else i5, s5 = index, [] i6 = index if has_terminal?('\G[{}]', true, index) r7 = true @index += 1 else r7 = nil end if r7 r6 = nil else @index = i6 r6 = instantiate_node(SyntaxNode,input, index...index) end s5 << r6 if r6 if index < input_length r8 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r8 = nil end s5 << r8 end if s5.last r5 = instantiate_node(SyntaxNode,input, i5...index, s5) r5.extend(InlineModule0) else @index = i5 r5 = nil end if r5 r3 = r5 else @index = i3 r3 = nil end end if r3 s2 << r3 else break end end r2 = instantiate_node(SyntaxNode,input, i2...index, s2) s0 << r2 if r2 if has_terminal?('}', false, index) r9 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('}') r9 = nil end s0 << r9 end end if s0.last r0 = instantiate_node(InlineModule,input, i0...index, s0) r0.extend(InlineModule1) else @index = i0 r0 = nil end node_cache[:inline_module][start_index] = r0 r0 end module KeywordInsideGrammar0 end def _nt_keyword_inside_grammar start_index = index if node_cache[:keyword_inside_grammar].has_key?(index) cached = node_cache[:keyword_inside_grammar][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1 = index if has_terminal?('rule', false, index) r2 = instantiate_node(SyntaxNode,input, index...(index + 4)) @index += 4 else terminal_parse_failure('rule') r2 = nil end if r2 r1 = r2 else if has_terminal?('end', false, index) r3 = instantiate_node(SyntaxNode,input, index...(index + 3)) @index += 3 else terminal_parse_failure('end') r3 = nil end if r3 r1 = r3 else @index = i1 r1 = nil end end s0 << r1 if r1 i4 = index r5 = _nt_non_space_char if r5 r4 = nil else @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s0 << r4 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(KeywordInsideGrammar0) else @index = i0 r0 = nil end node_cache[:keyword_inside_grammar][start_index] = r0 r0 end module NonSpaceChar0 end def _nt_non_space_char start_index = index if node_cache[:non_space_char].has_key?(index) cached = node_cache[:non_space_char][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1 = index r2 = _nt_space if r2 r1 = nil else @index = i1 r1 = instantiate_node(SyntaxNode,input, index...index) end s0 << r1 if r1 if index < input_length r3 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r3 = nil end s0 << r3 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(NonSpaceChar0) else @index = i0 r0 = nil end node_cache[:non_space_char][start_index] = r0 r0 end def _nt_alpha_char start_index = index if node_cache[:alpha_char].has_key?(index) cached = node_cache[:alpha_char][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?('\G[A-Za-z_]', true, index) r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else r0 = nil end node_cache[:alpha_char][start_index] = r0 r0 end def _nt_alphanumeric_char start_index = index if node_cache[:alphanumeric_char].has_key?(index) cached = node_cache[:alphanumeric_char][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index r1 = _nt_alpha_char if r1 r0 = r1 else if has_terminal?('\G[0-9]', true, index) r2 = true @index += 1 else r2 = nil end if r2 r0 = r2 else @index = i0 r0 = nil end end node_cache[:alphanumeric_char][start_index] = r0 r0 end def _nt_space start_index = index if node_cache[:space].has_key?(index) cached = node_cache[:space][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end s0, i0 = [], index loop do i1 = index r2 = _nt_white if r2 r1 = r2 else r3 = _nt_comment_to_eol if r3 r1 = r3 else @index = i1 r1 = nil end end if r1 s0 << r1 else break end end if s0.empty? @index = i0 r0 = nil else r0 = instantiate_node(SyntaxNode,input, i0...index, s0) end node_cache[:space][start_index] = r0 r0 end module CommentToEol0 end module CommentToEol1 end def _nt_comment_to_eol start_index = index if node_cache[:comment_to_eol].has_key?(index) cached = node_cache[:comment_to_eol][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('#', false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('#') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if has_terminal?("\n", false, index) r5 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("\n") r5 = nil end if r5 r4 = nil else @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 if index < input_length r6 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("any character") r6 = nil end s3 << r6 end if s3.last r3 = instantiate_node(SyntaxNode,input, i3...index, s3) r3.extend(CommentToEol0) else @index = i3 r3 = nil end if r3 s2 << r3 else break end end r2 = instantiate_node(SyntaxNode,input, i2...index, s2) s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(CommentToEol1) else @index = i0 r0 = nil end node_cache[:comment_to_eol][start_index] = r0 r0 end def _nt_white start_index = index if node_cache[:white].has_key?(index) cached = node_cache[:white][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?('\G[ \\t\\n\\r]', true, index) r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else r0 = nil end node_cache[:white][start_index] = r0 r0 end end class MetagrammarParser < Treetop::Runtime::CompiledParser include Metagrammar end end end treetop-1.4.14/lib/treetop/compiler/ruby_builder.rb0000644000004100000410000000436212157663062022406 0ustar www-datawww-datarequire 'treetop/ruby_extensions/string' module Treetop module Compiler class RubyBuilder attr_reader :level, :address_space, :ruby def initialize @level = 0 @address_space = LexicalAddressSpace.new @ruby = "" end def <<(ruby_line) return if ruby_line.blank? ruby << ruby_line.tabto(level) << "\n" end def newline ruby << "\n" end def indented(depth = 2) self.in(depth) yield self.out(depth) end def class_declaration(name, &block) self << "class #{name}" indented(&block) self << "end" end def module_declaration(name, &block) self << "module #{name}" indented(&block) self << "end" end def method_declaration(name, &block) self << "def #{name}" indented(&block) self << "end" end def assign(left, right) if left.instance_of? Array self << "#{left.join(', ')} = #{right.join(', ')}" else self << "#{left} = #{right}" end end def extend(var, module_name) self << "#{var}.extend(#{module_name})" end def accumulate(left, right) self << "#{left} << #{right}" end def if__(condition, &block) self << "if #{condition}" indented(&block) end def if_(condition, &block) if__(condition, &block) self << 'end' end def else_(&block) self << 'else' indented(&block) self << 'end' end def loop(&block) self << 'loop do' indented(&block) self << 'end' end def break self << 'break' end def in(depth = 2) @level += depth self end def out(depth = 2) @level -= depth self end def next_address address_space.next_address end def reset_addresses address_space.reset_addresses end private def indent " " * level end end end end treetop-1.4.14/lib/treetop/version.rb0000644000004100000410000000022412157663062017563 0ustar www-datawww-datamodule Treetop #:nodoc: module VERSION #:nodoc: MAJOR = 1 MINOR = 4 TINY = 14 STRING = [MAJOR, MINOR, TINY].join('.') end end treetop-1.4.14/lib/treetop/runtime.rb0000644000004100000410000000032112157663062017557 0ustar www-datawww-datarequire 'treetop/ruby_extensions' require 'treetop/runtime/compiled_parser' require 'treetop/runtime/syntax_node' require 'treetop/runtime/terminal_parse_failure' require 'treetop/runtime/interval_skip_list' treetop-1.4.14/lib/treetop/polyglot.rb0000644000004100000410000000036112157663062017751 0ustar www-datawww-datamodule Treetop module Polyglot VALID_GRAMMAR_EXT = ['treetop', 'tt'] VALID_GRAMMAR_EXT_REGEXP = /\.(#{VALID_GRAMMAR_EXT.join('|')})\Z/o end end require 'polyglot' Polyglot.register(Treetop::Polyglot::VALID_GRAMMAR_EXT, Treetop) treetop-1.4.14/lib/treetop/ruby_extensions.rb0000644000004100000410000000005112157663062021334 0ustar www-datawww-datarequire 'treetop/ruby_extensions/string' treetop-1.4.14/lib/treetop/runtime/0000755000004100000410000000000012157663062017236 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/runtime/terminal_syntax_node.rb0000644000004100000410000000050112157663062024005 0ustar www-datawww-datamodule Treetop module Runtime class TerminalSyntaxNode < SyntaxNode def initialize(input, interval) super(input, interval, []) end def inspect(indent="") indent+ self.class.to_s.sub(/.*:/,'') + " offset=#{interval.first}" + " #{text_value.inspect}" end end end end treetop-1.4.14/lib/treetop/runtime/interval_skip_list/0000755000004100000410000000000012157663062023143 5ustar www-datawww-datatreetop-1.4.14/lib/treetop/runtime/interval_skip_list/interval_skip_list.rb0000644000004100000410000001207612157663062027403 0ustar www-datawww-dataclass IntervalSkipList attr_reader :probability def initialize @head = HeadNode.new(max_height) @ranges = {} @probability = 0.5 end def max_height 3 end def empty? head.forward[0].nil? end def expire(range, length_change) expired_markers, first_node_after_range = overlapping(range) expired_markers.each { |marker| delete(marker) } first_node_after_range.propagate_length_change(length_change) end def overlapping(range) markers, first_node = containing_with_node(range.first) cur_node = first_node begin markers.concat(cur_node.forward_markers.flatten) cur_node = cur_node.forward[0] end while cur_node.key < range.last return markers.uniq, cur_node end def containing(n) containing_with_node(n).first end def insert(range, marker) ranges[marker] = range first_node = insert_node(range.first) first_node.endpoint_of.push(marker) last_node = insert_node(range.last) last_node.endpoint_of.push(marker) cur_node = first_node cur_level = first_node.top_level while next_node_at_level_inside_range?(cur_node, cur_level, range) while can_ascend_from?(cur_node, cur_level) && next_node_at_level_inside_range?(cur_node, cur_level + 1, range) cur_level += 1 end cur_node = mark_forward_path_at_level(cur_node, cur_level, marker) end while node_inside_range?(cur_node, range) while can_descend_from?(cur_level) && next_node_at_level_outside_range?(cur_node, cur_level, range) cur_level -= 1 end cur_node = mark_forward_path_at_level(cur_node, cur_level, marker) end end def delete(marker) range = ranges[marker] path_to_first_node = make_path first_node = find(range.first, path_to_first_node) cur_node = first_node cur_level = first_node.top_level while next_node_at_level_inside_range?(cur_node, cur_level, range) while can_ascend_from?(cur_node, cur_level) && next_node_at_level_inside_range?(cur_node, cur_level + 1, range) cur_level += 1 end cur_node = unmark_forward_path_at_level(cur_node, cur_level, marker) end while node_inside_range?(cur_node, range) while can_descend_from?(cur_level) && next_node_at_level_outside_range?(cur_node, cur_level, range) cur_level -= 1 end cur_node = unmark_forward_path_at_level(cur_node, cur_level, marker) end last_node = cur_node first_node.endpoint_of.delete(marker) if first_node.endpoint_of.empty? first_node.delete(path_to_first_node) end last_node.endpoint_of.delete(marker) if last_node.endpoint_of.empty? path_to_last_node = make_path find(range.last, path_to_last_node) last_node.delete(path_to_last_node) end end protected attr_reader :head, :ranges def insert_node(key) path = make_path found_node = find(key, path) if found_node && found_node.key == key return found_node else return Node.new(key, next_node_height, path) end end def containing_with_node(n) containing = [] cur_node = head (max_height - 1).downto(0) do |cur_level| while (next_node = cur_node.forward[cur_level]) && next_node.key <= n cur_node = next_node if cur_node.key == n return containing + (cur_node.markers - cur_node.endpoint_of), cur_node end end containing.concat(cur_node.forward_markers[cur_level]) end return containing, cur_node end def delete_node(key) path = make_path found_node = find(key, path) found_node.delete(path) if found_node.key == key end def find(key, path) cur_node = head (max_height - 1).downto(0) do |cur_level| while (next_node = cur_node.forward[cur_level]) && next_node.key < key cur_node = next_node end path[cur_level] = cur_node end cur_node.forward[0] end def make_path Array.new(max_height, nil) end def next_node_height height = 1 while rand < probability && height < max_height height += 1 end height end def can_ascend_from?(node, level) level < node.top_level end def can_descend_from?(level) level > 0 end def node_inside_range?(node, range) node.key < range.last end def next_node_at_level_inside_range?(node, level, range) node.forward[level] && node.forward[level].key <= range.last end def next_node_at_level_outside_range?(node, level, range) (node.forward[level].nil? || node.forward[level].key > range.last) end def mark_forward_path_at_level(node, level, marker) node.forward_markers[level].push(marker) next_node = node.forward[level] next_node.markers.push(marker) node = next_node end def unmark_forward_path_at_level(node, level, marker) node.forward_markers[level].delete(marker) next_node = node.forward[level] next_node.markers.delete(marker) node = next_node end def nodes nodes = [] cur_node = head.forward[0] until cur_node.nil? nodes << cur_node cur_node = cur_node.forward[0] end nodes end endtreetop-1.4.14/lib/treetop/runtime/interval_skip_list/head_node.rb0000644000004100000410000000045012157663062025375 0ustar www-datawww-dataclass IntervalSkipList class HeadNode attr_reader :height, :forward, :forward_markers def initialize(height) @height = height @forward = Array.new(height, nil) @forward_markers = Array.new(height) {|i| []} end def top_level height - 1 end end endtreetop-1.4.14/lib/treetop/runtime/interval_skip_list/node.rb0000644000004100000410000001026712157663062024423 0ustar www-datawww-dataclass IntervalSkipList class Node < HeadNode attr_accessor :key attr_reader :markers, :endpoint_of def initialize(key, height, path) super(height) @key = key @markers = [] @endpoint_of = [] update_forward_pointers(path) promote_markers(path) end def all_forward_markers markers.flatten end def delete(path) 0.upto(top_level) do |i| path[i].forward[i] = forward[i] end demote_markers(path) end def propagate_length_change(length_change) cur_node = self while cur_node do cur_node.key += length_change cur_node = cur_node.forward[0] end end protected def update_forward_pointers(path) 0.upto(top_level) do |i| forward[i] = path[i].forward[i] path[i].forward[i] = self end end def promote_markers(path) promoted = [] new_promoted = [] 0.upto(top_level) do |i| incoming_markers = path[i].forward_markers[i] markers.concat(incoming_markers) incoming_markers.each do |marker| if can_be_promoted_higher?(marker, i) new_promoted.push(marker) forward[i].delete_marker_from_path(marker, i, forward[i+1]) else forward_markers[i].push(marker) end end promoted.each do |marker| if can_be_promoted_higher?(marker, i) new_promoted.push(marker) forward[i].delete_marker_from_path(marker, i, forward[i+1]) else forward_markers[i].push(marker) end end promoted = new_promoted new_promoted = [] end end def can_be_promoted_higher?(marker, level) level < top_level && forward[level + 1] && forward[level + 1].markers.include?(marker) end def delete_marker_from_path(marker, level, terminus) cur_node = self until cur_node == terminus cur_node.forward_markers[level].delete(marker) cur_node.markers.delete(marker) cur_node = cur_node.forward[level] end end def demote_markers(path) demote_inbound_markers(path) demote_outbound_markers(path) end def demote_inbound_markers(path) demoted = [] new_demoted = [] top_level.downto(0) do |i| incoming_markers = path[i].forward_markers[i].dup incoming_markers.each do |marker| unless forward_node_with_marker_at_or_above_level?(marker, i) path[i].forward_markers[i].delete(marker) new_demoted.push(marker) end end demoted.each do |marker| path[i + 1].place_marker_on_inbound_path(marker, i, path[i]) if forward[i].markers.include?(marker) path[i].forward_markers[i].push(marker) else new_demoted.push(marker) end end demoted = new_demoted new_demoted = [] end end def demote_outbound_markers(path) demoted = [] new_demoted = [] top_level.downto(0) do |i| forward_markers[i].each do |marker| new_demoted.push(marker) unless path[i].forward_markers[i].include?(marker) end demoted.each do |marker| forward[i].place_marker_on_outbound_path(marker, i, forward[i + 1]) new_demoted.push(marker) unless path[i].forward_markers[i].include?(marker) end demoted = new_demoted new_demoted = [] end end def forward_node_with_marker_at_or_above_level?(marker, level) level.upto(top_level) do |i| return true if forward[i].markers.include?(marker) end false end def place_marker_on_outbound_path(marker, level, terminus) cur_node = self until cur_node == terminus cur_node.forward_markers[level].push(marker) cur_node.markers.push(marker) cur_node = cur_node.forward[level] end end def place_marker_on_inbound_path(marker, level, terminus) cur_node = self until cur_node == terminus cur_node.forward_markers[level].push(marker) cur_node = cur_node.forward[level] cur_node.markers.push(marker) end end end endtreetop-1.4.14/lib/treetop/runtime/terminal_parse_failure.rb0000644000004100000410000000050712157663062024301 0ustar www-datawww-datamodule Treetop module Runtime class TerminalParseFailure attr_reader :index, :expected_string def initialize(index, expected_string) @index = index @expected_string = expected_string end def to_s "String matching #{expected_string} expected." end end end end treetop-1.4.14/lib/treetop/runtime/compiled_parser.rb0000644000004100000410000000640412157663062022737 0ustar www-datawww-datamodule Treetop module Runtime class CompiledParser include Treetop::Runtime attr_reader :input, :index, :max_terminal_failure_index attr_writer :root attr_accessor :consume_all_input alias :consume_all_input? :consume_all_input def initialize self.consume_all_input = true end def parse(input, options = {}) prepare_to_parse(input) @index = options[:index] if options[:index] result = send("_nt_#{options[:root] || root}") should_consume_all = options.include?(:consume_all_input) ? options[:consume_all_input] : consume_all_input? return nil if (should_consume_all && index != input.size) return SyntaxNode.new(input, index...(index + 1)) if result == true return result end def failure_index max_terminal_failure_index end def failure_line @terminal_failures && input.line_of(failure_index) end def failure_column @terminal_failures && input.column_of(failure_index) end def failure_reason return nil unless (tf = terminal_failures) && tf.size > 0 "Expected " + (tf.size == 1 ? tf[0].expected_string : "one of #{tf.map{|f| f.expected_string}.uniq*', '}" ) + " at line #{failure_line}, column #{failure_column} (byte #{failure_index+1})" + " after #{input[index...failure_index]}" end def terminal_failures if @terminal_failures.empty? || @terminal_failures[0].is_a?(TerminalParseFailure) @terminal_failures else @terminal_failures.map! {|tf_ary| TerminalParseFailure.new(*tf_ary) } end end protected attr_reader :node_cache, :input_length attr_writer :index def prepare_to_parse(input) @input = input @input_length = input.length reset_index @node_cache = Hash.new {|hash, key| hash[key] = Hash.new} @regexps = {} @terminal_failures = [] @max_terminal_failure_index = 0 end def reset_index @index = 0 end def parse_anything(node_class = SyntaxNode, inline_module = nil) if index < input.length result = instantiate_node(node_class,input, index...(index + 1)) result.extend(inline_module) if inline_module @index += 1 result else terminal_parse_failure("any character") end end def instantiate_node(node_type,*args) if node_type.respond_to? :new node_type.new(*args) else SyntaxNode.new(*args).extend(node_type) end end def has_terminal?(terminal, regex, index) if regex rx = @regexps[terminal] ||= Regexp.new(terminal) input.index(rx, index) == index else input[index, terminal.size] == terminal end end def terminal_parse_failure(expected_string) return nil if index < max_terminal_failure_index if index > max_terminal_failure_index @max_terminal_failure_index = index @terminal_failures = [] end @terminal_failures << [index, expected_string] return nil end end end end treetop-1.4.14/lib/treetop/runtime/interval_skip_list.rb0000644000004100000410000000025112157663062023466 0ustar www-datawww-datarequire 'treetop/runtime/interval_skip_list/interval_skip_list' require 'treetop/runtime/interval_skip_list/head_node' require 'treetop/runtime/interval_skip_list/node' treetop-1.4.14/lib/treetop/runtime/syntax_node.rb0000644000004100000410000000552512157663062022125 0ustar www-datawww-datamodule Treetop module Runtime class SyntaxNode attr_reader :input, :interval attr_accessor :parent def initialize(input, interval, elements = nil) @input = input @interval = interval @elements = elements end def elements return @elements if terminal? # replace the character class placeholders in the sequence (lazy instantiation) last_element = nil @comprehensive_elements ||= @elements.map do |element| if element == true index = last_element ? last_element.interval.last : interval.first element = SyntaxNode.new(input, index...(index + 1)) end element.parent = self last_element = element end @comprehensive_elements end def terminal? @elements.nil? end def nonterminal? !terminal? end def text_value input[interval] end def empty? interval.first == interval.last && interval.exclude_end? end def <=>(other) self.interval.first <=> other.interval.first end def extension_modules local_extensions = class < 0 local_extensions else [] # There weren't any; must be a literal node end end def inspect(indent="") em = extension_modules interesting_methods = methods-[em.last ? em.last.methods : nil]-self.class.instance_methods im = interesting_methods.size > 0 ? " (#{interesting_methods.join(",")})" : "" tv = text_value tv = "...#{tv[-20..-1]}" if tv.size > 20 indent + self.class.to_s.sub(/.*:/,'') + em.map{|m| "+"+m.to_s.sub(/.*:/,'')}*"" + " offset=#{interval.first}" + ", #{tv.inspect}" + im + (elements && elements.size > 0 ? ":" + (elements||[]).map{|e| begin "\n"+e.inspect(indent+" ") rescue # Defend against inspect not taking a parameter "\n"+indent+" "+e.inspect end }.join("") : "" ) end @@dot_id_counter = 0 def dot_id @dot_id ||= @@dot_id_counter += 1 end def write_dot(io) io.puts "node#{dot_id} [label=\"'#{text_value}'\"];" if nonterminal? then elements.each do |x| io.puts "node#{dot_id} -> node#{x.dot_id};" x.write_dot(io) end end end def write_dot_file(fname) File.open(fname + ".dot","w") do |file| file.puts "digraph G {" write_dot(file) file.puts "}" end end end end end treetop-1.4.14/lib/treetop/bootstrap_gen_1_metagrammar.rb0000644000004100000410000000366312157663062023553 0ustar www-datawww-data# This file's job is to load a Treetop::Compiler::Metagrammar and Treetop::Compiler::MetagrammarParser # into the environment by compiling the current metagrammar.treetop using a trusted version of Treetop. require 'rubygems' TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP = '>= 1.1.5' # Loading trusted version of Treetop to compile the compiler gem_spec = Gem.source_index.find_name('treetop', TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP).last raise "Install a Treetop Gem version #{TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP} to bootstrap." unless gem_spec require "#{gem_spec.full_gem_path}/lib/treetop" # Relocating trusted version of Treetop to Trusted::Treetop Trusted = Module.new Trusted::Treetop = Treetop Object.send(:remove_const, :Treetop) # Requiring version of Treetop that is under test $exclude_metagrammar = true require File.expand_path('../treetop') # Compile and evaluate freshly generated metagrammar source METAGRAMMAR_PATH = File.expand_path('../compiler/metagrammar.treetop', __FILE__) compiled_metagrammar_source = Trusted::Treetop::Compiler::GrammarCompiler.new.ruby_source(METAGRAMMAR_PATH) Object.class_eval(compiled_metagrammar_source) # The compiler under test was compiled with the trusted grammar and therefore depends on its runtime # But the runtime in the global namespace is the new runtime. We therefore inject the trusted runtime # into the compiler so its parser functions correctly. It will still not work for custom classes that # explicitly subclass the wrong runtime. For now I am working around this by keeping 1 generation of # backward compatibility in these cases. # Treetop::Compiler::Metagrammar.module_eval do # include Trusted::Treetop::Runtime # end # # Treetop::Compiler.send(:remove_const, :MetagrammarParser) # class Treetop::Compiler::MetagrammarParser < Trusted::Treetop::Runtime::CompiledParser # include Treetop::Compiler::Metagrammar # include Trusted::Treetop::Runtime # end $bootstrapped_gen_1_metagrammar = true treetop-1.4.14/lib/treetop/compiler.rb0000644000004100000410000000043512157663062017714 0ustar www-datawww-datarequire 'treetop/ruby_extensions' require 'treetop/compiler/lexical_address_space' require 'treetop/compiler/ruby_builder' require 'treetop/compiler/node_classes' require 'treetop/compiler/metagrammar' unless defined?($exclude_metagrammar) require 'treetop/compiler/grammar_compiler' treetop-1.4.14/lib/treetop.rb0000644000004100000410000000012012157663062016071 0ustar www-datawww-datarequire 'treetop/runtime' require 'treetop/compiler' require 'treetop/polyglot' treetop-1.4.14/treetop.gemspec0000644000004100000410000001726712157663062016367 0ustar www-datawww-data# Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "treetop" s.version = "1.4.14" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Nathan Sobo", "Clifford Heath"] s.autorequire = "treetop" s.date = "2013-06-04" s.email = "cliffordheath@gmail.com" s.executables = ["tt"] s.extra_rdoc_files = [ "LICENSE", "README.md" ] s.files = [ "LICENSE", "README.md", "Rakefile", "bin/tt", "doc/contributing_and_planned_features.markdown", "doc/grammar_composition.markdown", "doc/index.markdown", "doc/pitfalls_and_advanced_techniques.markdown", "doc/semantic_interpretation.markdown", "doc/site.rb", "doc/site/contribute.html", "doc/site/images/bottom_background.png", "doc/site/images/middle_background.png", "doc/site/images/paren_language_output.png", "doc/site/images/pivotal.gif", "doc/site/images/top_background.png", "doc/site/index.html", "doc/site/pitfalls_and_advanced_techniques.html", "doc/site/robots.txt", "doc/site/screen.css", "doc/site/semantic_interpretation.html", "doc/site/syntactic_recognition.html", "doc/site/using_in_ruby.html", "doc/sitegen.rb", "doc/syntactic_recognition.markdown", "doc/using_in_ruby.markdown", "examples/lambda_calculus/arithmetic.rb", "examples/lambda_calculus/arithmetic.treetop", "examples/lambda_calculus/arithmetic_node_classes.rb", "examples/lambda_calculus/arithmetic_test.rb", "examples/lambda_calculus/lambda_calculus", "examples/lambda_calculus/lambda_calculus.rb", "examples/lambda_calculus/lambda_calculus.treetop", "examples/lambda_calculus/lambda_calculus_node_classes.rb", "examples/lambda_calculus/lambda_calculus_test.rb", "examples/lambda_calculus/test_helper.rb", "lib/treetop.rb", "lib/treetop/bootstrap_gen_1_metagrammar.rb", "lib/treetop/compiler.rb", "lib/treetop/compiler/grammar_compiler.rb", "lib/treetop/compiler/lexical_address_space.rb", "lib/treetop/compiler/metagrammar.rb", "lib/treetop/compiler/metagrammar.treetop", "lib/treetop/compiler/node_classes.rb", "lib/treetop/compiler/node_classes/anything_symbol.rb", "lib/treetop/compiler/node_classes/atomic_expression.rb", "lib/treetop/compiler/node_classes/character_class.rb", "lib/treetop/compiler/node_classes/choice.rb", "lib/treetop/compiler/node_classes/declaration_sequence.rb", "lib/treetop/compiler/node_classes/grammar.rb", "lib/treetop/compiler/node_classes/inline_module.rb", "lib/treetop/compiler/node_classes/nonterminal.rb", "lib/treetop/compiler/node_classes/optional.rb", "lib/treetop/compiler/node_classes/parenthesized_expression.rb", "lib/treetop/compiler/node_classes/parsing_expression.rb", "lib/treetop/compiler/node_classes/parsing_rule.rb", "lib/treetop/compiler/node_classes/predicate.rb", "lib/treetop/compiler/node_classes/predicate_block.rb", "lib/treetop/compiler/node_classes/repetition.rb", "lib/treetop/compiler/node_classes/sequence.rb", "lib/treetop/compiler/node_classes/terminal.rb", "lib/treetop/compiler/node_classes/transient_prefix.rb", "lib/treetop/compiler/node_classes/treetop_file.rb", "lib/treetop/compiler/ruby_builder.rb", "lib/treetop/polyglot.rb", "lib/treetop/ruby_extensions.rb", "lib/treetop/ruby_extensions/string.rb", "lib/treetop/runtime.rb", "lib/treetop/runtime/compiled_parser.rb", "lib/treetop/runtime/interval_skip_list.rb", "lib/treetop/runtime/interval_skip_list/head_node.rb", "lib/treetop/runtime/interval_skip_list/interval_skip_list.rb", "lib/treetop/runtime/interval_skip_list/node.rb", "lib/treetop/runtime/syntax_node.rb", "lib/treetop/runtime/terminal_parse_failure.rb", "lib/treetop/runtime/terminal_syntax_node.rb", "lib/treetop/version.rb", "spec/compiler/and_predicate_spec.rb", "spec/compiler/anything_symbol_spec.rb", "spec/compiler/character_class_spec.rb", "spec/compiler/choice_spec.rb", "spec/compiler/circular_compilation_spec.rb", "spec/compiler/failure_propagation_functional_spec.rb", "spec/compiler/grammar_compiler_spec.rb", "spec/compiler/grammar_spec.rb", "spec/compiler/multibyte_chars_spec.rb", "spec/compiler/namespace_spec.rb", "spec/compiler/nonterminal_symbol_spec.rb", "spec/compiler/not_predicate_spec.rb", "spec/compiler/occurrence_range_spec.rb", "spec/compiler/one_or_more_spec.rb", "spec/compiler/optional_spec.rb", "spec/compiler/parenthesized_expression_spec.rb", "spec/compiler/parsing_rule_spec.rb", "spec/compiler/repeated_subrule_spec.rb", "spec/compiler/semantic_predicate_spec.rb", "spec/compiler/sequence_spec.rb", "spec/compiler/terminal_spec.rb", "spec/compiler/terminal_symbol_spec.rb", "spec/compiler/test_grammar.treetop", "spec/compiler/test_grammar.tt", "spec/compiler/test_grammar_do.treetop", "spec/compiler/tt_compiler_spec.rb", "spec/compiler/zero_or_more_spec.rb", "spec/composition/a.treetop", "spec/composition/b.treetop", "spec/composition/c.treetop", "spec/composition/d.treetop", "spec/composition/f.treetop", "spec/composition/grammar_composition_spec.rb", "spec/composition/subfolder/e_includes_c.treetop", "spec/ruby_extensions/string_spec.rb", "spec/runtime/compiled_parser_spec.rb", "spec/runtime/interval_skip_list/delete_spec.rb", "spec/runtime/interval_skip_list/expire_range_spec.rb", "spec/runtime/interval_skip_list/insert_and_delete_node_spec.rb", "spec/runtime/interval_skip_list/insert_spec.rb", "spec/runtime/interval_skip_list/interval_skip_list_spec.graffle", "spec/runtime/interval_skip_list/interval_skip_list_spec.rb", "spec/runtime/interval_skip_list/palindromic_fixture.rb", "spec/runtime/interval_skip_list/palindromic_fixture_spec.rb", "spec/runtime/interval_skip_list/spec_helper.rb", "spec/runtime/syntax_node_spec.rb", "spec/spec_helper.rb", "treetop.gemspec" ] s.homepage = "https://github.com/cjheath/treetop" s.licenses = ["MIT"] s.require_paths = ["lib"] s.rubygems_version = "1.8.24" s.summary = "A Ruby-based text parsing and interpretation DSL" if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, ["~> 0.5.0"]) s.add_development_dependency(%q, ["~> 1.0"]) s.add_development_dependency(%q, [">= 2.0.0"]) s.add_development_dependency(%q, [">= 0"]) s.add_runtime_dependency(%q, [">= 0.3.1"]) else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, ["~> 0.5.0"]) s.add_dependency(%q, ["~> 1.0"]) s.add_dependency(%q, [">= 2.0.0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0.3.1"]) end else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, ["~> 0.5.0"]) s.add_dependency(%q, ["~> 1.0"]) s.add_dependency(%q, [">= 2.0.0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0.3.1"]) end end