├── .gitignore ├── ziffers.png ├── Cheatsheet.pdf ├── vendor ├── treetop │ ├── lib │ │ ├── treetop │ │ │ ├── ruby_extensions.rb │ │ │ ├── version.rb │ │ │ ├── runtime │ │ │ │ ├── interval_skip_list.rb │ │ │ │ ├── interval_skip_list │ │ │ │ │ ├── head_node.rb │ │ │ │ │ └── node.rb │ │ │ │ ├── terminal_syntax_node.rb │ │ │ │ ├── terminal_parse_failure.rb │ │ │ │ └── syntax_node.rb │ │ │ ├── compiler │ │ │ │ ├── node_classes │ │ │ │ │ ├── treetop_file.rb │ │ │ │ │ ├── transient_prefix.rb │ │ │ │ │ ├── parenthesized_expression.rb │ │ │ │ │ ├── atomic_expression.rb │ │ │ │ │ ├── nonterminal.rb │ │ │ │ │ ├── optional.rb │ │ │ │ │ ├── declaration_sequence.rb │ │ │ │ │ ├── inline_module.rb │ │ │ │ │ ├── anything_symbol.rb │ │ │ │ │ ├── grammar.rb │ │ │ │ │ ├── predicate_block.rb │ │ │ │ │ ├── character_class.rb │ │ │ │ │ ├── choice.rb │ │ │ │ │ ├── predicate.rb │ │ │ │ │ ├── terminal.rb │ │ │ │ │ ├── parsing_rule.rb │ │ │ │ │ ├── sequence.rb │ │ │ │ │ ├── repetition.rb │ │ │ │ │ └── parsing_expression.rb │ │ │ │ ├── lexical_address_space.rb │ │ │ │ ├── node_classes.rb │ │ │ │ ├── grammar_compiler.rb │ │ │ │ └── ruby_builder.rb │ │ │ ├── runtime.rb │ │ │ ├── polyglot.rb │ │ │ ├── compiler.rb │ │ │ ├── ruby_extensions │ │ │ │ └── string.rb │ │ │ └── bootstrap_gen_1_metagrammar.rb │ │ └── treetop.rb │ ├── .travis.yml │ ├── spec │ │ ├── compiler │ │ │ ├── test_grammar.treetop │ │ │ ├── test_grammar.tt │ │ │ ├── test_grammar_do.treetop │ │ │ ├── test_grammar_magic_coding.treetop │ │ │ ├── test_grammar_magic_encoding.treetop │ │ │ ├── failure_propagation_functional_spec.rb │ │ │ ├── repeated_subrule_spec.rb │ │ │ ├── circular_compilation_spec.rb │ │ │ ├── namespace_spec.rb │ │ │ ├── parenthesized_expression_spec.rb │ │ │ ├── grammar_spec.rb │ │ │ ├── nonterminal_symbol_spec.rb │ │ │ ├── optional_spec.rb │ │ │ ├── and_predicate_spec.rb │ │ │ ├── one_or_more_spec.rb │ │ │ ├── multibyte_chars_spec.rb │ │ │ ├── terminal_symbol_spec.rb │ │ │ ├── not_predicate_spec.rb │ │ │ ├── parsing_rule_spec.rb │ │ │ ├── anything_symbol_spec.rb │ │ │ ├── zero_or_more_spec.rb │ │ │ ├── choice_spec.rb │ │ │ ├── grammar_compiler_spec.rb │ │ │ └── sequence_spec.rb │ │ ├── composition │ │ │ ├── c.treetop │ │ │ ├── a.treetop │ │ │ ├── d.treetop │ │ │ ├── b.treetop │ │ │ ├── subfolder │ │ │ │ └── e_includes_c.treetop │ │ │ ├── f.treetop │ │ │ └── grammar_composition_spec.rb │ │ ├── ruby_extensions │ │ │ └── string_spec.rb │ │ ├── runtime │ │ │ ├── syntax_node_spec.rb │ │ │ └── compiled_parser_spec.rb │ │ └── spec_helper.rb │ ├── examples │ │ ├── lambda_calculus │ │ │ ├── lambda_calculus_node_classes.rb │ │ │ ├── arithmetic_node_classes.rb │ │ │ ├── test_helper.rb │ │ │ ├── arithmetic_test.rb │ │ │ ├── arithmetic.treetop │ │ │ ├── lambda_calculus_test.rb │ │ │ └── lambda_calculus.treetop │ │ └── indented_blocks │ │ │ ├── indented_blocks_test.rb │ │ │ └── indented_blocks.tt │ ├── Treetop.tmbundle │ │ ├── Support │ │ │ ├── nibs │ │ │ │ └── SyntaxTreeViewer.nib │ │ │ │ │ └── keyedobjects.nib │ │ │ └── syntax_tree_viewer.rb │ │ ├── info.plist │ │ ├── Snippets │ │ │ ├── rule ___ end.tmSnippet │ │ │ └── grammar ___ end.tmSnippet │ │ └── Preferences │ │ │ └── Comments.tmPreferences │ ├── Gemfile │ ├── script │ │ ├── svnrm │ │ ├── svnadd │ │ └── generate_metagrammar.rb │ ├── benchmark │ │ ├── seqpar.treetop │ │ ├── seqpar.gnuplot │ │ └── seqpar_benchmark.rb │ ├── History.txt │ ├── LICENSE │ ├── treetop.gemspec │ ├── Rakefile │ ├── doc │ │ ├── grammar_composition.markdown │ │ ├── tt.1 │ │ ├── index.markdown │ │ ├── pitfalls_and_advanced_techniques.markdown │ │ └── using_in_ruby.markdown │ └── bin │ │ └── tt └── polyglot │ ├── lib │ ├── polyglot │ │ └── version.rb │ └── polyglot.rb │ ├── License.txt │ ├── Rakefile │ ├── website │ ├── template.rhtml │ ├── index.txt │ ├── stylesheets │ │ └── screen.css │ └── index.html │ ├── History.txt │ ├── script │ └── txt2html │ └── README.txt ├── load_libs.rb ├── examples ├── multiplying_lambda_loop.rb ├── custom_lambda_progression.rb ├── cowbell_synth_example.rb ├── simple_cycles.rb ├── ziffers_with_define.rb ├── moonlight_loop.rb ├── solfeggio_2.rb ├── solfeggio.rb ├── royal_theme_loop.rb ├── fibonacci_chords.rb ├── keyboard_input.rb ├── solfeggio_3.rb ├── canone.rb ├── ievan_polka.rb ├── not_tested │ ├── kircher │ │ └── test_kircher.rb │ └── ziffers_keyboard.rb ├── pitch_helper.rb ├── markov_chain.rb └── avril14th.rb ├── CITATION.cff ├── test ├── play_loop_tests.rb └── run_wiki_test_multi.rb ├── lib ├── parser │ ├── repeats.treetop │ ├── scala.rb │ ├── scala.treetop │ └── parameters.treetop └── monkeypatches.rb ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ziffers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiika/ziffers/HEAD/ziffers.png -------------------------------------------------------------------------------- /Cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiika/ziffers/HEAD/Cheatsheet.pdf -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/ruby_extensions.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/ruby_extensions/string' 2 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/runtime' 2 | require 'treetop/compiler' 3 | require 'treetop/polyglot' 4 | -------------------------------------------------------------------------------- /vendor/treetop/.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | rvm: 4 | - 2.1 5 | - 2.0 6 | - 1.9.3 7 | - rbx-2 8 | - jruby 9 | -------------------------------------------------------------------------------- /load_libs.rb: -------------------------------------------------------------------------------- 1 | Dir["#{File.expand_path("../vendor", __FILE__)}/*/lib/"].each do |vendor_lib| 2 | $:.unshift vendor_lib 3 | end 4 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/test_grammar.treetop: -------------------------------------------------------------------------------- 1 | module Test 2 | grammar Grammar 3 | rule foo 4 | 'foo' 5 | end 6 | end 7 | end -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/test_grammar.tt: -------------------------------------------------------------------------------- 1 | class Test 2 | grammar Grammar 3 | rule foo 4 | 'foo' 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/test_grammar_do.treetop: -------------------------------------------------------------------------------- 1 | module Test 2 | grammar Grammar do 3 | rule foo do 4 | 'foo' 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/lambda_calculus_node_classes.rb: -------------------------------------------------------------------------------- 1 | module LambdaCalculus 2 | class Application < Treetop::Runtime::SyntaxNode 3 | 4 | end 5 | end -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/c.treetop: -------------------------------------------------------------------------------- 1 | module Test 2 | grammar C 3 | include A 4 | include B 5 | 6 | rule c 7 | a b 'c' 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/test_grammar_magic_coding.treetop: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | module Test 3 | grammar Grammar do 4 | rule foo do 5 | 'foo' 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/test_grammar_magic_encoding.treetop: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Test 3 | grammar Grammar do 4 | rule foo do 5 | 'foo' 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/a.treetop: -------------------------------------------------------------------------------- 1 | module Test 2 | grammar A 3 | rule a 4 | 'a' 5 | end 6 | 7 | rule inherit 8 | 'super' 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/d.treetop: -------------------------------------------------------------------------------- 1 | module Test 2 | grammar D 3 | include A 4 | include B 5 | 6 | rule inherit 7 | super 'works' 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /examples/multiplying_lambda_loop.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | use_bpm 200 4 | 5 | z1 "q1 e3 q4", seed: 1, rules: { 6 | /([a-z])*([1-9]*)/=> ->(i,m){ m[1]+(m[2].to_i*2%7).to_s } 7 | } 8 | -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/b.treetop: -------------------------------------------------------------------------------- 1 | module Test 2 | grammar B 3 | rule b 4 | 'bb' 5 | end 6 | 7 | rule inherit 8 | super 'keyword' 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /vendor/treetop/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiika/ziffers/HEAD/vendor/treetop/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/keyedobjects.nib -------------------------------------------------------------------------------- /examples/custom_lambda_progression.rb: -------------------------------------------------------------------------------- 1 | 2 | load "~/ziffers/ziffers.rb" 3 | 4 | seq = [->n{n+2},->n{n-2},->n{n+rrand_i(-8,1)},->n{n/2}].ring.reflect 5 | 6 | 1.upto(50) do |m| 7 | zplay seq.tick(:note).(m).to_s 8 | end 9 | -------------------------------------------------------------------------------- /vendor/polyglot/lib/polyglot/version.rb: -------------------------------------------------------------------------------- 1 | module Polyglot #:nodoc: 2 | module VERSION #:nodoc: 3 | MAJOR = 0 4 | MINOR = 3 5 | TINY = 5 6 | 7 | STRING = [MAJOR, MINOR, TINY].join('.') 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/version.rb: -------------------------------------------------------------------------------- 1 | module Treetop #:nodoc: 2 | module VERSION #:nodoc: 3 | MAJOR = 1 4 | MINOR = 6 5 | TINY = 12 6 | 7 | STRING = [MAJOR, MINOR, TINY].join('.') 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime/interval_skip_list.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/runtime/interval_skip_list/interval_skip_list' 2 | require 'treetop/runtime/interval_skip_list/head_node' 3 | require 'treetop/runtime/interval_skip_list/node' 4 | -------------------------------------------------------------------------------- /vendor/treetop/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem "polyglot", "~> 0.3" 4 | 5 | gemspec 6 | 7 | group :website do 8 | platforms :ruby do 9 | gem "bluecloth", "~> 2" 10 | gem "erector", "~> 0.8" 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /examples/cowbell_synth_example.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | use_bpm 200 4 | 5 | live_loop :te do 6 | zplay "q 4 4 3 e 4 5 0 1 2 1 2 3 4 5 q 2 2 3 e 4 5 [q 6 6 5 4,e 6 4 5 3 4 2 3 2,e (0..8)~]", sample: :drum_cowbell, rate_based: true 7 | end 8 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/treetop_file.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class TreetopFile < Runtime::SyntaxNode 4 | def compile 5 | (elements.map {|elt| elt.compile}).join 6 | end 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /vendor/treetop/script/svnrm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w 2 | 3 | def missing_files 4 | `svn status`. 5 | select { |line| line =~ /^\!/ }. 6 | collect { |line| line[7..-1] } 7 | end 8 | 9 | missing_files.each do |file| 10 | `svn rm #{file}` 11 | end -------------------------------------------------------------------------------- /examples/simple_cycles.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | z1 "q 1 2 3 4", key: :g, seed: 1, 4 | cycle: [ 5 | { at: 2, offset: ->(i){i%10}, inverse: true }, 6 | { at: 4, first: 2, retrograde: 2, inverse: -1 }, 7 | { at: 8, from: 6, to: 7, inverse: 3 } 8 | ] 9 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/ruby_extensions' 2 | 3 | require 'treetop/runtime/compiled_parser' 4 | require 'treetop/runtime/syntax_node' 5 | require 'treetop/runtime/terminal_parse_failure' 6 | require 'treetop/runtime/interval_skip_list' 7 | -------------------------------------------------------------------------------- /vendor/treetop/script/svnadd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w 2 | 3 | def unversioned_files 4 | `svn status`. 5 | select { |line| line =~ /^\?/ }. 6 | collect { |line| line[7..-1] } 7 | end 8 | 9 | unversioned_files.each do |file| 10 | `svn add #{file}` 11 | end -------------------------------------------------------------------------------- /examples/ziffers_with_define.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | define :foo do 4 | zplay "s123" 5 | end 6 | 7 | define :bar do |v=nil| 8 | zplay v ? v.to_s : "s531" 9 | end 10 | 11 | zplay "q F B F e B B B", F: :foo, B: :bar 12 | 13 | zplay "e:foo:bar(342) n:bar(012) :bar(438)" 14 | -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/subfolder/e_includes_c.treetop: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + "/../c" 2 | 3 | module Test 4 | grammar E 5 | include C 6 | 7 | rule e 8 | 'e' 9 | end 10 | 11 | rule inherit 12 | 'super' 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/polyglot.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Polyglot 3 | VALID_GRAMMAR_EXT = ['treetop', 'tt'] 4 | VALID_GRAMMAR_EXT_REGEXP = /\.(#{VALID_GRAMMAR_EXT.join('|')})\Z/o 5 | end 6 | end 7 | 8 | require 'polyglot' 9 | Polyglot.register(Treetop::Polyglot::VALID_GRAMMAR_EXT, Treetop) 10 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/transient_prefix.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class TransientPrefix < ParsingExpression 4 | def compile(address, builder, parent_expression) 5 | parent_expression.prefixed_expression.compile(address, builder) 6 | end 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /examples/moonlight_loop.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | use_synth :piano 4 | use_bpm 100 5 | 6 | zloop :moonlight, "h 07 [: (-3 0 2) :4] -16 [: (-3 0 2) :4] -25 [: (-2 0 2) :] -43 [: (-2 b1 3) :] -34 (-3 #-1 3) (-3 0 2) -34 (-3 0 #1) (-4 -1 1)", 7 | key: :cs4, scale: :minor, release: 4, sustain: 3, decay: 1, 8 | chord_key: :cs2 9 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/ruby_extensions' 2 | 3 | require 'treetop/compiler/lexical_address_space' 4 | require 'treetop/compiler/ruby_builder' 5 | require 'treetop/compiler/node_classes' 6 | require 'treetop/compiler/metagrammar' unless defined?($exclude_metagrammar) 7 | require 'treetop/compiler/grammar_compiler' 8 | -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/f.treetop: -------------------------------------------------------------------------------- 1 | 2 | require "a" 3 | 4 | require File.dirname(__FILE__) + "/b" 5 | require File.dirname(__FILE__) + "/subfolder/e_includes_c" 6 | 7 | module Test 8 | grammar F 9 | include A 10 | include B 11 | include E 12 | 13 | rule f 14 | c e 'f' 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/arithmetic_node_classes.rb: -------------------------------------------------------------------------------- 1 | module Arithmetic 2 | class BinaryOperation < Treetop::Runtime::SyntaxNode 3 | def eval(env={}) 4 | tail.elements.inject(head.eval(env)) do |value, element| 5 | element.operator.apply(value, element.operand.eval(env)) 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /examples/solfeggio_2.rb: -------------------------------------------------------------------------------- 1 | 2 | Ziffers.set_default_opts(synth: :hollow, sustain: 3.0, duration: 0.5, scale: :minor) 3 | 4 | z1 "^0 r ^2 r r r r r r", rotate: 1, store: true 5 | z2 " r _1 r r r _6 r r _0", rotate: 1, store: true 6 | z3 " r r __3 r _5 r __0 r __2", rotate: 1, store: true 7 | z4 " r r r 4 r r r 1 r", rotate: 1, store: true 8 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | message: "Please cite Ziffers as below:" 3 | authors: 4 | - family-names: "Alonen" 5 | given-names: "Miika" 6 | orcid: "https://orcid.org/0000-0002-0065-0017" 7 | title: "Ziffers: Numbered notation for algorithmic composition" 8 | version: 2.0 9 | date-released: 2022-12-12 10 | url: "https://github.com/amiika/ziffers" 11 | -------------------------------------------------------------------------------- /examples/solfeggio.rb: -------------------------------------------------------------------------------- 1 | # Simple example inspired by Arvo Pärt's Solfeggio 2 | 3 | Ziffers.set_default_opts(synth: :hollow, sustain: 1.5) 4 | 5 | z1 "0 r r r r 5 r r r r 4 r r r r 2 r r r 6" 6 | z2 "r 1 r r r r 6 r r r r r r r 1 r 3 r r r", octave: -1 7 | z3 "r r 2 r 4 r r r 2 r r 5 r 0 r r r 4 r r", octave: -2 8 | z4 "r r r 3 r r r 1 r 3 r r 6 r r r r r 5 r", octave: -3 9 | -------------------------------------------------------------------------------- /examples/royal_theme_loop.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | use_bpm 140 4 | royal_theme = zparse "h 0 2 | 4 5 | #-1 q r 4 | h #3 3 | #2 b2 | q 2 1 b1 0 | q #-1 e #-2 #-3 q 0 3 | h 2 1 | w 0 |", scale: :minor 5 | 6 | z0 royal_theme, synth: :piano 7 | z1 royal_theme, phase: 0.15, synth: :kalimba 8 | z2 royal_theme, phase: 0.25, synth: :piano, octave: -1: :fm, octave: -1 9 | -------------------------------------------------------------------------------- /vendor/treetop/Treetop.tmbundle/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Treetop 7 | uuid 8 | 83A8B700-143D-4BD6-B4EA-D73796E8F883 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/fibonacci_chords.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | # Good 'old' way to use enumerations 4 | 5 | def fibonacci 6 | Enumerator.new do |y| 7 | a = b = 1 8 | while true 9 | y << a 10 | a, b = b, a + b 11 | end 12 | end 13 | end 14 | 15 | enum = fibonacci 16 | 17 | live_loop :fibonacci_chords do 18 | zplay enum, duration: 0.5, parse_chord: true 19 | end 20 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/lexical_address_space.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class LexicalAddressSpace 4 | def initialize 5 | reset_addresses 6 | end 7 | 8 | def next_address 9 | @next_address += 1 10 | end 11 | 12 | def reset_addresses 13 | @next_address = -1 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /test/play_loop_tests.rb: -------------------------------------------------------------------------------- 1 | 2 | def loop_tests 3 | z1 "0", stop: 1 4 | z2 ->(){rrand_i(1,4)}, stop: 1 5 | z3 (0..Float::INFINITY).lazy.collect{|n|n.to_s(2).split('').count('1')%7}, rhythm:spread(7,9), stop: 1 6 | z4 pi.take(1), scale: :kumoi, synth: :tb303, rhythm: 0.125, cutoff: tweak(:sine,60,100,10).reflect, stop: 1 7 | z5 "q0", rules: {"q"=>"e", "e"=>"q"}, stop: 1 8 | end 9 | 10 | loop_tests 11 | -------------------------------------------------------------------------------- /vendor/treetop/benchmark/seqpar.treetop: -------------------------------------------------------------------------------- 1 | grammar SeqPar 2 | 3 | rule statement 4 | 'par ' (statement ' ')+ 'end' 5 | / 'sequence' ' ' (statement ' ')+ 'end' 6 | / 'seq' ' ' (statement ' ')+ 'end' 7 | / ('fit' [\s] (statement ' ')+ 'end') { 8 | def foo 9 | "foo" 10 | end 11 | } 12 | / 'art'+ [ ] (statement ' ')+ 'end' 13 | / [A-Z] [a-zA-z0-9]* 14 | end 15 | 16 | end -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime/interval_skip_list/head_node.rb: -------------------------------------------------------------------------------- 1 | class IntervalSkipList 2 | class HeadNode 3 | attr_reader :height, :forward, :forward_markers 4 | 5 | def initialize(height) 6 | @height = height 7 | @forward = Array.new(height, nil) 8 | @forward_markers = Array.new(height) {|i| []} 9 | end 10 | 11 | def top_level 12 | height - 1 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /examples/keyboard_input.rb: -------------------------------------------------------------------------------- 1 | require "~/ziffers/ziffers.rb" 2 | 3 | # Play ziffers using keyboard 4 | # On windows: https://in-thread.sonic-pi.net/t/connecting-sonic-pi-to-virtual-midi-piano-keyboard-on-windows-10/176 5 | 6 | live_loop :midi_piano do 7 | use_real_time 8 | note, velocity = sync "/midi/loopmidi_port/0/1/note_on" 9 | print note 10 | zmidi note, {sample: :ambi_glass_rub, key: :e}, {rateBased: true} 11 | end 12 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/parenthesized_expression.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class ParenthesizedExpression < ParsingExpression 4 | def compile(address, builder, parent_expression = nil) 5 | elements[2].compile(address, builder, parent_expression) 6 | end 7 | 8 | def expected 9 | elements[2].expected 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /vendor/treetop/benchmark/seqpar.gnuplot: -------------------------------------------------------------------------------- 1 | f1(x) = a*x 2 | a = 0.5 3 | fit f1(x) 'before.dat' using 1:2 via a 4 | 5 | f2(x) = b*x 6 | b = 0.5 7 | fit f2(x) 'after.dat' using 1:2 via b 8 | 9 | set xlabel "Length of input" 10 | set ylabel "CPU time to parse" 11 | 12 | plot a*x title 'a*x (Before)',\ 13 | b*x title 'b*x (After)',\ 14 | "before.dat" using 1:2 title 'Before', \ 15 | "after.dat" using 1:2 title 'After' -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/atomic_expression.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class AtomicExpression < ParsingExpression 4 | def inline_modules 5 | [] 6 | end 7 | 8 | def single_quote(string) 9 | # Double any backslashes, then backslash any single-quotes: 10 | "'#{string.gsub(/\\/) { '\\\\' }.gsub(/'/) { "\\'"}}'" 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require 'rubygems' 3 | require 'treetop' 4 | 5 | module ParserTestHelper 6 | def assert_evals_to_self(input) 7 | assert_evals_to(input, input) 8 | end 9 | 10 | def parse(input) 11 | result = @parser.parse(input) 12 | unless result 13 | puts @parser.terminal_failures.join("\n") 14 | end 15 | assert !result.nil? 16 | result 17 | end 18 | end -------------------------------------------------------------------------------- /examples/solfeggio_3.rb: -------------------------------------------------------------------------------- 1 | 2 | use_bpm 60 3 | melody = zparse "0..6" 4 | octaves = [0,-2,1,-1,2,0,1] 5 | 6 | # Deal melody to 5 parts (Like dealing cards) 7 | parts = melody.deal 5 8 | 9 | 12.times do 10 | melody.length.times do |i| 11 | parts.each_with_index do |z,j| 12 | zplay z[i], octave: octaves[i+j], synth: :hollow, sustain: 6.0, decay: 4.0, duration: rrand(0.5,1.5) if z[i] 13 | end 14 | end 15 | octaves = octaves.shuffle 16 | end 17 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime/terminal_syntax_node.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Runtime 3 | class TerminalSyntaxNode < SyntaxNode 4 | 5 | def initialize(input, interval) 6 | super(input, interval, []) 7 | end 8 | 9 | def inspect(indent="") 10 | indent+ 11 | self.class.to_s.sub(/.*:/,'') + 12 | " offset=#{interval.first}" + 13 | " #{text_value.inspect}" 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /examples/canone.rb: -------------------------------------------------------------------------------- 1 | 2 | load "~/ziffers/ziffers.rb" 3 | 4 | use_bpm 120 5 | 6 | a = zparse "| q. _ 0 e 0 q 1 e 2 2 | C q _ 3 3 2 e 2 2 | q _ 1 h 4 q 3 | e r s _ 4 3 e 2 s 3 2 h 1 | q. _ 0 e 0 q 1 e 2 2 | w _ 3 |", C: {cue: :foo } 7 | 8 | b = "| q. _ 0 e 0 q 1 e 2 2 | q _ 3 3 2 e 2 2 | q _ 1 h 4 q 3 | e r s _ 4 3 e 2 s 3 2 h 1 | w _ 3 |" 9 | 10 | z1 a, synth: :piano, scale: :minor, inverse: -1 11 | 12 | z2 b, wait: :foo, scale: :minor, synth: :piano, transpose: -3, retrograde: true, inverse: 2 13 | -------------------------------------------------------------------------------- /examples/ievan_polka.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | use_bpm 300 4 | 5 | ievanpolka = \ 6 | "[:q 0 e 0 0 q 0 1 | q 2 0 0 2 | <(q1 _ 6 6 ^1 |q2 0 h0) (q. 4 e3 q 2 1|q 2 0 h0)> :]"\ 7 | "[:q 4 e 4 4 q 3 2 | q 1 _ 6 6 ^1 | <(q3 e3 3 q2 1|q2 0 0 2) (q3 e 3 3 q 2 1|q 2 0 h0)> :]" 8 | 9 | n = zparse ievanpolka, key:"g", scale:"minor" 10 | notes = zparams(n, :note) 11 | durations = zparams(n, :beats) 12 | 13 | with_synth :mod_tri do 14 | play_pattern_timed notes, durations, release: 0.1 15 | end 16 | -------------------------------------------------------------------------------- /vendor/treetop/History.txt: -------------------------------------------------------------------------------- 1 | == 1.4.1 2009-09-04 2 | 3 | * several enhancements: 4 | * Many small-to-medium performance improvements 5 | * Semantic predicates 6 | * Support for UTF-8 characters 7 | * Generation of graphvis DOT files for visualising parse results 8 | * Commandline revamped with help 9 | 10 | == 1.2.5 2009-03-10 11 | 12 | * 1 minor enhancement: 13 | * Extensions may always be modules, instead of sometimes modules, sometimes classes 14 | 15 | == 0.0.1 2008-05-21 16 | 17 | * 1 major enhancement: 18 | * Initial release 19 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime/terminal_parse_failure.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Runtime 3 | class TerminalParseFailure 4 | attr_reader :index, :expected_string, :unexpected 5 | 6 | def initialize(index, expected_string, unexpected = false) 7 | @index = index 8 | @expected_string = expected_string 9 | @unexpected = unexpected 10 | end 11 | 12 | def to_s 13 | "String matching #{expected_string} #{@unexpected ? 'not ' : ''}expected." 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /examples/not_tested/kircher/test_kircher.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/examples/kircher.rb" 2 | 3 | use_bpm 100 4 | 5 | r = 1 6 | 7 | use_synth :hollow 8 | use_synth_defaults release: 2.0 9 | 10 | live_loop :kircher do 11 | r = rand_i(2) 12 | rp = rand_i(2) 13 | print r 14 | m = get_cardset(3)[:cards][r][:p][rp] 15 | rh = get_cardset(4)[:cards][r][:r][rp] 16 | zthread m[1], rhythm: rh[1].map{|v|v/4} 17 | zthread m[2], rhythm: rh[2].map{|v|v/4} 18 | zthread m[3], rhythm: rh[3].map{|v|v/4} 19 | zplay m[0], rhythm: rh[0].map{|v|v/4} 20 | end 21 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/nonterminal.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Nonterminal < AtomicExpression 4 | def compile(address, builder, parent_expression = nil) 5 | super 6 | use_vars :result 7 | assign_result text_value == 'super' ? 'super' : "_nt_#{text_value}" 8 | extend_result_with_declared_module 9 | extend_result_with_inline_module parent_expression 10 | end 11 | 12 | def inline_module 13 | nil 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /vendor/treetop/script/generate_metagrammar.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | require File.expand_path('../../lib/treetop/bootstrap_gen_1_metagrammar', __FILE__) 5 | 6 | GENERATED_METAGRAMMAR_PATH = File.expand_path('../../lib/treetop/compiler/metagrammar.rb') 7 | 8 | File.open(METAGRAMMAR_PATH) do |source_file| 9 | File.open(GENERATED_METAGRAMMAR_PATH, 'w') do |target_file| 10 | generated_source = Treetop::Compiler::MetagrammarParser.new.parse(source_file.read).compile 11 | target_file.write(generated_source) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /vendor/treetop/Treetop.tmbundle/Snippets/rule ___ end.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | rule ${1:rule_name} 7 | $0 8 | end 9 | name 10 | rule ... end 11 | scope 12 | meta.grammar.treetop 13 | tabTrigger 14 | r 15 | uuid 16 | 498A1881-498E-4BDA-9303-7E42B425C5EE 17 | 18 | 19 | -------------------------------------------------------------------------------- /vendor/treetop/examples/indented_blocks/indented_blocks_test.rb: -------------------------------------------------------------------------------- 1 | require 'polyglot' 2 | require 'byebug' 3 | require 'treetop' 4 | require 'indented_blocks' 5 | 6 | parser = IndentedBlocksParser.new 7 | 8 | input = < 2 | 3 | 4 | 5 | content 6 | grammar ${1:GrammarName} 7 | rule ${2:rule_name} 8 | $0 9 | end 10 | end 11 | name 12 | grammar ... end 13 | scope 14 | source.treetop 15 | tabTrigger 16 | g 17 | uuid 18 | 2AE73FBB-88B9-4049-B208-D2440A146164 19 | 20 | 21 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/declaration_sequence.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class DeclarationSequence < Runtime::SyntaxNode 4 | 5 | def compile(builder) 6 | unless rules.empty? 7 | builder.method_declaration("root") do 8 | builder << "@root ||= :#{rules.first.name}" 9 | end 10 | builder.newline 11 | end 12 | 13 | declarations.each do |declaration| 14 | declaration.compile(builder) 15 | builder.newline 16 | end 17 | end 18 | 19 | def rules 20 | declarations.select { |declaration| declaration.instance_of?(ParsingRule) } 21 | end 22 | end 23 | end 24 | end -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/inline_module.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | module InlineModuleMixin 4 | attr_reader :module_name 5 | 6 | def compile(index, builder, rule) 7 | @module_name = "#{rule.name.treetop_camelize}#{index}" 8 | end 9 | end 10 | 11 | class InlineModule < Runtime::SyntaxNode 12 | 13 | include InlineModuleMixin 14 | 15 | def compile(index, builder, rule) 16 | super 17 | builder.module_declaration(module_name) do 18 | builder << ruby_code.gsub(/\A\n/, '').rstrip 19 | end 20 | end 21 | 22 | def ruby_code 23 | elements[1].text_value 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/parser/repeats.treetop: -------------------------------------------------------------------------------- 1 | grammar Repeats 2 | 3 | rule anything 4 | (repeat / any / array)+ 5 | { 6 | def value 7 | elements.map{|v| v.value}.join("") 8 | end 9 | } 10 | end 11 | 12 | rule repeat 13 | '[:' l:(any+) ':' p:([0-9]*) ']' 14 | { 15 | def value 16 | ([l.text_value] * (p.text_value.strip.empty? ? 2 : p.text_value.to_i)).join(" | ") 17 | end 18 | } 19 | end 20 | 21 | rule any 22 | ([!\~&@|{}<>=();#\^_%\n\r\s\t\-\/\*\+\.`´\,\'] / (':'? [a-zA-Z0-9+] ':'?)) 23 | { 24 | def value 25 | text_value 26 | end 27 | } 28 | end 29 | 30 | rule array 31 | '[' any+ ']' 32 | { 33 | def value 34 | text_value 35 | end 36 | } 37 | end 38 | 39 | end 40 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/failure_propagation_functional_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "An expression for braces surrounding zero or more letters followed by semicolons" do 4 | testing_expression "'{' ([a-z] ';')* '}'" 5 | 6 | it "parses matching input successfully" do 7 | parse('{a;b;c;}').should_not be_nil 8 | end 9 | 10 | it "fails to parse input with an expression that is missing a semicolon, reporting the terminal failure occurring at the maximum index" do 11 | parse('{a;b;c}') do |result| 12 | result.should be_nil 13 | 14 | terminal_failures = parser.terminal_failures 15 | terminal_failures.size.should == 1 16 | failure = terminal_failures[0] 17 | failure.index.should == 6 18 | failure.expected_string.should == "';'" 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/repeated_subrule_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module RepeatedSubruleSpec 4 | describe "a repeated subrule" do 5 | testing_grammar %{ 6 | grammar Foo 7 | rule foo 8 | a:'a' space b:'b' space 'cc' 9 | end 10 | 11 | rule space 12 | ' ' 13 | end 14 | end 15 | } 16 | 17 | it "should produce a parser having sequence-numbered node accessor methods" do 18 | parse("a b cc") do |result| 19 | result.should_not be_nil 20 | result.should respond_to(:space1) 21 | result.should respond_to(:space2) 22 | result.should_not respond_to(:space) 23 | result.should respond_to(:a) 24 | result.should respond_to(:b) 25 | result.should_not respond_to(:c) 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /vendor/treetop/Treetop.tmbundle/Preferences/Comments.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Misc 7 | scope 8 | source.treetop 9 | settings 10 | 11 | decreaseIndentPattern 12 | ^\s*end\s*$ 13 | increaseIndentPattern 14 | ^\s*(grammar|rule)\s+\w+\s*$ 15 | shellVariables 16 | 17 | 18 | name 19 | TM_COMMENT_START 20 | value 21 | # 22 | 23 | 24 | 25 | uuid 26 | 1BC307B6-CE08-449E-9074-1AEAA5CE99F4 27 | 28 | 29 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/ruby_extensions/string.rb: -------------------------------------------------------------------------------- 1 | class String 2 | def column_of(index) 3 | return 1 if index == 0 4 | newline_index = rindex("\n", index - 1) 5 | if newline_index 6 | index - newline_index 7 | else 8 | index + 1 9 | end 10 | end 11 | 12 | def line_of(index) 13 | self[0...index].count("\n") + 1 14 | end 15 | 16 | # The following methods are lifted from Facets 2.0.2 17 | def tabto(n) 18 | if self =~ /^( *)\S/ 19 | # Inlined due to collision with ActiveSupport 4.0: indent(n - $1.length) 20 | m = n - $1.length 21 | if m >= 0 22 | gsub(/^/, ' ' * m) 23 | else 24 | gsub(/^ {0,#{-m}}/, "") 25 | end 26 | else 27 | self 28 | end 29 | end 30 | 31 | def treetop_camelize 32 | to_s.gsub(/\/(.?)/){ "::" + $1.upcase }.gsub(/(^|_)(.)/){ $2.upcase } 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/anything_symbol.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class AnythingSymbol < AtomicExpression 4 | def compile(address, builder, parent_expression = nil) 5 | super 6 | builder.if__ "index < input_length" do 7 | if address == 0 || decorated? 8 | assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))" 9 | extend_result_with_inline_module parent_expression 10 | else 11 | assign_lazily_instantiated_node 12 | end 13 | builder << "@index += 1" 14 | end 15 | builder.else_ do 16 | builder << 'terminal_parse_failure("any character")' 17 | assign_result 'nil' 18 | end 19 | end 20 | 21 | def expected 22 | '"any character"' 23 | end 24 | 25 | def inline_module 26 | nil 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /vendor/treetop/spec/ruby_extensions/string_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe String do 4 | before do 5 | @string = %{ 6 | 0123456789 7 | 012345 8 | 01234567 9 | 0123 10 | }.tabto(0).strip 11 | end 12 | 13 | it "can translate indices to column numbers" do 14 | @string.column_of(0).should == 1 15 | @string.column_of(5).should == 6 16 | @string.column_of(10).should == 11 17 | @string.column_of(11).should == 1 18 | @string.column_of(17).should == 7 19 | @string.column_of(18).should == 1 20 | @string.column_of(24).should == 7 21 | end 22 | 23 | it "can translate indices to line numbers" do 24 | @string.line_of(0).should == 1 25 | @string.line_of(5).should == 1 26 | @string.line_of(10).should == 1 27 | @string.line_of(11).should == 2 28 | @string.line_of(17).should == 2 29 | @string.line_of(18).should == 3 30 | @string.line_of(24).should == 3 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/parser/scala.rb: -------------------------------------------------------------------------------- 1 | require "prime" 2 | 3 | def cents_to_semitones(cents) 4 | """Tranform cents to semitones""" 5 | cents = [0.0] + cents unless cents[0] == 0.0 6 | semitone_scale = [] 7 | cents.each_with_index do |cent, i| 8 | break if i == cents.length - 1 9 | semitone_interval = (cents[i + 1] - cent) / 100.0 10 | semitone_scale << semitone_interval 11 | end 12 | semitone_scale 13 | end 14 | 15 | def ratio_to_cents(ratio) 16 | # Transform ratio to cents 17 | (1200.0 * Math.log2(ratio.to_f)) 18 | end 19 | 20 | def monzo_to_cents(monzo) 21 | # Calculate the prime factors of the indices in the monzo 22 | max_index = monzo.length 23 | primes = Prime.first(max_index + 1) 24 | 25 | # Product of the prime factors raised to the corresponding exponents 26 | ratio = 1 27 | 28 | (0...max_index).each do |i| 29 | ratio *= primes[i] ** monzo[i] 30 | end 31 | 32 | # Frequency ratio to cents 33 | 1200 * Math.log2(ratio) 34 | 35 | end 36 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/grammar.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Grammar < Runtime::SyntaxNode 4 | def compile 5 | builder = RubyBuilder.new 6 | 7 | builder.module_declaration "#{grammar_name.text_value}" do 8 | builder.in(indent_level) # account for initial indentation of grammar declaration 9 | builder << "include Treetop::Runtime" 10 | builder.newline 11 | declaration_sequence.compile(builder) 12 | end 13 | builder.newline 14 | builder.class_declaration "#{parser_name} < Treetop::Runtime::CompiledParser" do 15 | builder << "include #{grammar_name.text_value}" 16 | end 17 | end 18 | 19 | def indent_level 20 | input.column_of(interval.begin) - 1 21 | end 22 | 23 | def parser_name 24 | grammar_name.text_value + 'Parser' 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/predicate_block.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class PredicateBlock < ParsingExpression 4 | def compile(index, builder, parent_expression = nil) 5 | super 6 | # REVISIT: This is distinctly dodgey, but since we can only be called from 7 | # two contexts, and it works in both those, I'm going with it for now, as 8 | # opposed to doing the major refactor of providing a proper way of accessing 9 | # the parent's accumulator variable. 10 | p = parent 11 | p = p.parent while p && !p.respond_to?(:accumulator_var) 12 | assign_result "lambda #{text_value}.call(#{p ? p.accumulator_var : ""})" 13 | builder.if_ '!'+result_var do 14 | builder << "terminal_parse_failure(#{expected})" 15 | end 16 | end 17 | 18 | def expected 19 | '""' # Should I include (some of) the text_value here? 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/circular_compilation_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | BENCHMARK = false 4 | METAGRAMMAR_PATH = File.expand_path('../../../lib/treetop/compiler/metagrammar.treetop', __FILE__) 5 | 6 | module CircularCompilationSpec 7 | describe "a parser for the metagrammar" do 8 | attr_reader :parser 9 | 10 | before do 11 | @parser = Treetop::Compiler::MetagrammarParser.new 12 | end 13 | 14 | it "can parse the metagrammar.treetop whence it was generated" do 15 | File.open(METAGRAMMAR_PATH, 'r') do |f| 16 | metagrammar_source = f.read 17 | result = parser.parse(metagrammar_source) 18 | result.should_not be_nil 19 | 20 | # generated_parser = result.compile 21 | # Object.class_eval(generated_parser) 22 | # parser_2 = Treetop::Compiler::MetagrammarParser.new 23 | # optionally_benchmark do 24 | # result = parser_2.parse(metagrammar_source) 25 | # result.should_not be_nil 26 | # end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/namespace_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module NamespaceSpec 4 | 5 | describe "a grammar" do 6 | class_eval("module Foo; end") 7 | testing_grammar %{ 8 | module Foo::Bar 9 | module Baz 10 | grammar Bat 11 | rule foo 12 | bar / baz 13 | end 14 | 15 | rule bar 16 | 'bar' 'bar' 17 | end 18 | 19 | rule baz 20 | 'baz' 'baz' 21 | end 22 | end 23 | end 24 | end 25 | } 26 | 27 | it "parses matching input" do 28 | parse('barbar').should_not be_nil 29 | parse('bazbaz').should_not be_nil 30 | end 31 | 32 | it "mixes in included modules" do 33 | foo = self.class.const_get(:Foo) 34 | bar = foo.const_get(:Bar) 35 | baz = bar.const_get(:Baz) 36 | baz.class.should == Module 37 | bat = baz.const_get(:Bat) 38 | bat.class.should == Module 39 | baz.const_get(:BatParser).class.should == Class 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/parenthesized_expression_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module ParenthesizedExpressionSpec 4 | describe "An unadorned expression inside of parentheses" do 5 | testing_expression '("foo")' 6 | 7 | it "should behave as normal" do 8 | parse('foo').should_not be_nil 9 | end 10 | end 11 | 12 | describe "A prefixed-expression inside of parentheses" do 13 | testing_expression '(!"foo")' 14 | 15 | it "should behave as normal" do 16 | parse('foo') do |result| 17 | result.should be_nil 18 | parser.terminal_failures.size.should == 1 19 | end 20 | end 21 | end 22 | 23 | describe "An expression with code both inside and outside parentheses" do 24 | testing_expression '("foo" { def inner; end } ) { def outer; end} ' 25 | it "should extend both code modules " do 26 | parse('foo') do |result| 27 | skip "Arbitrarily nested modules are not yet compiled" 28 | result.should respond_to(:inner) 29 | result.should respond_to(:outer) 30 | end 31 | end 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/grammar_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module GrammarSpec 4 | module Bar 5 | end 6 | 7 | describe "a grammar" do 8 | testing_grammar %{ 9 | grammar Foo 10 | # This comment should not cause a syntax error, nor should the following empty one 11 | # 12 | include GrammarSpec::Bar 13 | 14 | rule foo 15 | bar / baz 16 | end 17 | 18 | rule bar 19 | 'bar' 'bar' 20 | end 21 | 22 | rule baz 23 | 'baz' 'baz' 24 | end 25 | end 26 | } 27 | 28 | it "parses matching input" do 29 | parse('barbar').should_not be_nil 30 | parse('bazbaz').should_not be_nil 31 | end 32 | 33 | it "fails if it does not parse all input" do 34 | parse('barbarbazbaz') do |result| 35 | result.should be_nil 36 | parser.terminal_failures.size.should == 1 37 | end 38 | end 39 | 40 | it "mixes in included modules" do 41 | self.class.const_get(:Foo).ancestors.should include(GrammarSpec::Bar) 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/compiler/node_classes/parsing_expression' 2 | require 'treetop/compiler/node_classes/atomic_expression' 3 | require 'treetop/compiler/node_classes/inline_module' 4 | require 'treetop/compiler/node_classes/predicate_block' 5 | require 'treetop/compiler/node_classes/treetop_file' 6 | require 'treetop/compiler/node_classes/grammar' 7 | require 'treetop/compiler/node_classes/declaration_sequence' 8 | require 'treetop/compiler/node_classes/parsing_rule' 9 | require 'treetop/compiler/node_classes/parenthesized_expression' 10 | require 'treetop/compiler/node_classes/nonterminal' 11 | require 'treetop/compiler/node_classes/terminal' 12 | require 'treetop/compiler/node_classes/anything_symbol' 13 | require 'treetop/compiler/node_classes/character_class' 14 | require 'treetop/compiler/node_classes/sequence' 15 | require 'treetop/compiler/node_classes/choice' 16 | require 'treetop/compiler/node_classes/repetition' 17 | require 'treetop/compiler/node_classes/optional' 18 | require 'treetop/compiler/node_classes/predicate' 19 | require 'treetop/compiler/node_classes/transient_prefix' 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 amiika 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/treetop/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007 Nathan Sobo. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/polyglot/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007 Clifford Heath 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/nonterminal_symbol_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module NonterminalSymbolSpec 4 | describe "A nonterminal symbol followed by a block" do 5 | testing_expression 'foo { def a_method; end }' 6 | 7 | parser_class_under_test.class_eval do 8 | def _nt_foo 9 | '_nt_foo called' 10 | end 11 | end 12 | 13 | it "compiles to a method call, extending its results with the anonymous module for the block" do 14 | result = parse('') 15 | result.should == '_nt_foo called' 16 | result.should respond_to(:a_method) 17 | end 18 | end 19 | 20 | module TestModule 21 | def a_method 22 | end 23 | end 24 | 25 | describe "a non-terminal followed by a module declaration" do 26 | testing_expression 'foo ' 27 | 28 | parser_class_under_test.class_eval do 29 | def _nt_foo 30 | '_nt_foo called' 31 | end 32 | end 33 | 34 | it "compiles to a method call, extending its results with the anonymous module for the block" do 35 | result = parse('') 36 | result.should == '_nt_foo called' 37 | result.should respond_to(:a_method) 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /vendor/treetop/spec/composition/grammar_composition_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module GrammarCompositionSpec 4 | describe "several composed grammars" do 5 | before do 6 | dir = File.dirname(__FILE__) 7 | Treetop.load File.join(dir, 'a') 8 | Treetop.load File.join(dir, 'b') 9 | Treetop.load File.join(dir, 'c') 10 | # Check that polyglot finds d.treetop and loads it: 11 | $: << dir 12 | require 'd' 13 | 14 | @c = ::Test::CParser.new 15 | @d = ::Test::DParser.new 16 | end 17 | 18 | specify "rules in C have access to rules defined in A and B" do 19 | @c.parse('abbc').should_not be_nil 20 | end 21 | 22 | specify "rules in C can override rules in A and B with super semantics" do 23 | @d.parse('superkeywordworks').should_not be_nil 24 | end 25 | end 26 | 27 | describe "composed grammar chaining with require" do 28 | before do 29 | # Load f with polyglot without using the load path: 30 | require File.dirname(__FILE__) + '/f' 31 | 32 | @f = ::Test::FParser.new 33 | end 34 | 35 | specify "rules in F have access to rule defined in E" do 36 | @f.parse('abbcef').should_not be_nil 37 | end 38 | 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/character_class.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class CharacterClass < AtomicExpression 4 | def compile(address, builder, parent_expression = nil) 5 | super 6 | 7 | builder.if__ "has_terminal?(@regexps[gr = #{grounded_regexp(text_value)}] ||= Regexp.new(gr), :regexp, index)" do 8 | if address == 0 || decorated? 9 | assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))" 10 | extend_result_with_inline_module parent_expression 11 | else 12 | assign_lazily_instantiated_node 13 | end 14 | builder << "@index += 1" # Always one character 15 | end 16 | builder.else_ do 17 | builder << "terminal_parse_failure(#{expected})" 18 | assign_result 'nil' 19 | end 20 | end 21 | 22 | def expected 23 | single_quote('['+characters+']') 24 | end 25 | 26 | def inline_module 27 | nil 28 | end 29 | 30 | def grounded_regexp(string) 31 | # Double any backslashes, then backslash any single-quotes: 32 | "'\\A#{string.gsub(/\\/) { '\\\\' }.gsub(/'/) { "\\'"}}'" 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/optional_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module OptionalSpec 4 | describe "An optional terminal symbol" do 5 | testing_expression '"foo"?' 6 | 7 | it "parses input matching the terminal" do 8 | parse('foo').should_not be_nil 9 | end 10 | 11 | it "parses epsilon, recording a failure" do 12 | parse('') do |result| 13 | result.should_not be_nil 14 | result.interval.should == (0...0) 15 | 16 | terminal_failures = parser.terminal_failures 17 | terminal_failures.size.should == 1 18 | failure = terminal_failures.first 19 | failure.index.should == 0 20 | failure.expected_string.should == '"foo"' 21 | end 22 | end 23 | 24 | it "parses input not matching the terminal, returning an epsilon result and recording a failure" do 25 | parse('bar', :consume_all_input => false) do |result| 26 | result.should_not be_nil 27 | result.interval.should == (0...0) 28 | 29 | terminal_failures = parser.terminal_failures 30 | terminal_failures.size.should == 1 31 | failure = terminal_failures.first 32 | failure.index.should == 0 33 | failure.expected_string.should == '"foo"' 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /examples/pitch_helper.rb: -------------------------------------------------------------------------------- 1 | require "~/ziffers/ziffers.rb" 2 | 3 | # Have a perfect pitch? Find out! 4 | # This pling plong tool can also help you to: 5 | # Relate sound to numbers or note names 6 | # Relate note names to pcs 7 | 8 | # Configuration 9 | pitch_key = :C # Choose key C-B 10 | pitch_scale = :chromatic # Scale :chromatic, :major, :minor, :major_pentatonic, :minor_pentatonic 11 | pitch_octave = 0 # Starting octave 12 | play_scale = true # "Preview" scale before starting 13 | show_degrees = false # Show degrees instead of pcs 14 | number_of_octaves = 1 # More octaves means more fun? 15 | speed = 1.0 # Waiting time for the next note 16 | t_synth = :piano # Change synth 17 | 18 | # Code starts here 19 | notes = scale pitch_key, pitch_scale 20 | zplay "q (0..#{(notes.length-2)*number_of_octaves})", synth: t_synth, octave: pitch_octave, scale: pitch_scale, key: pitch_key if play_scale 21 | 22 | live_loop :run_trainer do 23 | sleep speed 24 | random = (rrand_i 0, (notes.length-2)*number_of_octaves) 25 | r = zparse "{#{random}}", synth: t_synth, octave: pitch_octave, scale: pitch_scale, key: pitch_key 26 | zplay r 27 | sleep speed 28 | if show_degrees 29 | print "Scale degree: #{r[0].dgr}" 30 | else 31 | print "Pitch class: #{r[0].pc}" 32 | end 33 | print "Note name: #{r[0].note_name}" 34 | end 35 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/and_predicate_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module AndPredicateSpec 4 | describe "An &-predicated terminal symbol" do 5 | testing_expression '&"foo"' 6 | 7 | it "successfully parses input matching the terminal symbol, returning an epsilon syntax node" do 8 | parse('foo', :consume_all_input => false) do |result| 9 | result.should_not be_nil 10 | result.interval.should == (0...0) 11 | end 12 | end 13 | end 14 | 15 | describe "A sequence of a terminal and an and another &-predicated terminal" do 16 | testing_expression '"foo" &"bar"' 17 | 18 | it "matches input matching both terminals, but only consumes the first" do 19 | parse('foobar', :consume_all_input => false) do |result| 20 | result.should_not be_nil 21 | result.text_value.should == 'foo' 22 | end 23 | end 24 | 25 | it "fails to parse input matching only the first terminal, with a terminal failure recorded at index 3" do 26 | parse('foo') do |result| 27 | result.should be_nil 28 | terminal_failures = parser.terminal_failures 29 | terminal_failures.size.should == 1 30 | failure = terminal_failures[0] 31 | failure.index.should == 3 32 | failure.expected_string.should == '"bar"' 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /vendor/treetop/treetop.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'date' 5 | require 'treetop/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = "treetop" 9 | spec.version = Treetop::VERSION::STRING 10 | spec.authors = ["Nathan Sobo", "Clifford Heath"] 11 | 12 | spec.email = "cliffordheath@gmail.com" 13 | spec.date = Date.today.strftime("%F") 14 | spec.summary = "A Ruby-based text parsing and interpretation DSL" 15 | spec.description = "A Parsing Expression Grammar (PEG) Parser generator DSL for Ruby" 16 | spec.homepage = "https://github.com/cjheath/treetop" 17 | spec.licenses = ["MIT"] 18 | 19 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|website|script|\.|benchmark)}) } 20 | spec.executables = ["tt"] 21 | spec.require_paths = ["lib"] 22 | spec.extra_rdoc_files = [ 23 | "LICENSE", 24 | "README.md" 25 | ] 26 | 27 | spec.add_runtime_dependency(%q, ["~> 0.3"]) 28 | spec.add_development_dependency(%q, [">= 4"]) 29 | spec.add_development_dependency(%q, ["~> 1.0"]) 30 | spec.add_development_dependency(%q, ["~> 3.0"]) 31 | spec.add_development_dependency(%q, ["~> 3"]) 32 | spec.add_development_dependency(%q, [">= 11"]) 33 | end 34 | 35 | -------------------------------------------------------------------------------- /vendor/treetop/Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rspec/core/rake_task' 3 | require File.expand_path("../lib/treetop/version", __FILE__) 4 | 5 | task :default => :spec 6 | RSpec::Core::RakeTask.new do |t| 7 | t.pattern = 'spec/**/*spec.rb' 8 | # t.libs << 'spec' # @todo not sure what this did in the original rspec 1.3 9 | end 10 | 11 | task :spec => 'lib/treetop/compiler/metagrammar.treetop' 12 | file 'lib/treetop/compiler/metagrammar.treetop' do |t| 13 | unless $bootstrapped_gen_1_metagrammar 14 | load File.expand_path('../lib/treetop/bootstrap_gen_1_metagrammar.rb', __FILE__) 15 | end 16 | 17 | Treetop::Compiler::GrammarCompiler.new.compile(METAGRAMMAR_PATH) 18 | end 19 | 20 | task :rebuild do 21 | $:.unshift "lib" 22 | require './lib/treetop' 23 | load File.expand_path('../lib/treetop/compiler/metagrammar.rb', __FILE__) 24 | Treetop::Compiler::GrammarCompiler.new.compile('lib/treetop/compiler/metagrammar.treetop') 25 | end 26 | 27 | task :version do 28 | puts 'Ruby is '+RUBY_VERSION 29 | puts 'Treetop is '+Treetop::VERSION::STRING 30 | end 31 | 32 | desc 'Generate and upload website files' 33 | task :website do 34 | system <<-END 35 | rm -rf .doc-tmp 36 | cp -r doc .doc-tmp 37 | git checkout gh-pages 38 | rm -r doc 39 | mv .doc-tmp doc 40 | rake website upload 41 | git checkout master 42 | END 43 | end 44 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/one_or_more_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module OneOrMoreSpec 4 | class Foo < Treetop::Runtime::SyntaxNode 5 | end 6 | 7 | describe "one or more of a terminal symbol followed by a node class declaration and a block" do 8 | testing_expression '"foo"+ { def a_method; end }' 9 | 10 | it "fails to parse epsilon, reporting a failure" do 11 | parse('') do |result| 12 | result.should be_nil 13 | terminal_failures = parser.terminal_failures 14 | terminal_failures.size.should == 1 15 | failure = terminal_failures.first 16 | failure.index.should == 0 17 | failure.expected_string.should == '"foo"' 18 | end 19 | end 20 | 21 | 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 22 | parse("foofoo") do |result| 23 | result.should_not be_nil 24 | result.should be_an_instance_of(Foo) 25 | result.should respond_to(:a_method) 26 | 27 | terminal_failures = parser.terminal_failures 28 | terminal_failures.size.should == 1 29 | failure = terminal_failures.first 30 | failure.index.should == 6 31 | failure.expected_string.should == '"foo"' 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /examples/markov_chain.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | use_bpm 90 4 | 5 | barrios = "| s 0 _4 #4 1 4 _4 0 _4 #4 1 4 _4 | s _6 _4 #4 1 4 _4 _6 _4 #4 1 4 _4 | s 1 _4 4 _6 3 _6 1 _4 4 _6 3 _4 | \ 6 | | s _0 _4 3 0 #1 _4 _0 _4 3 0 #1 _4 | s _#5 _4 3 0 #1 _4 _#5 _4 3 0 #1 _4 | s _5 _#3 #1 0 1 _#3 _5 _#3 #1 0 1 _#3 | \ 7 | | s _#4 _3 #1 0 1 _3 _#4 _3 #1 0 1 _3 | s _4 4 #1 0 1 _4 _4 4 #1 _4 1 _4 | s _4 _3 #1 0 1 _3 _4 _3 #1 _4 1 _3 | \ 8 | | s _4 _#1 1 _4 0 _#1 _4 _#1 1 _4 0 _#1 | s _4 _1 0 _3 _#5 _1 _4 _1 0 _3 _#5 _1 | s _4 _0 _#5 _#1 _#4 _0 _4 _0 _#5 _#1 _#4 _0 | \ 9 | | s _4 _6 _#4 _1 _4 _6 _4 _6 _#4 _1 _4 _6 | s _3 _1 1 _4 _6 _1 _3 _1 1 _4 _6 _1 | s _2 _4 4 _#5 #0 _4 _2 _#5 #4 #0 4 _#5 | \ 10 | | s _3 _#4 4 0 3 _#4 _3 _#4 4 0 3 _#4 | s _#1 _#4 #4 0 3 _#4 _#1 _#4 #4 0 3 _#4 | s _1 3 1 #4 0 3 _1 3 1 #4 0 3 | \ 11 | | s _#1 #1 #0 4 #0 #1 _#1 #1 #0 4 _#5 #1 | s _2 #0 #0 4 _#5 #0 _2 #0 #0 4 _#5 #0 | s _3 0 _#5 3 #4 0 _3 0 _#5 3 #4 0 | \ 12 | | s _1 0 _0 3 #4 0 _1 0 _0 3 #4 0 | s _4 _6 6 3 4 _6 _4 _6 _6 3 4 _6 | s _4 0 ^0 #1 4 0 _4 0 ^0 #1 4 0 | \ 13 | | s _3 0 ^0 #1 #4 0 _3 0 ^0 #1 #4 0 | s _3 _#5 #5 1 #4 _#5 _3 _#5 #5 1 #4 _#5 | s _#1 _#5 #5 #1 4 _#5 _#1 _#5 #5 #1 4 _#5 | \ 14 | | s _3 _#4 #4 1 3 _#4 __3 _#4 #4 1 3 _#4 | s __4_5 _4 4 0 #1 _4 __4 _4 4 0 #1 _4 | s __4 _4 3 _6 1 _4 __4 _4 3 _6 1 _4 |" 15 | 16 | m = zparse barrios, synth: :kalimba 17 | 18 | zplay markov_analyzer m, 4 19 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/choice.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Choice < ParsingExpression 4 | def compile(address, builder, parent_expression = nil) 5 | super 6 | begin_comment(self) 7 | use_vars :result, :start_index 8 | compile_alternatives(alternatives, parent_expression) 9 | end_comment(self) 10 | end 11 | 12 | def compile_alternatives(alternatives, parent_expression) 13 | obtain_new_subexpression_address 14 | alternatives.first.compile(subexpression_address, builder) 15 | builder.if__ subexpression_success? do 16 | # Undo lazy instantiation: 17 | builder << "#{subexpression_result_var} = SyntaxNode.new(input, (index-1)...index) if #{subexpression_result_var} == true" 18 | assign_result subexpression_result_var 19 | extend_result_with_declared_module 20 | extend_result_with_inline_module parent_expression 21 | end 22 | builder.else_ do 23 | if alternatives.size == 1 24 | reset_index 25 | assign_failure start_index_var 26 | else 27 | compile_alternatives(alternatives[1..-1], parent_expression) 28 | end 29 | end 30 | end 31 | 32 | def expected 33 | '"(any alternative)"' 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/predicate.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Predicate < ParsingExpression 4 | def compile(address, builder, parent_expression) 5 | super 6 | begin_comment(parent_expression) 7 | use_vars :result, :start_index 8 | obtain_new_subexpression_address 9 | parent_expression.prefixed_expression.compile(subexpression_address, builder) 10 | builder.if__(subexpression_success?) { when_success } 11 | builder.else_ { when_failure } 12 | end_comment(parent_expression) 13 | end 14 | 15 | def assign_failure 16 | reset_index 17 | super(start_index_var) 18 | end 19 | 20 | def assign_success 21 | reset_index 22 | assign_result epsilon_node 23 | end 24 | end 25 | 26 | class AndPredicate < Predicate 27 | def when_success 28 | assign_success 29 | end 30 | 31 | def when_failure 32 | assign_failure 33 | end 34 | end 35 | 36 | class NotPredicate < Predicate 37 | def when_success 38 | assign_failure 39 | if (e = parent.atomic.expected) 40 | builder << "terminal_parse_failure(#{e}, true)" 41 | end 42 | end 43 | 44 | def when_failure 45 | if (e = parent.atomic.expected) 46 | builder << "@terminal_failures.pop" 47 | end 48 | assign_success 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /vendor/polyglot/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'yaml' 4 | require 'jeweler' 5 | require './lib/polyglot/version' 6 | 7 | Jeweler::Tasks.new do |gem| 8 | gem.name = "polyglot" 9 | gem.version = Polyglot::VERSION::STRING 10 | gem.homepage = "http://github.com/cjheath/polyglot" 11 | gem.license = "MIT" 12 | gem.summary = %Q{Augment 'require' to load non-Ruby file types} 13 | gem.description = %Q{ 14 | The Polyglot library allows a Ruby module to register a loader 15 | for the file type associated with a filename extension, and it 16 | augments 'require' to find and load matching files.} 17 | gem.email = %w[clifford.heath@gmail.com] 18 | gem.authors = ["Clifford Heath"] 19 | gem.files.exclude "website/**/*.*", "script/*" 20 | end 21 | Jeweler::RubygemsDotOrgTasks.new 22 | 23 | require 'rdoc/task' 24 | Rake::RDocTask.new do |rdoc| 25 | rdoc.rdoc_dir = 'rdoc' 26 | rdoc.title = "polyglot #{Polyglot::VERSION::STRING}" 27 | rdoc.rdoc_files.include('README.txt') 28 | rdoc.rdoc_files.include('lib/**/*.rb') 29 | end 30 | 31 | desc 'Generate website files' 32 | task :website_generate do 33 | sh %q{ruby script/txt2html website/index.txt > website/index.html} 34 | end 35 | 36 | desc 'Upload website files via rsync' 37 | task :website_upload do 38 | rfconfig = YAML.load_file("#{ENV['HOME']}/.rubyforge/user-config.yml") 39 | ENV['RSYNC_PASSWORD'] = rfconfig['password'] 40 | sh %{rsync -aCv website #{rfconfig['username']}@rubyforge.org:/var/www/gforge-projects/polyglot} 41 | end 42 | 43 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/multibyte_chars_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | 5 | module MultibyteCharsSpec 6 | describe "an anything symbol", :multibyte => true do 7 | testing_expression '.' 8 | it "matches an UTF-8 character" do 9 | parse_multibyte("ø").should_not be_nil 10 | end 11 | end 12 | 13 | describe "A character class containing UTF-8 characters", :multibyte => true do 14 | testing_expression "[æøå]" 15 | it "recognizes the UTF-8 characters" do 16 | parse_multibyte("ø").should_not be_nil 17 | end 18 | end 19 | 20 | describe( "a character class repetition containing UTF-8 characters mixed with other expressions", 21 | :multibyte => true 22 | ) do 23 | testing_expression '[æøå]+ "a"' 24 | it "lazily instantiates a node for the character" do 25 | result = parse_multibyte('æøåa') 26 | pending "Multibyte support is not supported in Ruby 1.8.6" if RUBY_VERSION =~ /^1\.8.6/ 27 | result.elements[0].instance_variable_get("@elements").should include(true) 28 | result.elements[0].elements.should_not include(true) 29 | result.elements[0].elements.size.should == 3 30 | result.elements.size.should == 2 31 | result.elements[0].text_value.should == "æøå" 32 | result.elements[0].elements[0].text_value.should == "æ" 33 | result.elements[0].elements[1].text_value.should == "ø" 34 | result.elements[0].elements[2].text_value.should == "å" 35 | result.elements[1].text_value == "a" 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/terminal_symbol_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module TerminalSymbolSpec 4 | class Foo < Treetop::Runtime::SyntaxNode 5 | end 6 | 7 | describe "a terminal symbol followed by a node class declaration and a block" do 8 | testing_expression "'foo' { def a_method; end }" 9 | 10 | 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 11 | parse "foo", :index => 0 do |result| 12 | result.should be_an_instance_of(Foo) 13 | result.should respond_to(:a_method) 14 | result.interval.should == (0...3) 15 | result.text_value.should == 'foo' 16 | end 17 | 18 | parse "xfoo", :index => 1 do |result| 19 | result.should be_an_instance_of(Foo) 20 | result.should respond_to(:a_method) 21 | result.interval.should == (1...4) 22 | result.text_value.should == 'foo' 23 | end 24 | 25 | parse "---foo", :index => 3 do |result| 26 | result.should be_an_instance_of(Foo) 27 | result.should respond_to(:a_method) 28 | result.interval.should == (3...6) 29 | result.text_value.should == 'foo' 30 | end 31 | end 32 | 33 | it "fails to parse nonmatching input at the index even if a match occurs later" do 34 | parse(" foo", :index => 0) do |result| 35 | result.should be_nil 36 | parser.terminal_failures.size.should == 1 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/arithmetic_test.rb: -------------------------------------------------------------------------------- 1 | dir = File.dirname(__FILE__) 2 | require File.expand_path("#{dir}/test_helper") 3 | 4 | require File.expand_path("#{dir}/arithmetic_node_classes") 5 | Treetop.load File.expand_path("#{dir}/arithmetic") 6 | 7 | class ArithmeticParserTest < Test::Unit::TestCase 8 | include ParserTestHelper 9 | 10 | def setup 11 | @parser = ArithmeticParser.new 12 | end 13 | 14 | def test_number 15 | assert_equal 0, parse('0').eval 16 | assert_equal 1, parse('1').eval 17 | assert_equal 123, parse('123').eval 18 | end 19 | 20 | def test_variable 21 | assert_equal 0, parse('x').eval('x' => 0) 22 | assert_equal 3, parse('x').eval('x' => 3) 23 | assert_equal 10, parse('y').eval('y' => 10) 24 | end 25 | 26 | def test_addition 27 | assert_equal 10, parse('x + 5').eval('x' => 5) 28 | end 29 | 30 | def test_subtraction 31 | assert_equal 0, parse('x - 5').eval('x' => 5) 32 | end 33 | 34 | def test_multiplication 35 | assert_equal 6, parse('x * 2').eval('x' => 3) 36 | end 37 | 38 | def test_division 39 | assert_equal 3, parse('x / 2').eval('x' => 6) 40 | end 41 | 42 | def test_order_of_operations 43 | assert_equal 11, parse('1 + 2 * 3 + 4').eval 44 | end 45 | 46 | def test_left_to_right 47 | assert_equal 2, parse('5 - 2 - 1').eval 48 | end 49 | 50 | def test_parentheses 51 | assert_equal 25, parse('(5 + x) * (10 - y)').eval('x' => 0, 'y' => 5) 52 | end 53 | 54 | def test_equality 55 | assert parse('4 == 4').eval 56 | assert !parse('4 == 3').eval 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/not_predicate_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module NotPredicateSpec 4 | describe "A !-predicated terminal symbol" do 5 | testing_expression '!"foo"' 6 | 7 | it "fails to parse input matching the terminal symbol" do 8 | parse('foo') do |result| 9 | result.should be_nil 10 | parser.terminal_failures.size.should == 1 11 | end 12 | end 13 | end 14 | 15 | describe "A !-predicated character class symbol" do 16 | testing_expression '![aeiou]' 17 | 18 | it "fails to parse input matching the terminal symbol" do 19 | parse('e') do |result| 20 | result.should be_nil 21 | parser.terminal_failures.size.should == 1 22 | end 23 | end 24 | end 25 | 26 | describe "A sequence of a terminal and an and another !-predicated terminal" do 27 | testing_expression '"foo" !"bar"' 28 | 29 | it "fails to match input matching both terminals" do 30 | parse('foobar').should be_nil 31 | end 32 | 33 | it "successfully parses input matching the first terminal and not the second, reporting the parse failure of the second terminal" do 34 | parse('foo') do |result| 35 | result.should_not be_nil 36 | terminal_failures = parser.terminal_failures 37 | terminal_failures.size.should == 0 38 | end 39 | end 40 | end 41 | 42 | describe "A !-predicated sequence" do 43 | testing_expression '!("a" "b" "cc")' 44 | 45 | it "fails to parse matching input" do 46 | parse('abcc') do |result| 47 | result.should be_nil 48 | parser.terminal_failures.size.should == 1 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /vendor/polyglot/website/template.rhtml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | <%= title %> 9 | 10 | 11 | 14 | 29 | 30 | 31 |
32 | 33 |

<%= title %>

34 |
35 |

Get Version

36 | <%= version %> 37 |
38 | <%= body %> 39 |

40 | Clifford Heath, <%= modified.pretty %>
41 | Theme extended from Paul Battley 42 |

43 |
44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/parsing_rule_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module ParsingRuleSpec 4 | describe "a grammar with one parsing rule" do 5 | 6 | testing_grammar %{ 7 | grammar Foo 8 | rule bar 9 | "baz" 10 | end 11 | end 12 | } 13 | 14 | it "stores and retrieves nodes in its node cache" do 15 | parser = self.class.const_get(:FooParser).new 16 | parser.send(:prepare_to_parse, 'baz') 17 | node_cache = parser.send(:node_cache) 18 | 19 | node_cache[:bar][0].should be_nil 20 | 21 | parser._nt_bar 22 | 23 | cached_node = node_cache[:bar][0] 24 | cached_node.should be_an_instance_of(Runtime::SyntaxNode) 25 | cached_node.text_value.should == 'baz' 26 | 27 | parser.instance_eval { @index = 0 } 28 | parser._nt_bar.should equal(cached_node) 29 | parser.index.should == cached_node.interval.end 30 | end 31 | end 32 | 33 | 34 | describe "a grammar with choice that uses the cache and has a subsequent expression" do 35 | testing_grammar %{ 36 | grammar Logic 37 | rule expression 38 | value_plus 39 | / 40 | value 41 | end 42 | 43 | rule value_plus 44 | value "something else" 45 | end 46 | 47 | rule value 48 | [a-z] 49 | / 50 | "foobar" # the subsequent expression that needs cached.interval.end 51 | end 52 | end 53 | } 54 | 55 | it "parses a single-character value and generates a node from the cache" do 56 | result = parse('a') 57 | result.should be_a(Treetop::Runtime::SyntaxNode) 58 | result.elements.should be_nil 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/anything_symbol_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module AnythingSymbolSpec 4 | class Foo < Treetop::Runtime::SyntaxNode 5 | end 6 | 7 | describe "an anything symbol followed by a node class declaration and a block" do 8 | testing_expression '. { def a_method; end }' 9 | 10 | 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 11 | (33..127).each do |digit| 12 | parse(digit.chr) do |result| 13 | result.should_not be_nil 14 | result.should be_an_instance_of(Foo) 15 | result.should respond_to(:a_method) 16 | result.interval.should == (0...1) 17 | end 18 | end 19 | end 20 | 21 | it "fails to parse epsilon" do 22 | parse('') do |result| 23 | result.should be_nil 24 | parser.terminal_failures.size.should == 1 25 | end 26 | end 27 | end 28 | 29 | module ModFoo 30 | end 31 | 32 | describe "an anything symbol followed by a module declaration and a block" do 33 | testing_expression '. { def a_method; end }' 34 | 35 | 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 36 | (33..127).each do |digit| 37 | parse(digit.chr) do |result| 38 | result.should_not be_nil 39 | result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) 40 | result.should be_a_kind_of(ModFoo) 41 | result.should respond_to(:a_method) 42 | result.interval.should == (0...1) 43 | end 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/arithmetic.treetop: -------------------------------------------------------------------------------- 1 | grammar Arithmetic 2 | rule expression 3 | comparative / additive 4 | end 5 | 6 | rule comparative 7 | head:additive 8 | tail:( 9 | space operator:equality_op 10 | space operand:additive)* 11 | end 12 | 13 | rule equality_op 14 | '==' { 15 | def apply(a, b) 16 | a == b 17 | end 18 | } 19 | end 20 | 21 | rule additive 22 | head:multitive 23 | tail:( 24 | space operator:additive_op 25 | space operand:multitive)* 26 | end 27 | 28 | rule additive_op 29 | '+' { 30 | def apply(a, b) 31 | a + b 32 | end 33 | } 34 | / 35 | '-' { 36 | def apply(a, b) 37 | a - b 38 | end 39 | } 40 | end 41 | 42 | rule multitive 43 | head:primary 44 | tail:( 45 | space operator:multitive_op 46 | space operand:primary)* 47 | end 48 | 49 | rule multitive_op 50 | '*' { 51 | def apply(a, b) 52 | a * b 53 | end 54 | } 55 | / 56 | '/' { 57 | def apply(a, b) 58 | a / b 59 | end 60 | } 61 | end 62 | 63 | rule primary 64 | variable 65 | / 66 | number 67 | / 68 | '(' space expression space ')' { 69 | def eval(env={}) 70 | expression.eval(env) 71 | end 72 | } 73 | end 74 | 75 | rule variable 76 | [a-z]+ { 77 | def eval(env={}) 78 | env[name] 79 | end 80 | 81 | def name 82 | text_value 83 | end 84 | } 85 | end 86 | 87 | rule number 88 | ([1-9] [0-9]* / '0') { 89 | def eval(env={}) 90 | text_value.to_i 91 | end 92 | } 93 | end 94 | 95 | rule space 96 | ' '* 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/grammar_compiler.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | AUTOGENERATED = "# Autogenerated from a Treetop grammar. Edits may be lost.\n" 4 | class GrammarCompiler 5 | def compile(source_path, target_path = source_path.gsub(/\.(treetop|tt)\Z/, '.rb')) 6 | File.open(target_path, 'w') do |target_file| 7 | ruby = ruby_source(source_path) 8 | if ruby =~ /\A#.*\n/ 9 | ruby.sub!(/\n/, "\n"+AUTOGENERATED+"\n\n") 10 | else 11 | ruby = AUTOGENERATED+"\n\n"+ruby 12 | end 13 | target_file.write(ruby) 14 | end 15 | end 16 | 17 | # compile a treetop file into ruby 18 | def ruby_source(source_path) 19 | ruby_source_from_string(File.read(source_path)) 20 | end 21 | 22 | # compile a string containing treetop source into ruby 23 | def ruby_source_from_string(s) 24 | parser = MetagrammarParser.new 25 | result = parser.parse(s) 26 | unless result 27 | raise RuntimeError.new(parser.failure_reason) 28 | end 29 | result.compile 30 | end 31 | end 32 | end 33 | 34 | # compile a treetop source file and load it 35 | def self.load(path) 36 | unless path =~ Treetop::Polyglot::VALID_GRAMMAR_EXT_REGEXP 37 | ext = Treetop::Polyglot::VALID_GRAMMAR_EXT.select {|ext| File.exist?(path+".#{ext}")}.shift 38 | path += ".#{ext}" unless ext.nil? 39 | end 40 | File.open(path) do |source_file| 41 | source = source_file.read 42 | source.gsub!(/\b__FILE__\b/, %Q{"#{path}"}) 43 | load_from_string(source) 44 | end 45 | end 46 | 47 | # compile a treetop source string and load it 48 | def self.load_from_string(s) 49 | compiler = Treetop::Compiler::GrammarCompiler.new 50 | Object.class_eval(compiler.ruby_source_from_string(s)) 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /vendor/polyglot/History.txt: -------------------------------------------------------------------------------- 1 | == 0.3.2 2011-07-27 2 | 3 | * 1 minor fix: 4 | * Load file without extension if found exactly as required 5 | 6 | == 0.3.1 2010-02-29 7 | 8 | * 1 minor fix: 9 | * Enumerable strings are deprecated in Ruby 1.8.8 10 | 11 | == 0.3.0 2010-02-14 12 | 13 | * 1 minor fix: 14 | * Compatibility with Rails 3 15 | 16 | == 0.2.9 2009-09-13 17 | 18 | * 1 minor fix: 19 | * Use to_s on Pathname to support Ruby 1.9 20 | 21 | == 0.2.8 2009-08-18 22 | 23 | * 1 minor fix: 24 | * Previous fix for LoadErrors failed for cucumber. 25 | 26 | == 0.2.7 2009-08-17 27 | 28 | * 1 minor fix: 29 | * Fix Polyglot catching LoadErrors not raised in Polyglot.find and re-raising the 30 | wrong message. 31 | 32 | == 0.2.6 2009-06-21 33 | 34 | * 1 significant fix: 35 | * Require using absolute pathname now works correctly on Ruby 1.8 36 | 37 | == 0.2.5 2009-03-04 38 | 39 | * 1 significant fix: 40 | * Polyglot's require may be called with a Pathname, or other object allowed by Kernel#require that doesn't support [] (Kernel#require uses to_str apparently) 41 | 42 | == 0.2.4 2008-05-29 43 | 44 | * 1 significant fix: 45 | * Previous LoadError change is checked in this time (oops!) 46 | 47 | == 0.2.3 2008-05-29 48 | 49 | * 2 minor enhancements: 50 | * Raise MissingSourceFile exception instead of LoadError if ActiveSupport is loaded 51 | * Re-raise original exception new one on require load fail 52 | 53 | == 0.2.2 2008-05-12 54 | 55 | * 2 minor enhancements: 56 | * Doesn't search $: when asked to load an absolute path 57 | * Adds a helpful exception message on LoadError 58 | 59 | == 0.2.1 2008-03-05 60 | 61 | * 1 minor defect: 62 | * code to raise LoadError itself raised an exception 63 | 64 | == 0.2.0 2008-02-13 65 | 66 | * 1 major enhancement: 67 | * Doesn't reload on every require 68 | 69 | == 0.1.0 2007-10-22 70 | 71 | * 1 major enhancement: 72 | * Initial release 73 | -------------------------------------------------------------------------------- /vendor/treetop/examples/indented_blocks/indented_blocks.tt: -------------------------------------------------------------------------------- 1 | grammar IndentedBlocks 2 | rule top 3 | # Initialise the indent stack with a sentinel: 4 | &{|s| @indents = [-1] } 5 | foo:('foo'?) 6 | nested_blocks 7 | { 8 | def inspect 9 | nested_blocks.inspect 10 | end 11 | } 12 | end 13 | 14 | rule nested_blocks 15 | ( 16 | # Do not try to extract this semantic predicate into a new rule. 17 | # It will be memo-ized incorrectly because @indents.last will change. 18 | !{|s| 19 | # Peek at the following indentation: 20 | save = index; i = _nt_indentation; index = save 21 | # We're closing if the indentation is less or the same as our enclosing block's: 22 | closing = i.text_value.length <= @indents.last 23 | } 24 | block 25 | )* 26 | { 27 | def inspect 28 | elements.map{|e| e.block.inspect}*"\n" 29 | end 30 | } 31 | end 32 | 33 | rule block 34 | indented_line # The block's opening line 35 | &{|s| # Push the indent level to the stack 36 | level = s[0].indentation.text_value.length 37 | @indents << level 38 | true 39 | } 40 | nested_blocks # Parse any nested blocks 41 | &{|s| # Pop the indent stack 42 | # Note that under no circumstances should "nested_blocks" fail, or the stack will be mis-aligned 43 | @indents.pop 44 | true 45 | } 46 | { 47 | def inspect 48 | indented_line.inspect + 49 | (nested_blocks.elements.size > 0 ? ( 50 | "\n{\n" + 51 | nested_blocks.elements.map { |content| 52 | content.block.inspect+"\n" 53 | }*'' + 54 | "}" 55 | ) 56 | : "") 57 | end 58 | } 59 | end 60 | 61 | rule indented_line 62 | indentation text:((!"\n" .)*) "\n" 63 | { 64 | def inspect 65 | text.text_value 66 | end 67 | } 68 | end 69 | 70 | rule indentation 71 | ' '* 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/terminal.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Terminal < AtomicExpression 4 | def compile(address, builder, parent_expression = nil) 5 | super 6 | # Handle modifiers: 7 | insensitive = modifiers.text_value.include? 'i' 8 | re = modifiers.text_value.include? 'r' 9 | if re 10 | grounded_regexp = "#{('\A'+eval(string)).inspect}" 11 | cache_key = "'__#{modifiers.text_value}__'+(gr = #{grounded_regexp})" 12 | re_modifiers = "#{insensitive ? 'Regexp::IGNORECASE' : 0}" 13 | str = "@regexps[#{cache_key}] ||= Regexp.new(gr, #{re_modifiers})" 14 | mode = ':regexp' 15 | elsif insensitive 16 | str = string.downcase 17 | string_length = eval(str).length 18 | mode = ':insens' 19 | else 20 | str = string 21 | string_length = eval(str).length 22 | mode = 'false' 23 | end 24 | 25 | builder.if__ "(match_len = has_terminal?(#{str}, #{mode}, index))" do 26 | if address == 0 || decorated? || mode != 'false' || string_length > 1 27 | assign_result "instantiate_node(#{node_class_name},input, index...(index + match_len))" 28 | # debugger if parent_expression and parent_expression.inline_modules.size > 0 29 | # extend_result_with_inline_module parent_expression 30 | if parent_expression 31 | parent_expression.inline_modules.each do |inline| 32 | extend_result inline.module_name 33 | end 34 | end 35 | else 36 | assign_lazily_instantiated_node 37 | end 38 | builder << "@index += match_len" 39 | end 40 | builder.else_ do 41 | builder << "terminal_parse_failure(#{expected})" 42 | assign_result 'nil' 43 | end 44 | end 45 | 46 | def expected 47 | single_quote(string) 48 | end 49 | 50 | def inline_module 51 | nil 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/parsing_rule.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class ParsingRule < Runtime::SyntaxNode 4 | 5 | def compile(builder) 6 | compile_inline_module_declarations(builder) 7 | generate_method_definition(builder) 8 | end 9 | 10 | def compile_inline_module_declarations(builder) 11 | parsing_expression.inline_modules.each_with_index do |inline_module, i| 12 | inline_module.compile(i, builder, self) 13 | builder.newline 14 | end 15 | end 16 | 17 | def generate_method_definition(builder) 18 | builder.reset_addresses 19 | expression_address = builder.next_address 20 | result_var = "r#{expression_address}" 21 | 22 | builder.method_declaration(method_name) do 23 | builder.assign 'start_index', 'index' 24 | generate_cache_lookup(builder) 25 | builder.newline 26 | parsing_expression.compile(expression_address, builder) 27 | builder.newline 28 | generate_cache_storage(builder, result_var) 29 | builder.newline 30 | builder << result_var 31 | end 32 | end 33 | 34 | def generate_cache_lookup(builder) 35 | builder.if_ "node_cache[:#{name}].has_key?(index)" do 36 | cache_address = "node_cache[:#{name}][index]" 37 | builder.assign 'cached', cache_address 38 | builder.if_ "cached" do 39 | # Handle lazily instantiated nodes: 40 | builder << "#{cache_address} = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true" 41 | builder << '@index = cached.interval.end' 42 | end 43 | builder << 'return cached' 44 | end 45 | end 46 | 47 | def generate_cache_storage(builder, result_var) 48 | builder.assign "node_cache[:#{name}][start_index]", result_var 49 | end 50 | 51 | def method_name 52 | "_nt_#{name}" 53 | end 54 | 55 | def name 56 | nonterminal.text_value 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/bootstrap_gen_1_metagrammar.rb: -------------------------------------------------------------------------------- 1 | # This file's job is to load a Treetop::Compiler::Metagrammar and Treetop::Compiler::MetagrammarParser 2 | # into the environment by compiling the current metagrammar.treetop using a trusted version of Treetop. 3 | 4 | require 'rubygems' 5 | 6 | TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP = '>= 1.1.5' 7 | 8 | # Loading trusted version of Treetop to compile the compiler 9 | gem_spec = Gem.source_index.find_name('treetop', TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP).last 10 | raise "Install a Treetop Gem version #{TREETOP_VERSION_REQUIRED_TO_BOOTSTRAP} to bootstrap." unless gem_spec 11 | require "#{gem_spec.full_gem_path}/lib/treetop" 12 | 13 | # Relocating trusted version of Treetop to Trusted::Treetop 14 | Trusted = Module.new 15 | Trusted::Treetop = Treetop 16 | Object.send(:remove_const, :Treetop) 17 | 18 | # Requiring version of Treetop that is under test 19 | $exclude_metagrammar = true 20 | require File.expand_path('../treetop') 21 | 22 | # Compile and evaluate freshly generated metagrammar source 23 | METAGRAMMAR_PATH = File.expand_path('../compiler/metagrammar.treetop', __FILE__) 24 | compiled_metagrammar_source = Trusted::Treetop::Compiler::GrammarCompiler.new.ruby_source(METAGRAMMAR_PATH) 25 | Object.class_eval(compiled_metagrammar_source) 26 | 27 | # The compiler under test was compiled with the trusted grammar and therefore depends on its runtime 28 | # But the runtime in the global namespace is the new runtime. We therefore inject the trusted runtime 29 | # into the compiler so its parser functions correctly. It will still not work for custom classes that 30 | # explicitly subclass the wrong runtime. For now I am working around this by keeping 1 generation of 31 | # backward compatibility in these cases. 32 | # Treetop::Compiler::Metagrammar.module_eval do 33 | # include Trusted::Treetop::Runtime 34 | # end 35 | # 36 | # Treetop::Compiler.send(:remove_const, :MetagrammarParser) 37 | # class Treetop::Compiler::MetagrammarParser < Trusted::Treetop::Runtime::CompiledParser 38 | # include Treetop::Compiler::Metagrammar 39 | # include Trusted::Treetop::Runtime 40 | # end 41 | 42 | $bootstrapped_gen_1_metagrammar = true 43 | -------------------------------------------------------------------------------- /vendor/polyglot/script/txt2html: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | begin 5 | require 'newgem' 6 | rescue LoadError 7 | puts "\n\nGenerating the website requires the newgem RubyGem" 8 | puts "Install: gem install newgem\n\n" 9 | exit(1) 10 | end 11 | require 'redcloth' 12 | require 'syntax/convertors/html' 13 | require 'erb' 14 | require File.dirname(__FILE__) + '/../lib/polyglot/version.rb' 15 | 16 | version = Polyglot::VERSION::STRING 17 | download = 'http://rubyforge.org/projects/polyglot' 18 | 19 | class Fixnum 20 | def ordinal 21 | # teens 22 | return 'th' if (10..19).include?(self % 100) 23 | # others 24 | case self % 10 25 | when 1: return 'st' 26 | when 2: return 'nd' 27 | when 3: return 'rd' 28 | else return 'th' 29 | end 30 | end 31 | end 32 | 33 | class Time 34 | def pretty 35 | return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}" 36 | end 37 | end 38 | 39 | def convert_syntax(syntax, source) 40 | return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^
|
$!,'') 41 | end 42 | 43 | if ARGV.length >= 1 44 | src, template = ARGV 45 | template ||= File.join(File.dirname(__FILE__), '/../website/template.rhtml') 46 | 47 | else 48 | puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html") 49 | exit! 50 | end 51 | 52 | template = ERB.new(File.open(template).read) 53 | 54 | title = nil 55 | body = nil 56 | File.open(src) do |fsrc| 57 | title_text = fsrc.readline 58 | body_text = fsrc.read 59 | syntax_items = [] 60 | body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)!m){ 61 | ident = syntax_items.length 62 | element, syntax, source = $1, $2, $3 63 | syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}" 64 | "syntax-temp-#{ident}" 65 | } 66 | title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip 67 | body = RedCloth.new(body_text).to_html 68 | body.gsub!(%r!(?:
)?syntax-temp-(\d+)(?:
)?!){ syntax_items[$1.to_i] } 69 | end 70 | stat = File.stat(src) 71 | created = stat.ctime 72 | modified = stat.mtime 73 | 74 | $stdout << template.result(binding) 75 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/zero_or_more_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module ZeroOrMoreSpec 4 | class Foo < Treetop::Runtime::SyntaxNode 5 | end 6 | 7 | describe "zero or more of a terminal symbol followed by a node class declaration and a block" do 8 | # testing_expression '("foo" { def b_method; end } )* { def a_method; end }' 9 | # testing_expression '("foo" { def a_method; end } )* ' 10 | testing_expression '"foo"* { def a_method; end }' 11 | 12 | it "successfully parses epsilon, returning an instance declared node class and recording a terminal failure" do 13 | parse('') do |result| 14 | result.should_not be_nil 15 | result.should be_an_instance_of(Foo) 16 | result.should respond_to(:a_method) 17 | 18 | terminal_failures = parser.terminal_failures 19 | terminal_failures.size.should == 1 20 | failure = terminal_failures.first 21 | failure.index.should == 0 22 | failure.expected_string.should == '"foo"' 23 | end 24 | end 25 | 26 | 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 27 | parse("foofoo") do |result| 28 | result.should_not be_nil 29 | result.should be_an_instance_of(Foo) 30 | 31 | terminal_failures = parser.terminal_failures 32 | terminal_failures.size.should == 1 33 | failure = terminal_failures.first 34 | failure.index.should == 6 35 | failure.expected_string.should == '"foo"' 36 | end 37 | end 38 | end 39 | 40 | describe "Zero or more of a sequence" do 41 | testing_expression '("foo" "bar")*' 42 | 43 | it "resets the index appropriately following partially matcing input" do 44 | parse('foobarfoo', :consume_all_input => false) do |result| 45 | result.should_not be_nil 46 | result.interval.should == (0...6) 47 | end 48 | end 49 | end 50 | 51 | describe "Zero or more of a choice" do 52 | testing_expression '("a" / "bb")*' 53 | 54 | it "successfully parses matching input" do 55 | parse('abba').should_not be_nil 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /examples/avril14th.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | # Avril 14th by Aphex Twin 4 | # Created automatically from MIDI file using: https://github.com/amiika/ziffers-musescore 5 | 6 | ziff " 7 | / synth: :piano, sustain: 2.0, decay: 0.6 8 | | [: q ^ 2 _ 5 ^ 0 e r s 0 | sq. 5 e 5 ^ 4 3 2 0 :] | [: q ^^ 2 _ 5 ^ 0 e r s 0 | \ 9 | | sw ^ 5 :] | [: q. 2 s 2 sq. 4 e 2 | q. 2 s 2 4 q. 5 e 4 :] | q. 2 s 2 sq. 4 e 2 | \ 10 | | q. 2 s 2 4 q. 5 e 4 | e r 5 6 ^ 0 2 q. _ 6 | e r 5 6 ^ 0 2 _ 6 q 5 | \ 11 | | e r 5 6 ^ 0 2 q. _ 6 | e r 5 6 ^ 0 e. 2 ss _ 6 e. 5 | [: q ^ 2 _ 5 ^ 0 e r s 0 | \ 12 | | sq. 5 e 5 ^ 4 3 2 0 :] | [: q ^^ 2 _ 5 ^ 0 e r s 0 | sq. ^ 5 e 5 ^ 4 3 2 0 :] | q.s ^ 2 s 1 q.s 2 s 2 | \ 13 | | s ^ 4 5 e 4 h 2 q 4 | q.s ^ 2 s 1 q.s 0 s 2 | s ^ 4 5 e _ 5 q ^ 2 _ 5 ^ 0 | s r e.q ^^ 2 h _ 1 | \ 14 | | s ^^ 4 5 e 4 r eq ^ 2 q _ 4 | s ^ 2 e. ^^ 0 e _ 5 s r _ 1 qs ^ 1 e _ 5 s ^ 2 | s ^^ 4 5 es _ 5 e.q ^ 2 s _ 4 4 | ew ^ 4 | 15 | 16 | | [: w r | w r :] | [: q ^ 2 _ 5 ^ 0 e r s 0 | \ 17 | | sw 5 :] | [: w r | w r :] | w r | \ 18 | | w r | w r | w r | \ 19 | | w r | w r | [: w r | \ 20 | | w r :] | [: q ^ 2 _ 5 ^ 0 e r s 0 | sq. 5 e 5 ^ 4 3 2 0 :] | w r | \ 21 | | w r | w r | w r | h ^ 2 q 2 e r s r 2 | \ 22 | | s ^ 4 5 e 4 q 2 r 4 | h r q.s ^ 0 s 2 | s ^ 4 5 q.q _ 5 q r | w r | 23 | 24 | | [: e _ 0 5 ^ 0 2 _ 2 ^ 0 2 4 | e _ 3 ^ 0 3 4 _ 1 ^ 0 3 2 :] | [: e _ 0 5 ^ 0 2 _ 2 ^ 0 2 4 | \ 25 | | e _ 3 ^ 0 3 4 _ 1 ^ 0 3 2 :] | [: e _ 0 ^ 0 _ 5 4 _ 4 ^ 4 5 4 | e _ 0 ^ 0 _ 5 4 _ 3 ^ 3 4 3 :] | e _ 0 ^ 0 _ 5 4 _ 4 ^ 4 5 4 | \ 26 | | e _ 0 ^ 0 _ 5 4 _ 3 ^ 3 4 3 | e _ 1 ^ 1 2 ee _ 4 s ^ 2 ss 1 e. _ 5 | e _ 1 ^ 1 2 es _ 4 e ^ 2 ss 1 e. 2 | \ 27 | | e _ 1 ^ 1 2 ee 4 s 2 1 e _ 4 5 | e _ 1 ^ 1 2 es _ 4 e ^ 2 s 1 q 2 | [: e _ 0 5 ^ 0 2 _ 2 ^ 0 2 4 | \ 28 | | e _ 3 ^ 0 3 4 _ 1 ^ 0 3 2 :] | [: e _ 0 5 ^ 0 2 _ 2 ^ 0 2 4 | e _ 3 ^ 0 3 4 _ 1 ^ 0 3 2 :] | h _ 5 5 | \ 29 | | h 0 0 | h 0 2 | h 2 0 | e __ 5 ^ 5 ^ 0 1 _ 2 ^ 0 1 4 | \ 30 | | e _ 3 ^ 0 2 5 _ 1 ^ 0 3 ^ 0 | e 2 0 _ 5 3 2 ^ 0 2 4 | e _ 5 ^ 0 2 5 _ 0 ^ 0 ^ 0 | ew 2 | 31 | 32 | | [: w r | w r :] | [: w r | \ 33 | | w r :] | [: w r | w r :] | w r | \ 34 | | w r | w r | w r | \ 35 | | w r | w r | [: w r | \ 36 | | w r :] | [: w r | w r :] | h _ 3 13 | \ 37 | | h _ 2 03 | h __ 5 4^1 | h _ 0 _30 | h r e.e. ^^ 2 s 2 r | \ 38 | | s r r e r se ^^^ 4 s r h r | w r | q _ 1 r h r | w r | 39 | " 40 | -------------------------------------------------------------------------------- /vendor/polyglot/lib/polyglot.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | 3 | module Polyglot 4 | @registrations ||= {} # Guard against reloading 5 | @loaded ||= {} 6 | 7 | class PolyglotLoadError < LoadError; end 8 | 9 | class NestedLoadError < LoadError 10 | def initialize le 11 | @le = le 12 | end 13 | def reraise 14 | raise @le 15 | end 16 | end 17 | 18 | def self.register(extension, klass) 19 | extension = [extension] unless Array === extension 20 | extension.each{|e| 21 | @registrations[e] = klass 22 | } 23 | end 24 | 25 | def self.find(file, *options, &block) 26 | is_absolute = Pathname.new(file).absolute? 27 | is_dot_relative = file =~ /\.[\/\\]/ 28 | paths = is_absolute ? [''] : Array(is_dot_relative ? '.' : nil) + $: 29 | paths.each do |lib| 30 | base = is_absolute ? "" : lib+File::SEPARATOR 31 | # In Windows, repeated SEPARATOR chars have a special meaning, avoid adding them 32 | matches = Dir["#{base}#{file}{,.#{@registrations.keys*',.'}}"] 33 | # Revisit: Should we do more do if more than one candidate found? 34 | $stderr.puts "Polyglot: found more than one candidate for #{file}: #{matches*", "}" if matches.size > 1 35 | if path = matches[0] 36 | return [ path, @registrations[path.gsub(/.*\./,'')]] 37 | end 38 | end 39 | return nil 40 | end 41 | 42 | def self.load(*a, &b) 43 | file = a[0].to_s 44 | return if @loaded[file] # Check for $: changes or file time changes and reload? 45 | begin 46 | source_file, loader = Polyglot.find(file, *a[1..-1], &b) 47 | if (loader) 48 | begin 49 | loader.load(source_file) 50 | @loaded[file] = true 51 | rescue LoadError => e 52 | raise Polyglot::NestedLoadError.new(e) 53 | end 54 | else 55 | raise PolyglotLoadError.new("Failed to load #{file} using extensions #{(@registrations.keys+["rb"]).sort*", "}") 56 | end 57 | end 58 | end 59 | end 60 | 61 | module Kernel 62 | alias polyglot_original_require require 63 | 64 | def require(*a, &b) 65 | polyglot_original_require(*a, &b) 66 | rescue LoadError => load_error 67 | begin 68 | Polyglot.load(*a, &b) 69 | rescue Polyglot::NestedLoadError => e 70 | e.reraise 71 | rescue LoadError 72 | # Raise the original exception, possibly a MissingSourceFile with a path 73 | raise load_error 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /vendor/treetop/spec/runtime/syntax_node_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module SyntaxNodeSpec 4 | describe "A new terminal syntax node" do 5 | attr_reader :node 6 | 7 | before do 8 | @node = Runtime::SyntaxNode.new("input", 0...3) 9 | end 10 | 11 | it "reports itself as terminal" do 12 | node.should be_terminal 13 | node.should_not be_nonterminal 14 | end 15 | 16 | it "has a text value based on the input and the interval" do 17 | node.text_value.should == "inp" 18 | end 19 | 20 | it "has itself as its only element" do 21 | node.elements.should be_nil 22 | end 23 | end 24 | 25 | describe "A new nonterminal syntax node" do 26 | attr_reader :node 27 | 28 | before do 29 | @elements = [Runtime::SyntaxNode.new('input', 0...3)] 30 | @node = Runtime::SyntaxNode.new('input', 0...3, @elements) 31 | end 32 | 33 | it "reports itself as nonterminal" do 34 | node.should be_nonterminal 35 | node.should_not be_terminal 36 | end 37 | 38 | it "has a text value based on the input and the interval" do 39 | node.text_value.should == "inp" 40 | end 41 | 42 | it "has the elements with which it was instantiated" do 43 | node.elements.should == @elements 44 | end 45 | 46 | it "sets itself as the parent of its elements" do 47 | node.elements.each do |element| 48 | element.parent.should == node 49 | end 50 | end 51 | end 52 | 53 | describe "A new nonterminal syntax node with all children lazily instantiated" do 54 | attr_reader :node 55 | 56 | it "should lazily instantiate its child nodes" do 57 | @node = Runtime::SyntaxNode.new('input', 0...3, [true, true, true]) 58 | node.elements.size.should == 3 59 | node.elements.first.interval.should == (0...1) 60 | node.elements.first.parent.should == node 61 | end 62 | 63 | it "should lazily replace stand-in child nodes around real ones" do 64 | @input = "input" 65 | child1 = Runtime::SyntaxNode.new(@input, 1...2) 66 | child2 = Runtime::SyntaxNode.new(@input, 3...4) 67 | @node = Runtime::SyntaxNode.new(@input, 0...5, [true, child1, true, child2, true]) 68 | node.elements.size.should == 5 69 | 70 | node.elements[0].interval.should == (0...1) 71 | node.elements[0].parent.should == node 72 | 0.upto(4) do |index| 73 | node.elements[index].text_value.should == @input[index, 1] 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /vendor/treetop/doc/grammar_composition.markdown: -------------------------------------------------------------------------------- 1 | #Grammar Composition 2 | 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. 3 | 4 | ##The Mapping of Treetop Constructs to Ruby Constructs 5 | 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: 6 | 7 | grammar Foo 8 | ... 9 | end 10 | 11 | results in a Ruby module named `Foo` and a Ruby class named `FooParser` that `include`s the `Foo` module. 12 | 13 | ##Using Mixin Semantics to Compose Grammars 14 | Because grammars are just modules, they can be mixed into one another. This enables grammars to share rules. 15 | 16 | grammar A 17 | rule a 18 | 'a' 19 | end 20 | end 21 | 22 | grammar B 23 | include A 24 | 25 | rule ab 26 | a 'b' 27 | end 28 | end 29 | 30 | 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. 31 | 32 | grammar A 33 | rule a 34 | 'a' 35 | end 36 | end 37 | 38 | grammar B 39 | include A 40 | 41 | rule a 42 | super / 'b' 43 | end 44 | end 45 | 46 | Now rule `a` in grammar `B` matches either `'a'` or `'b'`. 47 | 48 | ##Motivation 49 | 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. 50 | 51 | grammar RubyPlusSQL 52 | include Ruby 53 | include SQL 54 | 55 | rule expression 56 | ruby_expression 57 | end 58 | 59 | rule ruby_string 60 | ruby_quote sql_expression ruby_quote / ruby_string 61 | end 62 | end 63 | 64 | ##Work to be Done 65 | 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. -------------------------------------------------------------------------------- /vendor/polyglot/website/index.txt: -------------------------------------------------------------------------------- 1 | h1. polyglot 2 | 3 | h2. Poly => many, glot => languages 4 | 5 | 6 | h2. What 7 | 8 | Polyglot provides a registry of file types that can be loaded by 9 | calling its improved version of 'require'. Each file extension 10 | that can be handled by a custom loader is registered by calling 11 | Polyglot.register("ext", <class>), and then you can simply 12 | require "somefile", which will find and load "somefile.ext" 13 | using your custom loader. 14 | 15 | This supports the creation of DSLs having a syntax that is most 16 | appropriate to their purpose, instead of abusing the Ruby syntax. 17 | 18 | Required files are attempted first using the normal Ruby loader, 19 | and if that fails, Polyglot conducts a search for a file having 20 | a supported extension. 21 | 22 | h2. Installing 23 | 24 |
sudo gem install polyglot
25 | 26 | h2. Example 27 | 28 | Define and register your file type loader in file rubyglot.rb: 29 | 30 |
    require 'polyglot'
31 |     class RubyglotLoader
32 |         def self.load(filename, options = nil, &block)
33 |             File.open(filename) {|file|
34 |                 # Load the contents of file as Ruby code:
35 |                 # Implement your parser here instead!
36 |                 Kernel.eval(file.read)
37 |             }
38 |         end
39 |     end
40 |     Polyglot.register("rgl", RubyglotLoader)
41 | 
42 | 43 | This file, hello.rgl, will be loaded (this simple example uses Ruby code): 44 | 45 |
    puts "Initializing"
46 |     class Hello
47 |         def initialize()
48 |             puts "Hello, world\n"
49 |         end
50 |     end
51 | 
52 | 53 | Call it from file test.rb: 54 | 55 |
    require 'rubyglot'	# Create my file type handler
56 |     require 'hello'	# Can add extra options or even a block here
57 |     puts "Ready to go"
58 |     Hello.new
59 | 
60 | 61 | Run: 62 | 63 |
    $ ruby test.rb
64 |     Initializing
65 |     Ready to go
66 |     Hello, world
67 |     $
68 | 
69 | 70 | 71 | h2. How to submit patches 72 | 73 | Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8z: Submit patch":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8z-email, email me on the link below. 74 | 75 | The trunk repository is http://github.com/cjheath/polyglot. 76 | 77 | h2. License 78 | 79 | This code is free to use under the terms of the MIT license. 80 | 81 | h2. Contact 82 | 83 | Comments are welcome. Send an email to "Clifford Heath":http://github.com/cjheath 84 | -------------------------------------------------------------------------------- /vendor/polyglot/README.txt: -------------------------------------------------------------------------------- 1 | = polyglot 2 | 3 | * http://github.com/cjheath/polyglot 4 | 5 | == DESCRIPTION: 6 | 7 | Author: Clifford Heath, 2007 8 | 9 | The Polyglot library allows a Ruby module to register a loader 10 | for the file type associated with a filename extension, and it 11 | augments 'require' to find and load matching files. 12 | 13 | This supports the creation of DSLs having a syntax that is most 14 | appropriate to their purpose, instead of abusing the Ruby syntax. 15 | 16 | Files are sought using the normal Ruby search path. 17 | 18 | == EXAMPLE: 19 | 20 | In file rubyglot.rb, define and register a file type handler: 21 | 22 | require 'polyglot' 23 | 24 | class RubyglotLoader 25 | def self.load(filename, options = nil, &block) 26 | File.open(filename) {|file| 27 | # Load the contents of file as Ruby code: 28 | # Implement your parser here instead! 29 | Kernel.eval(file.read) 30 | } 31 | end 32 | end 33 | 34 | Polyglot.register("rgl", RubyglotLoader) 35 | 36 | In file test.rb: 37 | 38 | require 'rubyglot' # Create my file type handler 39 | require 'hello' # Can add extra options or even a block here 40 | puts "Ready to go" 41 | Hello.new 42 | 43 | In file hello.rgl (this simple example uses Ruby code): 44 | 45 | puts "Initializing" 46 | class Hello 47 | def initialize() 48 | puts "Hello, world\n" 49 | end 50 | end 51 | 52 | Run: 53 | 54 | $ ruby test.rb 55 | Initializing 56 | Ready to go 57 | Hello, world 58 | $ 59 | 60 | == INSTALL: 61 | 62 | sudo gem install polyglot 63 | 64 | == LICENSE: 65 | 66 | (The MIT License) 67 | 68 | Copyright (c) 2007 Clifford Heath 69 | 70 | Permission is hereby granted, free of charge, to any person obtaining 71 | a copy of this software and associated documentation files (the 72 | "Software"), to deal in the Software without restriction, including 73 | without limitation the rights to use, copy, modify, merge, publish, 74 | distribute, sublicense, and/or sell copies of the Software, and to 75 | permit persons to whom the Software is furnished to do so, subject to 76 | the following conditions: 77 | 78 | The above copyright notice and this permission notice shall be 79 | included in all copies or substantial portions of the Software. 80 | 81 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 82 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 83 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 84 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 85 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 86 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 87 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 88 | -------------------------------------------------------------------------------- /vendor/treetop/doc/tt.1: -------------------------------------------------------------------------------- 1 | .\" treetop - Bringing the simplicity of Ruby to syntactic analysis 2 | .\" 3 | .\" Copyright (c) 2007 Nathan Sobo. 4 | .\" 5 | .\" Permission is hereby granted, free of charge, to any person obtaining a copy 6 | .\" of this software and associated documentation files (the "Software"), to deal 7 | .\" in the Software without restriction, including without limitation the rights 8 | .\" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | .\" copies of the Software, and to permit persons to whom the Software is 10 | .\" furnished to do so, subject to the following conditions: 11 | .\" 12 | .\" The above copyright notice and this permission notice shall be included in 13 | .\" all copies or substantial portions of the Software. 14 | .\" 15 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | .\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | .\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | .\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | .\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | .\" THE SOFTWARE. 22 | .TH tt 1 2013-06-19 Treetop "Treetop v1.4.14" 23 | .SH NAME 24 | tt \- Compile a treetop grammar file to ruby source code 25 | .SH SYNOPSIS 26 | .B tt 27 | .RI [ options "] " grammar_file "[.treetop|.tt] ..." 28 | 29 | .SH DESCRIPTION 30 | The 31 | .B tt 32 | program is a command-line script to compile .treetop files into Ruby 33 | source code. 34 | 35 | The 36 | .B tt 37 | program takes a list of files with a .treetop extension and compiles 38 | them into .rb files of the same name. You can then require these files 39 | like any other Ruby script. 40 | 41 | Alternately, you can supply just one .treetop file and a \-o flag to 42 | specify the name of the output file. 43 | 44 | Note: while treetop grammar files 45 | .B must 46 | have a supported filename extensions, (.treetop or .tt), the extension 47 | name is not required when calling the compiler with grammar file 48 | names. 49 | .SH OPTIONS 50 | .TP 4 51 | .BI "\-o, \-\-output" " FILENAME" 52 | 53 | Write parser source to 54 | .I FILENAME. 55 | .TP 4 56 | .B \-f, \-\-force 57 | 58 | Overwrite existing output file(s) 59 | .TP 4 60 | .B \-v, \-\-version 61 | 62 | Show Treetop version 63 | .TP 4 64 | .B \-h, \-\-help 65 | 66 | .SH EXAMPLES 67 | .TP 4 68 | 1 grammar -> 1 parser source 69 | 70 | tt foo.tt 71 | .TP 4 72 | 2 grammars -> 2 separate parsers 73 | 74 | tt foo bar.treetop 75 | .TP 4 76 | Alternately named output file 77 | 78 | tt \-o alterate_name.rb foo 79 | .SH SEE ALSO 80 | 81 | The treetop website: 82 | 83 | .B http://cjheath.github.io/treetop/ 84 | -------------------------------------------------------------------------------- /test/run_wiki_test_multi.rb: -------------------------------------------------------------------------------- 1 | load "~/ziffers/ziffers.rb" 2 | 3 | Ziffers.debug 4 | 5 | def test_play 6 | 7 | # Multistaff 8 | 9 | a = parse_rows " 10 | / synth: :pretty_bell 11 | [:q 2 2 2 4 q. 4 e 3 h 2 q 2 1 2 4 q. 2 e 1 h 0 :] [: 4 e 5 4 3 2 h 3 e 4 3 2 1 h 2 e 3 2 1 0 q. 1 e _ 4 h 4 q ^ 0 1 2 3 h 2 1 :] 12 | [: q 0 0 _ 6 6 ^ 1 _ 6 h ^ 0 q 0 _ 6 ^ 0 0 0 _ 6 h ^ 0 :] [: q 0 e 2 1 h 0 q 0 e 1 0 h _ 6 q 6 e ^ 0 _ 6 h 5 q. 4 e 4 h 4 q 4 6 ^ 0 0 h 0 _ 6 :] 13 | [: q 4 4 4 4 5 4 h 4 q 4 4 4 4 q. 4 e 3 h 2 :] [: h 2 5 5 4 4 3 q 1 0 h _ 6 q 6 ^ 4 4 5 h 4 4 :] / octave: -1, 14 | [: q 0 0 2 2 1 _ 4 h ^ 0 q 0 _ 4 ^ 0 _ 2 4 4 h ^ 0 :] [: h 0 q _ 5 ^ 0 h 1 q _ 4 6 h ^ 0 q _ 3 5 6 r 4 r 2 4 r 3 h 0 4 :] / octave: -1 15 | " 16 | assert_equal(a.length,4) 17 | 18 | a = parse_rows " 19 | / synth: :kalimba 20 | h H X / X: :bd_808, H: {sample: :drum_cowbell, amp: 0.025} 21 | h0 h. 2 q 2 h 1 0 3 3 2 1 2 4 4 #3 w. 4 h 2 h. 5 q 4 h 3 2 1 0 _6 2 1 0 0 _6 w. 0 / octave: 1 22 | h4 h. ^ 0 q 0 h _ 6 5 q 5 6 ^ 0 1 h 0 _ 6 4 q 6 ^ 0 h 1 1 _6 1 0 0 h. 0 q 0 h 0 0 _ 1 q 2 3 h 4 4 6 5 5 4 w. 4 23 | h2 h. 4 q 4 h 4 q 5 4 h 3 5 4 4 2 q 4 5 h 5 5 4 6 5 4 h. 3 q 4 h 3 4 _6 0 1 2 q 4 3 h 2 3 q 4 3 w. 2 / port: foo, channel: 3 24 | h0 q 0 _ 6 h 5 4 5 3 q 5 6 h ^0 4 ^ 0 0 1 1 w. _4 h 0 h. _ 3 q 3 h 1 q 2 3 h 4 5 4 ^0 4 5 3 4 w. ^ 0 25 | " 26 | assert_equal(a.length,5) 27 | 28 | a = parse_rows " 29 | / synth: :piano 30 | |[: q 2 2 1 0 | h _ 6 5 | q 2 2 #3 #4 | h 5 #4 | q 5 ^ 0 q. _ 6 e 5 | w 5 :] | \ 31 | | q 2 2 3 2 | q. 1 e 0 h 0 | q 2 #3 4 2 | q 5 4 h #3 | h 2 q 2 2 | q 1 0 h _ 6 | w _ 5 | 32 | 33 | / synth: :blade 34 | |[: q 0 e 0 _ 6 q 5 5 | q _ 5 #4 h 2 | q _ 5 5 5 6 | q _ 5 6 h 6 | q _ 5 ^ 2 h 1 | w 0 :] | \ 35 | | q _ 5 6 5 5 | h _ 6 5 | q _ 5 5 e 6 5 q 4 | q 0 _ 6 h 5 | h _ 4 q 5 5 | q _ 5 5 5 #4 | w _ 2 | 36 | 37 | / synth: :kalimba 38 | |[: q _ 5 4 3 2 | q _ 3 e 2 1 h 0 | e _ 0 1 q 2 e 1 2 q 3 | q _ 2 3 h 2 | q _ 2 5 h #4 | w _ 2 :] | \ 39 | | q _ 0 1 0 e 0 1 | h _ 2 2 | q _ 0 0 1 e 0 1 | q _ 2 2 1 0 | h __ 6 e ^ 0 1 q 2 | q _ 1 2 3 e 2 1 | w _ 0 | 40 | 41 | / synth: :pluck 42 | |[: e __ 5 6 q ^ 0 e _ 3 4 q 5 | q __ 1 2 h 5 | e __ 5 6 q ^ 0 1 1 | q _ #0 #1 h 2 | e _ 0 _ 6 q 5 ^ 2 _ 2 | w __ 5 :] | \ 43 | | q __ 5 #4 5 5 | h __ 4 5 | q __ 5 5 4 0 | q __ 0 0 h 1 | h __ 2 e 5 6 q ^ 0 | e __ 3 4 q 5 1 3 | w ___ 5 | 44 | " 45 | assert_equal(a.length,4) 46 | 47 | end 48 | 49 | def test_methods 50 | a = zparse "[: q 0 :foo :bar(2) :3] 7" 51 | assert_equal(a.vals(:method),[nil, "foo", "bar(2)", nil, "foo", "bar(2)", nil, "foo", "bar(2)", nil]) 52 | end 53 | 54 | def play_loop_test 55 | ziffers " 56 | / stop: 1 57 | 0 58 | 3 59 | " 60 | ziff " 61 | 0 62 | 3 63 | " 64 | end 65 | 66 | test_play 67 | test_methods 68 | play_loop_test 69 | 70 | print "All tests OK" 71 | -------------------------------------------------------------------------------- /examples/not_tested/ziffers_keyboard.rb: -------------------------------------------------------------------------------- 1 | require "~/ziffers/ziffers.rb" 2 | 3 | # Ziffers keyboard - Always on key & scale 4 | 5 | # These settings work with VMPK defaults using "QWERTYUIOP"-keys to play 6 | use_bpm 60 7 | use_synth :beep 8 | startNote = 60 # Change this to start degrees from other key. Q-button using VMPK. 9 | playKey = :c 10 | playScale = :mixolydian 11 | metronome = true 12 | waitBeats = 5.0 # Waits as many silent beats to print ziffers notation & starts over 13 | 14 | define :init do 15 | set :on_time, 0 16 | set :off_time, 0 17 | set :noteLength, 0 18 | set :deg, 0 19 | set :song, "" 20 | end 21 | 22 | s = (scale startNote, :major, num_octaves: 2).to_a # Dont change. This scale is used to map midi notes to degrees 23 | 24 | init 25 | 26 | live_loop :tick do 27 | use_debug false 28 | synth :pluck, note: 55, release: 0.01, amp: 0.5 if metronome 29 | sleep 1 30 | if get(:on_time)!=0 31 | diffTime = Time.now.to_f-get(:on_time) 32 | if diffTime>waitBeats 33 | setDegree(get(:deg),get(:off_time)) # Set last degree based on off_time 34 | print get(:song) 35 | init # Start from beginning after 5 empty beats 36 | end 37 | end 38 | end 39 | 40 | define :parse_sync_address do |address| 41 | v = get_event(address).to_s.split(",")[6] 42 | if v != nil 43 | return v[3..-2].split("/") 44 | else 45 | raise "Could not parse midi address" 46 | end 47 | end 48 | 49 | live_loop :playSong do 50 | use_real_time 51 | stop 52 | n = zparse song 53 | zplay n 54 | sleep (zbeats n)+1 55 | end 56 | 57 | live_loop :midi_piano_on do 58 | use_real_time 59 | note, vol = sync "/midi/*/*/*/note_*" 60 | res = parse_sync_address "/midi/*/*/*/*" 61 | event = res[4] 62 | deg = ((s.index note)+1) 63 | 64 | if deg!=nil then 65 | case event 66 | when "note_on" then 67 | zplay deg, key: playKey, scale: playScale 68 | if get(:on_time)==0 then # On first note 69 | set :on_time, Time.now.to_f 70 | set :deg, deg 71 | else 72 | setDegree(deg, nil) # Set degree and calculate note length 73 | set :on_time, Time.now.to_f 74 | end 75 | when "note_off" then 76 | set :off_time, Time.now.to_f 77 | end 78 | else 79 | print note.to_s+" IS NOT MAPPED!" 80 | end 81 | end 82 | 83 | def setDegree(deg, off_time) 84 | diffTime = off_time!=nil ? off_time-get(:on_time) : Time.now.to_f-get(:on_time) 85 | beatTimes = diffTime/current_beat_duration 86 | roundedTime = defaultDurs.values.min { |a,b| (a-beatTimes).abs <=> (b-beatTimes).abs } 87 | if get(:noteLength)!=roundedTime then 88 | set :noteLength, roundedTime 89 | defaultDurs.key(roundedTime) 90 | set :song, get(:song)+defaultDurs.key(roundedTime).to_s 91 | end 92 | set :song, get(:song)+get(:deg).to_s 93 | set :deg, deg 94 | end 95 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/lambda_calculus_test.rb: -------------------------------------------------------------------------------- 1 | dir = File.dirname(__FILE__) 2 | require File.expand_path("#{dir}/test_helper") 3 | require File.expand_path("#{dir}/arithmetic_node_classes") 4 | require File.expand_path("#{dir}/lambda_calculus_node_classes") 5 | Treetop.load File.expand_path("#{dir}/arithmetic") 6 | Treetop.load File.expand_path("#{dir}/lambda_calculus") 7 | 8 | class Treetop::Runtime::SyntaxNode 9 | def method_missing(method, *args) 10 | raise "Node representing #{text_value} does not respond to #{method}" 11 | end 12 | end 13 | 14 | class LambdaCalculusParserTest < Test::Unit::TestCase 15 | include ParserTestHelper 16 | 17 | def setup 18 | @parser = LambdaCalculusParser.new 19 | end 20 | 21 | def test_free_variable 22 | assert_equal 'x', parse('x').eval.to_s 23 | end 24 | 25 | def test_variable_binding 26 | variable = parse('x').eval 27 | env = variable.bind(1, {}) 28 | assert_equal 1, env['x'] 29 | end 30 | 31 | def test_bound_variable_evaluation 32 | assert_equal 1, parse('x').eval({'x' => 1}) 33 | end 34 | 35 | def test_identity_function 36 | assert_equal '\x(x)', parse('\x(x)').eval.to_s 37 | end 38 | 39 | def test_function_returning_constant_function 40 | assert_equal '\x(\y(x))', parse('\x(\y(x))').eval.to_s 41 | end 42 | 43 | def test_identity_function_application 44 | assert_equal 1, parse('\x(x) 1').eval 45 | assert_equal '\y(y)', parse('\x(x) \y(y)').eval.to_s 46 | end 47 | 48 | def test_constant_function_construction 49 | assert_equal '\y(1)', parse('\x(\y(x)) 1').eval.to_s 50 | end 51 | 52 | def test_multiple_argument_application_is_left_associative 53 | assert_equal '\b(b)', parse('\x(\y(x y)) \a(a) \b(b)').eval.to_s 54 | end 55 | 56 | def test_parentheses_override_application_order 57 | assert_equal '\y(\b(b) y)', parse('\x(\y(x y)) (\a(a) \b(b))').eval.to_s 58 | end 59 | 60 | def test_arithmetic_in_function_body 61 | assert_equal 10, parse('\x(x + 5) 5').eval 62 | end 63 | 64 | def test_addition_of_function_results 65 | assert_equal 20, parse('\x(x + 5) 5 + \x(15 - x) 5').eval 66 | end 67 | 68 | def test_conditional 69 | result = parse('if (x) 1 else 2') 70 | assert_equal 1, result.eval({'x' => true}) 71 | assert_equal 2, result.eval({'x' => false}) 72 | end 73 | 74 | def test_keyword 75 | assert @parser.parse('if').failure? 76 | assert @parser.parse('else').failure? 77 | assert parse('elsee').success? 78 | assert parse('iff').success? 79 | end 80 | 81 | def test_program 82 | result = parse('def fact \x(if (x == 0) 83 | 1 84 | else 85 | x * fact (x - 1)); 86 | fact(5)').eval 87 | assert_equal 5 * 4 * 3 * 2, result 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/sequence.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Sequence < ParsingExpression 4 | def compile(address, builder, parent_expression = nil) 5 | super 6 | begin_comment(self) 7 | use_vars :result, :start_index, :accumulator 8 | compile_sequence_elements(sequence_elements) 9 | builder.if__ "#{accumulator_var}.last" do 10 | assign_result "instantiate_node(#{node_class_name},input, #{start_index_var}...index, #{accumulator_var})" 11 | extend_result sequence_element_accessor_module_name if sequence_element_accessor_module_name 12 | extend_result_with_inline_module parent_expression 13 | end 14 | builder.else_ do 15 | reset_index 16 | assign_failure start_index_var 17 | end 18 | end_comment(self) 19 | end 20 | 21 | def node_class_name 22 | node_class_declarations.node_class_name || 'SyntaxNode' 23 | end 24 | 25 | def compile_sequence_elements(elements) 26 | obtain_new_subexpression_address 27 | elements.first.compile(subexpression_address, builder) 28 | accumulate_subexpression_result 29 | if elements.size > 1 30 | builder.if_ subexpression_success? do 31 | compile_sequence_elements(elements[1..-1]) 32 | end 33 | end 34 | end 35 | 36 | def sequence_element_accessor_module 37 | @sequence_element_accessor_module ||= SequenceElementAccessorModule.new(sequence_elements) 38 | end 39 | 40 | def sequence_element_accessor_module_name 41 | sequence_element_accessor_module.module_name 42 | end 43 | 44 | def expected 45 | '""' 46 | end 47 | end 48 | 49 | class SequenceElementAccessorModule 50 | include InlineModuleMixin 51 | attr_reader :sequence_elements 52 | 53 | def initialize(sequence_elements) 54 | @sequence_elements = sequence_elements 55 | end 56 | 57 | def compile(idx, builder, rule) 58 | super 59 | builder.module_declaration(module_name) do 60 | elements_by_name = sequence_elements.inject({}){|h,e| (h[e.label_name.to_s] ||= []) << e; h} 61 | sequence_elements.each_with_index do |element, index| 62 | if element.label_name 63 | repetitions = elements_by_name[element.label_name.to_s] 64 | label_name = element.label_name + (repetitions.size > 1 ? (repetitions.index(element)+1).to_s : "") 65 | builder.method_declaration(label_name) do 66 | builder << "elements[#{index}]" 67 | end 68 | builder.newline unless index == sequence_elements.size - 1 69 | end 70 | end 71 | end 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /vendor/polyglot/website/stylesheets/screen.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #E1D1F1; 3 | font-family: "Georgia", sans-serif; 4 | font-size: 16px; 5 | line-height: 1.6em; 6 | padding: 1.6em 0 0 0; 7 | color: #333; 8 | } 9 | h1, h2, h3, h4, h5, h6 { 10 | color: #444; 11 | } 12 | h1 { 13 | font-family: sans-serif; 14 | font-weight: normal; 15 | font-size: 4em; 16 | line-height: 0.8em; 17 | letter-spacing: -0.1ex; 18 | margin: 5px; 19 | } 20 | li { 21 | padding: 0; 22 | margin: 0; 23 | list-style-type: square; 24 | } 25 | a { 26 | color: #5E5AFF; 27 | background-color: #DAC; 28 | font-weight: normal; 29 | text-decoration: underline; 30 | } 31 | blockquote { 32 | font-size: 90%; 33 | font-style: italic; 34 | border-left: 1px solid #111; 35 | padding-left: 1em; 36 | } 37 | .caps { 38 | font-size: 80%; 39 | } 40 | 41 | #main { 42 | width: 45em; 43 | padding: 0; 44 | margin: 0 auto; 45 | } 46 | .coda { 47 | text-align: right; 48 | color: #77f; 49 | font-size: smaller; 50 | } 51 | 52 | table { 53 | font-size: 90%; 54 | line-height: 1.4em; 55 | color: #ff8; 56 | background-color: #111; 57 | padding: 2px 10px 2px 10px; 58 | border-style: dashed; 59 | } 60 | 61 | th { 62 | color: #fff; 63 | } 64 | 65 | td { 66 | padding: 2px 10px 2px 10px; 67 | } 68 | 69 | .success { 70 | color: #0CC52B; 71 | } 72 | 73 | .failed { 74 | color: #E90A1B; 75 | } 76 | 77 | .unknown { 78 | color: #995000; 79 | } 80 | pre, code { 81 | font-family: monospace; 82 | font-size: 90%; 83 | line-height: 1.4em; 84 | color: #ff8; 85 | background-color: #111; 86 | padding: 2px 10px 2px 10px; 87 | } 88 | .comment { color: #aaa; font-style: italic; } 89 | .keyword { color: #eff; font-weight: bold; } 90 | .punct { color: #eee; font-weight: bold; } 91 | .symbol { color: #0bb; } 92 | .string { color: #6b4; } 93 | .ident { color: #ff8; } 94 | .constant { color: #66f; } 95 | .regex { color: #ec6; } 96 | .number { color: #F99; } 97 | .expr { color: #227; } 98 | 99 | #version { 100 | float: right; 101 | text-align: right; 102 | font-family: sans-serif; 103 | font-weight: normal; 104 | background-color: #B3ABFF; 105 | color: #141331; 106 | padding: 15px 20px 10px 20px; 107 | margin: 0 auto; 108 | margin-top: 15px; 109 | border: 3px solid #141331; 110 | } 111 | 112 | #version .numbers { 113 | display: block; 114 | font-size: 4em; 115 | line-height: 0.8em; 116 | letter-spacing: -0.1ex; 117 | margin-bottom: 15px; 118 | } 119 | 120 | #version p { 121 | text-decoration: none; 122 | color: #141331; 123 | background-color: #B3ABFF; 124 | margin: 0; 125 | padding: 0; 126 | } 127 | 128 | #version a { 129 | text-decoration: none; 130 | color: #141331; 131 | background-color: #B3ABFF; 132 | } 133 | 134 | .clickable { 135 | cursor: pointer; 136 | cursor: hand; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/ruby_builder.rb: -------------------------------------------------------------------------------- 1 | require 'treetop/ruby_extensions/string' 2 | 3 | module Treetop 4 | module Compiler 5 | class RubyBuilder 6 | 7 | attr_reader :level, :address_space, :ruby 8 | 9 | def initialize 10 | @level = 0 11 | @address_space = LexicalAddressSpace.new 12 | @ruby = String.new("") 13 | end 14 | 15 | def <<(ruby_line) 16 | return if ruby_line == '' 17 | ruby << ruby_line.tabto(level) << "\n" 18 | end 19 | 20 | def newline 21 | ruby << "\n" 22 | end 23 | 24 | def indented(depth = 2) 25 | self.in(depth) 26 | yield 27 | self.out(depth) 28 | end 29 | 30 | def class_declaration(name, &block) 31 | self << "class #{name}" 32 | indented(&block) 33 | self << "end" 34 | end 35 | 36 | def module_declaration(name, &block) 37 | self << "module #{name}" 38 | indented(&block) 39 | self << "end" 40 | end 41 | 42 | def method_declaration(name, &block) 43 | self << "def #{name}" 44 | indented(&block) 45 | self << "end" 46 | end 47 | 48 | def assign(left, right) 49 | if left.instance_of? Array 50 | self << "#{left.join(', ')} = #{right.join(', ')}" 51 | else 52 | self << "#{left} = #{right}" 53 | end 54 | end 55 | 56 | def extend(var, module_name) 57 | self << "#{var}.extend(#{module_name})" 58 | end 59 | 60 | def accumulate(left, right) 61 | self << "#{left} << #{right}" 62 | end 63 | 64 | def if__(condition, &block) 65 | self << "if #{condition}" 66 | indented(&block) 67 | end 68 | 69 | def if_(condition, &block) 70 | if__(condition, &block) 71 | self << 'end' 72 | end 73 | 74 | def else_(&block) 75 | self << 'else' 76 | indented(&block) 77 | self << 'end' 78 | end 79 | 80 | def loop(&block) 81 | self << 'loop do' 82 | indented(&block) 83 | self << 'end' 84 | end 85 | 86 | def break 87 | self << 'break' 88 | end 89 | 90 | def in(depth = 2) 91 | @level += depth 92 | self 93 | end 94 | 95 | def out(depth = 2) 96 | @level -= depth 97 | self 98 | end 99 | 100 | def next_address 101 | address_space.next_address 102 | end 103 | 104 | def reset_addresses 105 | address_space.reset_addresses 106 | end 107 | 108 | private 109 | 110 | def indent 111 | " " * level 112 | end 113 | end 114 | end 115 | end 116 | -------------------------------------------------------------------------------- /lib/parser/scala.treetop: -------------------------------------------------------------------------------- 1 | grammar Scala 2 | 3 | rule lines 4 | (clause / s)+ { 5 | def value 6 | cents = elements.map { |item| item.value.is_a?(Integer) ? ratio_to_cents(item.value) : item.value } 7 | cents.compact 8 | end 9 | } 10 | end 11 | 12 | rule clause 13 | first:(atom) rest:(s* op:operator s* cl:(atom / sub_operations / operation))* 14 | { 15 | def value 16 | if rest.empty? 17 | first.value 18 | else 19 | r = rest.elements.map {|v| v.op.value+v.cl.value.to_s } 20 | val = first.value.to_s+r.flatten.reject {|e| e.to_s.empty? }.join("") 21 | eval(val) 22 | end 23 | end 24 | } 25 | end 26 | 27 | rule atom 28 | op_val:(ratio / number / monzo) { 29 | def value 30 | op_val.value 31 | end 32 | } 33 | end 34 | 35 | rule number 36 | num:(decimal / int) { 37 | def value 38 | num.value 39 | end 40 | } 41 | end 42 | 43 | rule decimal 44 | '-'? [0-9]+ '.' [0-9]* 45 | { 46 | def value 47 | text_value.to_f 48 | end 49 | } 50 | end 51 | 52 | rule int 53 | '-'? [0-9]+ 54 | { 55 | def value 56 | text_value.to_i 57 | end 58 | } 59 | end 60 | 61 | rule ratio 62 | rat:(frac_ratio / edo_ratio / edji_ratio / decimal_ratio) { 63 | def value 64 | zlog "IN RATIO?" 65 | rat.value 66 | end 67 | } 68 | end 69 | 70 | rule frac_ratio 71 | n:(int) "/" d:(int) { 72 | def value 73 | zlog "IN RATIOADAsDSAD?" 74 | ratio = n.value.to_f / d.value.to_f 75 | ratio_to_cents(ratio) 76 | end 77 | } 78 | end 79 | 80 | rule edo_ratio 81 | n:(int) "\\" d:(int) { 82 | def value 83 | ratio = 2 ** (n.value.to_f / d.value.to_f) 84 | ratio_to_cents(ratio) 85 | end 86 | } 87 | end 88 | 89 | rule edji_ratio 90 | n:(int) "\\" d:(int) "<" pn:(int) "/"? pd:(int)? ">" { 91 | def value 92 | if pd and pd.methods.include?(:value) 93 | power = pn.value.to_f / pd.value.to_f 94 | else 95 | power = pn.value.to_f 96 | end 97 | ratio = power ** (n.value.to_f / d.value.to_f) 98 | ratio_to_cents(ratio) 99 | end 100 | } 101 | end 102 | 103 | rule decimal_ratio 104 | s:(int) "," n:(int) { 105 | def value 106 | ratio = "#{s.value}.#{n.value}".to_f 107 | ratio_to_cents(ratio) 108 | end 109 | } 110 | end 111 | 112 | rule monzo 113 | "[" vals:(int / s)+ ">" { 114 | def value 115 | monzos = vals.elements.map{|v| v.value }.compact 116 | monzo_to_cents(monzos) 117 | end 118 | } 119 | end 120 | 121 | rule operator 122 | op:('**' / '*' / '+' / '-' / '^' / '%' / '|' / '&' / '<<' / '>>') 123 | { 124 | def value 125 | op.text_value 126 | end 127 | } 128 | end 129 | 130 | rule sub_operations 131 | "(" op:operation ")" { 132 | def value 133 | op.value 134 | end 135 | } 136 | end 137 | 138 | rule s 139 | [ \t\f\r\n] { 140 | def value 141 | nil 142 | end 143 | } 144 | end 145 | 146 | end 147 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/choice_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module ChoiceSpec 4 | describe "A choice between terminal symbols" do 5 | testing_expression '("foo" { def foo_method; end } / "bar" { def bar_method; end } / "baz" { def baz_method; end }) {def bat_method; end}' 6 | 7 | it "successfully parses input matching any of the alternatives, returning a node that responds to methods defined in its respective inline module" do 8 | result = parse('foo') 9 | result.should_not be_nil 10 | result.should respond_to(:foo_method) 11 | result.should_not respond_to(:bar_method) 12 | result.should_not respond_to(:baz_method) 13 | result.should respond_to(:bat_method) 14 | 15 | result = parse('bar') 16 | result.should_not be_nil 17 | result.should_not respond_to(:foo_method) 18 | result.should respond_to(:bar_method) 19 | result.should_not respond_to(:baz_method) 20 | result.should respond_to(:bat_method) 21 | 22 | result = parse('baz') 23 | result.should_not be_nil 24 | result.should_not respond_to(:foo_method) 25 | result.should_not respond_to(:bar_method) 26 | result.should respond_to(:baz_method) 27 | result.should respond_to(:bat_method) 28 | end 29 | 30 | it "upon parsing a string matching the second alternative, records the failure of the first terminal" do 31 | result = parse('bar') 32 | terminal_failures = parser.terminal_failures 33 | terminal_failures.size.should == 1 34 | failure = terminal_failures[0] 35 | failure.expected_string.should == '"foo"' 36 | failure.index.should == 0 37 | end 38 | 39 | it "upon parsing a string matching the third alternative, records the failure of the first two terminals" do 40 | result = parse('baz') 41 | 42 | terminal_failures = parser.terminal_failures 43 | 44 | terminal_failures.size.should == 2 45 | 46 | failure_1 = terminal_failures[0] 47 | failure_1.expected_string == 'foo' 48 | failure_1.index.should == 0 49 | 50 | failure_2 = terminal_failures[1] 51 | failure_2.expected_string == 'bar' 52 | failure_2.index.should == 0 53 | end 54 | end 55 | 56 | describe "A choice between sequences" do 57 | testing_expression "'foo' 'bar' 'baz'\n/\n'bing' 'bang' 'boom'" 58 | 59 | it "successfully parses input matching any of the alternatives" do 60 | parse('foobarbaz').should_not be_nil 61 | parse('bingbangboom').should_not be_nil 62 | end 63 | end 64 | 65 | describe "A choice between terminals followed by a block" do 66 | testing_expression "('a'/ 'bb' / [c]) { def a_method; end }" 67 | 68 | it "extends a match of any of its subexpressions with a module created from the block" do 69 | ['a', 'bb', 'c'].each do |letter| 70 | parse(letter).should respond_to(:a_method) 71 | end 72 | end 73 | end 74 | 75 | module TestModule 76 | def a_method 77 | end 78 | end 79 | 80 | describe "a choice followed by a declared module" do 81 | testing_expression "('a'/ 'bb' / [c]) " 82 | 83 | it "extends a match of any of its subexpressions with a module created from the block" do 84 | ['a', 'bb', 'c'].each do |letter| 85 | parse(letter).should respond_to(:a_method) 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/parser/parameters.treetop: -------------------------------------------------------------------------------- 1 | grammar Parameters 2 | 3 | rule base 4 | space? opts:(hash_elements / parameter) space? 5 | { 6 | def value 7 | h = opts.value 8 | h 9 | end 10 | } 11 | end 12 | 13 | rule parameter 14 | '$' p:(string) 15 | { 16 | def value 17 | Thread.current[:ziffers_param_opts][p.value.to_sym] 18 | end 19 | } 20 | end 21 | 22 | rule symbol 23 | ':' s:(string) 24 | { 25 | def value 26 | s.text_value.to_sym 27 | end 28 | } 29 | end 30 | 31 | rule boolean 32 | t:('true' / 'false') 33 | { 34 | def value 35 | t.text_value == 'true' 36 | end 37 | } 38 | end 39 | 40 | rule string 41 | [a-zA-Z_]+ [0-9]* 42 | { 43 | def value 44 | text_value 45 | end 46 | } 47 | end 48 | 49 | rule integer 50 | [-0-9]+ 51 | { 52 | def value 53 | text_value.to_i 54 | end 55 | } 56 | end 57 | 58 | rule random_integer 59 | '(' m:(integer) ',' x:(integer) ')' 60 | { 61 | def value 62 | ->(){sonic_random(m.value,x.value)} 63 | end 64 | } 65 | end 66 | 67 | rule decimal 68 | [0-9]+ '.' [0-9]+ 69 | { 70 | def value 71 | text_value.to_f 72 | end 73 | } 74 | end 75 | 76 | rule random_decimal 77 | '(' m:(decimal) ',' x:(decimal) ')' 78 | { 79 | def value 80 | ->(){sonic_random_float(m.value,x.value)} 81 | end 82 | } 83 | end 84 | 85 | rule range 86 | s:(integer) '..' e:(integer) 87 | { 88 | def value 89 | s.value..e.value 90 | end 91 | } 92 | end 93 | 94 | rule integer_range 95 | '(' a:(integer) '..' b:(integer) ')' type:('+' / '*')? step:(integer)? reflect:('%')? 96 | { 97 | def value 98 | sonic_range(a.value, b.value, step.methods.include?(:value) ? step.value : 1, type.text_value, reflect.text_value=="%" ? true : false) 99 | end 100 | } 101 | end 102 | 103 | rule decimal_range 104 | '(' a:(decimal) '..' b:(decimal) ')' type:('+' / '*')? step:(decimal)? reflect:('%')? 105 | { 106 | def value 107 | sonic_range(a.value,b.value, step.methods.include?(:value) ? step.value : 0.1, type.text_value, reflect.text_value=="%" ? true : false) 108 | end 109 | } 110 | end 111 | 112 | rule array 113 | '[' space? items:(val:(decimal / random_decimal / symbol / integer / random_integer / boolean / hash / array) ','? space?)+ ']' 114 | { 115 | def value 116 | items.elements.map {|v| v.val.value } 117 | end 118 | } 119 | end 120 | 121 | rule hash 122 | '{' hash_elements '}' 123 | { 124 | def value 125 | hash_elements.value 126 | end 127 | } 128 | end 129 | 130 | rule hash_elements 131 | space? items:(key:(string) ':' space? val:(symbol / parameter / decimal / random_decimal / range / integer_range / decimal_range / symbol / integer / random_integer / boolean / string / hash / array) ','? space?)+ 132 | { 133 | def value 134 | Hash[*items.elements.map {|p| [p.key.value.to_sym, p.val.value] }.flatten(1)] 135 | end 136 | } 137 | end 138 | 139 | rule space 140 | [\s\r\n]+ 141 | { 142 | def value 143 | text_value 144 | end 145 | } 146 | end 147 | 148 | end 149 | -------------------------------------------------------------------------------- /vendor/treetop/examples/lambda_calculus/lambda_calculus.treetop: -------------------------------------------------------------------------------- 1 | grammar LambdaCalculus 2 | include Arithmetic 3 | 4 | rule program 5 | expression more_expressions:(';' space expression)* { 6 | def eval(env={}) 7 | env = env.clone 8 | last_eval = nil 9 | expressions.each do |exp| 10 | last_eval = exp.eval(env) 11 | end 12 | last_eval 13 | end 14 | 15 | def expressions 16 | [expression] + more_expressions.elements.map {|elt| elt.expression} 17 | end 18 | } 19 | end 20 | 21 | rule expression 22 | definition / conditional / application / function / super 23 | end 24 | 25 | rule definition 26 | 'def' space variable space expression { 27 | def eval(env) 28 | env[variable.name] = expression.eval(env) 29 | end 30 | } 31 | end 32 | 33 | rule conditional 34 | 'if' space '(' space condition:expression space ')' space 35 | true_case:expression space 'else' space false_case:expression { 36 | def eval(env) 37 | if condition.eval(env) 38 | true_case.eval(env) 39 | else 40 | false_case.eval(env) 41 | end 42 | end 43 | } 44 | end 45 | 46 | rule primary 47 | application / super 48 | end 49 | 50 | rule application 51 | operator space expression { 52 | def eval(env={}) 53 | left_associative_apply(operator.eval(env), env) 54 | end 55 | 56 | def left_associative_apply(operator, env) 57 | if expression.instance_of?(Application) 58 | expression.left_associative_apply(operator.apply(expression.operator.eval(env)), env) 59 | else 60 | operator.apply(expression.eval(env)) 61 | end 62 | end 63 | 64 | def to_s(env={}) 65 | operator.to_s(env) + ' ' + expression.to_s(env) 66 | end 67 | } 68 | end 69 | 70 | rule operator 71 | function / variable 72 | end 73 | 74 | rule non_application 75 | function / variable 76 | end 77 | 78 | rule function 79 | '\\' param:variable '(' body:expression ')' { 80 | class Closure 81 | attr_reader :env, :function 82 | 83 | def initialize(function, env) 84 | @function = function 85 | @env = env 86 | end 87 | 88 | def apply(arg) 89 | function.body.eval(function.param.bind(arg, env)) 90 | end 91 | 92 | def to_s(other_env={}) 93 | "\\#{function.param.to_s}(#{function.body.to_s(other_env.merge(env))})" 94 | end 95 | end 96 | 97 | def eval(env={}) 98 | Closure.new(self, env) 99 | end 100 | 101 | def to_s(env={}) 102 | eval(env).to_s 103 | end 104 | } 105 | end 106 | 107 | rule variable 108 | !keyword ( 109 | super { 110 | def bind(value, env) 111 | env.merge(name => value) 112 | end 113 | 114 | def to_s(env={}) 115 | env.has_key?(name) ? env[name].to_s : name 116 | end 117 | } 118 | ) 119 | end 120 | 121 | rule keyword 122 | ('if' / 'else') !non_space_char 123 | end 124 | 125 | rule non_space_char 126 | ![ \n] . 127 | end 128 | 129 | rule space 130 | [ \n]* 131 | end 132 | end -------------------------------------------------------------------------------- /vendor/treetop/doc/index.markdown: -------------------------------------------------------------------------------- 1 |

2 | 3 | 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. 4 | 5 |

6 | 7 | sudo gem install treetop 8 | 9 | #Intuitive Grammar Specifications 10 | 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: 11 | 12 | grammar Arithmetic 13 | rule additive 14 | multitive ( '+' multitive )* 15 | end 16 | 17 | rule multitive 18 | primary ( [*/%] primary )* 19 | end 20 | 21 | rule primary 22 | '(' additive ')' / number 23 | end 24 | 25 | rule number 26 | '-'? [1-9] [0-9]* 27 | end 28 | end 29 | 30 | 31 | #Syntax-Oriented Programming 32 | 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... 33 | 34 | grammar Arithmetic 35 | rule additive 36 | multitive a:( '+' multitive )* { 37 | def value 38 | a.elements.inject(multitive.value) { |sum, e| 39 | sum+e.multitive.value 40 | } 41 | end 42 | } 43 | end 44 | 45 | # other rules below ... 46 | end 47 | 48 | ...or associate rules with classes of nodes you wish your parsers to instantiate upon matching a rule. 49 | 50 | grammar Arithmetic 51 | rule additive 52 | multitive ('+' multitive)* 53 | end 54 | 55 | # other rules below ... 56 | end 57 | 58 | 59 | #Reusable, Composable Language Descriptions 60 | 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. 61 | 62 | grammar RubyWithEmbeddedSQL 63 | include SQL 64 | 65 | rule string 66 | quote sql_expression quote / super 67 | end 68 | end 69 | 70 | 71 | #Acknowledgements 72 | 73 | 74 |
75 | 76 | First, thank you to my employer Rob Mee of Pivotal Labs for funding a substantial portion of Treetop's development. He gets it. 77 | 78 | 79 | I'd also like to thank: 80 | 81 | * Damon McCormick for several hours of pair programming. 82 | * Nick Kallen for lots of well-considered feedback and a few afternoons of programming. 83 | * Brian Takita for a night of pair programming. 84 | * Eliot Miranda for urging me rewrite as a compiler right away rather than putting it off. 85 | * Ryan Davis and Eric Hodel for hurting my code. 86 | * Dav Yaginuma for kicking me into action on my idea. 87 | * Bryan Ford for his seminal work on Packrat Parsers. 88 | * The editors of Lambda the Ultimate, where I discovered parsing expression grammars. 89 | -------------------------------------------------------------------------------- /vendor/treetop/Treetop.tmbundle/Support/syntax_tree_viewer.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'rubygems' 3 | require 'treetop' 4 | require "#{ENV["TM_SUPPORT_PATH"]}/lib/ui" 5 | 6 | # Monkey-patch SyntaxNode in a gross violation of its privacy. 7 | module Treetop 8 | module Runtime 9 | class SyntaxNode 10 | def interesting_methods 11 | # Copied from SyntaxNode#inspect 12 | methods-[extension_modules.last ? extension_modules.last.methods : nil]-self.class.instance_methods 13 | end 14 | 15 | def to_hash 16 | { 17 | "class_and_modules" => self.class.to_s.sub(/.*:/,'') + extension_modules.map{|m| "+"+m.to_s.sub(/.*:/,'')}*"", 18 | "offset" => interval.first, 19 | "text_value" => text_value, 20 | "methods" => interesting_methods * ", ", 21 | "elements" => elements ? elements.map {|e| e.to_hash} : [] 22 | } 23 | end 24 | end 25 | end 26 | end 27 | 28 | class SyntaxTreeViewer 29 | def self.nib_path 30 | File.dirname(__FILE__) + "/SyntaxTreeViewer.nib" 31 | end 32 | 33 | def self.new_with_unknown_grammar 34 | parser = if ENV['TM_SCOPE'] =~ /source\.ruby/ && ENV['TM_SELECTED_TEXT'] 35 | eval(ENV['TM_SELECTED_TEXT']) 36 | else 37 | parser_file = if ENV['TM_SCOPE'] =~ /source\.treetop/ 38 | ENV['TM_FILEPATH'] 39 | else 40 | ask_for_grammar 41 | end 42 | return unless parser_file 43 | Treetop.load(parser_file) 44 | end 45 | new(parser.new) 46 | end 47 | 48 | def self.ask_for_grammar 49 | files = TextMate::UI.request_file("title" => "Select a Grammar File") 50 | if files.nil? || files.empty? 51 | nil 52 | else 53 | files[0] 54 | end 55 | end 56 | 57 | def self.nib_path 58 | File.dirname(__FILE__) + "/nibs/SyntaxTreeViewer.nib" 59 | end 60 | 61 | def initialize(_parser) 62 | @parser = _parser 63 | run_parser! 64 | end 65 | 66 | def dialog 67 | TextMate::UI.dialog( 68 | :nib => self.class.nib_path, 69 | :parameters => parameters 70 | ) do |d| 71 | d.wait_for_input do |params| 72 | if params["returnArgument"] 73 | self.input = params["returnArgument"] 74 | run_parser! 75 | d.parameters = parameters 76 | true 77 | else 78 | false 79 | end 80 | end 81 | end 82 | end 83 | 84 | def input 85 | ENV['TM_TREETOP_SYNTAX_VIEWER_INPUT'] ||= "" 86 | end 87 | 88 | def input=(new_input) 89 | ENV['TM_TREETOP_SYNTAX_VIEWER_INPUT'] = new_input 90 | end 91 | 92 | private 93 | def run_parser! 94 | if input && !input.empty? 95 | @syntax_tree = @parser.parse(input) 96 | TextMate::UI.alert(:warning, "Parse error", @parser.failure_reason) unless @syntax_tree 97 | end 98 | end 99 | 100 | def parameters 101 | p = { 102 | "input" => input, 103 | "syntax_tree" => @syntax_tree ? @syntax_tree.to_hash : {}, 104 | "selected_tab" => !input.empty? && @syntax_tree ? "Syntax Tree" : "Input" 105 | } 106 | puts p 107 | p 108 | end 109 | end 110 | 111 | if __FILE__ == $0 112 | Dir.chdir("/Users/aobrien/Work/canopy/play/sparql/") 113 | require "/Users/aobrien/Work/canopy/play/sparql/lib/sparql" 114 | v = SyntaxTreeViewer.new(SparqlParser.new) 115 | v.input = %{PREFIX foaf: SELECT ?foo WHERE { ?x foaf:knows ?y . ?z foaf:knows ?x .}} 116 | v.dialog 117 | end 118 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/repetition.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class Repetition < ParsingExpression 4 | def compile(address, builder, parent_expression) 5 | super 6 | repeated_expression = parent_expression.atomic 7 | begin_comment(parent_expression) 8 | use_vars :result, :accumulator, :start_index 9 | 10 | builder.loop do 11 | obtain_new_subexpression_address 12 | repeated_expression.compile(subexpression_address, builder) 13 | builder.if__ subexpression_success? do 14 | accumulate_subexpression_result 15 | end 16 | builder.else_ do 17 | builder.break 18 | end 19 | if max && !max.empty? 20 | builder.if_ "#{accumulator_var}.size == #{max.text_value}" do 21 | builder.break 22 | end 23 | end 24 | end 25 | end 26 | 27 | def inline_module_name 28 | parent_expression.inline_module_name 29 | end 30 | 31 | def assign_and_extend_result parent_expression 32 | assign_result "instantiate_node(#{node_class_name},input, #{start_index_var}...index, #{accumulator_var})" 33 | extend_result_with_inline_module parent_expression 34 | end 35 | end 36 | 37 | 38 | class ZeroOrMore < Repetition 39 | def compile(address, builder, parent_expression) 40 | super 41 | assign_and_extend_result parent_expression 42 | end_comment(parent_expression) 43 | end 44 | 45 | def max 46 | nil 47 | end 48 | end 49 | 50 | class OneOrMore < Repetition 51 | def compile(address, builder, parent_expression) 52 | super 53 | builder.if__ "#{accumulator_var}.empty?" do 54 | reset_index 55 | assign_failure start_index_var 56 | end 57 | builder.else_ do 58 | assign_and_extend_result parent_expression 59 | end 60 | end_comment(parent_expression) 61 | end 62 | 63 | def max 64 | nil 65 | end 66 | 67 | def expected 68 | parent_expression.atomic.expected && '"at least one "+'+parent_expression.atomic.expected 69 | end 70 | end 71 | 72 | class OccurrenceRange < Repetition 73 | def compile(address, builder, parent_expression) 74 | super 75 | 76 | if !min.empty? && min.text_value.to_i != 0 77 | # We got some, but fewer than we wanted. There'll be a failure reported already 78 | builder.if__ "#{accumulator_var}.size < #{min.text_value}" do 79 | reset_index 80 | assign_failure start_index_var 81 | end 82 | builder.else_ do 83 | clean_unsaturated 84 | assign_and_extend_result parent_expression 85 | end 86 | else 87 | clean_unsaturated 88 | assign_and_extend_result parent_expression 89 | end 90 | 91 | end_comment(parent_expression) 92 | end 93 | 94 | # remove the last terminal_failure if we merely failed to reach the maximum 95 | def clean_unsaturated 96 | if !max.empty? && max.text_value.to_i > 0 97 | builder.if_ "#{accumulator_var}.size < #{max.text_value}" do 98 | builder << '@terminal_failures.pop' # Ignore the last failure. 99 | end 100 | end 101 | end 102 | 103 | def expected 104 | parent_expression.atomic.expected && "at least #{min.text_value} "+parent_expression.atomic.expected 105 | end 106 | end 107 | 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /vendor/treetop/benchmark/seqpar_benchmark.rb: -------------------------------------------------------------------------------- 1 | # Benchmarking written by Bernard Lambeau, improved by Jason Garber 2 | # 3 | # To test your optimizations: 4 | # 1. Run ruby seqpar_benchmark.rb 5 | # 2. cp after.dat before.dat 6 | # 3. Make your modifications to the treetop code 7 | # 4. Run ruby seqpar_benchmark.rb 8 | # 5. Run gnuplot seqpar.gnuplot 9 | # 10 | $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib') 11 | require 'treetop' 12 | require 'benchmark' 13 | 14 | srand(47562) # So it runs the same each time 15 | 16 | class Array; def sum; inject( nil ) { |sum,x| sum ? sum+x : x }; end; end 17 | class Array; def mean; sum / size; end; end 18 | 19 | class SeqParBenchmark 20 | 21 | OPERATORS = ["seq", "fit", "art"*5, "par", "sequence"] 22 | 23 | # Loads the grammar and returns a parser 24 | def initialize 25 | compiler = Treetop::Compiler::GrammarCompiler.new 26 | @where = File.expand_path(File.dirname(__FILE__)) 27 | grammar = File.join(@where, 'seqpar.treetop') 28 | output = File.join(@where, 'seqpar.rb') 29 | compiler.compile(grammar, output) 30 | load output 31 | File.delete(output) 32 | @parser = SeqParParser.new 33 | end 34 | 35 | # Checks the grammar 36 | def check 37 | ["Task", 38 | "seq Task end", 39 | "par Task end", 40 | "seq Task Task end", 41 | "par Task Task end", 42 | "par seq Task end Task end", 43 | "par seq seq Task end end Task end", 44 | "seq Task par seq Task end Task end Task end"].each do |input| 45 | raise ParseError.new(@parser) if @parser.parse(input).nil? 46 | end 47 | end 48 | 49 | # Generates an input text 50 | def generate(depth=0) 51 | return "Task" if depth>7 52 | return "seq #{generate(depth+1)} end" if depth==0 53 | which = rand(OPERATORS.length) 54 | case which 55 | when 0 56 | "Task" 57 | else 58 | raise unless OPERATORS[which] 59 | buffer = "#{OPERATORS[which]} " 60 | 0.upto(rand(4)+1) do 61 | buffer << generate(depth+1) << " " 62 | end 63 | buffer << "end" 64 | buffer 65 | end 66 | end 67 | 68 | # Launches benchmarking 69 | def benchmark 70 | number_by_size = Hash.new {|h,k| h[k] = 0} 71 | time_by_size = Hash.new {|h,k| h[k] = 0} 72 | 0.upto(250) do |i| 73 | input = generate 74 | length = input.length 75 | puts "Launching #{i}: #{input.length}" 76 | # puts input 77 | tms = Benchmark.measure { @parser.parse(input) } 78 | number_by_size[length] += 1 79 | time_by_size[length] += tms.total*1000 80 | end 81 | # puts number_by_size.inspect 82 | # puts time_by_size.inspect 83 | 84 | File.open(File.join(@where, 'after.dat'), 'w') do |dat| 85 | number_by_size.keys.sort.each do |size| 86 | dat << "#{size} #{(time_by_size[size]/number_by_size[size]).truncate}\n" 87 | end 88 | end 89 | 90 | if File.exist?(File.join(@where, 'before.dat')) 91 | before = {} 92 | performance_increases = [] 93 | File.foreach(File.join(@where, 'before.dat')) do |line| 94 | size, time = line.split(' ') 95 | before[size] = time 96 | end 97 | File.foreach(File.join(@where, 'after.dat')) do |line| 98 | size, time = line.split(' ') 99 | performance_increases << (before[size].to_f - time.to_f) / before[size].to_f unless time == "0" || before[size] == "0" 100 | end 101 | puts "Average performance increase: #{(performance_increases.mean * 100 * 10).round / 10.0}%" 102 | end 103 | end 104 | 105 | end 106 | 107 | SeqParBenchmark.new.benchmark -------------------------------------------------------------------------------- /vendor/treetop/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'benchmark' 3 | require 'rspec' 4 | require 'rspec/core/shared_context' 5 | require 'polyglot' 6 | 7 | $LOAD_PATH.unshift File.expand_path('../../lib') 8 | require 'treetop' 9 | include Treetop 10 | 11 | # We're still using the old expect syntax: 12 | RSpec.configure do |c| 13 | c.expect_with(:rspec) { |c| c.syntax = :should } 14 | end 15 | 16 | module Treetop 17 | module ExampleGroupInstanceMethods 18 | module ClassMethods 19 | attr_accessor :parser_class_under_test 20 | attr_accessor :parser_text 21 | attr_accessor :parser_code 22 | 23 | def testing_expression(expression_under_test) 24 | testing_grammar(%{ 25 | grammar Test 26 | rule expression_under_test 27 | }+expression_under_test+%{ 28 | end 29 | end 30 | }.tabto(0)) 31 | end 32 | 33 | def testing_grammar(grammar_under_test) 34 | self.parser_text = grammar_under_test 35 | grammar_node = parse_with_metagrammar(grammar_under_test.strip, :module_or_grammar) 36 | self.parser_code = grammar_node.compile 37 | class_eval(self.parser_code) 38 | self.parser_class_under_test = class_eval(grammar_node.parser_name) 39 | end 40 | 41 | def parse_with_metagrammar(input, root) 42 | parser = Treetop::Compiler::MetagrammarParser.new 43 | parser.root = root 44 | node = parser.parse(input) 45 | raise parser.failure_reason unless node 46 | node 47 | end 48 | 49 | end 50 | 51 | attr_reader :parser 52 | 53 | def parse_with_metagrammar(input, root) 54 | self.class.parse_with_metagrammar(input, root) 55 | end 56 | 57 | def parser_class_under_test 58 | self.class.parser_class_under_test 59 | end 60 | 61 | def parse(input, options = {}) 62 | @parser = parser_class_under_test.new 63 | unless options[:consume_all_input].nil? 64 | parser.consume_all_input = options.delete(:consume_all_input) 65 | end 66 | result = parser.parse(input, options) 67 | yield result if block_given? 68 | result 69 | end 70 | 71 | def parse_multibyte(input, options = {}) 72 | require 'active_support/all' 73 | 74 | if RUBY_VERSION !~ /^(1\.9|2\.)/ && 'NONE' == $KCODE then $KCODE = 'UTF8' end 75 | # rspec 1.3 used to do something similar (set it to 'u') that we need 76 | # for activerecord multibyte wrapper to kick in (1.8 only? @todo) 77 | 78 | parse(input.mb_chars, options) 79 | end 80 | 81 | def compiling_grammar(grammar_under_test) 82 | lambda { 83 | grammar_node = parse_with_metagrammar(grammar_under_test.strip, :grammar) 84 | parser_code = grammar_node.compile 85 | [grammar_node, parser_code] 86 | } 87 | end 88 | 89 | def compiling_expression(expression_under_test) 90 | compiling_grammar(%{ 91 | grammar Test 92 | rule expression_under_test 93 | #{expression_under_test} 94 | end 95 | end 96 | }.tabto(0)) 97 | end 98 | 99 | def optionally_benchmark(&block) 100 | if BENCHMARK 101 | Benchmark.bm do |x| 102 | x.report(&block) 103 | end 104 | else 105 | yield 106 | end 107 | end 108 | end 109 | end 110 | 111 | RSpec.configure do |c| 112 | c.mock_with :rr 113 | c.extend Treetop::ExampleGroupInstanceMethods::ClassMethods 114 | c.include Treetop::ExampleGroupInstanceMethods 115 | end 116 | 117 | class Symbol 118 | def to_proc 119 | lambda do |x| 120 | x.send(self) 121 | end 122 | end unless method_defined?(:to_proc) 123 | end 124 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime/syntax_node.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Runtime 3 | class SyntaxNode 4 | attr_reader :input, :interval 5 | attr_accessor :parent 6 | 7 | def initialize(input, interval, elements = nil) 8 | @input = input 9 | @interval = interval 10 | if (@elements = elements) 11 | @elements.each { |e| e.equal?(true) or e.parent = self } 12 | end 13 | end 14 | 15 | def elements 16 | return @elements if terminal? 17 | # replace the character class placeholders in the sequence (lazy instantiation) 18 | last_element = nil 19 | @comprehensive_elements ||= @elements.map do |element| 20 | if element == true 21 | index = last_element ? last_element.interval.last : interval.first 22 | element = SyntaxNode.new(input, index...(index + 1)) 23 | element.parent = self 24 | end 25 | last_element = element 26 | end 27 | 28 | @comprehensive_elements 29 | end 30 | 31 | def terminal? 32 | @elements.nil? 33 | end 34 | 35 | def nonterminal? 36 | !terminal? 37 | end 38 | 39 | def text_value 40 | input[interval] 41 | end 42 | 43 | def empty? 44 | interval.first == interval.last && interval.exclude_end? 45 | end 46 | 47 | def <=>(other) 48 | self.interval.first <=> other.interval.first 49 | end 50 | 51 | def extension_modules 52 | local_extensions = 53 | class < 0 57 | local_extensions 58 | else 59 | [] # There weren't any; must be a literal node 60 | end 61 | end 62 | 63 | def inspect_self(indent="") 64 | em = extension_modules 65 | interesting_methods = methods-[em.last ? em.last.methods : nil]-self.class.instance_methods 66 | im = interesting_methods.size > 0 ? " (#{interesting_methods.join(",")})" : "" 67 | tv = text_value 68 | tv = "...#{tv[-20..-1]}" if tv.size > 20 69 | 70 | indent + 71 | self.class.to_s.sub(/.*:/,'') + 72 | em.map{|m| "+"+m.to_s.sub(/.*:/,'')}*"" + 73 | " offset=#{interval.first}" + 74 | ", #{tv.inspect}" + 75 | im 76 | end 77 | 78 | def inspect_children(indent="") 79 | return '' unless elements && elements.size > 0 80 | ":" + 81 | elements.map do |e| 82 | begin 83 | "\n"+e.inspect(indent+" ") 84 | rescue # Defend against inspect not taking a parameter 85 | "\n"+indent+" "+e.inspect 86 | end 87 | end. 88 | join("") 89 | end 90 | 91 | def inspect(indent="") 92 | inspect_self(indent) + 93 | inspect_children(indent) 94 | end 95 | 96 | @@dot_id_counter = 0 97 | 98 | def dot_id 99 | @dot_id ||= @@dot_id_counter += 1 100 | end 101 | 102 | def write_dot(io) 103 | io.puts "node#{dot_id} [label=\"'#{text_value}'\"];" 104 | if nonterminal? then 105 | elements.each do 106 | |x| 107 | io.puts "node#{dot_id} -> node#{x.dot_id};" 108 | x.write_dot(io) 109 | end 110 | end 111 | end 112 | 113 | def write_dot_file(fname) 114 | File.open(fname + ".dot","w") do 115 | |file| 116 | file.puts "digraph G {" 117 | write_dot(file) 118 | file.puts "}" 119 | end 120 | end 121 | end 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /lib/monkeypatches.rb: -------------------------------------------------------------------------------- 1 | module RangeZiffers 2 | include SonicPi::Lang::WesternTheory 3 | def to_z 4 | self.to_a.map {|degree| get_ziff(degree) } 5 | end 6 | end 7 | 8 | Range.include RangeZiffers 9 | 10 | module NoteHelper 11 | include SonicPi::Lang::WesternTheory 12 | def to_h 13 | (note_info self).to_h 14 | end 15 | end 16 | 17 | Integer.include NoteHelper 18 | 19 | class SonicPi::Scale 20 | def self.patch(scales) 21 | scales.each { |name, intervals| 22 | self::SCALE[name] = intervals unless self::SCALE.key? name 23 | } 24 | end 25 | 26 | def initialize(tonic, name, num_octaves=1) 27 | if name.is_a?(Array) 28 | intervals = name 29 | name = :custom 30 | elsif name.is_a?(Integer) 31 | intervals = number_to_scale name 32 | name = :custom 33 | else 34 | name = name.to_sym 35 | intervals = SCALE[name] 36 | end 37 | 38 | unless intervals 39 | begin 40 | cents = parse_scala name 41 | intervals = cents_to_semitones cents 42 | rescue Exception 43 | raise InvalidScaleError, "Invalid scale: #{name.inspect}" 44 | end 45 | end 46 | 47 | raise InvalidScaleError, "Unknown scale name: #{name.inspect}" unless intervals 48 | 49 | intervals = intervals * num_octaves 50 | current = SonicPi::Note.resolve_midi_note(tonic) 51 | res = [current] 52 | intervals.each do |i| 53 | current += i 54 | res << current 55 | end 56 | 57 | @name = name 58 | @tonic = tonic 59 | @num_octaves = num_octaves 60 | @notes = res 61 | super(res) 62 | end 63 | 64 | end 65 | 66 | class SonicPi::Chord 67 | def self.patch(chords) 68 | chords.each { |name, intervals| 69 | unless self::CHORD.key? name.to_sym 70 | self::CHORD[name.to_sym] = intervals 71 | self::CHORD_LOOKUP[name.to_sym] = intervals 72 | self::CHORD_NAMES.append(name) 73 | end 74 | } 75 | end 76 | end 77 | 78 | #Missing scales based on: https://www.newjazz.dk/Compendiums/scales_of_harmonies.pdf 79 | scales = lambda { 80 | ionian1s = [1,2,1,2,2,2,2] 81 | ionian5s = [2,2,1,3,1,2,1] 82 | ionian6b = [2,2,1,2,1,3,1] 83 | { 84 | # Family 2 85 | :ionian1s=>ionian1s, 86 | :dorian7s=>ionian1s.rotate(1), 87 | :phrygian6s=>ionian1s.rotate(2), 88 | :lydian5s=>ionian1s.rotate(3), 89 | :mixolydian4s=>ionian1s.rotate(4), 90 | :aeolian3s=>ionian1s.rotate(5), 91 | :locrian2s=>ionian1s.rotate(6), 92 | # Family 3 93 | :ionian5s=>ionian5s, 94 | :dorian4s=>ionian5s.rotate(1), 95 | :phrygian3s=>ionian5s.rotate(2), 96 | :lydian2s=>ionian5s.rotate(3), 97 | :mixolydian1s=>ionian5s.rotate(4), 98 | :aeolian7s=>ionian5s.rotate(5), 99 | :locrian6s=>ionian5s.rotate(6), 100 | # Family 4 101 | :ionian6b=>ionian6b, 102 | :dorian5b=>ionian6b.rotate(1), 103 | :phrygian4b=>ionian6b.rotate(2), 104 | :lydian3b=>ionian6b.rotate(3), 105 | :mixolydian2b=>ionian6b.rotate(4), 106 | :aeolian1b=>ionian6b.rotate(5), 107 | :locrian7b=>ionian6b.rotate(6), 108 | } 109 | }.call 110 | 111 | chords = { 112 | # https://en.wikipedia.org/wiki/Minor_major_seventh_chord 113 | 'mM7'=> [0, 3, 7, 11], 114 | # https://en.wikipedia.org/wiki/Augmented_major_seventh_chord 115 | 'maj7+5'=> [0, 4, 8, 11], 116 | '6+5'=> [0, 4, 8, 9], 117 | # Missing majot 7 suspended chords 118 | 'maj7'=> [0, 2, 4, 6], # Same as ^major7 119 | 'maj7sus2'=> [0, 4, 6], 120 | 'maj7sus4'=> [0, 2, 6], 121 | # Missing altered chords: https://en.wikipedia.org/wiki/Altered_chord 122 | '7-5-3'=>[0, 3, 6, 10], 123 | '7+5+9'=>[0, 4, 8, 10, 14], 124 | '7-5-9'=>[0, 4, 6, 10, 13], 125 | '7-5+9'=>[0, 4, 6, 10, 14] 126 | } 127 | 128 | SonicPi::Scale.patch(scales) 129 | SonicPi::Chord.patch(chords) 130 | 131 | def zlog text 132 | File.open(ENV['HOME']+'/.sonic-pi/log/ziffers.log', 'a') {|log| 133 | log.print text 134 | log.print "\n" 135 | } 136 | end 137 | -------------------------------------------------------------------------------- /vendor/treetop/doc/pitfalls_and_advanced_techniques.markdown: -------------------------------------------------------------------------------- 1 | #Pitfalls 2 | ##Left Recursion 3 | An weakness shared by all recursive descent parsers is the inability to parse left-recursive rules. Consider the following rule: 4 | 5 | rule left_recursive 6 | left_recursive 'a' / 'a' 7 | end 8 | 9 | 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. 10 | 11 | #Advanced Techniques 12 | 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. 13 | 14 | ##Matching a String 15 | 16 | rule string 17 | '"' ('\"' / !'"' .)* '"' 18 | end 19 | 20 | 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. 21 | 22 | ##Matching Nested Structures With Non-Unique Delimeters 23 | Say I want to parse a diabolical wiki syntax in which the following interpretations apply. 24 | 25 | ** *hello* ** --> hello 26 | * **hello** * --> hello 27 | 28 | rule strong 29 | '**' (em / !'*' . / '\*')+ '**' 30 | end 31 | 32 | rule em 33 | '*' (strong / !'*' . / '\*')+ '*' 34 | end 35 | 36 | 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. 37 | 38 | ##Matching a Keyword But Not Words Prefixed Therewith 39 | 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. 40 | 41 | rule end_keyword 42 | 'end' &space 43 | end 44 | 45 | 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. 46 | 47 | rule end_keyword 48 | 'end' !(!' ' .) 49 | end 50 | 51 | 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. 52 | 53 | ## Poor Performance with Large Unicode Strings 54 | 55 | 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. 56 | 57 | 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. 58 | -------------------------------------------------------------------------------- /vendor/treetop/bin/tt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'optparse' 3 | require 'rubygems' 4 | 5 | $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib")) 6 | require 'treetop' 7 | require 'treetop/version' 8 | require 'treetop/polyglot' 9 | 10 | options = {} 11 | parser = OptionParser.new do |opts| 12 | exts = Treetop::Polyglot::VALID_GRAMMAR_EXT.collect { |i| '.' + i } 13 | 14 | opts.banner = "Treetop Parsing Expression Grammar (PEG) Comand Line Compiler" 15 | opts.define_head "Usage: tt [options] grammar_file[#{exts.join('|')}] ..." 16 | opts.separator '' 17 | opts.separator 'Examples:' 18 | opts.separator ' tt foo.tt # 1 grammar -> 1 parser source' 19 | opts.separator ' tt foo bar.treetop # 2 grammars -> 2 separate parsers' 20 | opts.separator ' tt -o alt_name.rb foo # alternately named output file' 21 | opts.separator '' 22 | opts.separator '' 23 | opts.separator 'NOTE: while treetop grammar files *must* have one of the following' 24 | opts.separator 'filename extensions, the extension name is not required when calling' 25 | opts.separator 'the compiler with grammar file names.' 26 | opts.separator '' 27 | opts.separator " Valid extensions: #{exts.join(', ')}" 28 | opts.separator '' 29 | opts.separator '' 30 | opts.separator 'Options:' 31 | 32 | opts.on('-o', '--output FILENAME', 'Write parser source to FILENAME') do |fn| 33 | options[:out_file] = fn 34 | end 35 | 36 | opts.on('-f', '--force', 'Overwrite existing output file(s)') do 37 | options[:force] = true 38 | end 39 | 40 | opts.on_tail('-v', '--version', 'Show Treetop version') do 41 | puts "Treetop v#{Treetop::VERSION::STRING}" 42 | exit 43 | end 44 | 45 | opts.on_tail('-h', '--help', 'Show this help message') do 46 | puts opts 47 | exit 48 | end 49 | 50 | end 51 | file_list = parser.parse! 52 | 53 | # check options and arg constraints 54 | if file_list.empty? || (options[:out_file] && file_list.size > 1) 55 | puts parser 56 | exit 1 57 | end 58 | 59 | def grammar_exist?(filename) 60 | if File.extname(filename).empty? 61 | Treetop::Polyglot::VALID_GRAMMAR_EXT.each do |ext| 62 | fn_ext = "#{filename}.#{ext}" 63 | return true if File.exist?(fn_ext) && !File.zero?(fn_ext) 64 | end 65 | end 66 | File.exist?(filename) && !File.zero?(filename) 67 | end 68 | 69 | def full_grammar_filename(filename) 70 | return filename if !File.extname(filename).empty? 71 | Treetop::Polyglot::VALID_GRAMMAR_EXT.each do |ext| 72 | fn_ext = "#{filename}.#{ext}" 73 | return fn_ext if File.exist?(fn_ext) && !File.zero?(fn_ext) 74 | end 75 | end 76 | 77 | def protect_output?(filename, forced=false) 78 | if !forced and 79 | File.exist?(filename) and 80 | File.open(filename) { |f| ![(f.gets rescue ''), (f.gets rescue '')].include? Treetop::Compiler::AUTOGENERATED } 81 | puts "ERROR: '#{filename}' output already exists; skipping compilation...\n" 82 | return true 83 | end 84 | false 85 | end 86 | 87 | compiler = Treetop::Compiler::GrammarCompiler.new 88 | 89 | while !file_list.empty? 90 | treetop_file = file_list.shift 91 | 92 | # handle nonexistent and existent grammar files mixed together 93 | if !grammar_exist?(treetop_file) 94 | puts "ERROR: input grammar file '#{treetop_file}' does not exist; continuing...\n" 95 | next 96 | end 97 | 98 | # try to compile 99 | treetop_file = full_grammar_filename(treetop_file) 100 | std_output_file = treetop_file.gsub(Treetop::Polyglot::VALID_GRAMMAR_EXT_REGEXP, '.rb') 101 | 102 | if options[:out_file] 103 | # explicit output file name option; never overwrite unless forced 104 | next if protect_output?(options[:out_file], options[:force]) 105 | compiler.compile(treetop_file, options[:out_file]) 106 | else 107 | # compile one input file from input file list option; never overwrite unless forced 108 | next if protect_output?(std_output_file, options[:force]) 109 | compiler.compile(treetop_file) 110 | end 111 | 112 | end 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Ziffers: Numeric notation for composing algorithmic and generative music using Sonic Pi 4 | Ziffers is a generative numbered musical notation (aka. Ziffersystem) and a live code golfing framework that makes composing melodies and rhythms easier and faster in [Sonic Pi](https://sonic-pi.net/). 5 | 6 | Writing and playing melodies in any key or scale will be as simple as: 7 | ``` 8 | zplay "q 4 e 1 1 q 2 1 r #3 4 ", key: "f", scale: "major", synth: :piano 9 | ``` 10 | or playing loops: 11 | ``` 12 | zloop :ride, "e 3 3 2 2 1 1 2 2", key: :c, scale: :chromatic, synth: :piano 13 | ``` 14 | or loops with generative live rules: 15 | ``` 16 | z1 "e1", 17 | rules: { 18 | "1"=>"3", 19 | "3"=>"2", 20 | "2"=>"4", 21 | "4"=>"(1,6)", 22 | "5"=>"1", 23 | "6"=>"2" 24 | }, synth: :pretty_bell 25 | ``` 26 | or play infinite sequences. Easy as: 27 | ``` 28 | zplay pi, rhythm: "q q h q q h h q ee h q ee" 29 | ``` 30 | or simple [aleatoric](https://en.wikipedia.org/wiki/Aleatoric_music) melodies: 31 | ``` 32 | z1 "[0,3,5] 4 (1,3) (4,6) 2 e <3 0 (2,4)> (5,7)", scale: :ahirbhairav, key: :e, synth: :piano, attack: 0.25 33 | ``` 34 | or go crazy and create lists and do list operations using transformations and nested notation: 35 | ``` 36 | z1 "q (0 1 (3,7) 3)~<*>(4 [6,4,[5,4,2,7]] (0,(5,8)) (1,6))", synth: :kalimba 37 | ``` 38 | and much more ... See [Ziffers wiki](https://github.com/amiika/ziffers/wiki) or download [A4 cheatsheet](https://github.com/amiika/ziffers/raw/master/Cheatsheet.pdf) to learn more. 39 | 40 | Here is a cheatsheet you can copy to Sonic Pi editor: 41 | ``` 42 | # Pitches: -2 -1 0 1 2 43 | # Chords: 0 024 2 246 44 | # Note lengths: w 0 h 1 q 2 e 3 s 4 45 | # Subdivision: [1 2 [3 4]] 46 | # Decimal durations: 0.25 0 1 <0.333>2 3 47 | # Octaves: ^ 0 ^ 1 _ 2 _ 3 48 | # Escaped octave: <2> 1 <1>1<-2>3 49 | # Roman chords: i ii iii+4 iv+5 v+8 vi+10 vii+20 50 | # Named chords: i^7 i^min i^dim i^maj7 51 | # Modal interchange (a-g): iiia ig ivf^7 52 | # Escape/eval: {10 11} {1.2 2.43} {3+1*2} 53 | # Randoms: % ? % ? % ? 54 | # Random between: (-3,6) 55 | # Random selections: [q 1 2, q 3 e 4 6] 56 | # Repeat: [: 1 (2,6) 3 :4] 57 | # Repeat cycles: [: (1,4) <(2 3) (3 (1,7))> :] 58 | # Lists: h 1 q(0 1 2 3) 2 59 | # List cycles: (: (1,4) <(2 3) (3 (1,7))> :) 60 | # Loop cycles (for zloop or z0-z9): <0 <1 <2 <3 <4 5>>>>> 61 | # Basic operations: (1 2 (3 4)+2)*2 ((1 2 3)+(0 9 13))-2 ((3 4 {10})*(2 9 3))%7 62 | # Product operations: (0 1 2 3)+(1 4 2 3) (0 1 2)-(0 2 1)+2 63 | # Euclid cycles: (q1)<6,7>(q4 (e3 e4) q2) or (q1)<6,7<(q4 q3 q2) 64 | # Transformations: (0 1 2) (0 1 2)(-2 1) etc. 65 | # List assignation: A=(0 (1,6) 3) B=(3 ? 2) B A B B A 66 | # Random repeat: (: 1 (2,6) 3 :4) 67 | # Conditionals: 1 {%<0.5?3} 3 4 (: 1 2 {%<0.2?3:2} :3) 68 | # Functions: (0 1 2 3){x%3==0?x-2:x+2} 69 | # Polynomials: (-10..10){(x**3)*(x+1)%12} 70 | ``` 71 | 72 | # Quick start 73 | 74 | ## Requirements 75 | 76 | - [Sonic Pi](https://sonic-pi.net/) 77 | - Clone using git or download [latest release](https://github.com/amiika/ziffers/releases/latest) 78 | 79 | ## Install ziffers 80 | 81 | Install Ziffers to your Sonic Pi by cloning this project into your home directory (this makes referencing easier as most of the examples use ~ shorthand to require stuff). Ziffers can then be required to your Sonic Pi project using: 82 | 83 | ``` 84 | require "~/ziffers/ziffers.rb" # ~ references ziffers under users home folder, works also in Windows 85 | ``` 86 | 87 | Stay up to date as the Ziffers is an ongoing project. Post Issues to report bugs or to ask questions. 88 | 89 | ## Examples 90 | 91 | There are some pretty random examples in the [Examples](https://github.com/amiika/ziffers/tree/master/examples)-folder. You can also try out [one line](https://github.com/amiika/ziffers/blob/master/test/play_tests.rb) examples from tests or browse trough [wiki](https://github.com/amiika/ziffers/wiki). If you make some nice tunes do a pull request to Examples folder to share! Thanks! 92 | 93 | ## Documentation 94 | 95 | Syntax and methods are documented in [Ziffers wiki](https://github.com/amiika/ziffers/wiki). 96 | 97 | # Help & Contributions 98 | 99 | For bugs post an [issue](https://github.com/amiika/ziffers/issues) or a fix using merge request. Use [discussions](https://github.com/amiika/ziffers/discussions) for general questions and feature requests. 100 | -------------------------------------------------------------------------------- /vendor/treetop/spec/runtime/compiled_parser_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module CompiledParserSpec 4 | describe Runtime::CompiledParser, "for a grammar with two rules" do 5 | attr_reader :parser 6 | 7 | testing_grammar %{ 8 | grammar TwoRules 9 | rule a 10 | 'a' 11 | end 12 | 13 | rule b 14 | 'bb' 15 | end 16 | end 17 | } 18 | 19 | before do 20 | @parser = parser_class_under_test.new 21 | end 22 | 23 | it "allows its root to be specified" do 24 | parser.parse('a').should_not be_nil 25 | parser.parse('b').should be_nil 26 | 27 | # Check that the temporary-override works: 28 | parser.parse('bb', :root => :b).should_not be_nil 29 | parser.parse('a', :root => :b).should be_nil 30 | 31 | # Check that the temporary-override isn't sticky: 32 | parser.parse('a').should_not be_nil 33 | 34 | # Try a permanent override: 35 | parser.root = :b 36 | parser.parse('bb').should_not be_nil 37 | parser.parse('a').should be_nil 38 | end 39 | 40 | it "allows the requirement that all input be consumed to be disabled" do 41 | parser.parse('ab').should be_nil 42 | 43 | # Try a temporary override, and check it's not sticky: 44 | result = parser.parse('ab', :consume_all_input => false) 45 | result.should_not be_nil 46 | result.interval.should == (0...1) 47 | parser.parse('ab').should be_nil 48 | 49 | # Now a permanent override: 50 | parser.consume_all_input = false 51 | result = parser.parse('ab') 52 | result.should_not be_nil 53 | result.interval.should == (0...1) 54 | end 55 | 56 | it "allows input to be parsed at a given index" do 57 | parser.parse('ba').should be_nil 58 | parser.parse('ba', :index => 1).should_not be_nil 59 | # Check that the index defaults again to zero: 60 | parser.parse('a').should_not be_nil 61 | 62 | result = parser.parse('ba', :consume_all_input => false, :index => 1) 63 | result.should_not be_nil 64 | result.interval.should == (1...2) 65 | end 66 | 67 | end 68 | 69 | describe Runtime::CompiledParser, "for a grammar with a choice between terminals" do 70 | attr_reader :parser 71 | 72 | testing_grammar %{ 73 | grammar Choice 74 | rule choice 75 | 'a' / 'b' / 'c' 76 | end 77 | end 78 | } 79 | 80 | before do 81 | @parser = parser_class_under_test.new 82 | end 83 | 84 | it "provides #failure_reason, #failure_column, and #failure_line when there is a parse failure" do 85 | parser.parse('z').should be_nil 86 | parser.failure_reason.should == "Expected one of 'a', 'b', 'c' at line 1, column 1 (byte 1)" 87 | parser.failure_line.should == 1 88 | parser.failure_column.should == 1 89 | end 90 | end 91 | 92 | describe Runtime::CompiledParser, "#terminal_failures" do 93 | attr_reader:parser 94 | 95 | testing_grammar %{ 96 | grammar SequenceOfTerminals 97 | rule foo 98 | 'a' 'b' 'c' 99 | end 100 | end 101 | } 102 | 103 | before do 104 | @parser = parser_class_under_test.new 105 | end 106 | 107 | it "is reset between parses" do 108 | parser.parse('ac') 109 | terminal_failures = parser.terminal_failures 110 | terminal_failures.size.should == 1 111 | failure = terminal_failures.first 112 | failure.index.should == 1 113 | failure.expected_string.should == "'b'" 114 | 115 | parser.parse('b') 116 | terminal_failures = parser.terminal_failures 117 | terminal_failures.size.should == 1 118 | failure = terminal_failures.first 119 | failure.index.should == 0 120 | failure.expected_string.should == "'a'" 121 | end 122 | end 123 | 124 | describe "a SyntaxNode" do 125 | attr_reader :parser 126 | 127 | testing_grammar %{ 128 | grammar Alternates 129 | rule main 130 | aa &{|s| s[0].elements[0].parent.should == s[0] } 131 | / ab &{|s| s[0].elements[0].parent.should == s[0] } 132 | end 133 | 134 | rule aa 135 | 'a' 'a' 136 | end 137 | 138 | rule ab 139 | 'a' 'b' 140 | end 141 | end 142 | } 143 | 144 | before do 145 | @parser = parser_class_under_test.new 146 | end 147 | 148 | it "should have its parent set and reset" do 149 | parser.parse('ab') 150 | end 151 | end 152 | 153 | end 154 | -------------------------------------------------------------------------------- /vendor/polyglot/website/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | polyglot 9 | 10 | 11 | 14 | 29 | 30 | 31 |
32 | 33 |

polyglot

34 |
35 |

Get Version

36 | 0.3.2 37 |
38 |

Poly => many, glot => languages

39 |

What

40 |

Polyglot provides a registry of file types that can be loaded by
41 | calling its improved version of ‘require’. Each file extension
42 | that can be handled by a custom loader is registered by calling
43 | Polyglot.register(“ext”, <class>), and then you can simply
44 | require “somefile”, which will find and load “somefile.ext”
45 | using your custom loader.

46 |

This supports the creation of DSLs having a syntax that is most
47 | appropriate to their purpose, instead of abusing the Ruby syntax.

48 |

Required files are attempted first using the normal Ruby loader,
49 | and if that fails, Polyglot conducts a search for a file having
50 | a supported extension.

51 |

Installing

52 |

sudo gem install polyglot

53 |

Example

54 |

Define and register your file type loader in file rubyglot.rb:

55 |
    require 'polyglot'
 56 |     class RubyglotLoader
 57 |         def self.load(filename, options = nil, &block)
 58 |             File.open(filename) {|file|
 59 |                 # Load the contents of file as Ruby code:
 60 |                 # Implement your parser here instead!
 61 |                 Kernel.eval(file.read)
 62 |             }
 63 |         end
 64 |     end
 65 |     Polyglot.register("rgl", RubyglotLoader)
 66 | 
67 |

This file, hello.rgl, will be loaded (this simple example uses Ruby code):

68 |
    puts "Initializing"
 69 |     class Hello
 70 |         def initialize()
 71 |             puts "Hello, world\n"
 72 |         end
 73 |     end
 74 | 
75 |

Call it from file test.rb:

76 |
    require 'rubyglot'	# Create my file type handler
 77 |     require 'hello'	# Can add extra options or even a block here
 78 |     puts "Ready to go"
 79 |     Hello.new
 80 | 
81 |

Run:

82 |
    $ ruby test.rb
 83 |     Initializing
 84 |     Ready to go
 85 |     Hello, world
 86 |     $
 87 | 
88 |

How to submit patches

89 |

Read the 8 steps for fixing other people’s code and for section 8z: Submit patch, email me on the link below.

90 |

The trunk repository is http://github.com/cjheath/polyglot.

91 |

License

92 |

This code is free to use under the terms of the MIT license.

93 |

Contact

94 |

Comments are welcome. Send an email to Clifford Heath

95 |

96 | Clifford Heath, 15th June 2010
97 | Theme extended from Paul Battley 98 |

99 |
100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/compiler/node_classes/parsing_expression.rb: -------------------------------------------------------------------------------- 1 | module Treetop 2 | module Compiler 3 | class ParsingExpression < Runtime::SyntaxNode 4 | attr_reader :address, :builder, :subexpression_address, :var_symbols, :parent_expression 5 | 6 | def compile(address, builder, parent_expression) 7 | @address = address 8 | @builder = builder 9 | @parent_expression = parent_expression 10 | end 11 | 12 | def node_class_name 13 | parent_expression && parent_expression.node_class_name || 'SyntaxNode' 14 | end 15 | 16 | def declared_module_name 17 | parent_expression && parent_expression.node_class_name 18 | end 19 | 20 | def inline_module_name 21 | parent_expression && parent_expression.inline_module_name 22 | end 23 | 24 | def decorated? 25 | parent_expression && (parent_expression.node_class_name || parent_expression.node_class_name || parent_expression.inline_module_name) 26 | end 27 | 28 | def optional_arg(arg) 29 | if arg 30 | ", #{arg}" 31 | else 32 | '' 33 | end 34 | end 35 | 36 | def use_vars(*var_symbols) 37 | @var_symbols = var_symbols 38 | builder << var_initialization 39 | end 40 | 41 | def result_var 42 | var(:result) 43 | end 44 | 45 | def accumulator_var 46 | var(:accumulator) 47 | end 48 | 49 | def start_index_var 50 | var(:start_index) 51 | end 52 | 53 | def subexpression_result_var 54 | "r#{subexpression_address}" 55 | end 56 | 57 | def subexpression_success? 58 | subexpression_result_var 59 | end 60 | 61 | def obtain_new_subexpression_address 62 | @subexpression_address = builder.next_address 63 | end 64 | 65 | def accumulate_subexpression_result 66 | builder.accumulate accumulator_var, subexpression_result_var 67 | end 68 | 69 | def assign_result(value_ruby) 70 | builder.assign result_var, value_ruby 71 | end 72 | 73 | def extend_result(module_name) 74 | builder.extend result_var, module_name 75 | end 76 | 77 | def extend_result_with_declared_module 78 | extend_result declared_module_name if declared_module_name 79 | end 80 | 81 | def extend_result_with_inline_module parent_expression = nil 82 | if parent_expression && parent_expression.parent_modules.size > 0 83 | parent_expression.parent_modules.each do |inline| 84 | extend_result inline.module_name 85 | end 86 | end 87 | extend_result inline_module_name if inline_module_name 88 | end 89 | 90 | def reset_index 91 | builder.assign '@index', start_index_var 92 | end 93 | 94 | def epsilon_node 95 | "instantiate_node(SyntaxNode,input, index...index)" 96 | end 97 | 98 | def assign_failure(start_index_var) 99 | assign_result("nil") 100 | end 101 | 102 | def assign_lazily_instantiated_node 103 | assign_result("true") 104 | end 105 | 106 | def var_initialization 107 | left, right = [], [] 108 | var_symbols.each do |symbol| 109 | if init_value(symbol) 110 | left << var(symbol) 111 | right << init_value(symbol) 112 | end 113 | end 114 | if left.empty? 115 | "" 116 | else 117 | left.join(', ') + ' = ' + right.join(', ') 118 | end 119 | end 120 | 121 | def var(var_symbol) 122 | case var_symbol 123 | when :result then "r#{address}" 124 | when :accumulator then "s#{address}" 125 | when :start_index then "i#{address}" 126 | else raise "Unknown var symbol #{var_symbol}." 127 | end 128 | end 129 | 130 | def init_value(var_symbol) 131 | case var_symbol 132 | when :accumulator then '[]' 133 | when :start_index then 'index' 134 | else nil 135 | end 136 | end 137 | 138 | def begin_comment(expression) 139 | #builder << "# begin #{on_one_line(expression)}" 140 | end 141 | 142 | def end_comment(expression) 143 | #builder << "# end #{on_one_line(expression)}" 144 | end 145 | 146 | def on_one_line(expression) 147 | expression.text_value.tr("\n", ' ') 148 | end 149 | 150 | def expected 151 | nil # Overridden for terminal parse failures 152 | end 153 | end 154 | end 155 | end 156 | -------------------------------------------------------------------------------- /vendor/treetop/doc/using_in_ruby.markdown: -------------------------------------------------------------------------------- 1 | #Using Treetop Grammars in Ruby 2 | ##Using the Command Line Compiler 3 | 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. 4 | 5 | tt foo.treetop bar.treetop 6 | tt foo.treetop -o foogrammar.rb 7 | 8 | ##Loading A Grammar Directly 9 | 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. 10 | 11 | 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: 12 | 13 | require 'polyglot' 14 | require 'treetop' 15 | 16 | in order to use Polyglot auto loading with Treetop in Ruby. 17 | 18 | ##Instantiating and Using Parsers 19 | If a grammar by the name of `Foo` is defined, the compiled Ruby source will define a `FooParser` class. 20 | To parse input, create an instance and call its `parse` method with a string. 21 | The parser will return the syntax tree of the match or `nil` if there is a failure. 22 | Note that by default, the parser will fail unless *all* input is consumed. 23 | 24 | Treetop.load "arithmetic" 25 | 26 | parser = ArithmeticParser.new 27 | if parser.parse('1+1') 28 | puts 'success' 29 | else 30 | puts 'failure' 31 | end 32 | 33 | ##Parser Options 34 | A Treetop parser has several options you may set. 35 | Some are settable permanently by methods on the parser, but all may be passed in as options to the `parse` method. 36 | 37 | parser = ArithmeticParser.new 38 | input = 'x = 2; y = x+3;' 39 | 40 | # Temporarily override an option: 41 | result1 = parser.parse(input, :consume_all_input => false) 42 | puts "consumed #{parser.index} characters" 43 | 44 | parser.consume_all_input = false 45 | result1 = parser.parse(input) 46 | puts "consumed #{parser.index} characters" 47 | 48 | # Continue the parse with the next character: 49 | result2 = parser.parse(input, :index => parser.index) 50 | 51 | # Parse, but match rule `variable` instead of the normal root rule: 52 | parser.parse(input, :root => :variable) 53 | parser.root = :variable # Permanent setting 54 | 55 | If you have a statement-oriented language, you can save memory by parsing just one statement at a time, 56 | and discarding the parse tree after each statement. 57 | 58 | 59 | ##Learning From Failure 60 | If a parse fails, it returns nil. In this case, you can ask the parser for an explanation. 61 | The failure reasons include the terminal nodes which were tried at the furthermost point the parse reached. 62 | 63 | parser = ArithmeticParser.new 64 | result = parser.parse('4+=3') 65 | 66 | if !result 67 | puts parser.failure_reason 68 | puts parser.failure_line 69 | puts parser.failure_column 70 | end 71 | 72 | => 73 | Expected one of (, - at line 1, column 3 (byte 3) after + 74 | 1 75 | 3 76 | 77 | 78 | ##Using Parse Results 79 | Please don't try to walk down the syntax tree yourself, and please don't use the tree as your own convenient data structure. 80 | It contains many more nodes than your application needs, often even more than one for every character of input. 81 | 82 | parser = ArithmeticParser.new 83 | p parser.parse('2+3') 84 | 85 | => 86 | SyntaxNode+Additive1 offset=0, "2+3" (multitive): 87 | SyntaxNode+Multitive1 offset=0, "2" (primary): 88 | SyntaxNode+Number0 offset=0, "2": 89 | SyntaxNode offset=0, "" 90 | SyntaxNode offset=0, "2" 91 | SyntaxNode offset=1, "" 92 | SyntaxNode offset=1, "" 93 | SyntaxNode offset=1, "+3": 94 | SyntaxNode+Additive0 offset=1, "+3" (multitive): 95 | SyntaxNode offset=1, "+" 96 | SyntaxNode+Multitive1 offset=2, "3" (primary): 97 | SyntaxNode+Number0 offset=2, "3": 98 | SyntaxNode offset=2, "" 99 | SyntaxNode offset=2, "3" 100 | SyntaxNode offset=3, "" 101 | SyntaxNode offset=3, "" 102 | 103 | Instead, add methods to the root rule which return the information you require in a sensible form. 104 | Each rule can call its sub-rules, and this method of walking the syntax tree is much preferable to 105 | attempting to walk it from the outside. 106 | -------------------------------------------------------------------------------- /vendor/treetop/lib/treetop/runtime/interval_skip_list/node.rb: -------------------------------------------------------------------------------- 1 | class IntervalSkipList 2 | class Node < HeadNode 3 | attr_accessor :key 4 | attr_reader :markers, :endpoint_of 5 | 6 | def initialize(key, height, path) 7 | super(height) 8 | @key = key 9 | @markers = [] 10 | @endpoint_of = [] 11 | update_forward_pointers(path) 12 | promote_markers(path) 13 | end 14 | 15 | def all_forward_markers 16 | markers.flatten 17 | end 18 | 19 | def delete(path) 20 | 0.upto(top_level) do |i| 21 | path[i].forward[i] = forward[i] 22 | end 23 | demote_markers(path) 24 | end 25 | 26 | def propagate_length_change(length_change) 27 | cur_node = self 28 | while cur_node do 29 | cur_node.key += length_change 30 | cur_node = cur_node.forward[0] 31 | end 32 | end 33 | 34 | protected 35 | 36 | def update_forward_pointers(path) 37 | 0.upto(top_level) do |i| 38 | forward[i] = path[i].forward[i] 39 | path[i].forward[i] = self 40 | end 41 | end 42 | 43 | def promote_markers(path) 44 | promoted = [] 45 | new_promoted = [] 46 | 0.upto(top_level) do |i| 47 | incoming_markers = path[i].forward_markers[i] 48 | markers.concat(incoming_markers) 49 | 50 | incoming_markers.each do |marker| 51 | if can_be_promoted_higher?(marker, i) 52 | new_promoted.push(marker) 53 | forward[i].delete_marker_from_path(marker, i, forward[i+1]) 54 | else 55 | forward_markers[i].push(marker) 56 | end 57 | end 58 | 59 | promoted.each do |marker| 60 | if can_be_promoted_higher?(marker, i) 61 | new_promoted.push(marker) 62 | forward[i].delete_marker_from_path(marker, i, forward[i+1]) 63 | else 64 | forward_markers[i].push(marker) 65 | end 66 | end 67 | 68 | promoted = new_promoted 69 | new_promoted = [] 70 | end 71 | end 72 | 73 | 74 | def can_be_promoted_higher?(marker, level) 75 | level < top_level && forward[level + 1] && forward[level + 1].markers.include?(marker) 76 | end 77 | 78 | def delete_marker_from_path(marker, level, terminus) 79 | cur_node = self 80 | until cur_node == terminus 81 | cur_node.forward_markers[level].delete(marker) 82 | cur_node.markers.delete(marker) 83 | cur_node = cur_node.forward[level] 84 | end 85 | end 86 | 87 | def demote_markers(path) 88 | demote_inbound_markers(path) 89 | demote_outbound_markers(path) 90 | end 91 | 92 | def demote_inbound_markers(path) 93 | demoted = [] 94 | new_demoted = [] 95 | 96 | top_level.downto(0) do |i| 97 | incoming_markers = path[i].forward_markers[i].dup 98 | incoming_markers.each do |marker| 99 | unless forward_node_with_marker_at_or_above_level?(marker, i) 100 | path[i].forward_markers[i].delete(marker) 101 | new_demoted.push(marker) 102 | end 103 | end 104 | 105 | demoted.each do |marker| 106 | path[i + 1].place_marker_on_inbound_path(marker, i, path[i]) 107 | 108 | if forward[i].markers.include?(marker) 109 | path[i].forward_markers[i].push(marker) 110 | else 111 | new_demoted.push(marker) 112 | end 113 | end 114 | 115 | demoted = new_demoted 116 | new_demoted = [] 117 | end 118 | end 119 | 120 | def demote_outbound_markers(path) 121 | demoted = [] 122 | new_demoted = [] 123 | 124 | top_level.downto(0) do |i| 125 | forward_markers[i].each do |marker| 126 | new_demoted.push(marker) unless path[i].forward_markers[i].include?(marker) 127 | end 128 | 129 | demoted.each do |marker| 130 | forward[i].place_marker_on_outbound_path(marker, i, forward[i + 1]) 131 | new_demoted.push(marker) unless path[i].forward_markers[i].include?(marker) 132 | end 133 | 134 | demoted = new_demoted 135 | new_demoted = [] 136 | end 137 | end 138 | 139 | def forward_node_with_marker_at_or_above_level?(marker, level) 140 | level.upto(top_level) do |i| 141 | return true if forward[i].markers.include?(marker) 142 | end 143 | false 144 | end 145 | 146 | def place_marker_on_outbound_path(marker, level, terminus) 147 | cur_node = self 148 | until cur_node == terminus 149 | cur_node.forward_markers[level].push(marker) 150 | cur_node.markers.push(marker) 151 | cur_node = cur_node.forward[level] 152 | end 153 | end 154 | 155 | def place_marker_on_inbound_path(marker, level, terminus) 156 | cur_node = self 157 | until cur_node == terminus 158 | cur_node.forward_markers[level].push(marker) 159 | cur_node = cur_node.forward[level] 160 | cur_node.markers.push(marker) 161 | end 162 | end 163 | end 164 | end -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/grammar_compiler_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'tmpdir' 3 | 4 | describe Compiler::GrammarCompiler do 5 | attr_reader :compiler, :source_path_with_treetop_extension, :source_path_with_tt_extension, :target_path, :alternate_target_path 6 | before do 7 | @compiler = Compiler::GrammarCompiler.new 8 | 9 | dir = File.dirname(__FILE__) 10 | @tmpdir = Dir.tmpdir 11 | 12 | @source_path_with_treetop_extension = "#{dir}/test_grammar.treetop" 13 | @source_path_with_do = "#{dir}/test_grammar_do.treetop" 14 | @source_path_with_tt_extension = "#{dir}/test_grammar.tt" 15 | @source_path_with_magic_coding = "#{dir}/test_grammar_magic_coding.treetop" 16 | @source_path_with_magic_encoding = "#{dir}/test_grammar_magic_encoding.treetop" 17 | @target_path = "#{@tmpdir}/test_grammar.rb" 18 | @target_path_with_do = "#{@tmpdir}/test_grammar_do.rb" 19 | @target_path_with_magic_coding = "#{@tmpdir}/test_grammar_magic_coding.rb" 20 | @target_path_with_magic_encoding = "#{@tmpdir}/test_grammar_magic_encoding.rb" 21 | @alternate_target_path = "#{@tmpdir}/test_grammar_alt.rb" 22 | delete_target_files 23 | end 24 | 25 | after do 26 | delete_target_files 27 | Object.class_eval do 28 | remove_const(:Test) if const_defined?(:Test) 29 | end 30 | end 31 | 32 | specify "compilation of a single file to a default file name" do 33 | src_copy = "#{@tmpdir}/test_grammar.treetop" 34 | File.open(source_path_with_treetop_extension) { |f| File.open(src_copy,'w'){|o|o.write(f.read)} } 35 | File.exist?(target_path).should be_falsey 36 | compiler.compile(src_copy) 37 | File.exist?(target_path).should be_truthy 38 | require target_path 39 | Test::GrammarParser.new.parse('foo').should_not be_nil 40 | end 41 | 42 | specify "compilation of a single file to an explicit file name" do 43 | File.exist?(alternate_target_path).should be_falsey 44 | compiler.compile(source_path_with_treetop_extension, alternate_target_path) 45 | File.exist?(alternate_target_path).should be_truthy 46 | require alternate_target_path 47 | Test::GrammarParser.new.parse('foo').should_not be_nil 48 | end 49 | 50 | specify "compilation of a single file without writing it to an output file" do 51 | compiler.ruby_source(source_path_with_treetop_extension).should_not be_nil 52 | end 53 | 54 | specify "ruby_source_from_string compiles a grammar stored in string" do 55 | compiler.ruby_source_from_string(File.read(source_path_with_treetop_extension)).should_not be_nil 56 | end 57 | 58 | specify "Treetop.load_from_string compiles and evaluates a source grammar stored in string" do 59 | Treetop.load_from_string File.read(source_path_with_treetop_extension) 60 | Test::GrammarParser.new.parse('foo').should_not be_nil 61 | end 62 | 63 | specify "Treetop.load compiles and evaluates a source grammar with a .treetop extension" do 64 | Treetop.load source_path_with_treetop_extension 65 | Test::GrammarParser.new.parse('foo').should_not be_nil 66 | end 67 | 68 | specify "Treetop.load compiles and evaluates a source grammar with a .tt extension" do 69 | path_without_extension = source_path_with_tt_extension 70 | Treetop.load path_without_extension 71 | Test::GrammarParser.new.parse('foo').should_not be_nil 72 | end 73 | 74 | 75 | specify "Treetop.load compiles and evaluates source grammar with no extension" do 76 | path_without_extension = source_path_with_treetop_extension.gsub(/\.treetop\Z/, '') 77 | Treetop.load path_without_extension 78 | Test::GrammarParser.new.parse('foo').should_not be_nil 79 | end 80 | 81 | specify "grammars with 'do' compile" do 82 | src_copy = "#{@tmpdir}/test_grammar_do.treetop" 83 | File.open(@source_path_with_do) { |f| File.open(src_copy,'w'){|o|o.write(f.read)} } 84 | compiler.compile(src_copy) 85 | require @target_path_with_do 86 | Test::GrammarParser.new.parse('foo').should_not be_nil 87 | end 88 | 89 | specify "grammars with magic 'encoding' comments keep those comments at the top" do 90 | src_copy = "#{@tmpdir}/test_grammar_magic_encoding.treetop" 91 | File.open(@source_path_with_magic_encoding) do |f| 92 | File.open(src_copy,'w'){|o|o.write(f.read)} 93 | end 94 | compiler.compile(src_copy) 95 | File.open(@target_path_with_magic_encoding).readline.should == "# encoding: UTF-8\n" 96 | end 97 | 98 | specify "grammars with magic 'coding' comments keep those comments at the top" do 99 | src_copy = "#{@tmpdir}/test_grammar_magic_coding.treetop" 100 | File.open(@source_path_with_magic_coding) do |f| 101 | File.open(src_copy,'w'){|o|o.write(f.read)} 102 | end 103 | compiler.compile(src_copy) 104 | File.open(@target_path_with_magic_coding).readline.should == "# coding: UTF-8\n" 105 | end 106 | 107 | def delete_target_files 108 | File.delete(target_path) if File.exist?(target_path) 109 | File.delete(@target_path_with_do) if File.exist?(@target_path_with_do) 110 | File.delete(alternate_target_path) if File.exist?(alternate_target_path) 111 | end 112 | end 113 | 114 | -------------------------------------------------------------------------------- /vendor/treetop/spec/compiler/sequence_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module SequenceSpec 4 | class Foo < Treetop::Runtime::SyntaxNode 5 | end 6 | 7 | describe "a sequence of labeled terminal symbols followed by a node class declaration and a block" do 8 | testing_expression 'foo:"foo" bar:"bar" baz:"baz" { def a_method; end }' 9 | 10 | 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 11 | parse('foobarbaz') do |result| 12 | result.should_not be_nil 13 | result.should be_an_instance_of(Foo) 14 | result.should respond_to(:a_method) 15 | result.foo.text_value.should == 'foo' 16 | result.bar.text_value.should == 'bar' 17 | result.baz.text_value.should == 'baz' 18 | end 19 | end 20 | 21 | it "successfully matches at a non-zero index" do 22 | parse('---foobarbaz', :index => 3) do |result| 23 | result.should_not be_nil 24 | result.should be_nonterminal 25 | (result.elements.map {|elt| elt.text_value}).join.should == 'foobarbaz' 26 | end 27 | end 28 | 29 | it "fails to match non-matching input, recording the parse failure of first non-matching terminal" do 30 | parse('---foobazbaz', :index => 3) do |result| 31 | result.should be_nil 32 | parser.index.should == 3 33 | terminal_failures = parser.terminal_failures 34 | terminal_failures.size.should == 1 35 | failure = terminal_failures.first 36 | failure.index.should == 6 37 | failure.expected_string.should == '"bar"' 38 | end 39 | end 40 | end 41 | 42 | module ModFoo 43 | def mod_method; end 44 | end 45 | 46 | describe "a sequence of labeled terminal symbols followed by a node module declaration and a block" do 47 | testing_expression 'foo:"foo" bar:"bar" baz:"baz" { def a_method; end }' 48 | 49 | 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 50 | parse('foobarbaz') do |result| 51 | result.should_not be_nil 52 | result.should respond_to(:mod_method) 53 | result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) 54 | result.should be_a_kind_of(ModFoo) 55 | result.should respond_to(:a_method) 56 | result.foo.text_value.should == 'foo' 57 | result.bar.text_value.should == 'bar' 58 | result.baz.text_value.should == 'baz' 59 | end 60 | end 61 | end 62 | 63 | describe "a labeled single element sequence followed by a node module declaration and a block" do 64 | testing_expression 'foo:"foo"+ { def a_method; end }' 65 | 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 66 | parse('foofoofoo') do |result| 67 | result.should_not be_nil 68 | result.should respond_to(:mod_method) 69 | result.should be_an_instance_of(Treetop::Runtime::SyntaxNode) 70 | result.should be_a_kind_of(ModFoo) 71 | result.should respond_to(:a_method) 72 | result.foo.text_value.should == 'foofoofoo' 73 | end 74 | end 75 | end 76 | 77 | describe "a sequence of non-terminals" do 78 | testing_grammar %{ 79 | grammar TestGrammar 80 | rule sequence 81 | foo bar baz { 82 | def baz 83 | 'override' + super.text_value 84 | end 85 | } 86 | end 87 | 88 | rule foo 'foo' end 89 | rule bar 'bar' end 90 | rule baz 'baz' end 91 | end 92 | } 93 | 94 | it "defines accessors for non-terminals automatically that can be overridden in the inline block" do 95 | parse('foobarbaz') do |result| 96 | result.foo.text_value.should == 'foo' 97 | result.bar.text_value.should == 'bar' 98 | result.baz.should == 'overridebaz' 99 | end 100 | end 101 | end 102 | 103 | describe "Compiling a sequence containing various white-space errors" do 104 | it "should succeed on a valid sequence" do 105 | compiling_expression('foo:"foo" "bar" { def a_method; end }').should_not raise_error 106 | end 107 | 108 | it "rejects space after a label" do 109 | compiling_expression('foo :"foo" "bar"').should raise_error(RuntimeError) 110 | end 111 | 112 | it "rejects space after label's colon" do 113 | compiling_expression('foo: "foo" "bar"').should raise_error(RuntimeError) 114 | end 115 | 116 | it "rejects missing space after a primary" do 117 | compiling_expression('foo:"foo""bar"').should raise_error(RuntimeError) 118 | end 119 | 120 | it "rejects missing space before node class declaration" do 121 | compiling_expression('foo:"foo" "bar"').should raise_error(RuntimeError) 122 | end 123 | 124 | it "rejects missing space before inline module" do 125 | compiling_expression('foo:"foo" "bar" {def a_method; end}').should raise_error(RuntimeError) 126 | end 127 | end 128 | 129 | end 130 | --------------------------------------------------------------------------------