class Muskox::Parser

Constants

ROOT
TYPE_WIDENINGS

Attributes

schema[R]

Public Class Methods

new(schema) click to toggle source
# File lib/muskox.rb, line 12
def initialize schema
  @schema = schema
end

Public Instance Methods

expected_type(schema, last) click to toggle source
# File lib/muskox.rb, line 132
def expected_type schema, last
  schema["properties"][last.last] && schema["properties"][last.last]["type"]
end
is_type(expected, actual) click to toggle source
# File lib/muskox.rb, line 148
def is_type expected, actual
  case expected
  when String
    expected == actual || expected == TYPE_WIDENINGS[actual]
  when Array
    expected.any? {|e| is_type e, actual }
  when nil
    true # is this really what the spec wants? really?
  else
    raise "unexpected type comparison #{expected}, #{actual}"
  end
end
matching_type(expected, actual, opt=true) { || ... } click to toggle source
# File lib/muskox.rb, line 136
def matching_type expected, actual, opt=true
  if is_type(expected, actual.to_s) && opt
    yield
  else
    raise ParserError, "expected node of type #{expected} but was #{actual}"
  end
end
parse(input) click to toggle source
# File lib/muskox.rb, line 16
    def parse input
      r = nil
      schema_stack = [schema]
      stack = [[ROOT, ROOT]]
      lexer = Pure::Lexer.new input, :quirks_mode => true
      lexer.lex do |type, value|
#        puts "token #{type}: #{value}"
#        puts "stack #{stack.inspect}"
#        puts "schema stack #{schema_stack.last["type"]}"
        case type
        when :property
          if schema_stack.last["properties"] && schema_stack.last["properties"].keys.include?(value)
            stack.push [type, value]
          else
            raise ParserError, "Unexpected property: #{value}"
          end
        when :array_begin
          case stack.last.first
          when :property
            last = stack.last
            matching_type expected_type(schema_stack.last, last), "array" do
              stack.push [:array, []]
              schema_stack.push(schema["properties"][last.last])
            end
          when ROOT
            stack.push [:array, []]
          else
            raise "unknown stack type #{stack.last}"
          end
        when :array_end
          array_top = stack.pop

          case stack.last.first
          when :property
            schema_stack.pop
            last = stack.pop
            matching_type expected_type(schema_stack.last, last), "array" do
              stack.last.last[last.last] = array_top.last
            end
          when :array
            matching_type expected_type(schema_stack.last, last), "array" do
              stack.last.last << array_top.last
            end
          when ROOT
            matching_type schema_stack.last["type"], "array" do
              r = stack.last.last
            end
          else
            raise "unknown stack type #{stack.last}"
          end
        when :object_begin
          case stack.last.first
          when :property
            last = stack.last
            matching_type expected_type(schema_stack.last, last), "object" do
              stack.push [:object, {}]
              schema_stack.push(schema["properties"][last.last])
            end
          when ROOT
            stack.push [:object, {}]
          end
        when :object_end
          object_top = stack.pop

          if schema_stack.last["required"] && !(schema_stack.last["required"] - object_top.last.keys).empty?
            raise ParserError
          end

          case stack.last.first
          when :property
            schema_stack.pop
            last = stack.pop
            matching_type expected_type(schema_stack.last, last), "object", stack.last.first == :object do
              stack.last.last[last.last] = object_top.last
            end
          when ROOT
            matching_type schema_stack.last["type"], "object" do
              r = object_top.last
            end
          else
            raise "unknown stack type #{stack.last.first}"
          end
        when :integer, :string, :float, :boolean, :null
          case stack.last.first
          when :property
            last = stack.pop
            matching_type expected_type(schema_stack.last, last), type, stack.last.first == :object do
              stack.last.last[last.last] = value
            end
          when :array
            case schema_stack.last["items"]
            when Hash
              matching_type schema_stack.last["items"]["type"], type do
                stack.last.last << value
              end
            when Array
              matching_type schema_stack.last["items"][stack.last.last.size]["type"], type do
                stack.last.last << value
              end
            else
              raise "Unexpected items type #{schema_stack.last["items"]}"
            end
          when ROOT
            matching_type schema_stack.last["type"], type do
              r = stack.last.last
            end
          else
            raise "unknown stack type #{stack.last.inspect}"
          end
        else
          raise "unhandled token type: #{type}: #{value}"
        end
      end
      r
    end