junoser 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +9 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +69 -0
 - data/Rakefile +37 -0
 - data/bin/console +14 -0
 - data/bin/setup +7 -0
 - data/example/vsrx-12.1.x47.rb +38421 -0
 - data/exe/junoser +51 -0
 - data/junoser.gemspec +27 -0
 - data/lib/junoser/cli.rb +55 -0
 - data/lib/junoser/development.rb +2 -0
 - data/lib/junoser/display/base.rb +40 -0
 - data/lib/junoser/display/config_store.rb +52 -0
 - data/lib/junoser/display/set.rb +82 -0
 - data/lib/junoser/display/structure.rb +29 -0
 - data/lib/junoser/display.rb +16 -0
 - data/lib/junoser/parser.rb +38453 -0
 - data/lib/junoser/ruler.rb +173 -0
 - data/lib/junoser/transformer.rb +41 -0
 - data/lib/junoser/version.rb +3 -0
 - data/lib/junoser/xsd/base.rb +54 -0
 - data/lib/junoser/xsd/choice.rb +33 -0
 - data/lib/junoser/xsd/complex_type.rb +74 -0
 - data/lib/junoser/xsd/element.rb +100 -0
 - data/lib/junoser/xsd/enumeration.rb +30 -0
 - data/lib/junoser/xsd/parsable.rb +33 -0
 - data/lib/junoser/xsd/restriction.rb +34 -0
 - data/lib/junoser/xsd/sequence.rb +39 -0
 - data/lib/junoser/xsd/simple_content.rb +31 -0
 - data/lib/junoser.rb +3 -0
 - metadata +146 -0
 
    
        data/exe/junoser
    ADDED
    
    | 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'pathname'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            $: << File.expand_path('../../lib', Pathname.new(__FILE__).realpath)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require 'junoser/cli'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            command = nil
         
     | 
| 
      
 12 
     | 
    
         
            +
            opts = OptionParser.new do |opts|
         
     | 
| 
      
 13 
     | 
    
         
            +
              opts.banner = 'junoser: an juniper configuration parser'
         
     | 
| 
      
 14 
     | 
    
         
            +
              opts.define_head 'Usage: junoser [options] [path]'
         
     | 
| 
      
 15 
     | 
    
         
            +
              opts.separator ''
         
     | 
| 
      
 16 
     | 
    
         
            +
              opts.separator 'Options:'
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              opts.on '-c', '--check', 'Verify syntax' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                command = :check
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              opts.on '-d', '--display-set', 'Translate to "display set" form' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                command = :display_set
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              opts.on '-s', '--structured', 'Translate to structured form' do
         
     | 
| 
      
 27 
     | 
    
         
            +
                command = :struct
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              opts.on_tail '-h', '--help', 'Show this message' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                puts opts
         
     | 
| 
      
 32 
     | 
    
         
            +
                exit
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              opts.on_tail '-v', '--version', 'Show version' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                puts Junoser::VERSION
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
            opts.parse!
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            case command
         
     | 
| 
      
 42 
     | 
    
         
            +
            when :check
         
     | 
| 
      
 43 
     | 
    
         
            +
              Junoser::Cli.commit_check $<
         
     | 
| 
      
 44 
     | 
    
         
            +
            when :display_set
         
     | 
| 
      
 45 
     | 
    
         
            +
              Junoser::Cli.display_set $<
         
     | 
| 
      
 46 
     | 
    
         
            +
            when :struct
         
     | 
| 
      
 47 
     | 
    
         
            +
              Junoser::Cli.struct $<
         
     | 
| 
      
 48 
     | 
    
         
            +
            else
         
     | 
| 
      
 49 
     | 
    
         
            +
              puts opts
         
     | 
| 
      
 50 
     | 
    
         
            +
              abort
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
    
        data/junoser.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'junoser/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.name          = "junoser"
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version       = Junoser::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors       = ["Shintaro Kojima"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.email         = ["goodies@codeout.net"]
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              spec.summary       = %q{PEG parser for JUNOS configuration.}
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.description   = %q{PEG parser to vefiry and translate into different formats for JUNOS configuration.}
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.homepage      = "https://github.com/codeout/sakura-cli"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.files         = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.bindir        = "exe"
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         
     | 
| 
      
 19 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              spec.add_dependency "parslet"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 1.9"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_development_dependency "rake", "~> 10.0"
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.add_development_dependency "activesupport"
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.add_development_dependency "nokogiri"
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/junoser/cli.rb
    ADDED
    
    | 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'parslet'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'junoser/display'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'junoser/parser'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Junoser
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Cli
         
     | 
| 
      
 8 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def commit_check(io_or_string)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    config = if io_or_string.respond_to?(:read)
         
     | 
| 
      
 11 
     | 
    
         
            +
                               $<.read
         
     | 
| 
      
 12 
     | 
    
         
            +
                             else
         
     | 
| 
      
 13 
     | 
    
         
            +
                               io_or_string.to_s
         
     | 
| 
      
 14 
     | 
    
         
            +
                             end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    if Junoser::Display.display_set?(config)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      commit_check_display_set config
         
     | 
| 
      
 18 
     | 
    
         
            +
                    else
         
     | 
| 
      
 19 
     | 
    
         
            +
                      commit_check_structured config
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def display_set(io_or_string)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    Junoser::Display::Set.new(io_or_string).transform
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def struct(io_or_string)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    Junoser::Display::Structure.new(io_or_string).transform
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  private
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def commit_check_structured(config)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    Junoser::Display::Set.new(config).commit_check
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def commit_check_display_set(config)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    parser = Junoser::Parser.new
         
     | 
| 
      
 40 
     | 
    
         
            +
                    failed = false
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    config.split("\n").each do |line|
         
     | 
| 
      
 43 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 44 
     | 
    
         
            +
                        parser.parse line
         
     | 
| 
      
 45 
     | 
    
         
            +
                      rescue Parslet::ParseFailed
         
     | 
| 
      
 46 
     | 
    
         
            +
                        $stderr.puts "Invalid syntax:  #{line}"
         
     | 
| 
      
 47 
     | 
    
         
            +
                        failed = true
         
     | 
| 
      
 48 
     | 
    
         
            +
                      end
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    abort if failed
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Junoser
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Display
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_accessor :output
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(io_or_string)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @input = io_or_string
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @output = $stdout
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def read_io_or_string
         
     | 
| 
      
 15 
     | 
    
         
            +
                    return @read_io_or_string if @read_io_or_string
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    config = if @input.respond_to?(:read)
         
     | 
| 
      
 18 
     | 
    
         
            +
                               @input.read
         
     | 
| 
      
 19 
     | 
    
         
            +
                             else
         
     | 
| 
      
 20 
     | 
    
         
            +
                               @input.to_s
         
     | 
| 
      
 21 
     | 
    
         
            +
                             end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    @read_io_or_string = remove_blank_and_comment(config)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @read_io_or_string = unify_carriage_return(@read_io_or_string)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def remove_blank_and_comment(str)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    str.gsub! /#.*/, ''
         
     | 
| 
      
 29 
     | 
    
         
            +
                    str.gsub! /\/\*((?!\*\/).)*\*\//m, ''
         
     | 
| 
      
 30 
     | 
    
         
            +
                    str.gsub! /\n\s*/, "\n"
         
     | 
| 
      
 31 
     | 
    
         
            +
                    str.strip
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def unify_carriage_return(str)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    str.gsub! /\r\n?/, "\n"
         
     | 
| 
      
 36 
     | 
    
         
            +
                    str
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Junoser
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Display
         
     | 
| 
      
 5 
     | 
    
         
            +
                class ConfigStore
         
     | 
| 
      
 6 
     | 
    
         
            +
                  extend Forwardable
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  OFFSET = '    '
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(depth=0)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @hash = {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @depth = depth
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def push(str)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    store = self
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    join_arg(str).split("\n").each_with_index do |element, index|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      store[element] ||= self.class.new(index+1)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      store = store[element]
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  alias << push
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 26 
     | 
    
         
            +
                    str = ''
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    each do |k, v|
         
     | 
| 
      
 29 
     | 
    
         
            +
                      if v.empty?
         
     | 
| 
      
 30 
     | 
    
         
            +
                        str << OFFSET*@depth << "#{k};\n"
         
     | 
| 
      
 31 
     | 
    
         
            +
                      else
         
     | 
| 
      
 32 
     | 
    
         
            +
                        str << OFFSET*@depth << "#{k} {\n"
         
     | 
| 
      
 33 
     | 
    
         
            +
                        str << v.to_s.chop << "\n"
         
     | 
| 
      
 34 
     | 
    
         
            +
                        str << OFFSET*@depth << "}\n"
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    str
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def_delegators :@hash, :[], :[]=, :each, :empty?
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  private
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def join_arg(str)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    str.gsub!(/\narg\((.*)\)$/) { " #$1" }
         
     | 
| 
      
 47 
     | 
    
         
            +
                    str.gsub!(/arg\((.*)\)/) { "#$1" }
         
     | 
| 
      
 48 
     | 
    
         
            +
                    str
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'junoser/display/base'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Junoser
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Display
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Set
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include Base
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def transform
         
     | 
| 
      
 9 
     | 
    
         
            +
                    process do |current_stack, str|
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @output.puts transform_line(current_stack, str)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def commit_check(&block)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    parser = Junoser::Parser.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                    failed = false
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    process do |current_stack, str|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      config = transform_line(current_stack, str)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 22 
     | 
    
         
            +
                        parser.parse config
         
     | 
| 
      
 23 
     | 
    
         
            +
                      rescue Parslet::ParseFailed
         
     | 
| 
      
 24 
     | 
    
         
            +
                        $stderr.puts "Invalid syntax:\n#{struct(current_stack.dup, str)}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                        failed = true
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    abort if failed
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  private
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def process(&block)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    stack = []
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    read_io_or_string.split("\n").each do |line|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      case line
         
     | 
| 
      
 40 
     | 
    
         
            +
                      when /(.*){/
         
     | 
| 
      
 41 
     | 
    
         
            +
                        stack.push $1.strip
         
     | 
| 
      
 42 
     | 
    
         
            +
                      when '}'
         
     | 
| 
      
 43 
     | 
    
         
            +
                        stack.pop
         
     | 
| 
      
 44 
     | 
    
         
            +
                      when /((?!\[).*)\[(.*)\];/
         
     | 
| 
      
 45 
     | 
    
         
            +
                        $2.split("\s").each do |i|
         
     | 
| 
      
 46 
     | 
    
         
            +
                          yield stack, "#{$1.strip} #{i}"
         
     | 
| 
      
 47 
     | 
    
         
            +
                        end
         
     | 
| 
      
 48 
     | 
    
         
            +
                      when /(.*);/
         
     | 
| 
      
 49 
     | 
    
         
            +
                        yield stack, $1
         
     | 
| 
      
 50 
     | 
    
         
            +
                      else
         
     | 
| 
      
 51 
     | 
    
         
            +
                        raise "ERROR* unknown statement:  #{line}"
         
     | 
| 
      
 52 
     | 
    
         
            +
                      end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  def transform_line(current_stack, str)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    statement = if current_stack.empty?
         
     | 
| 
      
 58 
     | 
    
         
            +
                                  str
         
     | 
| 
      
 59 
     | 
    
         
            +
                                else
         
     | 
| 
      
 60 
     | 
    
         
            +
                                  statement = "#{current_stack.join(' ')} #{str}"
         
     | 
| 
      
 61 
     | 
    
         
            +
                                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    if statement.gsub!('inactive: ', '')
         
     | 
| 
      
 64 
     | 
    
         
            +
                      "deactivate #{statement}"
         
     | 
| 
      
 65 
     | 
    
         
            +
                    else
         
     | 
| 
      
 66 
     | 
    
         
            +
                      "set #{statement}"
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def struct(stack, statement, offset=2)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    width = 2
         
     | 
| 
      
 72 
     | 
    
         
            +
                    if label = stack.shift
         
     | 
| 
      
 73 
     | 
    
         
            +
                      %[#{" "*offset}#{label} {
         
     | 
| 
      
 74 
     | 
    
         
            +
            #{struct(stack, statement, width+offset)}
         
     | 
| 
      
 75 
     | 
    
         
            +
            #{" "*offset}}]
         
     | 
| 
      
 76 
     | 
    
         
            +
                    else
         
     | 
| 
      
 77 
     | 
    
         
            +
                      %[#{" "*offset}#{statement};]
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'junoser/display/config_store'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'junoser/parser'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'junoser/transformer'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Junoser
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Display
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Structure
         
     | 
| 
      
 8 
     | 
    
         
            +
                  include Base
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(io_or_string)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    super
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @config = Junoser::Display::ConfigStore.new
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def transform
         
     | 
| 
      
 16 
     | 
    
         
            +
                    parser = Junoser::Parser.new
         
     | 
| 
      
 17 
     | 
    
         
            +
                    transform = Junoser::Transformer.new
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    read_io_or_string.split("\n").each do |line|
         
     | 
| 
      
 20 
     | 
    
         
            +
                      transformed = transform.apply(parser.parse(line))
         
     | 
| 
      
 21 
     | 
    
         
            +
                      raise "ERROR: parse failed" unless transformed.is_a?(String)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      @config << transformed
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    @output.puts @config.to_s
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'junoser/display/set'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'junoser/display/structure'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Junoser
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Display
         
     | 
| 
      
 6 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def display_set?(str)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    str =~ /\Aset|deactivate/
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def structured?(str)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    !display_set?(str)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     |