class PosxmlCompiler::XsdParser

Constants

DELIMITER_END_INSTRUCTION
DELIMITER_END_PARAMETER

Attributes

instructions[RW]
text[RW]

Public Class Methods

new(text) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 8
def initialize(text)
  @text = text
  index_start = text.index("<xs:group name=\"comandos\">")
  index_end = text.index("<\/xs:group>")
  groups = text[index_start..index_end] # select only group text

  complex = text[index_end..-1] # select only complex text

  commands = parse_bytecodes(groups)
  @instructions = parse_parameters(commands, complex)
  # => {"if" => {:bytecode => "I", :order => ["variable", "operator", "value"], :parameters => {"variable" => :string_or_integer, "operator" => :string, "value" => :string_or_integer}}
end

Public Instance Methods

find(name) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 47
def find(name)
  self.instructions[name] # => {:bytecode => "I", :order => ["variable", "operator", "value"], :parameters => {"variable" => :string_or_integer, "operator" => :string, "value" => :string_or_integer}
end
parameter_type(instruction, parameter) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 25
def parameter_type(instruction, parameter)
  self.instructions[instruction][:parameters][parameter.to_s]
end
parameters_validate(instruction_name, instruction, parameters) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 51
def parameters_validate(instruction_name, instruction, parameters)
  return unless instruction[:parameters]
  parameters_valid = instruction[:parameters].keys
  parameters.each do |name, data|
    unless parameters_valid.include? name
      raise ParameterNotFoundError.new("invalid parameter '#{name}' for instruction '#{instruction_name}'")
    end
  end
end
to_bytecode(name, parameters) click to toggle source

Receive:

("if", {"variable" => {:original => "$(sKeyTouchScreen)", :value => "$(1)", :type => :string}, "operator" => {:original => "equalto", :value => "equalto", :type => :string}, "value" => {:original => "KEY_CLEAR", :value => "KEY_CLEAR", :type => :string})

Return:

"I$(1)\nequalto\nKEY_CLEAR"
# File lib/posxml_compiler/xsd_parser.rb, line 33
def to_bytecode(name, parameters)
  instruction = self.find(name) # => {:bytecode => "I", :order => ["variable", "operator", "value"], :parameters => {"variable" => :string_or_integer, "operator" => :string, "value" => :string_or_integer}
  raise InstructionNotFoundError.new("Instruction #{name.inspect} not found") unless instruction

  parameters_validate(name, instruction, parameters)
  line = instruction[:order].collect { |param| parameters[param][:value] }

  if line.empty?
    instruction[:bytecode].chr + DELIMITER_END_INSTRUCTION
  else
    instruction[:bytecode].chr + line.join(DELIMITER_END_PARAMETER) + DELIMITER_END_PARAMETER + DELIMITER_END_INSTRUCTION
  end
end
valid?() click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 21
def valid?
  !! @instructions
end

Private Instance Methods

check_type(str) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 147
def check_type(str)
  if str.include? "<xs:documentation>"
    if type_string_or_integer?(str)
      :string_or_integer
    elsif type_integer?(str)
      :integer
    else
      :string
    end
  end
end
parse_bytecodes(str) click to toggle source

Will return a hash with instruction name and bytecode in array

{
  "if" => {:bytecode => "I", :order => ["variable", "operator", "value"]},
  "/if" => {:bytecode => "E"}
}
# File lib/posxml_compiler/xsd_parser.rb, line 83
def parse_bytecodes(str)
  last, end_element = nil
  str.split("\n").inject({}) do |hash, str|
    key = str.match(/<xs:element name="(.*)" type="/)
    if key
      last = key[1]
      hash[last] ||= {:order => []}
      end_element = false
    end

    value = str.match(/<xs:appinfo>(.*)<\/xs:appinfo>/)
    value = value[1] if value

    if value
      if end_element
        hash["/" + last] = {:order => [], :bytecode => string2byte(value)}
      elsif ! value.include?(";")
        hash[last][:order] = value.split(",")
      else
        end_element = true
        hash[last][:bytecode] = string2byte(value)
      end
    end
    hash
  end
end
parse_parameters(bytecodes, str) click to toggle source

With commands generate by parse_bytecodes:

{"if" => ["I"], "/if" => ["E"]}
{
  "if" => {:bytecode => "I", :order => ["variable", "operator", "value"]},
  "/if" => {:bytecode => "E"}
}

this method parse parameters and types:

{
  "if" => {
    :bytecode => "I",
    :order => ["variable", "operator", "value"],
    :parameters => {"variable" => :string_or_integer, "operator" => :string, "value" => :string_or_integer}
  },
  "/if" => {:bytecode => "E"}
}
# File lib/posxml_compiler/xsd_parser.rb, line 127
def parse_parameters(bytecodes, str)
  commands = bytecodes.dup
  last_byte  = nil
  last_param = nil
  str.split("\n").each do |str|
    key = str.match(/<xs:complexType name="(.*)">/)
    last_byte = key[1] if key

    value = str.match(/<xs:attribute name="(.*)" type/)
    last_param = value[1] if value

    value = check_type(str)
    if value && last_byte
      commands[last_byte][:parameters] ||= {}
      commands[last_byte][:parameters][last_param]    = value
    end
  end
  commands
end
string2byte(str) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 62
def string2byte(str)
  value = str.gsub(";", "").gsub("true", "").gsub("false", "")
  if value == "\\x0B"
    "\x0B"
  elsif value.include?("\\x")
    value.sub("\\x", "").to_i(16).chr
  elsif value == "&gt"
    ">"
  elsif value == "&lt"
    "<"
  else
    value
  end
end
type_integer?(str) click to toggle source

def type_string?(str) data = str.match(/(string)/) end

# File lib/posxml_compiler/xsd_parser.rb, line 167
def type_integer?(str)
  data = str.to_s.downcase.match(/(integer|inteiro)/)
end
type_string_or_integer?(str) click to toggle source
# File lib/posxml_compiler/xsd_parser.rb, line 159
def type_string_or_integer?(str)
  str.match(/(string ou inteiro|string or integer|float)/)
end