pax_global_header00006660000000000000000000000064143377747100014527gustar00rootroot0000000000000052 comment=b6a60e16e80f288dd25d45e372e5249f190f4561 treetop-1.6.12/000077500000000000000000000000001433777471000133005ustar00rootroot00000000000000treetop-1.6.12/.github/000077500000000000000000000000001433777471000146405ustar00rootroot00000000000000treetop-1.6.12/.github/workflows/000077500000000000000000000000001433777471000166755ustar00rootroot00000000000000treetop-1.6.12/.github/workflows/ci.yml000066400000000000000000000015431433777471000200160ustar00rootroot00000000000000# This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby name: build on: [pull_request, push] jobs: test: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: ruby: - '3.1' - '3.0' - '2.7' - '2.6' - '2.5' - '2.4' - '2.3' - '2.2' steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: bundle exec rspec treetop-1.6.12/.gitignore000066400000000000000000000001731433777471000152710ustar00rootroot00000000000000*.gem *.iml *.iws *.ipr website/*.html benchmark/*.dat benchmark/*.log *~ .DS_Store pkg .bundle Gemfile.lock .ruby-version treetop-1.6.12/.travis.yml000066400000000000000000000001031433777471000154030ustar00rootroot00000000000000language: ruby rvm: - 2.1 - 2.0 - 1.9.3 - rbx-2 - jruby treetop-1.6.12/Gemfile000066400000000000000000000002531433777471000145730ustar00rootroot00000000000000source 'https://rubygems.org' gem "polyglot", "~> 0.3" gemspec group :website do platforms :ruby do gem "bluecloth", "~> 2" gem "erector", "~> 0.8" end end treetop-1.6.12/History.txt000066400000000000000000000007021433777471000155010ustar00rootroot00000000000000== 1.4.1 2009-09-04 * several enhancements: * Many small-to-medium performance improvements * Semantic predicates * Support for UTF-8 characters * Generation of graphvis DOT files for visualising parse results * Commandline revamped with help == 1.2.5 2009-03-10 * 1 minor enhancement: * Extensions may always be modules, instead of sometimes modules, sometimes classes == 0.0.1 2008-05-21 * 1 major enhancement: * Initial release treetop-1.6.12/LICENSE000066400000000000000000000020401433777471000143010ustar00rootroot00000000000000Copyright (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.6.12/README.md000066400000000000000000000277051433777471000145720ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/cjheath/treetop.svg)](https://travis-ci.org/cjheath/treetop) Support ======= Support for Treetop is provided through the mailing list you can join or browse here: http://groups.google.com/group/treetop-dev The gem is released from https://cjheath.github.io/treetop/ so you should check there as well. 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. ```ruby # 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. A terminal symbol may use either double or single quotes. If the closing quote is immediately followed by the modifier 'i', the string is matched without case-sensitivity, that is, the input.downcase matches the terminal.downcase Treetop now also supports regular expressions as terminals. Use a string as before, but append the modifier character 'r' (you can combine this with 'i' to get case-insensitive regular expressions). Regular expressions are generally faster than the equivalent parsing expressions, but may have polynomial worst-case behaviour, which is worse than parsing expressions. Your regular expression will always be anchored (by prepending \A) to test the current location of the input, so some special expressions like \b for word boundaries may give unexpected results. 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 ```ruby # 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.6.12/Rakefile000066400000000000000000000022341433777471000147460ustar00rootroot00000000000000require 'bundler/gem_tasks' require 'rspec/core/rake_task' require File.expand_path("../lib/treetop/version", __FILE__) 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 :rebuild do $:.unshift "lib" require './lib/treetop' load File.expand_path('../lib/treetop/compiler/metagrammar.rb', __FILE__) Treetop::Compiler::GrammarCompiler.new.compile('lib/treetop/compiler/metagrammar.treetop') end task :version do puts 'Ruby is '+RUBY_VERSION puts 'Treetop is '+Treetop::VERSION::STRING end desc 'Generate and upload website files' task :website do system <<-END rm -rf .doc-tmp cp -r doc .doc-tmp git checkout gh-pages rm -r doc mv .doc-tmp doc rake website upload git checkout master END end treetop-1.6.12/Treetop.tmbundle/000077500000000000000000000000001433777471000165335ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Preferences/000077500000000000000000000000001433777471000207745ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Preferences/Comments.tmPreferences000066400000000000000000000013071433777471000253060ustar00rootroot00000000000000 name Misc scope source.treetop settings decreaseIndentPattern ^\s*end\s*$ increaseIndentPattern ^\s*(grammar|rule)\s+\w+\s*$ shellVariables name TM_COMMENT_START value # uuid 1BC307B6-CE08-449E-9074-1AEAA5CE99F4 treetop-1.6.12/Treetop.tmbundle/Snippets/000077500000000000000000000000001433777471000203405ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Snippets/grammar ___ end.tmSnippet000066400000000000000000000007731433777471000251260ustar00rootroot00000000000000 content grammar ${1:GrammarName} rule ${2:rule_name} $0 end end name grammar ... end scope source.treetop tabTrigger g uuid 2AE73FBB-88B9-4049-B208-D2440A146164 treetop-1.6.12/Treetop.tmbundle/Snippets/rule ___ end.tmSnippet000066400000000000000000000007321433777471000244420ustar00rootroot00000000000000 content rule ${1:rule_name} $0 end name rule ... end scope meta.grammar.treetop tabTrigger r uuid 498A1881-498E-4BDA-9303-7E42B425C5EE treetop-1.6.12/Treetop.tmbundle/Support/000077500000000000000000000000001433777471000202075ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Support/nibs/000077500000000000000000000000001433777471000211425ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/000077500000000000000000000000001433777471000252015ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/designable.nib000066400000000000000000002416111433777471000277750ustar00rootroot00000000000000 1050 9E17 629 949.33 352.00 YES YES com.apple.InterfaceBuilder.CocoaPlugin YES NSObject FirstResponder NSApplication YES input syntax_tree controller selected_tab YES YES class_and_modules offset text_value methods getIndexes YES YES YES YES elements 15 2 {{83, 222}, {1112, 670}} 603979776 Window NSWindow 256 YES 18 YES 256 YES 289 {{1001, 9}, {96, 32}} YES 67239424 134217728 Run LucidaGrande 1.300000e+01 1044 -2038284033 268435585 DQ 200 25 256 YES 2304 YES 2322 YES YES Apple HTML pasteboard type Apple PDF pasteboard type Apple PICT pasteboard type Apple PNG pasteboard type Apple URL pasteboard type CorePasteboardFlavorType 0x6D6F6F76 CorePasteboardFlavorType 0x75726C20 NSColor pasteboard type NSFilenamesPboardType NSStringPboardType NeXT Encapsulated PostScript v1.2 pasteboard type NeXT RTFD pasteboard type NeXT Rich Text Format v1.0 pasteboard type NeXT TIFF v4.0 pasteboard type NeXT font pasteboard type NeXT ruler pasteboard type WebURLsWithTitlesPboardType {1097, 36} Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda YES YES YES NSFont NSParagraphStyle YES 1.000000e+01 2843 3 YES 0.000000e+00 5.600000e+01 1.120000e+02 1.680000e+02 2.240000e+02 2.800000e+02 3.360000e+02 3.920000e+02 4.480000e+02 5.040000e+02 5.600000e+02 6.160000e+02 6.720000e+02 7.280000e+02 7.840000e+02 8.400000e+02 8.960000e+02 9.520000e+02 1.008000e+03 1.064000e+03 1.120000e+03 1.176000e+03 1.232000e+03 1.288000e+03 1.344000e+03 1.400000e+03 1.456000e+03 1.512000e+03 1.568000e+03 1.624000e+03 1.680000e+03 1.736000e+03 YES YES YES LucidaGrande-Bold 1.000000e+01 16 3 YES GQAEAQgADAEiAAcBhAQAA YES 6 1.097000e+03 1 12035 3 MQA 3 MAA YES YES NSBackgroundColor NSColor YES 6 System selectedTextBackgroundColor 3 MC42NjY2NjY2OQA 6 selectedTextColor YES YES NSUnderline YES 1 MCAwIDEAA 6 {1104, 1e+07} {223, 29} {{1, 1}, {1097, 566}} {4, -5} 1 4 256 {{1098, 1}, {15, 566}} _doScroller: 8.839779e-01 256 {{-100, -100}, {87, 18}} 1 1.000000e+00 9.456522e-01 {{-3, 57}, {1114, 568}} 18 {{10, 33}, {1108, 628}} {{-8, -10}, {1128, 674}} YES 1 256 YES 274 YES 2304 YES 256 {1097, 595} YES 256 {1097, 17} 256 {{1098, 0}, {16, 17}} YES 2.470000e+02 1.600000e+01 1.000000e+03 75628032 0 Class + Modules 1.100000e+01 3100 3 MC4zMzMzMzI5OQA 6 headerTextColor 337772096 2048 Text Cell 6 controlBackgroundColor 6 controlTextColor 2 YES 4.900000e+01 4.000000e+01 1.000000e+03 75628032 0 Offset 337772096 2048 2 YES 4.510000e+02 1.000000e+01 3.402823e+38 75628032 0 Text 6 headerColor 337772096 2048 3 YES 3.380000e+02 1.000000e+01 3.402823e+38 75628032 0 Methods 337772096 2048 3 YES 3.000000e+00 2.000000e+00 6 gridColor 3 MC41AA 1.700000e+01 -759136256 1 15 0 YES YES {{1, 17}, {1097, 595}} 4 256 {{1098, 17}, {15, 595}} 9.983193e-01 256 {{1, 612}, {1097, 15}} 1 9.990892e-01 2304 YES {{1, 0}, {1097, 17}} 4 {{-3, -3}, {1114, 628}} 50 QSAAAEEgAABBmAAAQZgAAA {{10, 33}, {1108, 628}} Syntax Tree 6 controlColor 2 Input 0 YES YES {1112, 670} {{0, 0}, {1680, 1028}} YES contentObject: parameters contentObject parameters 2 5 contentObject: selection.syntax_tree selection.syntax_tree 2 74 value: arrangedObjects.class_and_modules value arrangedObjects.class_and_modules 2 240 value: arrangedObjects.offset arrangedObjects.offset 2 242 value: arrangedObjects.text_value arrangedObjects.text_value 2 244 value: arrangedObjects.methods arrangedObjects.methods 2 245 value: selection.input value selection.input NSAlwaysPresentsApplicationModalAlerts 2 266 argument: selection.input argument selection.input NSSelectorName returnArgument: 2 271 target: selection.controller target selection.controller returnArgument: 2 272 selectedLabel: selection.selected_tab selectedLabel selection.selected_tab 2 274 YES 0 YES -2 RmlsZSdzIE93bmVyA -1 First Responder -3 Application 3 72 210 YES 211 YES 212 YES 214 YES 215 YES 221 YES 222 213 YES 216 YES 223 YES 236 226 YES 234 YES 235 232 YES 233 229 YES 230 228 YES 231 225 224 257 YES 258 259 260 YES YES -1.IBPluginDependency -2.IBPluginDependency -3.IBPluginDependency 210.IBPluginDependency 210.IBWindowTemplateEditedContentRect 210.NSWindowTemplate.visibleAtLaunch 210.editorWindowContentRectSynchronizationRect 211.IBPluginDependency 212.IBPluginDependency 213.IBPluginDependency 214.IBPluginDependency 215.IBPluginDependency 216.IBPluginDependency 221.IBPluginDependency 222.IBPluginDependency 223.IBPluginDependency 224.IBPluginDependency 225.IBPluginDependency 226.IBPluginDependency 228.IBPluginDependency 229.IBPluginDependency 230.IBPluginDependency 231.IBPluginDependency 257.IBPluginDependency 258.IBPluginDependency 259.IBPluginDependency 260.IBPluginDependency 3.IBPluginDependency 72.IBPluginDependency YES {{82, 256}, {1112, 670}} {{82, 256}, {1112, 670}} com.apple.InterfaceBuilder.CocoaPlugin YES YES YES YES YES YES 274 YES 0 3 YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxEBdgALAAwAMQA1ADYAOwA8 AEEAVQBWAFcAWAALAGUAaQB+AIIAiQCOAJkAmgCyALMAuwC8AL4AvwDAAMQAygDYAN4A7gDyAQcBGwEc AR0BHgEfASABIQEiASMBJAElASYBJwEoASkBKgErASwBMAExATsBQwFMAVABUwFYAWEAbQFiAWgBiwGP AZIBlQGYAZsBngGhAaQBpwGqAa0BsAGzAbYBuQG8Ab8BwgHFAcgBywHOAdEB1AHXAdoB3QHgAeMB5gHp AewB7wHyAfQB+QH8AgQCBwIqAi4CLwIyAjYCOgI+AkICRAJGAlYCWwJeAmECSgJdAmkCcAJxAnICdQJ6 AnsCgwE2AoQCiAKLAowCjQKQApEClgKXApkCnAKoAqkCqgKtArgCuQK6Ar0CvgLAAsECxgLQAtEC1gLa AusC8wL7Av8DGwMcAyMDKwMsAy8DNAM1AzgDPwNOA1YDVwNcA18DZANlA2kDcgNzA3gDeQN+A38DgQOE A4wDkgOTA5oDogOoA6kDrgOvA7YDvQPDA8QDywPQA9ED1APXA9gD4APhA+kD6gPuA+8CvQPwA/ED9gP3 A/oEAQQCBAMEBQALBAYEBwQKBBcEIwQzBD0EPgQ/BEAEQQRCBEMERQRHBEgETQROBE8EUARUBFsEYARn BGgEaQRqBGwEbgRvBHAEcQR4BHkEegSBBIIEgwSKBIsEjASTBJQElQSeBJ8EoAShBKcEqASpBLMEtAS1 BLYEqAS8BMQETgSgBMUEywB6BM0E1ATVBNYE1wT3BPoE+wUbBTwFXQVeBV8FYAVhBWIFYwVkBWUFZgVn BWgFaQVqBWsFbAVtBW4FbwVwBXEFcgVzBXQFdQV2BXcFeAV5BXoFewV+BYEFrAXXBdgF2QXaBdsF3AXd Bd4F3wXgBeEF4gXjBeQF5QXmBecF6AXpBeoF6wXsBe0F7gXvBfAF8QXyBfMF9AX1AucF9gX3AWcF+AX5 BfoF+wX8Bf0GAAYDBgZVJG51bGzfEBIADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4A HwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADBWTlNSb290ViRjbGFzc11OU09iamVjdHNL ZXlzXxAPTlNDbGFzc2VzVmFsdWVzXxAZTlNBY2Nlc3NpYmlsaXR5T2lkc1ZhbHVlc11OU0Nvbm5lY3Rp b25zW05TTmFtZXNLZXlzW05TRnJhbWV3b3JrXU5TQ2xhc3Nlc0tleXNaTlNPaWRzS2V5c11OU05hbWVz VmFsdWVzXxAZTlNBY2Nlc3NpYmlsaXR5Q29ubmVjdG9yc11OU0ZvbnRNYW5hZ2VyXxAQTlNWaXNpYmxl V2luZG93c18QD05TT2JqZWN0c1ZhbHVlc18QF05TQWNjZXNzaWJpbGl0eU9pZHNLZXlzWU5TTmV4dE9p ZFxOU09pZHNWYWx1ZXOAAoEBdYEBIoEBR4EBdIDhgQEmgAWBAUaBAUiBASeBAXKAAIAGgQElgQFzEQEU gQFJ0gAOADIAMwA0W05TQ2xhc3NOYW1lgASAA1hOU09iamVjdNIANwA4ADkAOlgkY2xhc3Nlc1okY2xh c3NuYW1logA6ADVeTlNDdXN0b21PYmplY3RfEBBJQkNvY29hRnJhbWV3b3Jr0gAOAD0APgA/Wk5TLm9i amVjdHOANKEAQIAH2gBCAA4AQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTACtcTlNXaW5k b3dWaWV3XE5TU2NyZWVuUmVjdF1OU1dpbmRvd1RpdGxlWU5TV1RGbGFnc11OU1dpbmRvd0NsYXNzXE5T V2luZG93UmVjdF8QD05TV2luZG93QmFja2luZ18QEU5TV2luZG93U3R5bGVNYXNrW05TVmlld0NsYXNz gAuA4IDfgAkSJAAAAIAKgAgQAhAPgABfEBh7ezgzLCAyMjJ9LCB7MTExMiwgNjcwfX1WV2luZG93WE5T V2luZG931wBZAA4AWgBbAFwAVwBdAF4AXwBgAGEAYgBeAGRfEA9OU05leHRSZXNwb25kZXJaTlNTdWJ2 aWV3c1hOU3ZGbGFnc1tOU0ZyYW1lU2l6ZVtOU1N1cGVydmlld4AMgJWADREBAIDdgAyA3tIADgA9AGYA Z4BroQBogA7dAFkADgBqAGsAbABtAFoAWwBXAG4AXQBvAHAASwByAHMAdAB1AHYAdwB4AF4AegBLAHoA fV5OU1RhYlZpZXdJdGVtc1lOU1R2RmxhZ3NXTlNGcmFtZVZOU0ZvbnRfEBFOU0RyYXdzQmFja2dyb3Vu ZF8QFk5TQWxsb3dUcnVuY2F0ZWRMYWJlbHNfEBVOU1NlbGVjdGVkVGFiVmlld0l0ZW2AC4DcgJcQAICW gBaADxASgAwJgAsJgNnSAA4APQBmAICAa6EAgYAQ1wBZAA4AbABaAFsAVwBdAGgAXwCFAIYAYQBeAGiA DoCVgJSAEYAMgA7SAA4APQBmAIuAa6IAjACNgBKAHdgAWQAOAGwAjwBbAJAAVwBdAIEAkgCTAJQAlQB6 AF4AgVZOU0NlbGxZTlNFbmFibGVkgBCAHIATgBQRASEJgAyAEF8QFXt7MTAwMSwgOX0sIHs5NiwgMzJ9 fdwAmwAOAJwAnQCeAJ8AoAChAKIAowCkAKUApgCnAKgAqQCqAKsArAB2AIwArwCwALFbTlNDZWxsRmxh Z3NfEBNOU0FsdGVybmF0ZUNvbnRlbnRzXxASTlNQZXJpb2RpY0ludGVydmFsXk5TQnV0dG9uRmxhZ3My XxAPTlNLZXlFcXVpdmFsZW50Wk5TQ29udGVudHNZTlNTdXBwb3J0XU5TQ29udHJvbFZpZXdfEA9OU1Bl cmlvZGljRGVsYXlcTlNDZWxsRmxhZ3MyXU5TQnV0dG9uRmxhZ3MSBAH+AIAbgBkQGRIQAACBgBqAFYAW gBIQyBIIAAAAE/////+GgkD/U1J1btQADgC0ALUAtgC3ALgAuQC6Vk5TU2l6ZVZOU05hbWVYTlNmRmxh Z3OAGCNAKgAAAAAAAIAXEQQUXEx1Y2lkYUdyYW5kZdIANwA4AL0AbaIAbQA1UFEN0gA3ADgAwQDCpADC AMMAjwA1XE5TQnV0dG9uQ2VsbFxOU0FjdGlvbkNlbGzSADcAOADFAMalAMYAxwDIAMkANVhOU0J1dHRv bllOU0NvbnRyb2xWTlNWaWV3W05TUmVzcG9uZGVy2wBZAMsADgBsAMwAWgBbAFcAXQDNAM4AgQDQANEA 0gB4ANMAYQBeAIEA1gDXW05TSFNjcm9sbGVyWE5Tc0ZsYWdzW05TVlNjcm9sbGVyXU5TQ29udGVudFZp ZXeAEICQgJOAkoAegAyAEICMgB/SAA4APQBmANqAa6MA1wDWANCAH4CMgJDbAFkADgBsAN8A4ABaAFsA 4QBXAOIAXQCNAOQA5QDmAOcA6ADpAOoAXgDsAI1YTlNDdXJzb3JZTlNjdkZsYWdzWU5TRG9jVmlld1lO U0JHQ29sb3KAHYCLgIeAiBAEgCARCQCAIYAMgHOAHdIADgA9AGYA8IBroQDqgCHdAFkADgDzAPQA9QD2 AFsAXAD3AFcA+ABdAPkA1wD7APwA/QD+AP8BAAEBAQIAXgEEANcAK18QD05TVGV4dENvbnRhaW5lcllO U1RWRmxhZ3NcTlNTaGFyZWREYXRhW05TRHJhZ1R5cGVzWU5TTWF4U2l6ZVhOU01pbml6ZVpOU0RlbGVn YXRlgB+AhoA2EAaAcoAiEQkSgDWAhIAMgIWAH4AA0gAOAD0APgEJgDSvEBEBCgELAQwBDQEOAQ8BEAER ARIBEwEUARUBFgEXARgBGQEagCOAJIAlgCaAJ4AogCmAKoArgCyALYAugC+AMIAxgDKAM18QGU5lWFQg UlRGRCBwYXN0ZWJvYXJkIHR5cGVfEBJOU1N0cmluZ1Bib2FyZFR5cGVfEBpOZVhUIHJ1bGVyIHBhc3Rl Ym9hcmQgdHlwZV8QHk5lWFQgVElGRiB2NC4wIHBhc3RlYm9hcmQgdHlwZV8QGUFwcGxlIFVSTCBwYXN0 ZWJvYXJkIHR5cGVfECNDb3JlUGFzdGVib2FyZEZsYXZvclR5cGUgMHg2RDZGNkY3Nl8QG1dlYlVSTHNX aXRoVGl0bGVzUGJvYXJkVHlwZV8QI0NvcmVQYXN0ZWJvYXJkRmxhdm9yVHlwZSAweDc1NzI2QzIwXxAZ QXBwbGUgUERGIHBhc3RlYm9hcmQgdHlwZV8QGUFwcGxlIFBORyBwYXN0ZWJvYXJkIHR5cGVfEBpBcHBs ZSBIVE1MIHBhc3RlYm9hcmQgdHlwZV8QFU5TRmlsZW5hbWVzUGJvYXJkVHlwZV8QMU5lWFQgRW5jYXBz dWxhdGVkIFBvc3RTY3JpcHQgdjEuMiBwYXN0ZWJvYXJkIHR5cGVfEBdOU0NvbG9yIHBhc3RlYm9hcmQg dHlwZV8QGkFwcGxlIFBJQ1QgcGFzdGVib2FyZCB0eXBlXxAZTmVYVCBmb250IHBhc3RlYm9hcmQgdHlw ZV8QKk5lWFQgUmljaCBUZXh0IEZvcm1hdCB2MS4wIHBhc3RlYm9hcmQgdHlwZdIANwA4AS0BLqMBLgEv ADVcTlNNdXRhYmxlU2V0VU5TU2V0WnsxMDk3LCAzNn3VATIADgEzATQBNQE2ATcA6gE5ATpZTlNUQ0Zs YWdzWk5TVGV4dFZpZXdXTlNXaWR0aF8QD05TTGF5b3V0TWFuYWdlchABgHGAISNAkSQAAAAAAIA31QAO ATwBPQE+APkBPwFAAUEA/QArXxAQTlNUZXh0Q29udGFpbmVyc11OU1RleHRTdG9yYWdlWU5TTE1GbGFn c4BwgG+AOIAA1QAOAUQBRQFGAPkBRwFIAUkBSgArXE5TQXR0cmlidXRlc1hOU1N0cmluZ18QD05TQXR0 cmlidXRlSW5mb4BugDuAOYBsgADSAA4BTQFOAU9ZTlMuc3RyaW5ngDpfEQJeTG9yZW0gaXBzdW0gZG9s b3Igc2l0IGVyIGVsaXQgbGFtZXQsIGNvbnNlY3RldGF1ciBjaWxsaXVtIGFkaXBpc2ljaW5nIHBlY3Us IHNlZCBkbyBlaXVzbW9kIHRlbXBvciBpbmNpZGlkdW50IHV0IGxhYm9yZSBldCBkb2xvcmUgbWFnbmEg YWxpcXVhLiBVdCBlbmltIGFkIG1pbmltIHZlbmlhbSwgcXVpcyBub3N0cnVkIGV4ZXJjaXRhdGlvbiB1 bGxhbWNvIGxhYm9yaXMgbmlzaSB1dCBhbGlxdWlwIGV4IGVhIGNvbW1vZG8gY29uc2VxdWF0LiBEdWlz IGF1dGUgaXJ1cmUgZG9sb3IgaW4gcmVwcmVoZW5kZXJpdCBpbiB2b2x1cHRhdGUgdmVsaXQgZXNzZSBj aWxsdW0gZG9sb3JlIGV1IGZ1Z2lhdCBudWxsYSBwYXJpYXR1ci4gRXhjZXB0ZXVyIHNpbnQgb2NjYWVj YXQgY3VwaWRhdGF0IG5vbiBwcm9pZGVudCwgc3VudCBpbiBjdWxwYSBxdWkgb2ZmaWNpYSBkZXNlcnVu dCBtb2xsaXQgYW5pbSBpZCBlc3QgbGFib3J1bSBFdCBoYXJ1bWQgdW5kIGxvb2t1bSBsaWtlIEdyZWVr IHRvIG1lLCBkZXJldWQgZmFjaWxpcyBlc3QgZXIgZXhwZWRpdCBkaXN0aW5jdC4gTmFtIGxpYmVyIHRl IGNvbnNjaWVudCB0byBmYWN0b3IgdHVtIHBvZW4gbGVndW0gb2Rpb3F1ZSBjaXZpdWRh0gA3ADgBUQFS owFSAUUANV8QD05TTXV0YWJsZVN0cmluZ9IADgA9AGYBVYBrogFWAVeAPIBm0wAOAVkAPQFaAVsBXldO Uy5rZXlzgGWiAVwBXYA9gD6iAV8BYIA/gGRfEBBOU1BhcmFncmFwaFN0eWxl0wFjAA4BZAFlAWYBZ1pO U1RhYlN0b3BzW05TQWxpZ25tZW50gECAYxAD0gAOAD0BaQFqgGKvECABawFsAW0BbgFvAXABcQFyAXMB dAF1AXYBdwF4AXkBegF7AXwBfQF+AX8BgAGBAYIBgwGEAYUBhgGHAYgBiQGKgEGAQ4BEgEWARoBHgEiA SYBKgEuATIBNgE6AT4BQgFGAUoBTgFSAVYBWgFeAWIBZgFqAW4BcgF2AXoBfgGCAYdIADgGMAY0BjlpO U0xvY2F0aW9ugEIjAAAAAAAAAADSADcAOAGQAZGiAZEANVlOU1RleHRUYWLSAA4BjAGNAZSAQiNATAAA AAAAANIADgGMAY0Bl4BCI0BcAAAAAAAA0gAOAYwBjQGagEIjQGUAAAAAAADSAA4BjAGNAZ2AQiNAbAAA AAAAANIADgGMAY0BoIBCI0BxgAAAAAAA0gAOAYwBjQGjgEIjQHUAAAAAAADSAA4BjAGNAaaAQiNAeIAA AAAAANIADgGMAY0BqYBCI0B8AAAAAAAA0gAOAYwBjQGsgEIjQH+AAAAAAADSAA4BjAGNAa+AQiNAgYAA AAAAANIADgGMAY0BsoBCI0CDQAAAAAAA0gAOAYwBjQG1gEIjQIUAAAAAAADSAA4BjAGNAbiAQiNAhsAA AAAAANIADgGMAY0Bu4BCI0CIgAAAAAAA0gAOAYwBjQG+gEIjQIpAAAAAAADSAA4BjAGNAcGAQiNAjAAA AAAAANIADgGMAY0BxIBCI0CNwAAAAAAA0gAOAYwBjQHHgEIjQI+AAAAAAADSAA4BjAGNAcqAQiNAkKAA AAAAANIADgGMAY0BzYBCI0CRgAAAAAAA0gAOAYwBjQHQgEIjQJJgAAAAAADSAA4BjAGNAdOAQiNAk0AA AAAAANIADgGMAY0B1oBCI0CUIAAAAAAA0gAOAYwBjQHZgEIjQJUAAAAAAADSAA4BjAGNAdyAQiNAleAA AAAAANIADgGMAY0B34BCI0CWwAAAAAAA0gAOAYwBjQHigEIjQJegAAAAAADSAA4BjAGNAeWAQiNAmIAA AAAAANIADgGMAY0B6IBCI0CZYAAAAAAA0gAOAYwBjQHrgEIjQJpAAAAAAADSAA4BjAGNAe6AQiNAmyAA AAAAANIANwA4AfAB8aIB8QA1V05TQXJyYXnSADcAOAHzAWGiAWEANdQADgC0ALUAtgC3AfYAuQH4gBgj QCQAAAAAAACAFxELG9IANwA4AfoB+6IB+wA1XE5TRGljdGlvbmFyedMADgFZAD0BWgH+AgGAZaIBXAFd gD2APqICAgIDgGeAadMBYwAOAWQCBQFmAWeAaIBj0gAOAD0BaQIJgGKvECABawFsAW0BbgFvAXABcQFy AXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8BgAGBAYIBgwGEAYUBhgGHAYgBiQGKgEGAQ4BEgEWARoBH gEiASYBKgEuATIBNgE6AT4BQgFGAUoBTgFSAVYBWgFeAWIBZgFqAW4BcgF2AXoBfgGCAYdQADgC0ALUA tgC3AfYCLAItgBiAahAQXxARTHVjaWRhR3JhbmRlLUJvbGTSADcAOAIwAjGjAjEB8QA1Xk5TTXV0YWJs ZUFycmF50gAOAjMCNAI1V05TLmRhdGGAbU8QDxkABAEIAAwBIgAHAYQEANIANwA4AjcCOKMCOAI5ADVd TlNNdXRhYmxlRGF0YVZOU0RhdGHSADcAOAI7AT2kAT0CPAI9ADVfEBlOU011dGFibGVBdHRyaWJ1dGVk U3RyaW5nXxASTlNBdHRyaWJ1dGVkU3RyaW5n0gAOAD0AZgJAgGuhAPyANtIANwA4AkMBNaIBNQA10gA3 ADgCRQDzogDzADXYAA4CRwJIAkkCSgJLAkwCTQJOAk8AKwJRAOwCUwArAlVXTlNGbGFnc18QF05TRGVm YXVsdFBhcmFncmFwaFN0eWxlXxAQTlNJbnNlcnRpb25Db2xvcl8QEU5TQmFja2dyb3VuZENvbG9yXxAU TlNTZWxlY3RlZEF0dHJpYnV0ZXNfEBJOU01hcmtlZEF0dHJpYnV0ZXNfEBBOU0xpbmtBdHRyaWJ1dGVz gIMRLwOAAIB1gHOAdoAAgH/TAA4CVwJYAlkBZwJaXE5TQ29sb3JTcGFjZVdOU1doaXRlgHRCMQDSADcA OAJcAl2iAl0ANVdOU0NvbG9y0wAOAlcCWAJZAWcCYIB0QjAA0wAOAVkAPQFaAmMCZoBlogJkAmWAd4B4 ogJnAmiAeYB91QAOAl0CVwJqAmsCWQJtAP0CbgJvW05TQ29sb3JOYW1lXU5TQ2F0YWxvZ05hbWWAdIB8 gHuAelZTeXN0ZW1fEBtzZWxlY3RlZFRleHRCYWNrZ3JvdW5kQ29sb3LTAA4CVwJYAlkBZwJ0gHRLMC42 NjY2NjY2OQDVAA4CXQJXAmoCawJZAlEA/QJ4Am+AdIB1gH6Ael8QEXNlbGVjdGVkVGV4dENvbG9y0wAO AVkAPQFaAn0CgIBlogJ+AmWAgIB4ogKBAoKAgYCCW05TVW5kZXJsaW5l0wAOAlcChQJZATYCh1VOU1JH QoB0RjAgMCAxANIANwA4AokCiqICigA1XxAUTlNUZXh0Vmlld1NoYXJlZERhdGFdezExMDQsIDFlKzA3 fVl7MjIzLCAyOX3SADcAOAKOATOlATMCjwDIAMkANVZOU1RleHRfEBV7ezEsIDF9LCB7MTA5NywgNTY2 fX3TAA4CkgKTApQClQE2WU5TSG90U3BvdFxOU0N1cnNvclR5cGWAioCJV3s0LCAtNX3SADcAOAKYAN+i AN8ANdIANwA4ApoCm6QCmwDIAMkANVpOU0NsaXBWaWV32QBZAp0ADgBsAFsAVwKeAF0CnwCNAI0CogKj AGEAXgKlAI0Cp1hOU1RhcmdldFhOU0FjdGlvbllOU1BlcmNlbnSAHYAdgI+AjYAMgI6AHSM/7EmMAAAA AF8QFnt7MTA5OCwgMX0sIHsxNSwgNTY2fX1cX2RvU2Nyb2xsZXI60gA3ADgCqwKspQKsAMcAyADJADVa TlNTY3JvbGxlctsAWQKdAA4AbADMAFsAVwKeAF0CrgKfAI0AjQKiArIBNgBhAF4CpQCNArYCt1pOU0N1 clZhbHVlgB2AHYCPgJGADICOgB0jP/AAAAAAAAAjP+5CyGAAAABfEBh7ey0xMDAsIC0xMDB9LCB7ODcs IDE4fX1fEBd7ey0zLCA1N30sIHsxMTE0LCA1Njh9fdIANwA4ArsCvKQCvADIAMkANVxOU1Njcm9sbFZp ZXdfEBd7ezEwLCAzM30sIHsxMTA4LCA2Mjh9fdIANwA4Ar8AyKMAyADJADVfEBh7ey04LCAtMTB9LCB7 MTEyOCwgNjc0fX3SAA4APQBmAsOAa6ICxAB9gJiA2dYADgLHAMgCyAJdAskCygLLAswAaALOAs9cTlNJ ZGVudGlmaWVyWU5TVGFiVmlld1dOU0xhYmVsgNiAmYCagA6A1oDVUTHVAFkADgBsAFoAWwArAF8C1ALV AGGAAICVgNSAm9IADgA9AGYC2IBroQLZgJzdAFkAywAOAGwAzALbAtwAWgLdAFsAXQDNAM4CzALfANEC 4QLiAuMC5ALlAuYC5wLMAukC6lxOU0Nvcm5lclZpZXdfEBBOU0hlYWRlckNsaXBWaWV3XE5TU2Nyb2xs QW10c4CagM+Ak4DTEDKApoCjgJ1PEBBBIAAAQSAAAEGYAABBmAAAEQESgJqAzYCe0gAOAD0AZgLtgGul AuoC6QLfAuQC44CegM2Az4CjgKbZAFkADgBsAOAAWgBbAOEA4gBdAtkA5AL2AOcC9wDpAvgC+QLZgJyA i4DMgJ+AoIC0gJzSAA4APQBmAv2Aa6EC+ICg3xAUAFkDAAAOAGsDAQJKAwIC2wMDAwQDBQBbAFwAkAMG AwcDCABdAwkDCgLqAHQDDAMNAw4A7AB6AuMDEgE2AxMAYQMUAHoAegMXAFMC6gMZAxpfEB9OU0RyYWdn aW5nU291cmNlTWFza0Zvck5vbkxvY2FsXE5TSGVhZGVyVmlld18QEk5TQWxsb3dzVHlwZVNlbGVjdF8Q F05TSW50ZXJjZWxsU3BhY2luZ1dpZHRoXxAZTlNDb2x1bW5BdXRvcmVzaXppbmdTdHlsZV8QGE5TSW50 ZXJjZWxsU3BhY2luZ0hlaWdodF8QJU5TT3V0bGluZVZpZXdBdXRvc2F2ZUV4cGFuZGVkSXRlbXNLZXlb TlNHcmlkQ29sb3JfEBxOU0RyYWdnaW5nU291cmNlTWFza0ZvckxvY2FsXk5TVGFibGVDb2x1bW5zW05T Um93SGVpZ2h0gJ6AyxP/////0sCAAICigHMJgKYjQAgAAAAAAAAjQAAAAAAAAACAoQkJgMiAnoCpI0Ax AAAAAAAAW3sxMDk3LCA1OTV91gBZAA4AWwBcAF0DHQLkAx8AYQMgAuQC+FtOU1RhYmxlVmlld4CjgKWA pICjgKDZAFkADgBsAOAAWgBbAOEA4gBdAtkA5AMmAOcDJwDpAw4C+QLZgJyAi4DSgNGAooC0gJxaezEw OTcsIDE3fdIANwA4Ay0DLqQDLgDIAMkANV8QEU5TVGFibGVIZWFkZXJWaWV31QBZAA4AbABbAF0C2QMx AzIAYQLZgJyAqICngJxfEBV7ezEwOTgsIDB9LCB7MTYsIDE3fX3SADcAOAM2AzekAzcAyADJADVdX05T Q29ybmVyVmlld9IADgA9AGYDOoBrpAM7AzwDPQM+gKqAuoC+gMTZA0AADgNBATQDQgNDA0QDRQMdAHoD RwNIA0kDSgBSA0sDTAL4Xk5TSXNSZXNpemVhYmxlXE5TSGVhZGVyQ2VsbFpOU0RhdGFDZWxsXk5TUmVz aXppbmdNYXNrWk5TTWluV2lkdGhaTlNNYXhXaWR0aAmAuYCrI0Bu4AAAAAAAgLIjQDAAAAAAAAAjQI9A AAAAAACAoNcAmwAOAkoAoAChAKQDTwNQA1EDUgNTA1QAdANVW05TVGV4dENvbG9yEgSB/gCAsYCugKyA rYCvXxAPQ2xhc3MgKyBNb2R1bGVz1AAOALQAtQC2ALcDWQC5A1uAGCNAJgAAAAAAAIAXEQwc0wAOAlcC WAJZAWcDXoB0SzAuMzMzMzMyOTkA1QAOAl0CVwJqAmsCWQJRAP0DYgJvgHSAdYCwgHpfEA9oZWFkZXJU ZXh0Q29sb3LSADcAOANmA2elA2cDaADDAI8ANV8QEU5TVGFibGVIZWFkZXJDZWxsXxAPTlNUZXh0Rmll bGRDZWxs2ACbAA4CSgCgAKEAogCkA08DagNrAvkDbQB2AvgDcANxEhQh/kCAuIC0gLOAFoCgEQgAgLZZ VGV4dCBDZWxs1QAOAl0CVwJqAmsCWQJtAP0DdgJvgHSAfIC1gHpfEBZjb250cm9sQmFja2dyb3VuZENv bG9y1QAOAl0CVwJqAmsCWQJRAP0DfAJvgHSAdYC3gHpfEBBjb250cm9sVGV4dENvbG9y0gA3ADgDgANo pANoAMMAjwA10gA3ADgDggODogODADVdTlNUYWJsZUNvbHVtbtkDQAAOA0EBNANCA0MDRANFAx0AegNH A4cDiAOJAFIDigNMAvgJgLmAuyNASIAAAAAAAIC9I0BEAAAAAAAAgKDXAJsADgJKAKAAoQCkA08DUANR A1IDjwNUAHQDVYCxgK6AvICtgK9WT2Zmc2V02ACbAA4CSgCgAKEAogCkA08DagNrAvkDbQB2AvgDcANx gLiAtICzgBaAoIC22QNAAA4DQQE0A0IDQwNEA0UDHQB6A0cDnQOeA58BZwH2A6AC+AmAuYC/I0B8MAAA AAAAgMMjR+///6AAAACAoNcAmwAOAkoAoAChAKQDTwNQA1EDpAOlA1QAdANVgLGAwYDAgK2Ar1RUZXh0 1QAOAl0CVwJqAmsCWQDsAP0DrAJvgHSAc4DCgHpbaGVhZGVyQ29sb3LYAJsADgJKAKAAoQCiAKQDTwNq A2sC+QNtAHYC+ANwA3GAuIC0gLOAFoCggLbZA0AADgNBATQDQgNDA0QDRQMdAHoDRwO5A7oDuwFnAfYD oAL4CYC5gMUjQHUgAAAAAACAx4Cg1wCbAA4CSgCgAKEApANPA1ADUQOkA8ADVAB0A1WAsYDBgMaArYCv V01ldGhvZHPYAJsADgJKAKAAoQCiAKQDTwNqA2sC+QNtAHYC+ANwA3GAuIC0gLOAFoCggLbVAA4CXQJX AmoCawJZA80A/QPOAm+AdIDKgMmAellncmlkQ29sb3LTAA4CVwJYAlkBZwPTgHREMC41ANIANwA4A9UD 1qYD1gMdAMcAyADJADVdTlNPdXRsaW5lVmlld18QFnt7MSwgMTd9LCB7MTA5NywgNTk1fX3YAFkCnQAO AGwAWwKeAF0CnwLZAtkCogPcAGECpQLZA9+AnICcgI+AzoCOgJwjP+/yO2AAAABfEBd7ezEwOTgsIDE3 fSwgezE1LCA1OTV9fdkAWQKdAA4AbADMAFsCngBdAp8C2QLZAqID5QE2AGECpQLZA+iAnICcgI+A0ICO gJwjP+/4igAAAABfEBZ7ezEsIDYxMn0sIHsxMDk3LCAxNX190gAOAD0AZgPsgGuhAw6Aol8QFHt7MSwg MH0sIHsxMDk3LCAxN319XxAXe3stMywgLTN9LCB7MTExNCwgNjI4fX1bU3ludGF4IFRyZWXVAA4CXQJX AmoCawJZAm0A/QP0Am+AdIB8gNeAelxjb250cm9sQ29sb3LSADcAOAP4A/miA/kANV1OU1RhYlZpZXdJ dGVt1gAOAscAyALIAl0CyQLKA/wAgQBoAs4EAIDYgNqAEIAOgNaA21EyVUlucHV00gA3ADgEBALIpALI AMgAyQA1W3sxMTEyLCA2NzB9XxAWe3swLCAwfSwgezE2ODAsIDEwMjh9fdIANwA4BAgECaIECQA1XxAQ TlNXaW5kb3dUZW1wbGF0ZdIADgA9AGYEDIBrqgQNBA4EDwQQBBEEEgQTBBQEFQQWgOKA84D+gQEBgQEE gQEHgQEKgQERgQEXgQEe1wAOBBgEGQQaBBsCyQQcBB0EHgQfBCADPQQiAFJdTlNEZXN0aW5hdGlvbllO U0tleVBhdGhZTlNCaW5kaW5nWE5TU291cmNlXxAcTlNOaWJCaW5kaW5nQ29ubmVjdG9yVmVyc2lvboDy gOOA8YDwgL6A79gADgQkBCUEJgQnBCgEKQQqBCsAegQtAHoELwB6BDEAel8QFE5TUHJlc2VydmVzU2Vs ZWN0aW9uXxAPX05TTWFuYWdlZFByb3h5Wk5TRWRpdGFibGVeTlNEZWNsYXJlZEtleXNfEBhOU1NlbGVj dHNJbnNlcnRlZE9iamVjdHNfEBhOU1RyZWVDb250ZW50Q2hpbGRyZW5LZXlfEBZOU0F2b2lkc0VtcHR5 U2VsZWN0aW9ugO4JgOsJgOQJgO0J0gAOAD0AZgQ1gGunBDYENwQ4BDkEOgCoBDyA5YDmgOeA6IDpgBmA 6l8QEWNsYXNzX2FuZF9tb2R1bGVzVm9mZnNldFp0ZXh0X3ZhbHVlV21ldGhvZHNaY29udHJvbGxlclpn ZXRJbmRleGVz0QAOBESA7NIANwA4BEYEJaIEJQA1WGVsZW1lbnRz0gA3ADgESQRKpARKBEsETAA1XxAQ TlNUcmVlQ29udHJvbGxlcl8QEk5TT2JqZWN0Q29udHJvbGxlclxOU0NvbnRyb2xsZXJfECF2YWx1ZTog YXJyYW5nZWRPYmplY3RzLnRleHRfdmFsdWVVdmFsdWVfEBphcnJhbmdlZE9iamVjdHMudGV4dF92YWx1 ZdIANwA4BFEEUqMEUgRTADVfEBVOU05pYkJpbmRpbmdDb25uZWN0b3JeTlNOaWJDb25uZWN0b3LXAA4E GAQZBBoEGwLJBBwEHQAfBFcEWARZBFoAUoDygAKA/YD8gPSA+9QADgQlBCYEJwRcBF0AegRfgPqA+QmA 9dIADgA9AGYEYoBrpARjBGQEOgRmgPaA94DpgPhVaW5wdXRbc3ludGF4X3RyZWVcc2VsZWN0ZWRfdGFi 0QAOBESA7NIANwA4BG0ES6MESwRMADVfEBljb250ZW50T2JqZWN0OiBwYXJhbWV0ZXJzXWNvbnRlbnRP YmplY3RacGFyYW1ldGVyc9cADgQYBBkEGgQbAskEHAQdBB4EdAQgAzwEdwBSgPKA44EBAIDwgLqA/18Q HXZhbHVlOiBhcnJhbmdlZE9iamVjdHMub2Zmc2V0XxAWYXJyYW5nZWRPYmplY3RzLm9mZnNldNcADgQY BBkEGgQbAskEHAQdBB4EfQQgAzsEgABSgPKA44EBA4DwgKqBAQJfECh2YWx1ZTogYXJyYW5nZWRPYmpl Y3RzLmNsYXNzX2FuZF9tb2R1bGVzXxAhYXJyYW5nZWRPYmplY3RzLmNsYXNzX2FuZF9tb2R1bGVz1wAO BBgEGQQaBBsCyQQcBB0EWQSGBFgEHgSJAFKA8oD0gQEGgPyA44EBBV8QJGNvbnRlbnRPYmplY3Q6IHNl bGVjdGlvbi5zeW50YXhfdHJlZV8QFXNlbGVjdGlvbi5zeW50YXhfdHJlZdcADgQYBBkEGgQbAskEHAQd BB4EjwQgAz4EkgBSgPKA44EBCYDwgMSBAQhfEB52YWx1ZTogYXJyYW5nZWRPYmplY3RzLm1ldGhvZHNf EBdhcnJhbmdlZE9iamVjdHMubWV0aG9kc9gADgQYBBkEGgQbAskElgQcBB0EWQSZBJoAjAScBJ0AUllO U09wdGlvbnOA8oD0gQENgQEMgBKBAQuBAQ5fEBlhcmd1bWVudDogc2VsZWN0aW9uLmlucHV0WGFyZ3Vt ZW50XxAPc2VsZWN0aW9uLmlucHV00wAOAVkAPQFaBKMEpYBloQSkgQEPoQSmgQEQXk5TU2VsZWN0b3JO YW1lXxAPcmV0dXJuQXJndW1lbnQ62QAOBBgEGQQaBKoEGwLJBJYEHAQdBFkErQSuBBMAjASxBLIAUl8Q E05TUHJldmlvdXNDb25uZWN0b3KA8oD0gQEUgQETgQEKgBKBARKBARVfEBx0YXJnZXQ6IHNlbGVjdGlv bi5jb250cm9sbGVyVnRhcmdldF8QFHNlbGVjdGlvbi5jb250cm9sbGVy0wAOAVkAPQFaBLgEuoBloQSk gQEPoQS7gQEW2AAOBBgEGQQaBBsCyQSWBBwEHQRZBL8EwADqBMIEwwBSgPKA9IEBGoEBGYAhgQEYgQEb XxAWdmFsdWU6IHNlbGVjdGlvbi5pbnB1dNMADgFZAD0BWgTHBMmAZaEEyIEBHKEEyoEBHV8QJk5TQWx3 YXlzUHJlc2VudHNBcHBsaWNhdGlvbk1vZGFsQWxlcnRzCdcADgQYBBkEGgQbAskEHAQdBFkE0ATRAGgE 0wBSgPKA9IEBIYEBIIAOgQEfXxAlc2VsZWN0ZWRMYWJlbDogc2VsZWN0aW9uLnNlbGVjdGVkX3RhYl1z ZWxlY3RlZExhYmVsXxAWc2VsZWN0aW9uLnNlbGVjdGVkX3RhYtIADgA9AWkE2YBirxAdA7sDPALMAtkA SwCMAzsCxATiAz4AfQM9A4kAaACBAvgAjQOfANYDSgMOAOoC3wLpAEAEWQCUANAEHoDHgLqAmoCcgAuA EoCqgJiBASOAxIDZgL6AvYAOgBCAoIAdgMOAjICygKKAIYDPgM2AB4D0gBSAkIDj0gAOADIAMwT5gASB ASRdTlNBcHBsaWNhdGlvbtIADgA9AWkE/YBirxAdAz4C+ALEAswAQACBAvgAaAAfAvgAaAL4AzwASwB9 AtkAgQM9AI0DOwLZAI0C2QLZAB8AHwCMAI0AH4DEgKCAmICagAeAEICggA6AAoCggA6AoIC6gAuA2YCc gBCAvoAdgKqAnIAdgJyAnIACgAKAEoAdgALSAA4APQFpBR2AYq8QHgAfAzwDuwLMAtkASwCMAzsCxATi Az4AfQM9A4kAaACBAvgAjQNKANYDnwMOAt8C6QDqAEAEWQCUANAEHoACgLqAx4CagJyAC4ASgKqAmIEB I4DEgNmAvoC9gA6AEICggB2AsoCMgMOAooDPgM2AIYAHgPSAFICQgOPSAA4APQFpBT6AYq8QHgU/BUAF QQVCBUMFRAVFBUYFRwVIBUkFSgVLBUwFTQVOBU8FUAVRBVIFUwVUBVUFVgVXBVgFWQVaBVsFXIEBKIEB KYEBKoEBK4EBLIEBLYEBLoEBL4EBMIEBMYEBMoEBM4EBNIEBNYEBNoEBN4EBOIEBOYEBOoEBO4EBPIEB PYEBPoEBP4EBQIEBQYEBQoEBQ4EBRIEBRVxGaWxlJ3MgT3duZXJfEBVUYWJsZSBDb2x1bW4gKE9mZnNl dClfEB1UZXh0IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktMlRWaWV3W1Njcm9sbCBWaWV3XENvbnRlbnQg Vmlld18QEVB1c2ggQnV0dG9uIChSdW4pXxAeVGFibGUgQ29sdW1uIChDbGFzcyArIE1vZHVsZXMpXxAb VGFiIFZpZXcgSXRlbSAoU3ludGF4IFRyZWUpW0FwcGxpY2F0aW9uXxAWVGFibGUgQ29sdW1uIChNZXRo b2RzKV8QFVRhYiBWaWV3IEl0ZW0gKElucHV0KV8QE1RhYmxlIENvbHVtbiAoVGV4dClfEBtUZXh0IEZp ZWxkIENlbGwgKFRleHQgQ2VsbClfECFUb3AgVGFiIFZpZXcgKFN5bnRheCBUcmVlLCBJbnB1dClWVmll dy0xXxA1T3V0bGluZSBWaWV3IChDbGFzcyArIE1vZHVsZXMsIE9mZnNldCwgVGV4dCwgTWV0aG9kcyld U2Nyb2xsIFZpZXctMV8QHVRleHQgRmllbGQgQ2VsbCAoVGV4dCBDZWxsKS0xXxATVmVydGljYWwgU2Ny b2xsZXItMV8QHVRleHQgRmllbGQgQ2VsbCAoVGV4dCBDZWxsKS0zXxARVGFibGUgSGVhZGVyIFZpZXdf EBNIb3Jpem9udGFsIFNjcm9sbGVyXxARVmVydGljYWwgU2Nyb2xsZXJZVGV4dCBWaWV3XxAPV2luZG93 IChXaW5kb3cpXxART2JqZWN0IENvbnRyb2xsZXJfEBFCdXR0b24gQ2VsbCAoUnVuKV8QFUhvcml6b250 YWwgU2Nyb2xsZXItMV8QD1RyZWUgQ29udHJvbGxlctIADgA9AWkFfYBioNIADgA9AWkFgIBioNIADgA9 AWkFg4BirxAoBA0AHwO7AzwCzALZAEsAjAM7BBUCxATiAz4EFAB9Az0DiQBoAIEEEgL4AI0DnwDWA0oE EAQPAw4A6gLfAukEFgBABBEEWQCUBBMA0AQOBB6A4oACgMeAuoCagJyAC4ASgKqBAReAmIEBI4DEgQER gNmAvoC9gA6AEIEBB4CggB2Aw4CMgLKBAQGA/oCigCGAz4DNgQEegAeBAQSA9IAUgQEKgJCA84Dj0gAO AD0BaQWugGKvECgFrwWwBbEFsgWzBbQFtQW2BbcFuAW5BboFuwW8Bb0FvgW/BcAFwQXCBcMFxAXFBcYF xwXIBckFygXLBcwFzQXOBc8F0AXRBdIF0wXUBdUF1oEBSoEBS4EBTIEBTYEBToEBT4EBUIEBUYEBUoEB U4EBVIEBVYEBVoEBV4EBWIEBWYEBWoEBW4EBXIEBXYEBXoEBX4EBYIEBYYEBYoEBY4EBZIEBZYEBZoEB Z4EBaIEBaYEBaoEBa4EBbIEBbYEBboEBb4EBcIEBcRD0EQETEOsQ5RDYEN8Q0xDdEOQRAQoQ1RP///// /////RDqEQEQENYQ6BDmENQQ1xD1EOIRAQEQ6REBAhDnEPAQ8hDsEQEEEOEQ4BDSEEoQ3hEBDxEBAxAF EEjSAA4APQBmBf+Aa6DSAA4APQFpBgKAYqDSAA4APQFpBgWAYqDSADcAOAYHBgiiBggANV5OU0lCT2Jq ZWN0RGF0YQAIABkAIgAnADEAOgA/AEQAUgBUAGYDVgNcA6cDrgO1A8MD1QPxA/8ECwQXBCUEMAQ+BFoE aAR7BI0EpwSxBL4EwATDBMYEyQTMBM4E0QTTBNYE2QTcBN8E4QTjBOYE6QTsBO8E+AUEBQYFCAURBRoF IwUuBTMFQgVVBV4FaQVrBW4FcAWZBaYFswXBBcsF2QXmBfgGDAYYBhoGHAYeBiAGJQYnBikGKwYtBi8G SgZRBloGdwaJBpQGnQapBrUGtwa5BrsGvgbABsIGxAbNBs8G0gbUBwkHGAciByoHMQdFB14Hdgd4B3oH fAd+B4AHggeEB4YHiAeJB4sHjAeOB5cHmQecB54Huwe9B78HwQfDB8UHxwfQB9IH1wfZB9sH/AgDCA0I DwgRCBMIFQgYCBkIGwgdCDUIZghyCIgInQisCL4IyQjTCOEI8wkACQ4JEwkVCRcJGQkeCSAJIgkkCSYJ KAktCTYJOglLCVIJWQliCWQJbQlvCXIJfwmICY0JjgmQCZkJogmvCbwJxQnQCdkJ4wnqCfYKIwovCjgK RApSClQKVgpYCloKXApeCmAKYgpkCm0Kbwp2CngKegp8CqkKsgq8CsYK0ArSCtQK1grYCtoK3ArfCuEK 4wrlCucK8AryCvUK9wssCz4LSAtVC2ELawt0C38LgQuDC4ULhwuJC4sLjguQC5ILlAuWC5gLmgujC6UL ygvMC84L0AvSC9QL1gvYC9oL3AveC+AL4gvkC+YL6AvqC+wMCAwdDDoMWwx3DJ0MuwzhDP0NGQ02DU4N gg2cDbkN1Q4CDgsOEg4fDiUOMA5FDk8OWg5iDnQOdg54DnoOgw6FDpoOrQ67DsUOxw7JDssOzQ7iDu8O +A8KDwwPDg8QDxIPFA8dDycPKRGLEZQRmxGtEbYRuBG9Eb8RwRHOEdYR2BHdEd8R4RHmEegR6hH9EgoS FRIhEiMSJRInEjASMhJ1EncSeRJ7En0SfxKBEoMShRKHEokSixKNEo8SkRKTEpUSlxKZEpsSnRKfEqES oxKlEqcSqRKrEq0SrxKxErMStRK+EskSyxLUEt0S4hLsEvUS9xMAEwkTCxMUEx0THxMoEzETMxM8E0UT RxNQE1kTWxNkE20TbxN4E4ETgxOME5UTlxOgE6kTqxO0E70TvxPIE9ET0xPcE+UT5xPwE/kT+xQEFA0U DxQYFCEUIxQsFDUUNxRAFEkUSxRUFF0UXxRoFHEUcxR8FIUUhxSQFJkUmxSkFK0UrxS4FMEUwxTMFNUU 1xTgFOkU6xT0FP0U/xUIFREVExUcFSUVJxUwFTkVOxVEFU0VTxVYFWEVZhVuFXcVfBWNFY8VmBWaFZ0V phWrFbgVxRXHFcwVzhXQFdUV1xXZFeYV6BXqFfMV9RY4FjoWPBY+FkAWQhZEFkYWSBZKFkwWThZQFlIW VBZWFlgWWhZcFl4WYBZiFmQWZhZoFmoWbBZuFnAWchZ0FnYWeBaJFosWjRaPFqMWrBazFsIWyxbTFtUW 5xbwFvcXBRcMFxUXHhc6F08XWBdaF10XXxdoF20Xdhd7F5wXpBe+F9EX5Rf8GBEYJBgmGCkYKxgtGC8Y MRgzGDUYQhhPGFcYWRhcGGUYahhyGH8YgRiEGJEYkxiYGJoYnBihGKMYpRi6GMYY1BjWGNgY2hjcGOMZ ARkOGRAZHBkxGTMZNRk3GTkZTRlaGVwZYRljGWUZahlsGW4ZehmHGY0ZjxmWGZ8ZpBm7GckZ0xncGecZ 7hoGGhMaHRoqGiwaLho2Gj8aRBpNGlYaYRqGGo8amBqiGqQaphqoGqoarBquGrAauRrSGt8a6BrzGv4b Kxs2GzgbOhs8Gz4bQBtCG0QbTRtWG3EbixuUG50bqhvEG80b1BvvG/gb+hv/HAEcAxwcHCkcMxw7HD0c PxxBHEMcRRxHHEkcXhxgHGIcZBxmHG8ccRx0HHYcqxy4HMsc2BzaHNwc3hzgHOIc5BzmHOgc+xz+HQAd Ah0EHQ0dDx0aHRwdHh0gHSIdJB1JHUsdTR1PHVEdUx1VHVcdYB1iHWUdZx26Hdwd6R3+HhgeNB5PHnce gx6iHrEevR6/HsEeyh7MHs4ezx7RHtoe4x7lHuYe5x7pHuse7R72HwIfGx8nHykfKx8tHy8fMR9WH1gf Wh9cH14fYB9iH2Qfbx94H4EflR+qH6wfrh+wH7Ifyh/TH9wf6h/zH/Uf/iAAIAIgBCAGICsgOiBHIFIg YSBsIHcgeCB6IHwghSCHIJAgmSCbILggxCDJIMsgzSDPINEg0yDlIPYg+CEBIQMhBiETIRUhISE2ITgh OiE8IT4hUCFZIWQheCGKIashsCGyIbQhtiG4IbohvSG/Ickh3iHgIeIh5CHmIf8iFCIWIhgiGiIcIi8i OCJBIkoiTyJdIoIigyKFIocikCKSIpsinSK6IrwiviLAIsIixCLLIuwi7iLwIvIi9CL2IvgjHSMeIyAj IiMrIy0jNiM4I1UjVyNZI1sjXSNfI2QjeSN7I30jfyOBI40jriOwI7IjtCO2I7gjuiPfI+Aj4iPkI+0j 7yPxJA4kECQSJBQkFiQYJCAkQSRDJEUkRyRJJEskTSRiJGQkZiRoJGokdCSBJIMkiCSRJJ4krCTFJOYk 6CTqJOwk7iTwJPIk+yUVJTolPCU+JUAlQiVEJUYlTyVoJXElcyV2JXgljyWpJbUlyiXMJc4l0CXSJd8l 6CXtJfsmFCYWJhgmGiYcJh4mICYiJigmMSY6JkYmXyZoJm0mgCaJJosmoCaiJqQmpiapJqwmryayJrUm uCa7Jtgm5ibwJvonAyciJyQnJicoJyonLCcuJ08nZid4J4MnkietJ8gn4SfjJ+Qn5ifnJ+kn6ifsJ+0n 9if4KAcoCSgLKA0oDygRKBMoFSgpKDAoOyhDKE4oWSheKGAoaShuKHcogCiJKJwosSi+KOIo6CkFKQ4p FSktKTwpWSlbKV0pXylhKWMpZSl2KXgpeil7KX0phimIKZEpkymVKZcpmSmfKaspuCm9Kb8pyCnPKesp +SoEKiEqIyolKigqKiosKi4qTipnKoQqhiqIKosqjSqPKpIqvSrhKv4rACsCKwUrBysJKwwrMytLK2gr aitsK28rcStzK3YrlyuxK9Ir3CveK+Ar4yvmK+gr6yvuLAosEywlLDIsNCw3LDosPSxALE8sYSyGLJws niygLKMspiypLKssriyxLNAs1yzuLPss/S0ALQMtBi0JLSotLC0uLTEtNC02LTktPC1VLWItZC1nLWot bS1wLZktmi23Lbktuy2+LcEtwy3GLe4t/C4VLh4uIC5dLl8uYS5jLmUuZy5pLmsubS5wLnIudC52Lngu ei58Ln4ugC6CLoQuhi6ILooujC6OLpAuki6ULpYumC6hLqMupi60Lr0uvy78Lv4vAC8CLwQvBi8ILwov DC8OLxAvEi8ULxYvGC8aLxwvHi8gLyIvJC8mLygvKi8sLy4vMC8yLzQvNi8/L0EvgC+CL4Qvhi+IL4ov jC+OL5Avki+VL5cvmS+bL50vny+hL6MvpS+nL6kvqy+tL68vsS+zL7Uvty+5L7svvS/GL8gwBzAKMA0w EDATMBYwGTAcMB8wIjAlMCgwKzAuMDEwNDA3MDowPTBAMEMwRjBJMEwwTzBSMFUwWDBbMF4wYTBuMIYw pjCrMLcwxDDYMPkxFzEjMTwxVDFqMYgxrDGzMesx+TIZMi8yTzJjMnkyjTKXMqkyvTLRMuky+zMEMwYz BzMQMxIzEzMcMx4zcTNzM3UzdzN5M3szfTN/M4EzgzOGM4gzizONM5AzkjOUM5YzmDOaM50znzOhM6Mz pTOnM6ozrDOuM7AzsjO0M7czuTO8M74zwDPDM8UzxzPJM9Iz1DQnNCo0LTQwNDM0NjQ5NDw0PzRCNEU0 SDRLNE40UTRUNFc0WjRdNGA0YzRmNGk0bDRvNHI0dTR4NHs0fjSBNIQ0hzSKNI00kDSTNJY0mTScNJ80 oTSkNKY0qDSqNKw0rjSwNLI0tTS3NMA0wjTFNMc0yTTLNM00zzTRNNM01jTYNNs03TTfNOE04zTmNOg0 6jTsNO408DTzNPY0+DT6NQM1BTUGNQ81ETUSNRs1HTUeNSc1LAAAAAAAAAICAAAAAAAABgkAAAAAAAAA AAAAAAAAADU7A treetop-1.6.12/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/keyedobjects.nib000066400000000000000000000405701433777471000303540ustar00rootroot00000000000000bplist00Ô X$versionT$topY$archiverX$objects† Ñ]IB.objectdata€_NSKeyedArchiver¯w 156;<AUVWX ei€„‹›œ´µ½¾ÀÁÂÆÌÚàðô !"#$%&'()*+,-12<DMQTYbmciŒ“–™œŸ¢¥¨«®±´·º½ÀÃÆÉÌÏÒÕØÛÞáäçêíðóõúý+/037;?CEGW\_bK^jqrsv{|„7…‰ŒŽ‘’—˜š©ª«®¹º»¾¿ÁÂÇÑÒ×Ûìôü$,-0569@OWX]`efjstyz€‚…“”›£©ª¯°·¾ÄÅÌÑÒÕØÙáâêëïð¾ñò÷øû   $4>?@ABCDFHINOPQU\ahijkmopqryz{‚ƒ„‹Œ”•–Ÿ ¡¢¨©ª´µ¶·©½ÅO¡ÆÌ{ÎÕÖרøûü=^_`abcdefghijklmnopqrstuvwxyz{|‚­ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöè÷øhùúûüýþU$nullß  !"#$%&'()*+,-./0VNSRootV$class]NSObjectsKeys_NSClassesValues_NSAccessibilityOidsValues]NSConnections[NSNamesKeys[NSFramework]NSClassesKeysZNSOidsKeys]NSNamesValues_NSAccessibilityConnectors]NSFontManager_NSVisibleWindows_NSObjectsValues_NSAccessibilityOidsKeysYNSNextOid\NSOidsValues€v#Hu€â'€GI(s€€&tJÒ234[NSClassName€€XNSObjectÒ789:X$classesZ$classname¢:5^NSCustomObject_IBCocoaFrameworkÒ=>?ZNS.objects€4¡@€ÚBCDEFGHIJKLMNOPQRS+\NSWindowView\NSScreenRect]NSWindowTitleYNSWTFlags]NSWindowClass\NSWindowRect_NSWindowBacking_NSWindowStyleMask[NSViewClass€ €á€à€ $€ €€_{{83, 222}, {1112, 670}}VWindowXNSWindow×YZ[\W]^_`ab^d_NSNextResponderZNSSubviewsXNSvFlags[NSFrameSize[NSSuperview€ €•€ €Þ€ €ßÒ=fg€k¡h€ÞYjklmZ[Wn]opqKstuvwxy^{K{~^NSTabViewItemsYNSTvFlagsWNSFrameVNSFont_NSDrawsBackground_NSAllowTruncatedLabels_NSSelectedTabViewItemZNSDelegate€ €Ý€—€–€€€ € €Ù€ÜÒ=f‚€k¡ƒ€×YlZ[W]h_‡ˆa^h€€•€”€€ €Ò=f€k¢Ž€€ØYl‘[’W]ƒ”•–—{^ƒVNSCellYNSEnabled€€€€! € €_{{1001, 9}, {96, 32}}ÜžŸ ¡¢£¤¥¦§¨©ª«¬­®wޱ²³[NSCellFlags_NSAlternateContents_NSPeriodicInterval^NSButtonFlags2_NSKeyEquivalentZNSContentsYNSSupport]NSControlView_NSPeriodicDelay\NSCellFlags2]NSButtonFlagsþ€€€€€€Èÿÿÿÿ†‚@ÿSRunÔ¶·¸¹º»¼VNSSizeVNSNameXNSfFlags€#@*€\LucidaGrandeÒ78¿m¢m5PQ Ò78ÃĤÄÅ‘5\NSButtonCell\NSActionCellÒ78ÇÈ¥ÈÉÊË5XNSButtonYNSControlVNSView[NSResponderÛYÍlÎZ[W]ÏЃÒÓÔyÕa^ƒØÙ[NSHScrollerXNSsFlags[NSVScroller]NSContentView€€€“€’€€ €€Œ€Ò=fÜ€k£ÙØÒ€€Œ€ÛYláâZ[ãWä]æçèéêëì^îXNSCursorYNScvFlagsYNSDocViewYNSBGColor€€‹€‡€ˆ€  €!€ €s€Ò=fò€k¡ì€!ÝYõö÷ø[\ùWú]qÙüýþÿ^Ù+_NSTextContainerYNSTVFlags\NSSharedData[NSDragTypesYNSMaxSizeXNSMinize€€†€6€r€" €5€„€ €…€€Ò=> €4¯   €#€$€%€&€'€(€)€*€+€,€-€.€/€0€1€2€3_NeXT RTFD pasteboard type_NSStringPboardType_NeXT ruler pasteboard type_NeXT TIFF v4.0 pasteboard type_Apple URL pasteboard type_#CorePasteboardFlavorType 0x6D6F6F76_WebURLsWithTitlesPboardType_#CorePasteboardFlavorType 0x75726C20_Apple PDF pasteboard type_Apple PNG pasteboard type_Apple HTML pasteboard type_NSFilenamesPboardType_1NeXT Encapsulated PostScript v1.2 pasteboard type_NSColor pasteboard type_Apple PICT pasteboard type_NeXT font pasteboard type_*NeXT Rich Text Format v1.0 pasteboard typeÒ78./£/05\NSMutableSetUNSSetZ{1097, 36}Õ345678ì:;YNSTCFlagsZNSTextViewWNSWidth_NSLayoutManager€q€!#@‘$€7Õ=>?q@ABþ+_NSTextContainers]NSTextStorageYNSLMFlags€p€o€8€ÕEFGqHIJK+\NSAttributesXNSString_NSAttributeInfo€n€;€9€l€ÒNOPYNS.string€:_^Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiudaÒ78RS£SF5_NSMutableStringÒ=fV€k¢WX€<€fÓZ=[\_WNS.keys€e¢]^€=€>¢`a€?€d_NSParagraphStyleÓdefghZNSTabStops[NSAlignment€@€cÒ=jk€b¯ lmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹€A€C€D€E€F€G€H€I€J€K€L€M€N€O€P€Q€R€S€T€U€V€W€X€Y€Z€[€\€]€^€_€`€aÒŽZNSLocation€B#Ò78‘’¢’5YNSTextTabÒŽ•€B#@LÒŽ˜€B#@\ÒŽ›€B#@eÒŽž€B#@lÒŽ¡€B#@q€Òޤ€B#@uÒŽ§€B#@x€ÒŽª€B#@|ÒŽ­€B#@€Òް€B#@€Ò޳€B#@ƒ@ÒŽ¶€B#@…ÒŽ¹€B#@†ÀÒŽ¼€B#@ˆ€ÒŽ¿€B#@Š@ÒŽ€B#@ŒÒŽÅ€B#@ÀÒŽÈ€B#@€ÒŽË€B#@ ÒŽ΀B#@‘€ÒŽÑ€B#@’`ÒŽÔ€B#@“@Ҏ׀B#@” ÒŽÚ€B#@•ÒŽÝ€B#@•àÒŽà€B#@–ÀÒŽã€B#@— ÒŽæ€B#@˜€ÒŽé€B#@™`ÒŽì€B#@š@ÒŽï€B#@› Ò78ñò¢ò5WNSArrayÒ78ôb¢b5Ô¶·¸¹÷»ù€#@$€ Ò78ûü¢ü5\NSDictionaryÓZ=[ÿ€e¢]^€=€>¢€g€iÓdegh€h€cÒ=j €b¯ lmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹€A€C€D€E€F€G€H€I€J€K€L€M€N€O€P€Q€R€S€T€U€V€W€X€Y€Z€[€\€]€^€_€`€aÔ¶·¸¹÷-.€€j_LucidaGrande-BoldÒ7812£2ò5^NSMutableArrayÒ456WNS.data€mO "„Ò7889£9:5]NSMutableDataVNSDataÒ78<>¤>=>5_NSMutableAttributedString_NSAttributedStringÒ=fA€k¡ý€6Ò78D6¢65Ò78Fõ¢õ5ØHIJKLMNOP+RîT+VWNSFlags_NSDefaultParagraphStyle_NSInsertionColor_NSBackgroundColor_NSSelectedAttributes_NSMarkedAttributes_NSLinkAttributes€ƒ/€€u€s€v€€ÓXYZh[\NSColorSpaceWNSWhite€tB1Ò78]^¢^5WNSColorÓXYZha€tB0ÓZ=[dg€e¢ef€w€x¢hi€y€}Õ^XklZnþop[NSColorName]NSCatalogName€t€|€{€zVSystem_selectedTextBackgroundColorÓXYZhu€tK0.66666669Õ^XklZRþyp€t€u€~€z_selectedTextColorÓZ=[~€e¢f€€€x¢‚ƒ€€‚[NSUnderlineÓX†Z7ˆUNSRGB€tF0 0 1Ò78Š‹¢‹5_NSTextViewSharedData]{1104, 1e+07}Y{223, 29}Ò784¥4ÊË5VNSText_{{1, 1}, {1097, 566}}Ó“”•–7YNSHotSpot\NSCursorType€Š€‰W{4, -5}Ò78™á¢á5Ò78›œ¤œÊË5ZNSClipViewÙYžl[WŸ] £¤a^¦¨XNSTargetXNSActionYNSPercent€€€€€ €Ž€#?ìIŒ_{{1098, 1}, {15, 566}}\_doScroller:Ò78¬­¥­ÉÊË5ZNSScrollerÛYžlÎ[WŸ]¯ £³7a^¦·¸ZNSCurValue€€€€‘€ €Ž€#?ð#?îBÈ`_{{-100, -100}, {87, 18}}_{{-3, 57}, {1114, 568}}Ò78¼½¤½ÊË5\NSScrollView_{{10, 33}, {1108, 628}}Ò78ÀÊ£ÊË5_{{-8, -10}, {1128, 674}}Ò=fÄ€k¢Å~€˜€ÙÖÈÊÉ^ÊËÌÍhÏÐ\NSIdentifierYNSTabViewWNSLabel€Ø€™€š€€Ö€ÕQ1ÕYlZ[+_ÕÖa€€•€Ô€›Ò=fÙ€k¡Ú€œÝYÍlÎÜÝZÞ[]ÏÐÍàÓâãäåæçèÍêë\NSCornerView_NSHeaderClipView\NSScrollAmts€š€Ï€“€Ó2€¦€£€OA A A˜A˜€š€Í€žÒ=fî€k¥ëêàå䀞€Í€Ï€£€¦ÙYlâZ[ãä]Úæ÷éøëùúÚ€œ€‹€Ì€Ÿ€ €´€œÒ=fþ€k¡ù€ ßYkKÜ[\’ ]  ëu î{ä7a{{Së_NSDraggingSourceMaskForNonLocal\NSHeaderView_NSAllowsTypeSelect_NSIntercellSpacingWidth_NSColumnAutoresizingStyle_NSIntercellSpacingHeight_%NSOutlineViewAutosaveExpandedItemsKey[NSGridColor_NSDraggingSourceMaskForLocal^NSTableColumns[NSRowHeight€ž€ËÿÿÿÿÒÀ€€¢€s €¦#@#@€¡ €È€ž€©#@1[{1097, 595}ÖY[\]å a!åù[NSTableView€£€¥€¤€£€ ÙYlâZ[ãä]Úæ'é(ëúÚ€œ€‹€Ò€Ñ€¢€´€œZ{1097, 17}Ò78./¤/ÊË5_NSTableHeaderViewÕYl[]Ú23aÚ€œ€¨€§€œ_{{1098, 0}, {16, 17}}Ò7878¤8ÊË5]_NSCornerViewÒ=f;€k¤<=>?€ª€º€¾€ÄÙAB5CDEF{HIJKRLMù^NSIsResizeable\NSHeaderCellZNSDataCell^NSResizingMaskZNSMinWidthZNSMaxWidth €¹€«#@nà€²#@0#@@€ ×K¢£¦PQRSTUuV[NSTextColorþ€±€®€¬€­€¯_Class + ModulesÔ¶·¸¹Z»\€#@&€ ÓXYZh_€tK0.33333299Õ^XklZRþcp€t€u€°€z_headerTextColorÒ78gh¥hiÅ‘5_NSTableHeaderCell_NSTextFieldCellØK¢£¤¦Pklúnwùqr!þ@€¸€´€³€€ €¶YText CellÕ^XklZnþwp€t€|€µ€z_controlBackgroundColorÕ^XklZRþ}p€t€u€·€z_controlTextColorÒ78i¤iÅ‘5Ò78ƒ„¢„5]NSTableColumnÙAB5CDEF{Hˆ‰ŠR‹Mù €¹€»#@H€€½#@D€ ×K¢£¦PQRSUuV€±€®€¼€­€¯VOffsetØK¢£¤¦Pklúnwùqr€¸€´€³€€ €¶ÙAB5CDEF{HžŸ h÷¡ù €¹€¿#@|0€Ã#Gïÿÿ € ×K¢£¦PQR¥¦UuV€±€Á€À€­€¯TTextÕ^XklZîþ­p€t€s€Â€z[headerColorØK¢£¤¦Pklúnwùqr€¸€´€³€€ €¶ÙAB5CDEF{Hº»¼h÷¡ù €¹€Å#@u €Ç€ ×K¢£¦PQR¥ÁUuV€±€Á€Æ€­€¯WMethodsØK¢£¤¦Pklúnwùqr€¸€´€³€€ €¶Õ^XklZÎþÏp€t€Ê€É€zYgridColorÓXYZhÔ€tD0.5Ò78Öצ×ÉÊË5]NSOutlineView_{{1, 17}, {1097, 595}}ØYžl[Ÿ] ÚÚ£Ýa¦Úà€œ€œ€€Î€Ž€œ#?ïò;`_{{1098, 17}, {15, 595}}ÙYžlÎ[Ÿ] ÚÚ£æ7a¦Ú逜€œ€€Ð€Ž€œ#?ïøŠ_{{1, 612}, {1097, 15}}Ò=fí€k¡€¢_{{1, 0}, {1097, 17}}_{{-3, -3}, {1114, 628}}[Syntax TreeÕ^XklZnþõp€t€|€×€z\controlColorÒ78ùú¢ú5]NSTabViewItemÖÈÊÉ^ÊËýƒhπ؀ڀ€€Ö€ÛQ2UInputÒ78ɤÉÊË5[{1112, 670}_{{0, 0}, {1680, 1028}}Ò78  ¢ 5_NSWindowTemplateÒ=f €kª€ã€ô€ÿ ×Ê !>#R]NSDestinationYNSKeyPathYNSBindingXNSSource_NSNibBindingConnectorVersion€ó€ä€ò€ñ€¾€ðØ%&'()*+,{.{0{2{_NSPreservesSelection__NSManagedProxyZNSEditable^NSDeclaredKeys_NSSelectsInsertedObjects_NSTreeContentChildrenKey_NSAvoidsEmptySelection€ï €ì €å €î Ò=f6€k§789:;ª=€æ€ç€è€é€ê€€ë_class_and_modulesVoffsetZtext_valueWmethodsZcontrollerZgetIndexesÑE€íÒ78G&¢&5XelementsÒ78JK¤KLM5_NSTreeController_NSObjectController\NSController_!value: arrangedObjects.text_valueUvalue_arrangedObjects.text_valueÒ78RS£ST5_NSNibBindingConnector^NSNibConnector×ÊXYZ[R€ó€€þ€ý€õ€üÔ&'(]^{`€û€ú €öÒ=fc€k¤de;g€÷€ø€ê€ùUinput[syntax_tree\selected_tabÑE€íÒ78nL£LM5_contentObject: parameters]contentObjectZparameters×Êu!=xR€ó€ä€ñ€º_value: arrangedObjects.offset_arrangedObjects.offset×Ê~!<R€ó€ä€ñ€ª_(value: arrangedObjects.class_and_modules_!arrangedObjects.class_and_modules×ÊZ‡YŠR€ó€õ€ý€ä_$contentObject: selection.syntax_tree_selection.syntax_tree×Ê!?“R€ó€ä €ñ€Ä _value: arrangedObjects.methods_arrangedObjects.methodsØÊ—Zš›ŽžRYNSOptions€ó€õ € _argument: selection.inputXargument_selection.inputÓZ=[¤¦€e¡¥¡§^NSSelectorName_returnArgument:Ù«Ê—Z®¯Ž²³R_NSPreviousConnector€ó€õ €_target: selection.controllerVtarget_selection.controllerÓZ=[¹»€e¡¥¡¼ØÊ—ZÀÁìÃÄR€ó€õ€!_value: selection.inputÓZ=[ÈÊ€e¡É¡Ë_&NSAlwaysPresentsApplicationModalAlerts ×ÊZÑÒhÔR€ó€õ"!€ _%selectedLabel: selection.selected_tab]selectedLabel_selection.selected_tabÒ=jÚ€b¯¼=ÍÚKŽ<Åã?~>Šhƒù ØKìàê@Z–Ҁǀº€š€œ€ €€ª€˜$€Ä€Ù€¾€½€€€ €€Ã€Œ€²€¢€!€Ï€Í€€õ€€€äÒ23ú€%]NSApplicationÒ=jþ€b¯?ùÅÍ@ƒùhùhù=K~Úƒ><ÚÚÚŽ€Ä€ €˜€š€€€ €€€ €€ €º€ €Ù€œ€€¾€€ª€œ€€œ€œ€€€€€Ò=j€b¯=¼ÍÚKŽ<Åã?~>ŠhƒùKØ àêì@Z–Ò€€º€Ç€š€œ€ €€ª€˜$€Ä€Ù€¾€½€€€ €€²€Œ€Ã€¢€Ï€Í€!€€õ€€€äÒ=j?€b¯@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\])*+,-./0123456789:;<=>?@ABCDEF\File's Owner_Table Column (Offset)_Text Field Cell (Text Cell)-2TView[Scroll View\Content View_Push Button (Run)_Table Column (Class + Modules)_Tab View Item (Syntax Tree)[Application_Table Column (Methods)_Tab View Item (Input)_Table Column (Text)_Text Field Cell (Text Cell)_!Top Tab View (Syntax Tree, Input)VView-1_5Outline View (Class + Modules, Offset, Text, Methods)]Scroll View-1_Text Field Cell (Text Cell)-1_Vertical Scroller-1_Text Field Cell (Text Cell)-3_Table Header View_Horizontal Scroller_Vertical ScrollerYText View_Window (Window)_Object Controller_Button Cell (Run)_Horizontal Scroller-1_Tree ControllerÒ=j~€b Ò=j€b Ò=j„€b¯(¼=ÍÚKŽ<Åã?~>Šhƒù ØKìàê@Z–Ҁ ǀº€š€œ€ €€ª€˜$€Ä€Ù€¾€½€€€ €€Ã€Œ€²€ÿ€¢€!€Ï€Í€€õ€ €€ô€äÒ=j¯€b¯(°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrôëåØßÓÝä ÕÿÿÿÿÿÿÿýêÖèæÔ×õâéçðòìáàÒJÞHÒ=f€k Ò=j€b Ò=j€b Ò78 ¢ 5^NSIBObjectData"'1:?DRTfX^©°·Å×ó '2@\j}©³ÀÂÅÈËÎÐÓÕØÛÞáãåèëîñú %05DW`kmpr›¨µÃÍÛèú "')+-/1LS\y‹–Ÿ«·¹»½ÀÂÄÆÏÑÔÖ(07Kd|‡‰‹‘“•—™šœŸ¡ª¬¯±ÎÐÒÔÖØÚãåêìî "$&(+,.0Hy…›°¿ÑÜæô   ! & ( * , 1 3 5 7 9 ; @ I M ^ e l u w € ‚ … ’ ›   ¡ £ ¬ µ Â Ï Ø ã ì ö ý 6 B K W e g i k m o q s u w € ‚ ‰ ‹ ¼ Å Ï Ù ã å ç é ë í ï ò ô ö ø ú    ? Q [ h t ~ ‡ ‰ ‹ ‘ “ – ˜ š œ ž   ¢ « ­ Ò Ô Ö Ø Ú Ü Þ à â ä æ è ê ì î ð ò ô  % B c  ¥ à é  ! > V Š ¤ Á Ý '-8MWbj|~€‚‹¢µÃÍÏÑÓÕê÷%/1“œ£µ¾ÀÅÇÉÖÞàåçéîðò)+-/8:}ƒ…‡‰‹‘“•—™›Ÿ¡£¥§©«­¯±³µ·¹»½ÆÑÓÜåêôýÿ%'09;DMOXacluw€‰‹”Ÿ¨±³¼ÅÇÐÙÛäíïø  )+4=?HQS\egpy{„˜¡£¬µ·ÀÉËÔÝßèñóü$-/8ACLUW`inv„•— ¢¥®³ÀÍÏÔÖØÝßáîðòûý@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~€‘“•—«´»ÊÓÛÝïøÿ &BW`begpu~ƒ¤¬ÆÙí,.13579;=JW_admrz‡‰Œ™› ¢¤©«­ÂÎÜÞàâäë $9;=?AUbdikmrtv‚•—ž§¬ÃÑÛäïö%246>GLU^iŽ— ª¬®°²´¶¸ÁÚçðû3>@BDFHJLU^y“œ¥²ÌÕÜ÷  $1;CEGIKMOQfhjlnwy|~³ÀÓàâäæèêìîð  "$&(*,QSUWY[]_hjmoÂäñ <W‹ª¹ÅÇÉÒÔÖ×Ùâëíîïñóõþ #/13579^`bdfhjlw€‰²´¶¸ºÒÛäòûý    3 B O Z i t  € ‚ „ ˜ ¡ £ À Ì Ñ Ó Õ × Ù Û í þ!! ! !!!!)!>!@!B!D!F!X!a!l!€!’!³!¸!º!¼!¾!À!Â!Å!Ç!Ñ!æ!è!ê!ì!î"""" """$"7"@"I"R"W"e"Š"‹"""˜"š"£"¥"Â"Ä"Æ"È"Ê"Ì"Ó"ô"ö"ø"ú"ü"þ##%#&#(#*#3#5#>#@#]#_#a#c#e#g#l##ƒ#…#‡#‰#•#¶#¸#º#¼#¾#À#Â#ç#è#ê#ì#õ#÷#ù$$$$$$ $($I$K$M$O$Q$S$U$j$l$n$p$r$|$‰$‹$$™$¦$´$Í$î$ð$ò$ô$ö$ø$ú%%%B%D%F%H%J%L%N%W%p%y%{%~%€%—%±%½%Ò%Ô%Ö%Ø%Ú%ç%ð%õ&&&& &"&$&&&(&*&0&9&B&N&g&p&u&ˆ&‘&“&¨&ª&¬&®&±&´&·&º&½&À&Ã&à&î&ø'' '*','.'0'2'4'6'W'n'€'‹'š'µ'Ð'é'ë'ì'î'ï'ñ'ò'ô'õ'þ((((((((((1(8(C(K(V(a(f(h(q(v((ˆ(‘(¤(¹(Æ(ê(ð) )))5)D)a)c)e)g)i)k)m)~)€)‚)ƒ)…)Ž))™)›))Ÿ)¡)§)³)À)Å)Ç)Ð)×)ó** *)*+*-*0*2*4*7*W*p***‘*”*–*˜*›*Æ*ê++ + +++++<+T+q+s+u+x+z+|++ +º+Û+å+ç+é+ì+ï+ñ+ô+÷,,,.,;,=,@,C,F,I,X,j,,¥,§,©,¬,¯,²,´,·,º,Ù,à,÷--- - ---3-5-7-:-=-?-B-E-^-k-m-p-s-v-y-¢-£-À-Â-Ä-Ç-Ê-Ì-Ï-÷...'.).f.h.j.l.n.p.r.t.v.y.{.}...ƒ.….‡.‰.‹...‘.“.•.—.™.›..Ÿ.¡.ª.¬.¯.½.Æ.È/// / / //////////!/#/%/'/)/+/-///1/3/5/7/9/;/=/?/H/J/‰/‹///‘/“/•/—/™/›/ž/ /¢/¤/¦/¨/ª/¬/®/°/²/´/¶/¸/º/¼/¾/À/Â/Ä/Æ/Ï/Ñ0000000"0%0(0+0.0104070:0=0@0C0F0I0L0O0R0U0X0[0^0a0d0g0j0w00¯0´0À0Í0á11 1,1E1]1s1‘1µ1¼1ô22"282X2l2‚2–2 2²2Æ2Ú2ò33 333333%3'3z3|3~3€3‚3„3†3ˆ3Š3Œ33‘3”3–3™3›33Ÿ3¡3£3¦3¨3ª3¬3®3°3³3µ3·3¹3»3½3À3Â3Å3Ç3É3Ì3Î3Ð3Ò3Û3Ý404346494<4?4B4E4H4K4N4Q4T4W4Z4]4`4c4f4i4l4o4r4u4x4{4~44„4‡4Š444“4–4™4œ4Ÿ4¢4¥4¨4ª4­4¯4±4³4µ4·4¹4»4¾4À4É4Ë4Î4Ð4Ò4Ô4Ö4Ø4Ú4Ü4ß4á4ä4æ4è4ê4ì4ï4ñ4ó4õ4÷4ù4ü4ÿ555 555555$5&5'5055 5Dtreetop-1.6.12/Treetop.tmbundle/Support/syntax_tree_viewer.rb000066400000000000000000000055601433777471000244700ustar00rootroot00000000000000#!/usr/bin/env ruby require 'rubygems' require 'treetop' require "#{ENV["TM_SUPPORT_PATH"]}/lib/ui" # Monkey-patch SyntaxNode in a gross violation of its privacy. module Treetop module Runtime class SyntaxNode def interesting_methods # Copied from SyntaxNode#inspect methods-[extension_modules.last ? extension_modules.last.methods : nil]-self.class.instance_methods end def to_hash { "class_and_modules" => self.class.to_s.sub(/.*:/,'') + extension_modules.map{|m| "+"+m.to_s.sub(/.*:/,'')}*"", "offset" => interval.first, "text_value" => text_value, "methods" => interesting_methods * ", ", "elements" => elements ? elements.map {|e| e.to_hash} : [] } end end end end class SyntaxTreeViewer def self.nib_path File.dirname(__FILE__) + "/SyntaxTreeViewer.nib" end def self.new_with_unknown_grammar parser = if ENV['TM_SCOPE'] =~ /source\.ruby/ && ENV['TM_SELECTED_TEXT'] eval(ENV['TM_SELECTED_TEXT']) else parser_file = if ENV['TM_SCOPE'] =~ /source\.treetop/ ENV['TM_FILEPATH'] else ask_for_grammar end return unless parser_file Treetop.load(parser_file) end new(parser.new) end def self.ask_for_grammar files = TextMate::UI.request_file("title" => "Select a Grammar File") if files.nil? || files.empty? nil else files[0] end end def self.nib_path File.dirname(__FILE__) + "/nibs/SyntaxTreeViewer.nib" end def initialize(_parser) @parser = _parser run_parser! end def dialog TextMate::UI.dialog( :nib => self.class.nib_path, :parameters => parameters ) do |d| d.wait_for_input do |params| if params["returnArgument"] self.input = params["returnArgument"] run_parser! d.parameters = parameters true else false end end end end def input ENV['TM_TREETOP_SYNTAX_VIEWER_INPUT'] ||= "" end def input=(new_input) ENV['TM_TREETOP_SYNTAX_VIEWER_INPUT'] = new_input end private def run_parser! if input && !input.empty? @syntax_tree = @parser.parse(input) TextMate::UI.alert(:warning, "Parse error", @parser.failure_reason) unless @syntax_tree end end def parameters p = { "input" => input, "syntax_tree" => @syntax_tree ? @syntax_tree.to_hash : {}, "selected_tab" => !input.empty? && @syntax_tree ? "Syntax Tree" : "Input" } puts p p end end if __FILE__ == $0 Dir.chdir("/Users/aobrien/Work/canopy/play/sparql/") require "/Users/aobrien/Work/canopy/play/sparql/lib/sparql" v = SyntaxTreeViewer.new(SparqlParser.new) v.input = %{PREFIX foaf: SELECT ?foo WHERE { ?x foaf:knows ?y . ?z foaf:knows ?x .}} v.dialog end treetop-1.6.12/Treetop.tmbundle/Syntaxes/000077500000000000000000000000001433777471000203515ustar00rootroot00000000000000treetop-1.6.12/Treetop.tmbundle/Syntaxes/Treetop Grammar.tmLanguage000066400000000000000000000176271433777471000253650ustar00rootroot00000000000000 fileTypes treetop tt foldingStartMarker (module|grammer|rule).*$ foldingStopMarker ^\s*end keyEquivalent ^~T name Treetop Grammar patterns include #comment begin ^(\s*)(module) ([A-Z]\w+) beginCaptures 2 name keyword.begin.module.treetop 3 name entity.name.module.treetop end ^\1(end)$ endCaptures 1 name keyword.end.module.treetop name meta.module.treetop patterns include $self begin ^(\s*)(grammar) ([A-Z]\w+) beginCaptures 2 name keyword.begin.grammar.treetop 3 name entity.name.grammar.treetop end ^\1(end)$ endCaptures 1 name keyword.end.grammar.treetop name meta.grammar.treetop patterns include $self captures 1 name keyword.include.treetop 2 name entity.name.include.treetop match (include)\s+(\w+) name meta.include.treetop begin \b(rule)\b (\w+) beginCaptures 1 name keyword.begin.rule.treetop 2 name entity.name.rule.treetop end ^\s+\bend\b\s*$ endCaptures 0 name keyword.end.rule.treetop name meta.rule.treetop patterns include #comment include #strings include #character-class match \/ name keyword.operator.or.treetop match <\w+?> name variable.class-instance.treetop match \w+?: name support.operand.treetop begin \{ end \} name meta.embedded-ruby.treetop patterns include source.ruby repository character-class patterns match \\[wWsSdDhH]|\. name constant.character.character-class.regexp match \\. name constant.character.escape.backslash.regexp begin (\[)(\^)? beginCaptures 1 name punctuation.definition.character-class.regexp 2 name keyword.operator.negation.regexp end (\]) endCaptures 1 name punctuation.definition.character-class.regexp name constant.other.character-class.set.regexp patterns include #character-class captures 2 name constant.character.escape.backslash.regexp 4 name constant.character.escape.backslash.regexp match (.|(\\.))\-([^\]]|(\\.)) name constant.other.character-class.range.regexp match && name keyword.operator.intersection.regexp comment captures 1 name punctuation.definition.comment.treetop match (#).*$\n? name comment.line.number-sign.treetop strings patterns begin ' beginCaptures 0 name punctuation.definition.string.begin.treetop end ' endCaptures 0 name punctuation.definition.string.end.treetop name string.quoted.single.treetop patterns match \\(u\h{4}|.) name constant.character.escape.antlr begin " beginCaptures 0 name punctuation.definition.string.begin.treetop end " endCaptures 0 name punctuation.definition.string.end.treetop name string.quoted.double.treetop scopeName source.treetop uuid A1604A34-0B73-4D5A-9499-87D881DFA8D5 treetop-1.6.12/Treetop.tmbundle/info.plist000066400000000000000000000004571433777471000205510ustar00rootroot00000000000000 name Treetop uuid 83A8B700-143D-4BD6-B4EA-D73796E8F883 treetop-1.6.12/benchmark/000077500000000000000000000000001433777471000152325ustar00rootroot00000000000000treetop-1.6.12/benchmark/seqpar.gnuplot000066400000000000000000000005311433777471000201360ustar00rootroot00000000000000f1(x) = a*x a = 0.5 fit f1(x) 'before.dat' using 1:2 via a f2(x) = b*x b = 0.5 fit f2(x) 'after.dat' using 1:2 via b set xlabel "Length of input" set ylabel "CPU time to parse" plot a*x title 'a*x (Before)',\ b*x title 'b*x (After)',\ "before.dat" using 1:2 title 'Before', \ "after.dat" using 1:2 title 'After'treetop-1.6.12/benchmark/seqpar.treetop000066400000000000000000000004751433777471000201370ustar00rootroot00000000000000grammar SeqPar rule statement 'par ' (statement ' ')+ 'end' / 'sequence' ' ' (statement ' ')+ 'end' / 'seq' ' ' (statement ' ')+ 'end' / ('fit' [\s] (statement ' ')+ 'end') { def foo "foo" end } / 'art'+ [ ] (statement ' ')+ 'end' / [A-Z] [a-zA-z0-9]* end endtreetop-1.6.12/benchmark/seqpar_benchmark.rb000066400000000000000000000061231433777471000210660ustar00rootroot00000000000000# Benchmarking written by Bernard Lambeau, improved by Jason Garber # # To test your optimizations: # 1. Run ruby seqpar_benchmark.rb # 2. cp after.dat before.dat # 3. Make your modifications to the treetop code # 4. Run ruby seqpar_benchmark.rb # 5. Run gnuplot seqpar.gnuplot # $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib') require 'treetop' require 'benchmark' srand(47562) # So it runs the same each time class Array; def sum; inject( nil ) { |sum,x| sum ? sum+x : x }; end; end class Array; def mean; sum / size; end; end class SeqParBenchmark OPERATORS = ["seq", "fit", "art"*5, "par", "sequence"] # Loads the grammar and returns a parser def initialize compiler = Treetop::Compiler::GrammarCompiler.new @where = File.expand_path(File.dirname(__FILE__)) grammar = File.join(@where, 'seqpar.treetop') output = File.join(@where, 'seqpar.rb') compiler.compile(grammar, output) load output File.delete(output) @parser = SeqParParser.new end # Checks the grammar def check ["Task", "seq Task end", "par Task end", "seq Task Task end", "par Task Task end", "par seq Task end Task end", "par seq seq Task end end Task end", "seq Task par seq Task end Task end Task end"].each do |input| raise ParseError.new(@parser) if @parser.parse(input).nil? end end # Generates an input text def generate(depth=0) return "Task" if depth>7 return "seq #{generate(depth+1)} end" if depth==0 which = rand(OPERATORS.length) case which when 0 "Task" else raise unless OPERATORS[which] buffer = "#{OPERATORS[which]} " 0.upto(rand(4)+1) do buffer << generate(depth+1) << " " end buffer << "end" buffer end end # Launches benchmarking def benchmark number_by_size = Hash.new {|h,k| h[k] = 0} time_by_size = Hash.new {|h,k| h[k] = 0} 0.upto(250) do |i| input = generate length = input.length puts "Launching #{i}: #{input.length}" # puts input tms = Benchmark.measure { @parser.parse(input) } number_by_size[length] += 1 time_by_size[length] += tms.total*1000 end # puts number_by_size.inspect # puts time_by_size.inspect File.open(File.join(@where, 'after.dat'), 'w') do |dat| number_by_size.keys.sort.each do |size| dat << "#{size} #{(time_by_size[size]/number_by_size[size]).truncate}\n" end end if File.exist?(File.join(@where, 'before.dat')) before = {} performance_increases = [] File.foreach(File.join(@where, 'before.dat')) do |line| size, time = line.split(' ') before[size] = time end File.foreach(File.join(@where, 'after.dat')) do |line| size, time = line.split(' ') performance_increases << (before[size].to_f - time.to_f) / before[size].to_f unless time == "0" || before[size] == "0" end puts "Average performance increase: #{(performance_increases.mean * 100 * 10).round / 10.0}%" end end end SeqParBenchmark.new.benchmarktreetop-1.6.12/bin/000077500000000000000000000000001433777471000140505ustar00rootroot00000000000000treetop-1.6.12/bin/tt000077500000000000000000000067111433777471000144320ustar00rootroot00000000000000#!/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.6.12/doc/000077500000000000000000000000001433777471000140455ustar00rootroot00000000000000treetop-1.6.12/doc/contributing_and_planned_features.markdown000066400000000000000000000130671433777471000245500ustar00rootroot00000000000000#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.6.12/doc/grammar_composition.markdown000066400000000000000000000043521433777471000216660ustar00rootroot00000000000000#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.6.12/doc/index.markdown000066400000000000000000000061731433777471000167270ustar00rootroot00000000000000

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.6.12/doc/pitfalls_and_advanced_techniques.markdown000066400000000000000000000073461433777471000243400ustar00rootroot00000000000000#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. ## Poor Performance with Large Unicode Strings Treetop may perform poorly when parsing very large (more than 100KB) unicode strings. This is due to the fact that substring lookups on Ruby unicode strings are linear-time operations, and not constant-time operations like they are on ASCII encoded strings. This means that parse times for larger strings can be exponentially worse than for smaller strings. If your input and grammar only expect ASCII strings, you can achieve significant performance improvements for large strings by re-encoding them to ASCII using `input.encode(Encoding::US_ASCII)`. See [this issue on GitHub](https://github.com/cjheath/treetop/issues/31) for more information and other possible workarounds for unicode strings. treetop-1.6.12/doc/semantic_interpretation.markdown000066400000000000000000000163751433777471000225570ustar00rootroot00000000000000#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.6.12/doc/syntactic_recognition.markdown000066400000000000000000000203461433777471000222170ustar00rootroot00000000000000#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` or `class` statements, which provides a namespace for the generated Ruby parser. Note that you cannot specify a superclass for a class, so if your class has a superclass, it must be declared elsewhere and loaded first. Treetop will emit a module called `GrammarName` and a parser class called `GrammarNameParser` (in the 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. Treetop parsers will try to match the first rule defined in the grammar, unless you pass an optional parameter to set a different top rule. ##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. There's an example of how to use semantic predicates to parse a language with white-space indented blocks in the examples directory. treetop-1.6.12/doc/tt.1000066400000000000000000000046131433777471000145620ustar00rootroot00000000000000.\" treetop - Bringing the simplicity of Ruby to syntactic analysis .\" .\" Copyright (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. .TH tt 1 2013-06-19 Treetop "Treetop v1.4.14" .SH NAME tt \- Compile a treetop grammar file to ruby source code .SH SYNOPSIS .B tt .RI [ options "] " grammar_file "[.treetop|.tt] ..." .SH DESCRIPTION The .B tt program is a command-line script to compile .treetop files into Ruby source code. The .B tt program takes a 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 specify the name of the output file. Note: while treetop grammar files .B must have a supported filename extensions, (.treetop or .tt), the extension name is not required when calling the compiler with grammar file names. .SH OPTIONS .TP 4 .BI "\-o, \-\-output" " FILENAME" Write parser source to .I FILENAME. .TP 4 .B \-f, \-\-force Overwrite existing output file(s) .TP 4 .B \-v, \-\-version Show Treetop version .TP 4 .B \-h, \-\-help .SH EXAMPLES .TP 4 1 grammar -> 1 parser source tt foo.tt .TP 4 2 grammars -> 2 separate parsers tt foo bar.treetop .TP 4 Alternately named output file tt \-o alterate_name.rb foo .SH SEE ALSO The treetop website: .B http://cjheath.github.io/treetop/ treetop-1.6.12/doc/using_in_ruby.markdown000066400000000000000000000107431433777471000204720ustar00rootroot00000000000000#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.6.12/examples/000077500000000000000000000000001433777471000151165ustar00rootroot00000000000000treetop-1.6.12/examples/indented_blocks/000077500000000000000000000000001433777471000202455ustar00rootroot00000000000000treetop-1.6.12/examples/indented_blocks/indented_blocks.tt000066400000000000000000000030641433777471000237500ustar00rootroot00000000000000grammar IndentedBlocks rule top # Initialise the indent stack with a sentinel: &{|s| @indents = [-1] } foo:('foo'?) nested_blocks { def inspect nested_blocks.inspect end } end rule nested_blocks ( # Do not try to extract this semantic predicate into a new rule. # It will be memo-ized incorrectly because @indents.last will change. !{|s| # Peek at the following indentation: save = index; i = _nt_indentation; index = save # We're closing if the indentation is less or the same as our enclosing block's: closing = i.text_value.length <= @indents.last } block )* { def inspect elements.map{|e| e.block.inspect}*"\n" end } end rule block indented_line # The block's opening line &{|s| # Push the indent level to the stack level = s[0].indentation.text_value.length @indents << level true } nested_blocks # Parse any nested blocks &{|s| # Pop the indent stack # Note that under no circumstances should "nested_blocks" fail, or the stack will be mis-aligned @indents.pop true } { def inspect indented_line.inspect + (nested_blocks.elements.size > 0 ? ( "\n{\n" + nested_blocks.elements.map { |content| content.block.inspect+"\n" }*'' + "}" ) : "") end } end rule indented_line indentation text:((!"\n" .)*) "\n" { def inspect text.text_value end } end rule indentation ' '* end end treetop-1.6.12/examples/indented_blocks/indented_blocks_test.rb000066400000000000000000000007221433777471000247610ustar00rootroot00000000000000require 'polyglot' require 'byebug' require 'treetop' require 'indented_blocks' parser = IndentedBlocksParser.new input = < 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.6.12/examples/lambda_calculus/arithmetic_node_classes.rb000066400000000000000000000003721433777471000254330ustar00rootroot00000000000000module 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.6.12/examples/lambda_calculus/arithmetic_test.rb000066400000000000000000000024561433777471000237550ustar00rootroot00000000000000dir = 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.6.12/examples/lambda_calculus/lambda_calculus.rb000066400000000000000000000331351433777471000236760ustar00rootroot00000000000000module 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.6.12/examples/lambda_calculus/lambda_calculus.treetop000066400000000000000000000051651433777471000247570ustar00rootroot00000000000000grammar 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.6.12/examples/lambda_calculus/lambda_calculus_node_classes.rb000066400000000000000000000001271433777471000264130ustar00rootroot00000000000000module LambdaCalculus class Application < Treetop::Runtime::SyntaxNode end endtreetop-1.6.12/examples/lambda_calculus/lambda_calculus_test.rb000066400000000000000000000046421433777471000247360ustar00rootroot00000000000000dir = 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.6.12/examples/lambda_calculus/test_helper.rb000066400000000000000000000005121433777471000230720ustar00rootroot00000000000000require '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.6.12/lib/000077500000000000000000000000001433777471000140465ustar00rootroot00000000000000treetop-1.6.12/lib/treetop.rb000066400000000000000000000001201433777471000160460ustar00rootroot00000000000000require 'treetop/runtime' require 'treetop/compiler' require 'treetop/polyglot' treetop-1.6.12/lib/treetop/000077500000000000000000000000001433777471000155305ustar00rootroot00000000000000treetop-1.6.12/lib/treetop/bootstrap_gen_1_metagrammar.rb000066400000000000000000000036631433777471000235300ustar00rootroot00000000000000# 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.6.12/lib/treetop/compiler.rb000066400000000000000000000004351433777471000176710ustar00rootroot00000000000000require '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.6.12/lib/treetop/compiler/000077500000000000000000000000001433777471000173425ustar00rootroot00000000000000treetop-1.6.12/lib/treetop/compiler/grammar_compiler.rb000066400000000000000000000031471433777471000232140ustar00rootroot00000000000000module 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) unless path =~ Treetop::Polyglot::VALID_GRAMMAR_EXT_REGEXP ext = Treetop::Polyglot::VALID_GRAMMAR_EXT.select {|ext| File.exist?(path+".#{ext}")}.shift path += ".#{ext}" unless ext.nil? end File.open(path) do |source_file| source = source_file.read source.gsub!(/\b__FILE__\b/, %Q{"#{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.6.12/lib/treetop/compiler/lexical_address_space.rb000066400000000000000000000004201433777471000241640ustar00rootroot00000000000000module 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.6.12/lib/treetop/compiler/metagrammar.rb000066400000000000000000003403711433777471000221740ustar00rootroot00000000000000# 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 spacing elements[1] end def module_or_grammar elements[2] end def suffix elements[3] end end module TreetopFile2 def compile requires.text_value + spacing.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 node_cache[:treetop_file][index] = 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 spacing 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 node_cache[:require_statement][index] = 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 (match_len = has_terminal?("require", false, index)) r3 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('"require"') r3 = nil end s0 << r3 if r3 s4, i4 = [], index loop do if has_terminal?(@regexps[gr = '\A[ \\t]'] ||= Regexp.new(gr), :regexp, index) r5 = true @index += 1 else terminal_parse_failure('[ \\t]') 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?(@regexps[gr = '\A[^\\n\\r]'] ||= Regexp.new(gr), :regexp, index) r7 = true @index += 1 else terminal_parse_failure('[^\\n\\r]') 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?(@regexps[gr = '\A[\\n\\r]'] ||= Regexp.new(gr), :regexp, index) r8 = true @index += 1 else terminal_parse_failure('[\\n\\r]') 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 node_cache[:module_or_grammar][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_grammar if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 module_prefix elements[0] end def module_contents elements[1] end def suffix elements[2] end end module ModuleDeclaration5 def compile module_prefix.text_value + module_contents.compile + suffix.text_value end def parser_name module_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 node_cache[:module_declaration][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1, s1 = index, [] i2 = index if (match_len = has_terminal?('module', false, index)) r3 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'module\'') r3 = nil end if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true r2 = r3 else if (match_len = has_terminal?('class', false, index)) r4 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'class\'') r4 = nil end if r4 r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true r2 = r4 else @index = i2 r2 = nil end end s1 << r2 if r2 r5 = _nt_space s1 << r5 if r5 i6, s6 = index, [] if has_terminal?(@regexps[gr = '\A[A-Z]'] ||= Regexp.new(gr), :regexp, index) r7 = true @index += 1 else terminal_parse_failure('[A-Z]') r7 = nil end s6 << r7 if r7 s8, i8 = [], index loop do r9 = _nt_alphanumeric_char if r9 s8 << r9 else break end end r8 = instantiate_node(SyntaxNode,input, i8...index, s8) s6 << r8 if r8 s10, i10 = [], index loop do i11, s11 = index, [] if (match_len = has_terminal?('::', false, index)) r12 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'::\'') r12 = nil end s11 << r12 if r12 if has_terminal?(@regexps[gr = '\A[A-Z]'] ||= Regexp.new(gr), :regexp, index) r13 = true @index += 1 else terminal_parse_failure('[A-Z]') r13 = nil end s11 << r13 if r13 s14, i14 = [], index loop do r15 = _nt_alphanumeric_char if r15 s14 << r15 else break end end r14 = instantiate_node(SyntaxNode,input, i14...index, s14) s11 << r14 end end if s11.last r11 = instantiate_node(SyntaxNode,input, i11...index, s11) r11.extend(ModuleDeclaration0) else @index = i11 r11 = nil end if r11 s10 << r11 else break end end r10 = instantiate_node(SyntaxNode,input, i10...index, s10) s6 << r10 end end if s6.last r6 = instantiate_node(SyntaxNode,input, i6...index, s6) r6.extend(ModuleDeclaration1) else @index = i6 r6 = nil end s1 << r6 if r6 r16 = _nt_space s1 << r16 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 i17 = index r18 = _nt_module_declaration if r18 r18 = SyntaxNode.new(input, (index-1)...index) if r18 == true r17 = r18 else r19 = _nt_grammar if r19 r19 = SyntaxNode.new(input, (index-1)...index) if r19 == true r17 = r19 else @index = i17 r17 = nil end end s0 << r17 if r17 i20, s20 = index, [] r21 = _nt_space s20 << r21 if r21 if (match_len = has_terminal?('end', false, index)) r22 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'end\'') r22 = nil end s20 << r22 end if s20.last r20 = instantiate_node(SyntaxNode,input, i20...index, s20) r20.extend(ModuleDeclaration3) else @index = i20 r20 = nil end s0 << r20 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 node_cache[:grammar][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('grammar', false, index)) r1 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 (match_len = has_terminal?('do', false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 (match_len = has_terminal?('end', false, index)) r12 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 node_cache[:grammar_name][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?(@regexps[gr = '\A[A-Z]'] ||= Regexp.new(gr), :regexp, index) r1 = true @index += 1 else terminal_parse_failure('[A-Z]') 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 node_cache[:declaration_sequence][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else if (match_len = has_terminal?('', false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) r7.extend(DeclarationSequence3) @index += match_len else terminal_parse_failure('\'\'') r7 = nil end if r7 r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true 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 node_cache[:declaration][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_include_declaration if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 node_cache[:include_declaration][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('include', false, index)) r1 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'include\'') r1 = nil end s0 << r1 if r1 r2 = _nt_space s0 << r2 if r2 if has_terminal?(@regexps[gr = '\A[A-Z]'] ||= Regexp.new(gr), :regexp, index) r3 = true @index += 1 else terminal_parse_failure('[A-Z]') r3 = nil end s0 << r3 if r3 s4, i4 = [], index loop do i5 = index r6 = _nt_alphanumeric_char if r6 r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true r5 = r6 else if (match_len = has_terminal?('::', false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'::\'') r7 = nil end if r7 r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true 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 node_cache[:parsing_rule][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('rule', false, index)) r1 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 (match_len = has_terminal?('do', false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 (match_len = has_terminal?('end', false, index)) r11 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 node_cache[:parsing_expression][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_sequence if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r0 = r2 else r3 = _nt_primary if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true 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 parent_modules [] end def inline_modules (alternatives.map {|alt| alt.inline_modules }).flatten end def inline_module nil end end def _nt_choice start_index = index if node_cache[:choice].has_key?(index) cached = node_cache[:choice][index] if cached node_cache[:choice][index] = 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 (match_len = has_terminal?('/', false, index)) r6 = true @index += match_len 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 parent_modules node_class_declarations.inline_modules end def inline_modules (sequence_elements.map {|elt| elt.inline_modules}).flatten + [sequence_element_accessor_module] + parent_modules end def inline_module node_class_declarations.inline_module 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 node_cache[:sequence][index] = 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 node_cache[:sequence_body][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_labeled_expression_sequence_body if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 node_cache[:variable_length_sequence_body][index] = 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 node_cache[:labeled_expression_sequence_body][index] = 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) 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 node_cache[:alternative][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_primary if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 parent_modules [] end def inline_modules atomic.inline_modules end def inline_module atomic.inline_module end def inline_module_name nil end end module Primary2 def prefix elements[0] end def atomic elements[2] end end module Primary3 def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression atomic end def parent_modules [] end def inline_modules [] end def inline_module nil 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) if node_class_declarations.inline_module && atomic.inline_module STDERR.puts "Extraneous module ignored after suffix: #{input[interval].inspect}" end suffix.compile(address, builder, self) end def optional_expression atomic end def node_class_name node_class_declarations.node_class_name end def parent_modules node_class_declarations.inline_modules end def inline_modules atomic.inline_modules + parent_modules end def inline_module node_class_declarations.inline_module 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) if node_class_declarations.inline_module && atomic.inline_module STDERR.puts "Extraneous module ignored with nested atomic: #{input[interval].inspect}" end atomic.compile(address, builder, self) end def node_class_name node_class_declarations.node_class_name end def parent_modules node_class_declarations.inline_modules end def inline_modules atomic.inline_modules + parent_modules end def inline_module node_class_declarations.inline_module 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 node_cache[:primary][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true 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 r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true 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 r9 = SyntaxNode.new(input, (index-1)...index) if r9 == true 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 r13 = SyntaxNode.new(input, (index-1)...index) if r13 == true 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 node_cache[:optionally_labeled_sequence_primary][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_unlabeled_sequence_primary if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 parent_modules [] 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 node_cache[:labeled_sequence_primary][index] = 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 parent_modules [] 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 node_cache[:unlabeled_sequence_primary][index] = 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 node_cache[:label][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_null_label if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 node_cache[:named_label][index] = 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 (match_len = has_terminal?(':', false, index)) r5 = true @index += match_len 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 node_cache[:null_label][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if (match_len = has_terminal?('', false, index)) r0 = instantiate_node(SyntaxNode,input, index...(index + match_len)) r0.extend(NullLabel0) @index += match_len 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 parent_modules [] end def inline_modules atomic.inline_modules end def inline_module_name nil end end module SequencePrimary2 def prefix elements[0] end def atomic elements[2] end end module SequencePrimary3 def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression atomic end def parent_modules [] 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 parent_modules [] 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 node_cache[:sequence_primary][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true 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 r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true 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 r9 = SyntaxNode.new(input, (index-1)...index) if r9 == true r0 = r9 else r12 = _nt_atomic if r12 r12 = SyntaxNode.new(input, (index-1)...index) if r12 == true 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 node_cache[:suffix][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_optional_suffix if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 node_cache[:optional_suffix][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if (match_len = has_terminal?('?', false, index)) r0 = instantiate_node(Optional,input, index...(index + match_len)) @index += match_len 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 node_cache[:node_class_declarations][index] = 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 node_cache[:repetition_suffix][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index if (match_len = has_terminal?('+', false, index)) r1 = instantiate_node(OneOrMore,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'+\'') r1 = nil end if r1 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else if (match_len = has_terminal?('*', false, index)) r2 = instantiate_node(ZeroOrMore,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'*\'') r2 = nil end if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r0 = r2 else r3 = _nt_occurrence_range if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true 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 node_cache[:occurrence_range][index] = 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?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index) r4 = true @index += 1 else terminal_parse_failure('[0-9]') r4 = nil end if r4 s3 << r4 else break end end r3 = instantiate_node(SyntaxNode,input, i3...index, s3) s0 << r3 if r3 if (match_len = has_terminal?('..', false, index)) r5 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'..\'') r5 = nil end s0 << r5 if r5 s6, i6 = [], index loop do if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index) r7 = true @index += 1 else terminal_parse_failure('[0-9]') 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 node_cache[:prefix][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0 = index if (match_len = has_terminal?('&', false, index)) r1 = instantiate_node(AndPredicate,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'&\'') r1 = nil end if r1 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else if (match_len = has_terminal?('!', false, index)) r2 = instantiate_node(NotPredicate,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'!\'') r2 = nil end if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r0 = r2 else if (match_len = has_terminal?('~', false, index)) r3 = instantiate_node(TransientPrefix,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'~\'') r3 = nil end if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true 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 node_cache[:atomic][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_nonterminal if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r0 = r2 else r3 = _nt_parenthesized_expression if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true 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 parent_modules [] end def inline_modules parsing_expression.inline_modules end def inline_module parsing_expression.inline_module 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 node_cache[:parenthesized_expression][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('(', false, index)) r1 = true @index += match_len 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 (match_len = has_terminal?(')', false, index)) r7 = true @index += match_len 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 node_cache[:nonterminal][index] = 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 @index = i1 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 node_cache[:terminal][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else r2 = _nt_character_class if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r0 = r2 else r3 = _nt_anything_symbol if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true r0 = r3 else @index = i0 r0 = nil end end end node_cache[:terminal][start_index] = r0 r0 end module QuotedString0 def qs elements[0] end def modifiers elements[1] end end module QuotedString1 def string qs.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 node_cache[:quoted_string][index] = 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_single_quoted_string if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r1 = r2 else r3 = _nt_double_quoted_string if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true r1 = r3 else @index = i1 r1 = nil end end s0 << r1 if r1 s4, i4 = [], index loop do if has_terminal?(@regexps[gr = '\A[ir]'] ||= Regexp.new(gr), :regexp, index) r5 = true @index += 1 else terminal_parse_failure('[ir]') r5 = nil end if r5 s4 << r5 else break end end r4 = instantiate_node(SyntaxNode,input, i4...index, s4) s0 << r4 end if s0.last r0 = instantiate_node(Terminal,input, i0...index, s0) r0.extend(QuotedString0) r0.extend(QuotedString1) else @index = i0 r0 = nil 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 node_cache[:double_quoted_string][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('"', false, index)) r1 = true @index += match_len else terminal_parse_failure('\'"\'') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if (match_len = has_terminal?('"', false, index)) r5 = true @index += match_len else terminal_parse_failure('\'"\'') r5 = nil end if r5 @index = i4 r4 = nil terminal_parse_failure('\'"\'', true) else @terminal_failures.pop @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 i6 = index if (match_len = has_terminal?("\\\\", false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('"\\\\\\\\"') r7 = nil end if r7 r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true r6 = r7 else if (match_len = has_terminal?('\"', false, index)) r8 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'\\"\'') r8 = nil end if r8 r8 = SyntaxNode.new(input, (index-1)...index) if r8 == true r6 = r8 else if index < input_length r9 = true @index += 1 else terminal_parse_failure("any character") r9 = nil end if r9 r9 = SyntaxNode.new(input, (index-1)...index) if r9 == true 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 (match_len = has_terminal?('"', false, index)) r10 = true @index += match_len else terminal_parse_failure('\'"\'') r10 = nil end s0 << r10 end end if s0.last r0 = instantiate_node(SyntaxNode,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 node_cache[:single_quoted_string][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?("'", false, index)) r1 = true @index += match_len else terminal_parse_failure('"\'"') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if (match_len = has_terminal?("'", false, index)) r5 = true @index += match_len else terminal_parse_failure('"\'"') r5 = nil end if r5 @index = i4 r4 = nil terminal_parse_failure('"\'"', true) else @terminal_failures.pop @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 i6 = index if (match_len = has_terminal?("\\\\", false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('"\\\\\\\\"') r7 = nil end if r7 r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true r6 = r7 else if (match_len = has_terminal?("\\'", false, index)) r8 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('"\\\\\'"') r8 = nil end if r8 r8 = SyntaxNode.new(input, (index-1)...index) if r8 == true r6 = r8 else if index < input_length r9 = true @index += 1 else terminal_parse_failure("any character") r9 = nil end if r9 r9 = SyntaxNode.new(input, (index-1)...index) if r9 == true 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 (match_len = has_terminal?("'", false, index)) r10 = true @index += match_len else terminal_parse_failure('"\'"') r10 = nil end s0 << r10 end end if s0.last r0 = instantiate_node(SyntaxNode,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 node_cache[:character_class][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('[', false, index)) r1 = true @index += match_len else terminal_parse_failure('\'[\'') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if (match_len = has_terminal?(']', false, index)) r5 = true @index += match_len else terminal_parse_failure('\']\'') r5 = nil end if r5 @index = i4 r4 = nil terminal_parse_failure('\']\'', true) else @terminal_failures.pop @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 i6 = index i7, s7 = index, [] if (match_len = has_terminal?('\\', false, index)) r8 = true @index += match_len else terminal_parse_failure('\'\\\\\'') r8 = nil end s7 << r8 if r8 if index < input_length r9 = true @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 r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true r6 = r7 else r10 = _nt_bracket_expression if r10 r10 = SyntaxNode.new(input, (index-1)...index) if r10 == true r6 = r10 else i11, s11 = index, [] i12 = index if (match_len = has_terminal?('\\', false, index)) r13 = true @index += match_len else terminal_parse_failure('\'\\\\\'') r13 = nil end if r13 @index = i12 r12 = nil terminal_parse_failure('\'\\\\\'', true) else @terminal_failures.pop @index = i12 r12 = instantiate_node(SyntaxNode,input, index...index) end s11 << r12 if r12 if index < input_length r14 = true @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 r11 = SyntaxNode.new(input, (index-1)...index) if r11 == true 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 (match_len = has_terminal?(']', false, index)) r15 = true @index += match_len 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 node_cache[:bracket_expression][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('[:', false, index)) r1 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'[:\'') r1 = nil end s0 << r1 if r1 if (match_len = has_terminal?('^', false, index)) r3 = true @index += match_len 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 (match_len = has_terminal?('alnum', false, index)) r5 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'alnum\'') r5 = nil end if r5 r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true r4 = r5 else if (match_len = has_terminal?('alpha', false, index)) r6 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'alpha\'') r6 = nil end if r6 r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true r4 = r6 else if (match_len = has_terminal?('blank', false, index)) r7 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'blank\'') r7 = nil end if r7 r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true r4 = r7 else if (match_len = has_terminal?('cntrl', false, index)) r8 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'cntrl\'') r8 = nil end if r8 r8 = SyntaxNode.new(input, (index-1)...index) if r8 == true r4 = r8 else if (match_len = has_terminal?('digit', false, index)) r9 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'digit\'') r9 = nil end if r9 r9 = SyntaxNode.new(input, (index-1)...index) if r9 == true r4 = r9 else if (match_len = has_terminal?('graph', false, index)) r10 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'graph\'') r10 = nil end if r10 r10 = SyntaxNode.new(input, (index-1)...index) if r10 == true r4 = r10 else if (match_len = has_terminal?('lower', false, index)) r11 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'lower\'') r11 = nil end if r11 r11 = SyntaxNode.new(input, (index-1)...index) if r11 == true r4 = r11 else if (match_len = has_terminal?('print', false, index)) r12 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'print\'') r12 = nil end if r12 r12 = SyntaxNode.new(input, (index-1)...index) if r12 == true r4 = r12 else if (match_len = has_terminal?('punct', false, index)) r13 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'punct\'') r13 = nil end if r13 r13 = SyntaxNode.new(input, (index-1)...index) if r13 == true r4 = r13 else if (match_len = has_terminal?('space', false, index)) r14 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'space\'') r14 = nil end if r14 r14 = SyntaxNode.new(input, (index-1)...index) if r14 == true r4 = r14 else if (match_len = has_terminal?('upper', false, index)) r15 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'upper\'') r15 = nil end if r15 r15 = SyntaxNode.new(input, (index-1)...index) if r15 == true r4 = r15 else if (match_len = has_terminal?('xdigit', false, index)) r16 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'xdigit\'') r16 = nil end if r16 r16 = SyntaxNode.new(input, (index-1)...index) if r16 == true r4 = r16 else if (match_len = has_terminal?('word', false, index)) r17 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'word\'') r17 = nil end if r17 r17 = SyntaxNode.new(input, (index-1)...index) if r17 == true 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 (match_len = has_terminal?(':]', false, index)) r18 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len 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 node_cache[:anything_symbol][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if (match_len = has_terminal?('.', false, index)) r0 = instantiate_node(AnythingSymbol,input, index...(index + match_len)) @index += match_len 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 node_cache[:node_class_expression][index] = 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 (match_len = has_terminal?('<', false, index)) r3 = true @index += match_len else terminal_parse_failure('\'<\'') r3 = nil end s1 << r3 if r3 s4, i4 = [], index loop do i5, s5 = index, [] i6 = index if (match_len = has_terminal?('>', false, index)) r7 = true @index += match_len else terminal_parse_failure('\'>\'') r7 = nil end if r7 @index = i6 r6 = nil terminal_parse_failure('\'>\'', true) else @terminal_failures.pop @index = i6 r6 = instantiate_node(SyntaxNode,input, index...index) end s5 << r6 if r6 if index < input_length r8 = true @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 (match_len = has_terminal?('>', false, index)) r9 = true @index += match_len 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else if (match_len = has_terminal?('', false, index)) r10 = instantiate_node(SyntaxNode,input, index...(index + match_len)) r10.extend(NodeClassExpression3) @index += match_len else terminal_parse_failure('\'\'') r10 = nil end if r10 r10 = SyntaxNode.new(input, (index-1)...index) if r10 == true 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 parent_modules [] end def inline_modules [inline_module] end def inline_module_name inline_module.module_name end end module TrailingInlineModule2 def parent_modules [] end 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 node_cache[:trailing_inline_module][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else if (match_len = has_terminal?('', false, index)) r4 = instantiate_node(SyntaxNode,input, index...(index + match_len)) r4.extend(TrailingInlineModule2) @index += match_len else terminal_parse_failure('\'\'') r4 = nil end if r4 r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true 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 node_cache[:predicate_block][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('', false, index)) r1 = true @index += match_len 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 node_cache[:inline_module][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('{', false, index)) r1 = true @index += match_len else terminal_parse_failure('\'{\'') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3 = index r4 = _nt_inline_module if r4 r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true r3 = r4 else i5, s5 = index, [] i6 = index if has_terminal?(@regexps[gr = '\A[{}]'] ||= Regexp.new(gr), :regexp, index) r7 = true @index += 1 else terminal_parse_failure('[{}]') r7 = nil end if r7 @index = i6 r6 = nil terminal_parse_failure('[{}]', true) else @terminal_failures.pop @index = i6 r6 = instantiate_node(SyntaxNode,input, index...index) end s5 << r6 if r6 if index < input_length r8 = true @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 r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true 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 (match_len = has_terminal?('}', false, index)) r9 = true @index += match_len 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 node_cache[:keyword_inside_grammar][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] i1 = index if (match_len = has_terminal?('rule', false, index)) r2 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'rule\'') r2 = nil end if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r1 = r2 else if (match_len = has_terminal?('end', false, index)) r3 = instantiate_node(SyntaxNode,input, index...(index + match_len)) @index += match_len else terminal_parse_failure('\'end\'') r3 = nil end if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true r1 = r3 else @index = i1 r1 = nil end end s0 << r1 if r1 i4 = index r5 = _nt_non_space_char if r5 @index = i4 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 node_cache[:non_space_char][index] = 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 @index = i1 r1 = nil else @index = i1 r1 = instantiate_node(SyntaxNode,input, index...index) end s0 << r1 if r1 if index < input_length r3 = true @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 node_cache[:alpha_char][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?(@regexps[gr = '\A[A-Za-z_]'] ||= Regexp.new(gr), :regexp, index) r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('[A-Za-z_]') 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 node_cache[:alphanumeric_char][index] = 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 r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true r0 = r1 else if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index) r2 = true @index += 1 else terminal_parse_failure('[0-9]') r2 = nil end if r2 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true 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 node_cache[:space][index] = 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 r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true r1 = r2 else r3 = _nt_comment_to_eol if r3 r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true 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 node_cache[:comment_to_eol][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if (match_len = has_terminal?('#', false, index)) r1 = true @index += match_len else terminal_parse_failure('\'#\'') r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do i3, s3 = index, [] i4 = index if (match_len = has_terminal?("\n", false, index)) r5 = true @index += match_len else terminal_parse_failure('"\\n"') r5 = nil end if r5 @index = i4 r4 = nil terminal_parse_failure('"\\n"', true) else @terminal_failures.pop @index = i4 r4 = instantiate_node(SyntaxNode,input, index...index) end s3 << r4 if r4 if index < input_length r6 = true @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 node_cache[:white][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end if has_terminal?(@regexps[gr = '\A[ \\t\\n\\r]'] ||= Regexp.new(gr), :regexp, index) r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure('[ \\t\\n\\r]') r0 = nil end node_cache[:white][start_index] = r0 r0 end end class MetagrammarParser < Treetop::Runtime::CompiledParser include Metagrammar end end end treetop-1.6.12/lib/treetop/compiler/metagrammar.treetop000066400000000000000000000312001433777471000232370ustar00rootroot00000000000000module Treetop module Compiler grammar Metagrammar rule treetop_file requires:(space? require_statement)* spacing:space? module_or_grammar suffix:space? { def compile requires.text_value + spacing.text_value + module_or_grammar.compile + suffix.text_value end } end rule require_statement spacing:space? "require" [ \t]+ [^\n\r]+ [\n\r] end rule module_or_grammar module_declaration / grammar end rule module_declaration module_prefix:(('module'/'class') space name:([A-Z] alphanumeric_char* ('::' [A-Z] alphanumeric_char*)*) space) module_contents:(module_declaration / grammar) suffix:(space 'end') { def compile module_prefix.text_value + module_contents.compile + suffix.text_value end def parser_name module_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 parent_modules [] end def inline_modules (alternatives.map {|alt| alt.inline_modules }).flatten end def inline_module nil end } end rule sequence sequence_body node_class_declarations { def sequence_elements [sequence_body.head] + tail end def tail sequence_body.tail end def parent_modules node_class_declarations.inline_modules end def inline_modules (sequence_elements.map {|elt| elt.inline_modules}).flatten + [sequence_element_accessor_module] + parent_modules end def inline_module node_class_declarations.inline_module 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 parent_modules [] end def inline_modules atomic.inline_modules end def inline_module atomic.inline_module end def inline_module_name nil end } / prefix space? atomic:predicate_block { def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression atomic end def parent_modules [] end def inline_modules [] end def inline_module nil end } / atomic suffix node_class_declarations { def compile(address, builder, parent_expression=nil) if node_class_declarations.inline_module && atomic.inline_module STDERR.puts "Extraneous module ignored after suffix: #{input[interval].inspect}" end suffix.compile(address, builder, self) end def optional_expression atomic end def node_class_name node_class_declarations.node_class_name end def parent_modules node_class_declarations.inline_modules end def inline_modules atomic.inline_modules + parent_modules end def inline_module node_class_declarations.inline_module end def inline_module_name node_class_declarations.inline_module_name end } / atomic node_class_declarations { def compile(address, builder, parent_expression=nil) if node_class_declarations.inline_module && atomic.inline_module STDERR.puts "Extraneous module ignored with nested atomic: #{input[interval].inspect}" end atomic.compile(address, builder, self) end def node_class_name node_class_declarations.node_class_name end def parent_modules node_class_declarations.inline_modules end def inline_modules atomic.inline_modules + parent_modules end def inline_module node_class_declarations.inline_module 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 parent_modules [] 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 parent_modules [] 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 parent_modules [] end def inline_modules atomic.inline_modules end def inline_module_name nil end } / prefix space? atomic:predicate_block { def compile(address, builder, parent_expression=nil) prefix.compile(address, builder, self) end def prefixed_expression atomic end def parent_modules [] 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 parent_modules [] 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 parent_modules [] end def inline_modules parsing_expression.inline_modules end def inline_module parsing_expression.inline_module end } end rule nonterminal !keyword_inside_grammar (alpha_char alphanumeric_char*) end rule terminal quoted_string / character_class / anything_symbol end rule quoted_string qs:(single_quoted_string / double_quoted_string) modifiers:([ir]*) { def string qs.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 parent_modules [] end def inline_modules [inline_module] end def inline_module_name inline_module.module_name end } / '' { def parent_modules [] 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.6.12/lib/treetop/compiler/node_classes.rb000066400000000000000000000017771433777471000223450ustar00rootroot00000000000000require '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.6.12/lib/treetop/compiler/node_classes/000077500000000000000000000000001433777471000220045ustar00rootroot00000000000000treetop-1.6.12/lib/treetop/compiler/node_classes/anything_symbol.rb000066400000000000000000000014131433777471000255360ustar00rootroot00000000000000module Treetop module Compiler class AnythingSymbol < AtomicExpression def compile(address, builder, parent_expression = nil) super builder.if__ "index < input_length" do if address == 0 || decorated? assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))" extend_result_with_inline_module parent_expression else assign_lazily_instantiated_node end builder << "@index += 1" end builder.else_ do builder << 'terminal_parse_failure("any character")' assign_result 'nil' end end def expected '"any character"' end def inline_module nil end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/atomic_expression.rb000066400000000000000000000005031433777471000260620ustar00rootroot00000000000000module 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.6.12/lib/treetop/compiler/node_classes/character_class.rb000066400000000000000000000020551433777471000254540ustar00rootroot00000000000000module Treetop module Compiler class CharacterClass < AtomicExpression def compile(address, builder, parent_expression = nil) super builder.if__ "has_terminal?(@regexps[gr = #{grounded_regexp(text_value)}] ||= Regexp.new(gr), :regexp, index)" do if address == 0 || decorated? assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))" extend_result_with_inline_module parent_expression else assign_lazily_instantiated_node end builder << "@index += 1" # Always one character end builder.else_ do builder << "terminal_parse_failure(#{expected})" assign_result 'nil' end end def expected single_quote('['+characters+']') end def inline_module nil end def grounded_regexp(string) # Double any backslashes, then backslash any single-quotes: "'\\A#{string.gsub(/\\/) { '\\\\' }.gsub(/'/) { "\\'"}}'" end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/choice.rb000066400000000000000000000022551433777471000235670ustar00rootroot00000000000000module 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, parent_expression) end_comment(self) end def compile_alternatives(alternatives, parent_expression) obtain_new_subexpression_address alternatives.first.compile(subexpression_address, builder) builder.if__ subexpression_success? do # Undo lazy instantiation: builder << "#{subexpression_result_var} = SyntaxNode.new(input, (index-1)...index) if #{subexpression_result_var} == true" assign_result subexpression_result_var extend_result_with_declared_module extend_result_with_inline_module parent_expression end builder.else_ do if alternatives.size == 1 reset_index assign_failure start_index_var else compile_alternatives(alternatives[1..-1], parent_expression) end end end def expected '"(any alternative)"' end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/declaration_sequence.rb000066400000000000000000000010721433777471000265060ustar00rootroot00000000000000module 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.6.12/lib/treetop/compiler/node_classes/grammar.rb000066400000000000000000000014451433777471000237630ustar00rootroot00000000000000module 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.6.12/lib/treetop/compiler/node_classes/inline_module.rb000066400000000000000000000011031433777471000251470ustar00rootroot00000000000000module 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.6.12/lib/treetop/compiler/node_classes/nonterminal.rb000066400000000000000000000006571433777471000246670ustar00rootroot00000000000000module 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 parent_expression end def inline_module nil end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/optional.rb000066400000000000000000000007621433777471000241630ustar00rootroot00000000000000module 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.6.12/lib/treetop/compiler/node_classes/parenthesized_expression.rb000066400000000000000000000004601433777471000274550ustar00rootroot00000000000000module Treetop module Compiler class ParenthesizedExpression < ParsingExpression def compile(address, builder, parent_expression = nil) elements[2].compile(address, builder, parent_expression) end def expected elements[2].expected end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/parsing_expression.rb000066400000000000000000000075641433777471000262670ustar00rootroot00000000000000module 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 parent_expression = nil if parent_expression && parent_expression.parent_modules.size > 0 parent_expression.parent_modules.each do |inline| extend_result inline.module_name end end 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 def expected nil # Overridden for terminal parse failures end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/parsing_rule.rb000066400000000000000000000035101433777471000250220ustar00rootroot00000000000000module 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 cache_address = "node_cache[:#{name}][index]" builder.assign 'cached', cache_address builder.if_ "cached" do # Handle lazily instantiated nodes: builder << "#{cache_address} = 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.6.12/lib/treetop/compiler/node_classes/predicate.rb000066400000000000000000000023331433777471000242720ustar00rootroot00000000000000module 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 reset_index 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 if (e = parent.atomic.expected) builder << "terminal_parse_failure(#{e}, true)" end end def when_failure if (e = parent.atomic.expected) builder << "@terminal_failures.pop" end assign_success end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/predicate_block.rb000066400000000000000000000015361433777471000254500ustar00rootroot00000000000000module 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 : ""})" builder.if_ '!'+result_var do builder << "terminal_parse_failure(#{expected})" end end def expected '""' # Should I include (some of) the text_value here? end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/repetition.rb000066400000000000000000000060351433777471000245170ustar00rootroot00000000000000module 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 parent_expression assign_result "instantiate_node(#{node_class_name},input, #{start_index_var}...index, #{accumulator_var})" extend_result_with_inline_module parent_expression end end class ZeroOrMore < Repetition def compile(address, builder, parent_expression) super assign_and_extend_result parent_expression 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 parent_expression end end_comment(parent_expression) end def max nil end def expected parent_expression.atomic.expected && '"at least one "+'+parent_expression.atomic.expected end end class OccurrenceRange < Repetition def compile(address, builder, parent_expression) super if !min.empty? && min.text_value.to_i != 0 # 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 clean_unsaturated assign_and_extend_result parent_expression end else clean_unsaturated assign_and_extend_result parent_expression end end_comment(parent_expression) end # remove the last terminal_failure if we merely failed to reach the maximum def clean_unsaturated if !max.empty? && max.text_value.to_i > 0 builder.if_ "#{accumulator_var}.size < #{max.text_value}" do builder << '@terminal_failures.pop' # Ignore the last failure. end end end def expected parent_expression.atomic.expected && "at least #{min.text_value} "+parent_expression.atomic.expected end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/sequence.rb000066400000000000000000000047751433777471000241560ustar00rootroot00000000000000module 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 parent_expression 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 def expected '""' 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.6.12/lib/treetop/compiler/node_classes/terminal.rb000066400000000000000000000034531433777471000241510ustar00rootroot00000000000000module Treetop module Compiler class Terminal < AtomicExpression def compile(address, builder, parent_expression = nil) super # Handle modifiers: insensitive = modifiers.text_value.include? 'i' re = modifiers.text_value.include? 'r' if re grounded_regexp = "#{('\A'+eval(string)).inspect}" cache_key = "'__#{modifiers.text_value}__'+(gr = #{grounded_regexp})" re_modifiers = "#{insensitive ? 'Regexp::IGNORECASE' : 0}" str = "@regexps[#{cache_key}] ||= Regexp.new(gr, #{re_modifiers})" mode = ':regexp' elsif insensitive str = string.downcase string_length = eval(str).length mode = ':insens' else str = string string_length = eval(str).length mode = 'false' end builder.if__ "(match_len = has_terminal?(#{str}, #{mode}, index))" do if address == 0 || decorated? || mode != 'false' || string_length > 1 assign_result "instantiate_node(#{node_class_name},input, index...(index + match_len))" # debugger if parent_expression and parent_expression.inline_modules.size > 0 # extend_result_with_inline_module parent_expression if parent_expression parent_expression.inline_modules.each do |inline| extend_result inline.module_name end end else assign_lazily_instantiated_node end builder << "@index += match_len" end builder.else_ do builder << "terminal_parse_failure(#{expected})" assign_result 'nil' end end def expected single_quote(string) end def inline_module nil end end end end treetop-1.6.12/lib/treetop/compiler/node_classes/transient_prefix.rb000066400000000000000000000003511433777471000257140ustar00rootroot00000000000000module Treetop module Compiler class TransientPrefix < ParsingExpression def compile(address, builder, parent_expression) parent_expression.prefixed_expression.compile(address, builder) end end end endtreetop-1.6.12/lib/treetop/compiler/node_classes/treetop_file.rb000066400000000000000000000002521433777471000250110ustar00rootroot00000000000000module Treetop module Compiler class TreetopFile < Runtime::SyntaxNode def compile (elements.map {|elt| elt.compile}).join end end end endtreetop-1.6.12/lib/treetop/compiler/ruby_builder.rb000066400000000000000000000043751433777471000223670ustar00rootroot00000000000000require '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 = String.new("") end def <<(ruby_line) return if ruby_line == '' 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.6.12/lib/treetop/polyglot.rb000066400000000000000000000003611433777471000177260ustar00rootroot00000000000000module 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.6.12/lib/treetop/ruby_extensions.rb000066400000000000000000000000511433777471000213110ustar00rootroot00000000000000require 'treetop/ruby_extensions/string' treetop-1.6.12/lib/treetop/ruby_extensions/000077500000000000000000000000001433777471000207705ustar00rootroot00000000000000treetop-1.6.12/lib/treetop/ruby_extensions/string.rb000066400000000000000000000012721433777471000226250ustar00rootroot00000000000000class 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 # The following methods are lifted from Facets 2.0.2 def tabto(n) if self =~ /^( *)\S/ # Inlined due to collision with ActiveSupport 4.0: indent(n - $1.length) m = n - $1.length if m >= 0 gsub(/^/, ' ' * m) else gsub(/^ {0,#{-m}}/, "") end else self end end def treetop_camelize to_s.gsub(/\/(.?)/){ "::" + $1.upcase }.gsub(/(^|_)(.)/){ $2.upcase } end end treetop-1.6.12/lib/treetop/runtime.rb000066400000000000000000000003211433777471000175340ustar00rootroot00000000000000require '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.6.12/lib/treetop/runtime/000077500000000000000000000000001433777471000172135ustar00rootroot00000000000000treetop-1.6.12/lib/treetop/runtime/compiled_parser.rb000066400000000000000000000111271433777471000227120ustar00rootroot00000000000000module 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? if (should_consume_all && index != input.size) if index > max_terminal_failure_index # Otherwise the failure is already explained terminal_parse_failure('', true) end return nil end 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 OtherThan = 'something other than ' def failure_reason return nil unless (tf = terminal_failures) && tf.size > 0 "Expected " + (tf.size == 1 ? (tf[0].unexpected ? OtherThan : '')+tf[0].expected_string : "one of #{tf.map{|f| (f.unexpected ? OtherThan : '')+f.expected_string}.uniq*', '}" ) + " at line #{failure_line}, column #{failure_column} (byte #{failure_index+1})" + (failure_index > 0 ? " after #{input[index...failure_index]}" : '') end def terminal_failures if @terminal_failures.empty? || @terminal_failures[-1].is_a?(TerminalParseFailure) @terminal_failures else @terminal_failures.map! {|tf_ary| tf_ary.is_a?(TerminalParseFailure) ? 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 forget_failures_to_here @terminal_failures = [] @max_terminal_failure_index = -1 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, mode, index) case mode when :regexp # A Regexp has been passed in, either a character class or a literel regex 'foo'r (terminal =~ input[index..-1]) == 0 && $&.length when false # The terminal is a string which must match exactly input[index, terminal.size] == terminal && terminal.size when :insens # The terminal is a downcased string which must match input downcased input[index, terminal.size].downcase == terminal && terminal.size when true # Only occurs with old compiled grammars, for character classes rx = @regexps[terminal] ||= Regexp.new(terminal) input.index(rx, index) == index && $&.length end end def terminal_parse_failure(expected_string, unexpected = false) if @max_terminal_failure_index == -1 @max_terminal_failure_index = 0 return nil end 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, unexpected] # It's very slow, but this shows the last 5 nested rules: # caller.reject{|l| l =~ /`loop'|`block in /}[0..5].reverse.map{|l| l.sub(/[^`]*`_nt_/,'').sub(/'/,'')} terminal_failures return nil end end end end treetop-1.6.12/lib/treetop/runtime/interval_skip_list.rb000066400000000000000000000002511433777471000234430ustar00rootroot00000000000000require '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.6.12/lib/treetop/runtime/interval_skip_list/000077500000000000000000000000001433777471000231205ustar00rootroot00000000000000treetop-1.6.12/lib/treetop/runtime/interval_skip_list/head_node.rb000066400000000000000000000004501433777471000253520ustar00rootroot00000000000000class 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.6.12/lib/treetop/runtime/interval_skip_list/interval_skip_list.rb000066400000000000000000000120761433777471000273600ustar00rootroot00000000000000class 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.6.12/lib/treetop/runtime/interval_skip_list/node.rb000066400000000000000000000102671433777471000244000ustar00rootroot00000000000000class 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.6.12/lib/treetop/runtime/syntax_node.rb000066400000000000000000000060761433777471000221040ustar00rootroot00000000000000module Treetop module Runtime class SyntaxNode attr_reader :input, :interval attr_accessor :parent def initialize(input, interval, elements = nil) @input = input @interval = interval if (@elements = elements) @elements.each { |e| e.equal?(true) or e.parent = self } end 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)) element.parent = self end 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_self(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 end def inspect_children(indent="") return '' unless elements && elements.size > 0 ":" + elements.map do |e| begin "\n"+e.inspect(indent+" ") rescue # Defend against inspect not taking a parameter "\n"+indent+" "+e.inspect end end. join("") end def inspect(indent="") inspect_self(indent) + inspect_children(indent) 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.6.12/lib/treetop/runtime/terminal_parse_failure.rb000066400000000000000000000006451433777471000242610ustar00rootroot00000000000000module Treetop module Runtime class TerminalParseFailure attr_reader :index, :expected_string, :unexpected def initialize(index, expected_string, unexpected = false) @index = index @expected_string = expected_string @unexpected = unexpected end def to_s "String matching #{expected_string} #{@unexpected ? 'not ' : ''}expected." end end end end treetop-1.6.12/lib/treetop/runtime/terminal_syntax_node.rb000066400000000000000000000005351433777471000237710ustar00rootroot00000000000000module 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.6.12/lib/treetop/version.rb000066400000000000000000000002241433777471000175400ustar00rootroot00000000000000module Treetop #:nodoc: module VERSION #:nodoc: MAJOR = 1 MINOR = 6 TINY = 12 STRING = [MAJOR, MINOR, TINY].join('.') end end treetop-1.6.12/script/000077500000000000000000000000001433777471000146045ustar00rootroot00000000000000treetop-1.6.12/script/generate_metagrammar.rb000066400000000000000000000007261433777471000213050ustar00rootroot00000000000000#!/usr/bin/env ruby require 'rubygems' require File.expand_path('../../lib/treetop/bootstrap_gen_1_metagrammar', __FILE__) GENERATED_METAGRAMMAR_PATH = File.expand_path('../../lib/treetop/compiler/metagrammar.rb') File.open(METAGRAMMAR_PATH) do |source_file| File.open(GENERATED_METAGRAMMAR_PATH, 'w') do |target_file| generated_source = Treetop::Compiler::MetagrammarParser.new.parse(source_file.read).compile target_file.write(generated_source) end end treetop-1.6.12/script/svnadd000077500000000000000000000003031433777471000160050ustar00rootroot00000000000000#!/usr/bin/env ruby -w def unversioned_files `svn status`. select { |line| line =~ /^\?/ }. collect { |line| line[7..-1] } end unversioned_files.each do |file| `svn add #{file}` endtreetop-1.6.12/script/svnrm000077500000000000000000000002721433777471000157000ustar00rootroot00000000000000#!/usr/bin/env ruby -w def missing_files `svn status`. select { |line| line =~ /^\!/ }. collect { |line| line[7..-1] } end missing_files.each do |file| `svn rm #{file}` endtreetop-1.6.12/spec/000077500000000000000000000000001433777471000142325ustar00rootroot00000000000000treetop-1.6.12/spec/compiler/000077500000000000000000000000001433777471000160445ustar00rootroot00000000000000treetop-1.6.12/spec/compiler/and_predicate_spec.rb000066400000000000000000000022161433777471000221660ustar00rootroot00000000000000require '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.6.12/spec/compiler/anything_symbol_spec.rb000066400000000000000000000030541433777471000226130ustar00rootroot00000000000000require '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('') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end 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.6.12/spec/compiler/character_class_spec.rb000066400000000000000000000235401433777471000225300ustar00rootroot00000000000000require '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') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end 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" "bc"' it "lazily instantiates a node for the character" do result = parse('Aabc') result.instance_variable_get("@elements").should include(true) result.elements.should_not include(true) result.elements.size.should == 3 end end describe "a character class with a node class declaration mixed with other expressions" do testing_expression '([A-Z] ) "ab"' it "actively generates a node for the character because it has a node class declared" do result = parse('Aab') 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] ) "ab"' it "actively generates a node for the character because it has a node module declared" do result = parse('Aab') 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 }) "ab"' it "actively generates a node for the character because it has an inline block" do result = parse('Aab') 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" "cd"' it "returns the correct element for the labeled expression" do result = parse('Abcd') result.upper.text_value.should == "A" result.elements.size.should == 3 end end describe "a character class repetition mixed with other expressions" do testing_expression '[A-Z]+ "a" "bc"' it "lazily instantiates a node for the character" do result = parse('ABCabc') 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 == 3 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", SyntaxNode offset=4, "bc"]} end end describe "a character class that gets cached because of a choice" do testing_expression "[A-Z] 'a' 'bc' / [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.6.12/spec/compiler/choice_spec.rb000066400000000000000000000056431433777471000206450ustar00rootroot00000000000000require '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 }) {def bat_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.should_not respond_to(:bar_method) result.should_not respond_to(:baz_method) result.should respond_to(:bat_method) result = parse('bar') result.should_not be_nil result.should_not respond_to(:foo_method) result.should respond_to(:bar_method) result.should_not respond_to(:baz_method) result.should respond_to(:bat_method) result = parse('baz') result.should_not be_nil result.should_not respond_to(:foo_method) result.should_not respond_to(:bar_method) result.should respond_to(:baz_method) result.should respond_to(:bat_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'/ 'bb' / [c]) { def a_method; end }" it "extends a match of any of its subexpressions with a module created from the block" do ['a', 'bb', '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'/ 'bb' / [c]) " it "extends a match of any of its subexpressions with a module created from the block" do ['a', 'bb', 'c'].each do |letter| parse(letter).should respond_to(:a_method) end end end end treetop-1.6.12/spec/compiler/circular_compilation_spec.rb000066400000000000000000000015671433777471000236160ustar00rootroot00000000000000require '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.6.12/spec/compiler/failure_propagation_functional_spec.rb000066400000000000000000000012721433777471000256610ustar00rootroot00000000000000require '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.6.12/spec/compiler/grammar_compiler_spec.rb000066400000000000000000000110331433777471000227210ustar00rootroot00000000000000require '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" @source_path_with_magic_coding = "#{dir}/test_grammar_magic_coding.treetop" @source_path_with_magic_encoding = "#{dir}/test_grammar_magic_encoding.treetop" @target_path = "#{@tmpdir}/test_grammar.rb" @target_path_with_do = "#{@tmpdir}/test_grammar_do.rb" @target_path_with_magic_coding = "#{@tmpdir}/test_grammar_magic_coding.rb" @target_path_with_magic_encoding = "#{@tmpdir}/test_grammar_magic_encoding.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.exist?(target_path).should be_falsey compiler.compile(src_copy) File.exist?(target_path).should be_truthy 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.exist?(alternate_target_path).should be_falsey compiler.compile(source_path_with_treetop_extension, alternate_target_path) File.exist?(alternate_target_path).should be_truthy 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 specify "grammars with magic 'encoding' comments keep those comments at the top" do src_copy = "#{@tmpdir}/test_grammar_magic_encoding.treetop" File.open(@source_path_with_magic_encoding) do |f| File.open(src_copy,'w'){|o|o.write(f.read)} end compiler.compile(src_copy) File.open(@target_path_with_magic_encoding).readline.should == "# encoding: UTF-8\n" end specify "grammars with magic 'coding' comments keep those comments at the top" do src_copy = "#{@tmpdir}/test_grammar_magic_coding.treetop" File.open(@source_path_with_magic_coding) do |f| File.open(src_copy,'w'){|o|o.write(f.read)} end compiler.compile(src_copy) File.open(@target_path_with_magic_coding).readline.should == "# coding: UTF-8\n" end def delete_target_files File.delete(target_path) if File.exist?(target_path) File.delete(@target_path_with_do) if File.exist?(@target_path_with_do) File.delete(alternate_target_path) if File.exist?(alternate_target_path) end end treetop-1.6.12/spec/compiler/grammar_spec.rb000066400000000000000000000015701433777471000210340ustar00rootroot00000000000000require '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') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end it "mixes in included modules" do self.class.const_get(:Foo).ancestors.should include(GrammarSpec::Bar) end end end treetop-1.6.12/spec/compiler/multibyte_chars_spec.rb000066400000000000000000000025321433777471000226030ustar00rootroot00000000000000# 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.6.12/spec/compiler/namespace_spec.rb000066400000000000000000000015311433777471000213370ustar00rootroot00000000000000require '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.6.12/spec/compiler/nonterminal_symbol_spec.rb000066400000000000000000000017601433777471000233220ustar00rootroot00000000000000require '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.6.12/spec/compiler/not_predicate_spec.rb000066400000000000000000000026121433777471000222240ustar00rootroot00000000000000require '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') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end end describe "A !-predicated character class symbol" do testing_expression '![aeiou]' it "fails to parse input matching the terminal symbol" do parse('e') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end 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 == 0 end end end describe "A !-predicated sequence" do testing_expression '!("a" "b" "cc")' it "fails to parse matching input" do parse('abcc') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end end end treetop-1.6.12/spec/compiler/occurrence_range_spec.rb000066400000000000000000000144271433777471000227170ustar00rootroot00000000000000require '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 == 0 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 == 0 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 == 0 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 two of that terminal but fails because of an extra one" do parse("foofoofoo") do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end it "parses two of three of that terminal, reporting no failure" do parse("foofoofoo", :consume_all_input => false) do |result| result.should_not be_nil result.elements.size.should == 2 parser.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 == 0 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 four of that terminal because there's an extra unconsumed one" do parse("foofoofoofoofoo") do |result| result.should be_nil terminal_failures = parser.terminal_failures terminal_failures.size.should == 1 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.6.12/spec/compiler/one_or_more_spec.rb000066400000000000000000000022631433777471000217110ustar00rootroot00000000000000require '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.6.12/spec/compiler/optional_spec.rb000066400000000000000000000021361433777471000212320ustar00rootroot00000000000000require '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.6.12/spec/compiler/parenthesized_expression_spec.rb000066400000000000000000000016161433777471000245330ustar00rootroot00000000000000require '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') do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end end describe "An expression with code both inside and outside parentheses" do testing_expression '("foo" { def inner; end } ) { def outer; end} ' it "should extend both code modules " do parse('foo') do |result| skip "Arbitrarily nested modules are not yet compiled" result.should respond_to(:inner) result.should respond_to(:outer) end end end end treetop-1.6.12/spec/compiler/parsing_rule_spec.rb000066400000000000000000000026661433777471000221070ustar00rootroot00000000000000require '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.6.12/spec/compiler/repeated_subrule_spec.rb000066400000000000000000000012511433777471000227340ustar00rootroot00000000000000require 'spec_helper' module RepeatedSubruleSpec describe "a repeated subrule" do testing_grammar %{ grammar Foo rule foo a:'a' space b:'b' space 'cc' end rule space ' ' end end } it "should produce a parser having sequence-numbered node accessor methods" do parse("a b cc") 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.6.12/spec/compiler/semantic_predicate_spec.rb000066400000000000000000000136531433777471000232360ustar00rootroot00000000000000require '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 == 1 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 == 1 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 one terminal_failure 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 == 1 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 # We should get "prior " failed, and also the predicate block terminal_failures.size.should == 2 terminal_failures[0].index.should == 0 terminal_failures[0].expected_string.should == '"prior "' terminal_failures[1].index.should == 0 terminal_failures[1].expected_string.should == '' 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 == 1 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 == 1 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 one terminal_failure 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 == 1 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 == 2 terminal_failures[0].index.should == 0 terminal_failures[0].expected_string.should == '"prior "' end end end end treetop-1.6.12/spec/compiler/sequence_spec.rb000066400000000000000000000112141433777471000212120ustar00rootroot00000000000000require '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.6.12/spec/compiler/terminal_spec.rb000066400000000000000000000130401433777471000212140ustar00rootroot00000000000000require 'spec_helper' module TerminalSymbolSpec class Foo < Treetop::Runtime::SyntaxNode end describe "a terminal symbol" do testing_expression "'Foo'" it "matches the input string" do parse "Foo", :index => 0 do |result| result.should_not be_nil result.interval.should == (0...3) result.text_value.should == 'Foo' end end it "fails to match the input string other than at the start" do parse " Foo", :index => 0 do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end it "fails to match the input string in the wrong case" do parse "foo", :index => 0 do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end end describe "a terminal symbol with case-insensitive matching" do testing_expression "'Foo'i" it "matches the input string in the same case" do parse "Foo", :index => 0 do |result| result.should_not be_nil result.interval.should == (0...3) result.text_value.should == 'Foo' end end it "matches the input string in varied case" do parse "foO", :index => 0 do |result| result.should_not be_nil result.interval.should == (0...3) result.text_value.should == 'foO' end end 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) do |result| result.should be_nil parser.terminal_failures.size.should == 1 end 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 terminal regexp" do testing_expression "'Fo+'r" it "matches the input string" do parse "Fooo", :index => 0 do |result| result.should_not be_nil result.interval.should == (0...4) result.text_value.should == 'Fooo' end end it "fails to match the input string other than at the start" do parse " Foo", :index => 0 do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end it "fails to match the input string in the wrong case" do parse "foo", :index => 0 do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end end describe "a case-insensitive terminal regexp" do testing_expression "'Fo+'ri" it "matches the input string in the same case" do parse "Fooo", :index => 0 do |result| result.should_not be_nil result.interval.should == (0...4) result.text_value.should == 'Fooo' end end it "matches the input string in the same case" do parse "foOo", :index => 0 do |result| result.should_not be_nil result.interval.should == (0...4) result.text_value.should == 'foOo' end end end # Transient symbols were part of some idea of Nathan's that I no longer recall # 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_truthy # parse("-foo", :index => 1).should be_truthy # parse("---foo", :index => 3).should be_truthy # end # end end treetop-1.6.12/spec/compiler/terminal_symbol_spec.rb000066400000000000000000000025351433777471000226100ustar00rootroot00000000000000require '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) do |result| result.should be_nil parser.terminal_failures.size.should == 1 end end end end treetop-1.6.12/spec/compiler/test_grammar.treetop000066400000000000000000000001101433777471000221250ustar00rootroot00000000000000module Test grammar Grammar rule foo 'foo' end end endtreetop-1.6.12/spec/compiler/test_grammar.tt000066400000000000000000000001101433777471000210720ustar00rootroot00000000000000class Test grammar Grammar rule foo 'foo' end end end treetop-1.6.12/spec/compiler/test_grammar_do.treetop000066400000000000000000000001171433777471000226160ustar00rootroot00000000000000module Test grammar Grammar do rule foo do 'foo' end end end treetop-1.6.12/spec/compiler/test_grammar_magic_coding.treetop000066400000000000000000000001371433777471000246210ustar00rootroot00000000000000# coding: UTF-8 module Test grammar Grammar do rule foo do 'foo' end end end treetop-1.6.12/spec/compiler/test_grammar_magic_encoding.treetop000066400000000000000000000001411433777471000251370ustar00rootroot00000000000000# encoding: UTF-8 module Test grammar Grammar do rule foo do 'foo' end end end treetop-1.6.12/spec/compiler/tt_compiler_spec.rb000066400000000000000000000170451433777471000217330ustar00rootroot00000000000000require '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.exist?(@test_grammar) end after(:each) do # cleanup test grammar and parser output files File.delete(@test_grammar) if File.exist?(@test_grammar) File.delete(@test_ruby) if File.exist?(@test_ruby) end it 'can compile a grammar file' do # puts %q{emulate 'tt dumb.tt'} system("ruby -S tt #{@test_grammar}").should be_truthy File.exist?(@test_ruby).should be_truthy File.zero?(@test_ruby).should_not be_truthy 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_truthy File.exist?(@test_ruby).should be_truthy File.zero?(@test_ruby).should_not be_truthy 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_truthy File.exist?(@test_ruby).should be_truthy File.zero?(@test_ruby).should_not be_truthy end it 'can compile without explicit file extensions' do # puts %q{emulate 'tt dumb'} system("ruby -S tt #{@test_path}").should be_truthy File.exist?(@test_ruby).should be_truthy File.zero?(@test_ruby).should_not be_truthy 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.exist?("#{@test_base}.rb").should be_falsey 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_truthy File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy ensure File.delete(pf) if File.exist?(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_truthy File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy # 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.exist?(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_truthy File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy 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_truthy Digest::SHA1.hexdigest(File.read(pf)).should == orig_file_hash ensure File.delete(pf) if File.exist?(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_truthy File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy orig_file_hash = Digest::SHA1.hexdigest(File.read(pf)) system("ruby -S tt -f #{@test_path}").should be_truthy 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.exist?(grammar_file) end end after(:each) do # cleanup test grammar and output parser files @test_grammars.each { |f| File.delete(f) if File.exist?(f) } @test_bases.each { |f| File.delete("#{f}.rb") if File.exist?("#{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_truthy @test_bases.each do |f| pf = "#{f}.rb" File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy 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_truthy @test_bases.each do |f| pf = "#{f}.rb" File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy 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_truthy File.exist?('not_here.rb').should_not be_truthy File.exist?('bad_ext.rb').should_not be_truthy @test_bases.each do |f| pf = "#{f}.rb" File.exist?(pf).should be_truthy File.zero?(pf).should_not be_truthy 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_falsey File.exist?(pf).should be_falsey end end end treetop-1.6.12/spec/compiler/zero_or_more_spec.rb000066400000000000000000000037221433777471000221100ustar00rootroot00000000000000require '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 b_method; end } )* { def a_method; end }' # testing_expression '("foo" { def a_method; end } )* ' 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" / "bb")*' it "successfully parses matching input" do parse('abba').should_not be_nil end end end treetop-1.6.12/spec/composition/000077500000000000000000000000001433777471000165755ustar00rootroot00000000000000treetop-1.6.12/spec/composition/a.treetop000066400000000000000000000001521433777471000204170ustar00rootroot00000000000000module Test grammar A rule a 'a' end rule inherit 'super' end end endtreetop-1.6.12/spec/composition/b.treetop000066400000000000000000000001641433777471000204230ustar00rootroot00000000000000module Test grammar B rule b 'bb' end rule inherit super 'keyword' end end end treetop-1.6.12/spec/composition/c.treetop000066400000000000000000000001431433777471000204210ustar00rootroot00000000000000module Test grammar C include A include B rule c a b 'c' end end endtreetop-1.6.12/spec/composition/d.treetop000066400000000000000000000001571433777471000204270ustar00rootroot00000000000000module Test grammar D include A include B rule inherit super 'works' end end endtreetop-1.6.12/spec/composition/f.treetop000066400000000000000000000003421433777471000204250ustar00rootroot00000000000000 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.6.12/spec/composition/grammar_composition_spec.rb000066400000000000000000000020201433777471000241770ustar00rootroot00000000000000require '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('abbc').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('abbcef').should_not be_nil end end end treetop-1.6.12/spec/composition/subfolder/000077500000000000000000000000001433777471000205625ustar00rootroot00000000000000treetop-1.6.12/spec/composition/subfolder/e_includes_c.treetop000066400000000000000000000002501433777471000245770ustar00rootroot00000000000000require File.dirname(__FILE__) + "/../c" module Test grammar E include C rule e 'e' end rule inherit 'super' end end end treetop-1.6.12/spec/ruby_extensions/000077500000000000000000000000001433777471000174725ustar00rootroot00000000000000treetop-1.6.12/spec/ruby_extensions/string_spec.rb000066400000000000000000000014251433777471000223410ustar00rootroot00000000000000require '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.6.12/spec/runtime/000077500000000000000000000000001433777471000157155ustar00rootroot00000000000000treetop-1.6.12/spec/runtime/compiled_parser_spec.rb000066400000000000000000000073141433777471000224310ustar00rootroot00000000000000require '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 'bb' 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('bb', :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('bb').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)" 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 describe "a SyntaxNode" do attr_reader :parser testing_grammar %{ grammar Alternates rule main aa &{|s| s[0].elements[0].parent.should == s[0] } / ab &{|s| s[0].elements[0].parent.should == s[0] } end rule aa 'a' 'a' end rule ab 'a' 'b' end end } before do @parser = parser_class_under_test.new end it "should have its parent set and reset" do parser.parse('ab') end end end treetop-1.6.12/spec/runtime/syntax_node_spec.rb000066400000000000000000000041751433777471000216160ustar00rootroot00000000000000require '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.6.12/spec/spec_helper.rb000066400000000000000000000060751433777471000170600ustar00rootroot00000000000000require 'rubygems' require 'benchmark' require 'rspec' require 'rspec/core/shared_context' require 'polyglot' $LOAD_PATH.unshift File.expand_path('../../lib') require 'treetop' include Treetop # We're still using the old expect syntax: RSpec.configure do |c| c.expect_with(:rspec) { |c| c.syntax = :should } end module Treetop module ExampleGroupInstanceMethods module ClassMethods attr_accessor :parser_class_under_test attr_accessor :parser_text attr_accessor :parser_code 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) self.parser_text = grammar_under_test grammar_node = parse_with_metagrammar(grammar_under_test.strip, :module_or_grammar) self.parser_code = grammar_node.compile class_eval(self.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|2\.)/ && '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.6.12/treetop.gemspec000066400000000000000000000022761433777471000163360ustar00rootroot00000000000000# -*- encoding: utf-8 -*- lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'date' require 'treetop/version' Gem::Specification.new do |spec| spec.name = "treetop" spec.version = Treetop::VERSION::STRING spec.authors = ["Nathan Sobo", "Clifford Heath"] spec.email = "cliffordheath@gmail.com" spec.date = Date.today.strftime("%F") spec.summary = "A Ruby-based text parsing and interpretation DSL" spec.description = "A Parsing Expression Grammar (PEG) Parser generator DSL for Ruby" spec.homepage = "https://github.com/cjheath/treetop" spec.licenses = ["MIT"] spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|website|script|\.|benchmark)}) } spec.executables = ["tt"] spec.require_paths = ["lib"] spec.extra_rdoc_files = [ "LICENSE", "README.md" ] spec.add_runtime_dependency(%q, ["~> 0.3"]) spec.add_development_dependency(%q, [">= 4"]) spec.add_development_dependency(%q, ["~> 1.0"]) spec.add_development_dependency(%q, ["~> 3.0"]) spec.add_development_dependency(%q, ["~> 3"]) spec.add_development_dependency(%q, [">= 11"]) end