From b16cb772d53978a33c5bbcb3a61ec9721ac09a0f Mon Sep 17 00:00:00 2001 From: "Poet (Tim Sally)" Date: Wed, 13 Apr 2011 23:26:05 -0500 Subject: [PATCH] Grammar of primitives common between specs. Partial grammars for network status and router descriptors. --- Gemfile | 11 + Gemfile.lock | 21 + MIT-LICENSE.txt | 18 + Rakefile | 22 + lib/tasks/treetop.rake | 9 + lib/torspec.rb | 15 + lib/torspec/dir_spec_v2/network_status.treetop | 23 + lib/torspec/dir_spec_v2/router_descriptor.treetop | 33 + lib/torspec/primitives.rb | 1692 ++++++++++++++++++++ lib/torspec/primitives.treetop | 135 ++ spec/environment.rb | 4 + spec/spec_helper.rb | 11 + spec/torspec/dir_spec_v2/network_status_spec.rb | 38 + spec/torspec/dir_spec_v2/router_descriptor_spec.rb | 10 + spec/torspec/primitives_spec.rb | 21 + torspec.gemspec | 10 + 16 files changed, 2073 insertions(+) create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 MIT-LICENSE.txt create mode 100644 Rakefile create mode 100644 lib/tasks/treetop.rake create mode 100644 lib/torspec.rb create mode 100644 lib/torspec/dir_spec_v2/network_status.treetop create mode 100644 lib/torspec/dir_spec_v2/router_descriptor.treetop create mode 100644 lib/torspec/primitives.rb create mode 100644 lib/torspec/primitives.treetop create mode 100644 spec/environment.rb create mode 100644 spec/spec_helper.rb create mode 100644 spec/torspec/dir_spec_v2/network_status_spec.rb create mode 100644 spec/torspec/dir_spec_v2/router_descriptor_spec.rb create mode 100644 spec/torspec/primitives_spec.rb create mode 100644 torspec.gemspec diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..80973ae --- /dev/null +++ b/Gemfile @@ -0,0 +1,11 @@ +source :rubygems + +gem "treetop", "~> 1.4.8" + +group :test do + gem "bundler" + gem "diff-lcs" + gem "rake", "~> 0.8.7" + gem "rcov", "~> 0.9.8" + gem "rspec", "~> 1.3.0" +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..d0e37e5 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,21 @@ +GEM + remote: http://rubygems.org/ + specs: + diff-lcs (1.1.2) + polyglot (0.3.1) + rake (0.8.7) + rcov (0.9.9) + rspec (1.3.1) + treetop (1.4.9) + polyglot (>= 0.3.1) + +PLATFORMS + ruby + +DEPENDENCIES + bundler + diff-lcs + rake (~> 0.8.7) + rcov (~> 0.9.8) + rspec (~> 1.3.0) + treetop (~> 1.4.8) diff --git a/MIT-LICENSE.txt b/MIT-LICENSE.txt new file mode 100644 index 0000000..c150dde --- /dev/null +++ b/MIT-LICENSE.txt @@ -0,0 +1,18 @@ +Copyright (C) 2011 by Tim Sally + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..79a74da --- /dev/null +++ b/Rakefile @@ -0,0 +1,22 @@ +require 'rake/testtask' +require 'spec/rake/spectask' + +task :default => :spec + +Spec::Rake::SpecTask.new(:spec) do |t| + t.warning = true + t.spec_files = FileList["#{File.dirname(__FILE__)}/spec/**/*_spec.rb"] + t.spec_opts = %w(--backtrace --diff --color) + t.libs << "#{File.dirname(__FILE__)}/spec" + t.libs << "#{File.dirname(__FILE__)}/spec/torspec" +end + +desc "Build a gem file." +task :build do + system "gem build torspec.gemspec" +end + +# Load custom rake tasks. +Dir["#{File.dirname(__FILE__)}/lib/tasks/**/*.rake"].sort.each do |task| + load task +end diff --git a/lib/tasks/treetop.rake b/lib/tasks/treetop.rake new file mode 100644 index 0000000..e75522c --- /dev/null +++ b/lib/tasks/treetop.rake @@ -0,0 +1,9 @@ +namespace :tt do + desc "Generate Ruby parsers from Treetop grammars." + task :gen do + task_path = File.expand_path('../../torspec/**/*.treetop', __FILE__) + Dir.glob(task_path) do |filename| + `bundle exec tt #{filename}` + end + end +end diff --git a/lib/torspec.rb b/lib/torspec.rb new file mode 100644 index 0000000..5b1c0d0 --- /dev/null +++ b/lib/torspec.rb @@ -0,0 +1,15 @@ +module Torspec + grammars = %w[ primitives ] + grammars.each do |g| + begin + # If there is a pre-compiled grammar, load it. + require 'treetop/runtime' + require "torspec/#{g}" + rescue LoadError + # Otherwise, compile the grammar with Treetop." + require 'treetop/runtime' + require 'treetop/compiler' + Treetop.load(File.join(File.dirname(__FILE__) + "/torspec/#{g}")) + end + end +end diff --git a/lib/torspec/dir_spec_v2/network_status.treetop b/lib/torspec/dir_spec_v2/network_status.treetop new file mode 100644 index 0000000..d5484b1 --- /dev/null +++ b/lib/torspec/dir_spec_v2/network_status.treetop @@ -0,0 +1,23 @@ +module Torspec + module DirspecV2 + grammar NetworkStatus + include Primitives + + rule NetworkStatusVersion + "network-status-version 2" + end + + rule DirSourceLine + "dir-source" SP Hostname SP IPv4Address SP DirPort + end + + rule FingerprintLine + "fingerprint" SP Fingerprint + end + + rule PublishedLine + "published" SP DateTime + end + end + end +end \ No newline at end of file diff --git a/lib/torspec/dir_spec_v2/router_descriptor.treetop b/lib/torspec/dir_spec_v2/router_descriptor.treetop new file mode 100644 index 0000000..07ab2a5 --- /dev/null +++ b/lib/torspec/dir_spec_v2/router_descriptor.treetop @@ -0,0 +1,33 @@ +module Torspec + moudle DirspecV2 + grammar RouterDescriptor + include Primitives + + rule Descriptor + RouterItem / NL + end + + rule RouterItem + "router" Nickname Address ORPort SocksPort DirPort + end + + rule BandwidthItem + "bandwidth" BandwidthAvg BandwidthBurst BandwidthObserved + end + + rule PlatformItem + "platform" String + end + + rule PublishedItem + "published" DateTime + end + + rule HibernatingItem + "hibernating" Boolean + end + + + end + end +end \ No newline at end of file diff --git a/lib/torspec/primitives.rb b/lib/torspec/primitives.rb new file mode 100644 index 0000000..3c9739f --- /dev/null +++ b/lib/torspec/primitives.rb @@ -0,0 +1,1692 @@ +# Autogenerated from a Treetop grammar. Edits may be lost. + + +module Torspec + module Primitives + include Treetop::Runtime + + def root + @root ||= :Year + end + + module Year0 + end + + def _nt_Year + start_index = index + if node_cache[:Year].has_key?(index) + cached = node_cache[:Year][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0, s0 = index, [] + if has_terminal?('\G[0-9]', true, index) + r1 = true + @index += 1 + else + r1 = nil + end + s0 << r1 + if r1 + if has_terminal?('\G[0-9]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s0 << r2 + if r2 + if has_terminal?('\G[0-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s0 << r3 + if r3 + if has_terminal?('\G[0-9]', true, index) + r4 = true + @index += 1 + else + r4 = nil + end + s0 << r4 + end + end + end + if s0.last + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + r0.extend(Year0) + else + @index = i0 + r0 = nil + end + + node_cache[:Year][start_index] = r0 + + r0 + end + + module Month0 + end + + module Month1 + end + + def _nt_Month + start_index = index + if node_cache[:Month].has_key?(index) + cached = node_cache[:Month][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + if has_terminal?('\G[0]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s1 << r2 + if r2 + if has_terminal?('\G[1-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s1 << r3 + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(Month0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + i4, s4 = index, [] + if has_terminal?('\G[1]', true, index) + r5 = true + @index += 1 + else + r5 = nil + end + s4 << r5 + if r5 + if has_terminal?('\G[0-2]', true, index) + r6 = true + @index += 1 + else + r6 = nil + end + s4 << r6 + end + if s4.last + r4 = instantiate_node(SyntaxNode,input, i4...index, s4) + r4.extend(Month1) + else + @index = i4 + r4 = nil + end + if r4 + r0 = r4 + else + @index = i0 + r0 = nil + end + end + + node_cache[:Month][start_index] = r0 + + r0 + end + + module Day0 + end + + module Day1 + end + + def _nt_Day + start_index = index + if node_cache[:Day].has_key?(index) + cached = node_cache[:Day][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + if has_terminal?('\G[0-2]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s1 << r2 + if r2 + if has_terminal?('\G[0-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s1 << r3 + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(Day0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + i4, s4 = index, [] + if has_terminal?('\G[3]', true, index) + r5 = true + @index += 1 + else + r5 = nil + end + s4 << r5 + if r5 + if has_terminal?('\G[0-1]', true, index) + r6 = true + @index += 1 + else + r6 = nil + end + s4 << r6 + end + if s4.last + r4 = instantiate_node(SyntaxNode,input, i4...index, s4) + r4.extend(Day1) + else + @index = i4 + r4 = nil + end + if r4 + r0 = r4 + else + @index = i0 + r0 = nil + end + end + + node_cache[:Day][start_index] = r0 + + r0 + end + + module Hour0 + end + + module Hour1 + end + + module Hour2 + end + + def _nt_Hour + start_index = index + if node_cache[:Hour].has_key?(index) + cached = node_cache[:Hour][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + if has_terminal?('\G[0]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s1 << r2 + if r2 + if has_terminal?('\G[1-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s1 << r3 + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(Hour0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + i4, s4 = index, [] + if has_terminal?('\G[1]', true, index) + r5 = true + @index += 1 + else + r5 = nil + end + s4 << r5 + if r5 + if has_terminal?('\G[0-9]', true, index) + r6 = true + @index += 1 + else + r6 = nil + end + s4 << r6 + end + if s4.last + r4 = instantiate_node(SyntaxNode,input, i4...index, s4) + r4.extend(Hour1) + else + @index = i4 + r4 = nil + end + if r4 + r0 = r4 + else + i7, s7 = index, [] + if has_terminal?('\G[2]', true, index) + r8 = true + @index += 1 + else + r8 = nil + end + s7 << r8 + if r8 + if has_terminal?('\G[0-4]', true, index) + r9 = true + @index += 1 + else + r9 = nil + end + s7 << r9 + end + if s7.last + r7 = instantiate_node(SyntaxNode,input, i7...index, s7) + r7.extend(Hour2) + else + @index = i7 + r7 = nil + end + if r7 + r0 = r7 + else + @index = i0 + r0 = nil + end + end + end + + node_cache[:Hour][start_index] = r0 + + r0 + end + + module Minute0 + end + + module Minute1 + end + + def _nt_Minute + start_index = index + if node_cache[:Minute].has_key?(index) + cached = node_cache[:Minute][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + if has_terminal?('\G[0]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s1 << r2 + if r2 + if has_terminal?('\G[0-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s1 << r3 + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(Minute0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + i4, s4 = index, [] + if has_terminal?('\G[1-5]', true, index) + r5 = true + @index += 1 + else + r5 = nil + end + s4 << r5 + if r5 + if has_terminal?('\G[0-9]', true, index) + r6 = true + @index += 1 + else + r6 = nil + end + s4 << r6 + end + if s4.last + r4 = instantiate_node(SyntaxNode,input, i4...index, s4) + r4.extend(Minute1) + else + @index = i4 + r4 = nil + end + if r4 + r0 = r4 + else + @index = i0 + r0 = nil + end + end + + node_cache[:Minute][start_index] = r0 + + r0 + end + + module Second0 + end + + module Second1 + end + + def _nt_Second + start_index = index + if node_cache[:Second].has_key?(index) + cached = node_cache[:Second][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + if has_terminal?('\G[0]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s1 << r2 + if r2 + if has_terminal?('\G[0-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s1 << r3 + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(Second0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + i4, s4 = index, [] + if has_terminal?('\G[1-5]', true, index) + r5 = true + @index += 1 + else + r5 = nil + end + s4 << r5 + if r5 + if has_terminal?('\G[0-9]', true, index) + r6 = true + @index += 1 + else + r6 = nil + end + s4 << r6 + end + if s4.last + r4 = instantiate_node(SyntaxNode,input, i4...index, s4) + r4.extend(Second1) + else + @index = i4 + r4 = nil + end + if r4 + r0 = r4 + else + @index = i0 + r0 = nil + end + end + + node_cache[:Second][start_index] = r0 + + r0 + end + + module DateTime0 + def Year + elements[0] + end + + def Month + elements[2] + end + + def Day + elements[4] + end + + def Hour + elements[6] + end + + def Minute + elements[8] + end + + def Second + elements[10] + end + end + + def _nt_DateTime + start_index = index + if node_cache[:DateTime].has_key?(index) + cached = node_cache[:DateTime][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0, s0 = index, [] + r1 = _nt_Year + s0 << r1 + if r1 + if has_terminal?("-", false, index) + r2 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("-") + r2 = nil + end + s0 << r2 + if r2 + r3 = _nt_Month + s0 << r3 + if r3 + if has_terminal?("-", false, index) + r4 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("-") + r4 = nil + end + s0 << r4 + if r4 + r5 = _nt_Day + s0 << r5 + if r5 + if has_terminal?(" ", false, index) + r6 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(" ") + r6 = nil + end + s0 << r6 + if r6 + r7 = _nt_Hour + s0 << r7 + if r7 + if has_terminal?(":", false, index) + r8 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(":") + r8 = nil + end + s0 << r8 + if r8 + r9 = _nt_Minute + s0 << r9 + if r9 + if has_terminal?(":", false, index) + r10 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(":") + r10 = nil + end + s0 << r10 + if r10 + r11 = _nt_Second + s0 << r11 + end + end + end + end + end + end + end + end + end + end + if s0.last + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + r0.extend(DateTime0) + else + @index = i0 + r0 = nil + end + + node_cache[:DateTime][start_index] = r0 + + r0 + end + + def _nt_Base64Char + start_index = index + if node_cache[:Base64Char].has_key?(index) + cached = node_cache[:Base64Char][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + if has_terminal?('\G[A-Za-z0-9+/]', true, index) + r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + r0 = nil + end + + node_cache[:Base64Char][start_index] = r0 + + r0 + end + + def _nt_Base64Hash + start_index = index + if node_cache[:Base64Hash].has_key?(index) + cached = node_cache[:Base64Hash][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + s0, i0 = [], index + loop do + r1 = _nt_Base64Char + if r1 + s0 << r1 + else + break + end + end + if s0.empty? + @index = i0 + r0 = nil + else + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + end + + node_cache[:Base64Hash][start_index] = r0 + + r0 + end + + module IPv4Byte0 + end + + module IPv4Byte1 + end + + module IPv4Byte2 + end + + module IPv4Byte3 + end + + def _nt_IPv4Byte + start_index = index + if node_cache[:IPv4Byte].has_key?(index) + cached = node_cache[:IPv4Byte][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + if has_terminal?('\G[2]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + s1 << r2 + if r2 + if has_terminal?('\G[5]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + s1 << r3 + if r3 + if has_terminal?('\G[0-5]', true, index) + r4 = true + @index += 1 + else + r4 = nil + end + s1 << r4 + end + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(IPv4Byte0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + i5, s5 = index, [] + if has_terminal?('\G[2]', true, index) + r6 = true + @index += 1 + else + r6 = nil + end + s5 << r6 + if r6 + if has_terminal?('\G[0-4]', true, index) + r7 = true + @index += 1 + else + r7 = nil + end + s5 << r7 + if r7 + if has_terminal?('\G[0-9]', true, index) + r8 = true + @index += 1 + else + r8 = nil + end + s5 << r8 + end + end + if s5.last + r5 = instantiate_node(SyntaxNode,input, i5...index, s5) + r5.extend(IPv4Byte1) + else + @index = i5 + r5 = nil + end + if r5 + r0 = r5 + else + i9, s9 = index, [] + if has_terminal?('\G[1]', true, index) + r10 = true + @index += 1 + else + r10 = nil + end + s9 << r10 + if r10 + if has_terminal?('\G[0-9]', true, index) + r11 = true + @index += 1 + else + r11 = nil + end + s9 << r11 + if r11 + if has_terminal?('\G[0-9]', true, index) + r12 = true + @index += 1 + else + r12 = nil + end + s9 << r12 + end + end + if s9.last + r9 = instantiate_node(SyntaxNode,input, i9...index, s9) + r9.extend(IPv4Byte2) + else + @index = i9 + r9 = nil + end + if r9 + r0 = r9 + else + i13, s13 = index, [] + if has_terminal?('\G[1-9]', true, index) + r14 = true + @index += 1 + else + r14 = nil + end + s13 << r14 + if r14 + if has_terminal?('\G[0-9]', true, index) + r15 = true + @index += 1 + else + r15 = nil + end + s13 << r15 + end + if s13.last + r13 = instantiate_node(SyntaxNode,input, i13...index, s13) + r13.extend(IPv4Byte3) + else + @index = i13 + r13 = nil + end + if r13 + r0 = r13 + else + if has_terminal?('\G[0-9]', true, index) + r16 = true + @index += 1 + else + r16 = nil + end + if r16 + r0 = r16 + else + @index = i0 + r0 = nil + end + end + end + end + end + + node_cache[:IPv4Byte][start_index] = r0 + + r0 + end + + module IPv4Address0 + def IPv4Byte1 + elements[0] + end + + def IPv4Byte2 + elements[2] + end + + def IPv4Byte3 + elements[4] + end + + def IPv4Byte4 + elements[6] + end + end + + def _nt_IPv4Address + start_index = index + if node_cache[:IPv4Address].has_key?(index) + cached = node_cache[:IPv4Address][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0, s0 = index, [] + r1 = _nt_IPv4Byte + s0 << r1 + if r1 + if has_terminal?(".", false, index) + r2 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(".") + r2 = nil + end + s0 << r2 + if r2 + r3 = _nt_IPv4Byte + s0 << r3 + if r3 + if has_terminal?(".", false, index) + r4 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(".") + r4 = nil + end + s0 << r4 + if r4 + r5 = _nt_IPv4Byte + s0 << r5 + if r5 + if has_terminal?(".", false, index) + r6 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(".") + r6 = nil + end + s0 << r6 + if r6 + r7 = _nt_IPv4Byte + s0 << r7 + end + end + end + end + end + end + if s0.last + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + r0.extend(IPv4Address0) + else + @index = i0 + r0 = nil + end + + node_cache[:IPv4Address][start_index] = r0 + + r0 + end + + def _nt_IP + start_index = index + if node_cache[:IP].has_key?(index) + cached = node_cache[:IP][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + r0 = _nt_IPv4Address + + node_cache[:IP][start_index] = r0 + + r0 + end + + def _nt_Hostname + start_index = index + if node_cache[:Hostname].has_key?(index) + cached = node_cache[:Hostname][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + s0, i0 = [], index + loop do + if has_terminal?('\G[a-zA-Z\\.\\-]', true, index) + r1 = true + @index += 1 + else + r1 = nil + end + if r1 + s0 << r1 + else + break + end + end + if s0.empty? + @index = i0 + r0 = nil + else + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + end + + node_cache[:Hostname][start_index] = r0 + + r0 + end + + def _nt_Address + start_index = index + if node_cache[:Address].has_key?(index) + cached = node_cache[:Address][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + r1 = _nt_Hostname + if r1 + r0 = r1 + else + r2 = _nt_IP + if r2 + r0 = r2 + else + @index = i0 + r0 = nil + end + end + + node_cache[:Address][start_index] = r0 + + r0 + end + + def _nt_Port + start_index = index + if node_cache[:Port].has_key?(index) + cached = node_cache[:Port][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + s0, i0 = [], index + loop do + if has_terminal?('\G[0-9]', true, index) + r1 = true + @index += 1 + else + r1 = nil + end + if r1 + s0 << r1 + else + break + end + end + if s0.empty? + @index = i0 + r0 = nil + else + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + end + + node_cache[:Port][start_index] = r0 + + r0 + end + + def _nt_ORPort + start_index = index + if node_cache[:ORPort].has_key?(index) + cached = node_cache[:ORPort][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + r0 = _nt_Port + + node_cache[:ORPort][start_index] = r0 + + r0 + end + + def _nt_DirPort + start_index = index + if node_cache[:DirPort].has_key?(index) + cached = node_cache[:DirPort][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + r0 = _nt_Port + + node_cache[:DirPort][start_index] = r0 + + r0 + end + + def _nt_SP + start_index = index + if node_cache[:SP].has_key?(index) + cached = node_cache[:SP][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + if has_terminal?(" ", false, index) + r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure(" ") + r0 = nil + end + + node_cache[:SP][start_index] = r0 + + r0 + end + + def _nt_NL + start_index = index + if node_cache[:NL].has_key?(index) + cached = node_cache[:NL][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + if has_terminal?("\r\n", false, index) + r0 = instantiate_node(SyntaxNode,input, index...(index + 2)) + @index += 2 + else + terminal_parse_failure("\r\n") + r0 = nil + end + + node_cache[:NL][start_index] = r0 + + r0 + end + + def _nt_ALPHA + start_index = index + if node_cache[:ALPHA].has_key?(index) + cached = node_cache[:ALPHA][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + if has_terminal?('\G[A-Z]', true, index) + r1 = true + @index += 1 + else + r1 = nil + end + if r1 + r0 = r1 + else + if has_terminal?('\G[a-z]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + if r2 + r0 = r2 + else + @index = i0 + r0 = nil + end + end + + node_cache[:ALPHA][start_index] = r0 + + r0 + end + + def _nt_DIGIT + start_index = index + if node_cache[:DIGIT].has_key?(index) + cached = node_cache[:DIGIT][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + if has_terminal?('\G[0-9]', true, index) + r0 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + r0 = nil + end + + node_cache[:DIGIT][start_index] = r0 + + r0 + end + + def _nt_HEXDIG + start_index = index + if node_cache[:HEXDIG].has_key?(index) + cached = node_cache[:HEXDIG][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + r1 = _nt_DIGIT + if r1 + r0 = r1 + else + if has_terminal?("A", false, index) + r2 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("A") + r2 = nil + end + if r2 + r0 = r2 + else + if has_terminal?("B", false, index) + r3 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("B") + r3 = nil + end + if r3 + r0 = r3 + else + if has_terminal?("C", false, index) + r4 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("C") + r4 = nil + end + if r4 + r0 = r4 + else + if has_terminal?("D", false, index) + r5 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("D") + r5 = nil + end + if r5 + r0 = r5 + else + if has_terminal?("E", false, index) + r6 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("E") + r6 = nil + end + if r6 + r0 = r6 + else + if has_terminal?("F", false, index) + r7 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("F") + r7 = nil + end + if r7 + r0 = r7 + else + @index = i0 + r0 = nil + end + end + end + end + end + end + end + + node_cache[:HEXDIG][start_index] = r0 + + r0 + end + + def _nt_IDChar + start_index = index + if node_cache[:IDChar].has_key?(index) + cached = node_cache[:IDChar][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + r1 = _nt_ALPHA + if r1 + r0 = r1 + else + r2 = _nt_DIGIT + if r2 + r0 = r2 + else + @index = i0 + r0 = nil + end + end + + node_cache[:IDChar][start_index] = r0 + + r0 + end + + def _nt_NicknameChar + start_index = index + if node_cache[:NicknameChar].has_key?(index) + cached = node_cache[:NicknameChar][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + if has_terminal?('\G[A-Z]', true, index) + r1 = true + @index += 1 + else + r1 = nil + end + if r1 + r0 = r1 + else + if has_terminal?('\G[a-z]', true, index) + r2 = true + @index += 1 + else + r2 = nil + end + if r2 + r0 = r2 + else + if has_terminal?('\G[0-9]', true, index) + r3 = true + @index += 1 + else + r3 = nil + end + if r3 + r0 = r3 + else + @index = i0 + r0 = nil + end + end + end + + node_cache[:NicknameChar][start_index] = r0 + + r0 + end + + def _nt_Nickname + start_index = index + if node_cache[:Nickname].has_key?(index) + cached = node_cache[:Nickname][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + s0, i0 = [], index + loop do + r1 = _nt_NicknameChar + if r1 + s0 << r1 + else + break + end + if s0.size == 19 + break + end + end + if s0.size < 1 + @index = i0 + r0 = nil + else + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + end + + node_cache[:Nickname][start_index] = r0 + + r0 + end + + module Fingerprint0 + end + + def _nt_Fingerprint + start_index = index + if node_cache[:Fingerprint].has_key?(index) + cached = node_cache[:Fingerprint][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0, s0 = index, [] + if has_terminal?("$", false, index) + r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("$") + r1 = nil + end + s0 << r1 + if r1 + s2, i2 = [], index + loop do + r3 = _nt_HEXDIG + if r3 + s2 << r3 + else + break + end + if s2.size == 40 + break + end + end + if s2.size < 40 + @index = i2 + r2 = nil + else + r2 = instantiate_node(SyntaxNode,input, i2...index, s2) + end + s0 << r2 + end + if s0.last + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + r0.extend(Fingerprint0) + else + @index = i0 + r0 = nil + end + + node_cache[:Fingerprint][start_index] = r0 + + r0 + end + + def _nt_ServerID + start_index = index + if node_cache[:ServerID].has_key?(index) + cached = node_cache[:ServerID][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + r1 = _nt_Nickname + if r1 + r0 = r1 + else + r2 = _nt_Fingerprint + if r2 + r0 = r2 + else + @index = i0 + r0 = nil + end + end + + node_cache[:ServerID][start_index] = r0 + + r0 + end + + module LongName0 + def f + elements[0] + end + + def n + elements[2] + end + end + + def _nt_LongName + start_index = index + if node_cache[:LongName].has_key?(index) + cached = node_cache[:LongName][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + i1, s1 = index, [] + r2 = _nt_Fingerprint + s1 << r2 + if r2 + if has_terminal?("=", false, index) + r3 = instantiate_node(SyntaxNode,input, index...(index + 1)) + @index += 1 + else + terminal_parse_failure("=") + r3 = nil + end + s1 << r3 + if r3 + r4 = _nt_Nickname + s1 << r4 + end + end + if s1.last + r1 = instantiate_node(SyntaxNode,input, i1...index, s1) + r1.extend(LongName0) + else + @index = i1 + r1 = nil + end + if r1 + r0 = r1 + else + r5 = _nt_Fingerprint + if r5 + r0 = r5 + else + @index = i0 + r0 = nil + end + end + + node_cache[:LongName][start_index] = r0 + + r0 + end + + def _nt_ServerSpec + start_index = index + if node_cache[:ServerSpec].has_key?(index) + cached = node_cache[:ServerSpec][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + i0 = index + r1 = _nt_LongName + if r1 + r0 = r1 + else + r2 = _nt_Nickname + if r2 + r0 = r2 + else + @index = i0 + r0 = nil + end + end + + node_cache[:ServerSpec][start_index] = r0 + + r0 + end + + def _nt_StreamID + start_index = index + if node_cache[:StreamID].has_key?(index) + cached = node_cache[:StreamID][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + s0, i0 = [], index + loop do + r1 = _nt_IDChar + if r1 + s0 << r1 + else + break + end + if s0.size == 16 + break + end + end + if s0.size < 1 + @index = i0 + r0 = nil + else + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + end + + node_cache[:StreamID][start_index] = r0 + + r0 + end + + def _nt_CircuitID + start_index = index + if node_cache[:CircuitID].has_key?(index) + cached = node_cache[:CircuitID][index] + if cached + cached = SyntaxNode.new(input, index...(index + 1)) if cached == true + @index = cached.interval.end + end + return cached + end + + s0, i0 = [], index + loop do + r1 = _nt_IDChar + if r1 + s0 << r1 + else + break + end + if s0.size == 16 + break + end + end + if s0.size < 1 + @index = i0 + r0 = nil + else + r0 = instantiate_node(SyntaxNode,input, i0...index, s0) + end + + node_cache[:CircuitID][start_index] = r0 + + r0 + end + + end + + class PrimitivesParser < Treetop::Runtime::CompiledParser + include Primitives + end + +end \ No newline at end of file diff --git a/lib/torspec/primitives.treetop b/lib/torspec/primitives.treetop new file mode 100644 index 0000000..1322819 --- /dev/null +++ b/lib/torspec/primitives.treetop @@ -0,0 +1,135 @@ +module Torspec + grammar Primitives + rule Year + [0-9] [0-9] [0-9] [0-9] + end + + rule Month + [0] [1-9] / [1] [0-2] + end + + rule Day + [0-2] [0-9] / [3] [0-1] + end + + rule Hour + [0] [0-9] / [1] [0-9] / [2] [0-4] + end + + rule Minute + [0] [0-9] / [1-5] [0-9] + end + + rule Second + [0] [0-9] / [1-5] [0-9] + end + + rule DateTime + Year "-" Month "-" Day " " Hour ":" Minute ":" Second + end + + rule Base64Char + [A-Za-z0-9+/] + end + + rule Base64Hash + Base64Char+ + end + + rule IPv4Byte + [2] [5] [0-5] / [2] [0-4] [0-9] / [1] [0-9] [0-9] / [1-9] [0-9] / [0-9] + end + + rule IPv4Address + IPv4Byte "." IPv4Byte "." IPv4Byte "." IPv4Byte + end + + rule IP + IPv4Address + end + + rule Hostname + [a-zA-Z\.\-]+ # TODO: Wow this is a garbage production.... + end + + rule Address + Hostname / IP + end + + rule Port + [0-9]+ + end + + rule ORPort + Port + end + + rule SocksPOrt + [0] + end + + rule DirPort + Port + end + + rule SP + " " + end + + rule NL + "\r\n" + end + + rule ALPHA + [A-Z] / [a-z] + end + + rule DIGIT + [0-9] + end + + rule HEXDIG + DIGIT / "A" / "B" / "C" / "D" / "E" / "F" + end + + rule Boolean + [0] / [1] + end + + rule IDChar + ALPHA / DIGIT + end + + rule NicknameChar + [A-Z] / [a-z] / [0-9] + end + + rule Nickname + NicknameChar 1..19 + end + + rule Fingerprint + "$" HEXDIG 40..40 / HEXDIG 40..40 + end + + rule ServerID + Nickname / Fingerprint + end + + rule LongName + f:Fingerprint "=" n:Nickname / Fingerprint + end + + rule ServerSpec + LongName / Nickname + end + + rule StreamID + IDChar 1..16 + end + + rule CircuitID + IDChar 1..16 + end + end +end \ No newline at end of file diff --git a/spec/environment.rb b/spec/environment.rb new file mode 100644 index 0000000..3fc6497 --- /dev/null +++ b/spec/environment.rb @@ -0,0 +1,4 @@ +$VERBOSE = nil + +$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..ad99b5e --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,11 @@ +require File.expand_path('../environment', __FILE__) + +unless defined?(TORSPEC_ROOT) + TORSPEC_ROOT = File.join(File.dirname(__FILE__), '../') +end + +unless defined?(SPEC_ROOT) + SPEC_ROOT = File.join(File.dirname(__FILE__)) +end + +require 'torspec' diff --git a/spec/torspec/dir_spec_v2/network_status_spec.rb b/spec/torspec/dir_spec_v2/network_status_spec.rb new file mode 100644 index 0000000..3f6c094 --- /dev/null +++ b/spec/torspec/dir_spec_v2/network_status_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +require 'treetop/compiler' +Treetop.load(File.join(TORSPEC_ROOT, 'lib/torspec/dir_spec_v2/network_status')) + +describe "NetworkStatusGrammar" do + before(:each) do + @parser = Torspec::DirspecV2::NetworkStatusParser.new + end + + describe "Preamble" do + it "should parse a valid network status version" do + text = "network-status-version 2" + nodes = @parser.parse(text, :root => :NetworkStatusVersion) + nodes.should_not be_nil + + end + + it "should parse a valid directory source" do + text = "dir-source tor.dizum.com 194.109.206.212 80" + nodes = @parser.parse(text, :root => :DirSourceLine) + nodes.should_not be_nil + end + + it "should parse a valid fingerprint line" do + text = "fingerprint 7EA6EAD6FD83083C538F44038BBFA077587DD755" + nodes = @parser.parse(text, :root => :FingerprintLine) + nodes.should_not be_nil + end + + it "should parse a valid published line" do + text = "published 2007-08-01 00:38:25" + nodes = @parser.parse(text, :root => :PublishedLine) + nodes.should_not be_nil + end + + end +end diff --git a/spec/torspec/dir_spec_v2/router_descriptor_spec.rb b/spec/torspec/dir_spec_v2/router_descriptor_spec.rb new file mode 100644 index 0000000..5f49ee2 --- /dev/null +++ b/spec/torspec/dir_spec_v2/router_descriptor_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +require 'treetop/compiler' +Treetop.load(File.join(TORSPEC_ROOT, 'lib/torspec/primitives')) + +describe "RouterDescriptorGrammar" do + it "should parse a valid router item" do + + end +end diff --git a/spec/torspec/primitives_spec.rb b/spec/torspec/primitives_spec.rb new file mode 100644 index 0000000..0951e61 --- /dev/null +++ b/spec/torspec/primitives_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +require 'treetop/compiler' +Treetop.load(File.join(TORSPEC_ROOT, 'lib/torspec/primitives')) + +describe "PrimitivesGrammar" do + it "should parse a valid DateTime value" do + text = "2011-04-01 22:10:01" + parser = Torspec::PrimitivesParser.new + nodes = parser.parse(text, :root => :DateTime) + nodes.should_not be_nil + end + + it "should not parse a invalid DateTime value" do + text = "2011-04-01 25r:10:01" + parser = Torspec::PrimitivesParser.new + nodes = parser.parse(text, :root => :DateTime) + nodes.should be_nil + end + +end diff --git a/torspec.gemspec b/torspec.gemspec new file mode 100644 index 0000000..cca8be2 --- /dev/null +++ b/torspec.gemspec @@ -0,0 +1,10 @@ +Gem::Specification.new do |s| + s.name = "torspec" + s.version = "0.1.0" + s.author = "Poet (Tim Sally)" + s.email = "poet@stack.io" + s.homepage = "http://www.atomicpeace.com" + s.description = "Grammars matching the Tor Spec." + s.add_dependency('treetop', '>= 1.4.8') + s.files = %w(README.txt LICENSE.txt Rakefile) + Dir.glob("lib/**/*") +end -- 2.11.4.GIT