1. Brett Giles
  2. lqpl

Commits

Brett Giles  committed 18cf154

Broke out regexp parsers for classical stack, exec code, stack translation

  • Participants
  • Parent commits 2753de3
  • Branches master

Comments (0)

Files changed (20)

File GUI/spec/parsers/code_pointer_parser_spec.rb

View file
+require 'spec/spec_helper'
+describe CodePointerParser do
+  it "should return the created code map when given correct input when there is code" do
+    cpp = CodePointerParser.new("<pair><string>main</string><int>0</int></pair>")
+    cpp.parsed_value.should == [:main,0]
+  end
+
+  it "should throw an exception with bad input" do
+    expect {CodePointerParser.new("junk")}.to raise_error ParserError, /junk/
+  end
+  it "should throw an exception with nil input" do
+    expect {CodePointerParser.new(nil)}.to raise_error ParserError, /No match/
+  end
+  it "should throw an exception with blank input" do
+    expect {CodePointerParser.new("")}.to raise_error ParserError, /No match/
+  end
+end

File GUI/spec/parsers/executable_code_parser_spec.rb

View file
+require 'spec/spec_helper'
+require 'spec/specdata/executable_code_data'
+
+describe ExecutableCodeParser do
+  describe "class method instructions_to_list" do
+    it "should make an empty list when no pairs" do
+      ExecutableCodeParser::instructions_to_list("").should == []
+    end
+    it "should make a singleton list when there is one <i> and </i> pair and prepend '  0  ' to the item" do
+      ExecutableCodeParser::instructions_to_list("<i>EnScope</i>").should == ["  0  EnScope"]
+    end
+    it "should make a list of all items between <i> and </i> pairs and prepend the index of the item " do
+      ExecutableCodeParser::instructions_to_list(KVPS6).should == ['  0  EnScope',
+        '  1  QLoad "@q" 0',
+        '  2  QApply 0 Hadamard "@q"',
+        '  3  QPullup "@q"',
+        '  4  EnScope',
+        '  5  Measure "@q" 14 6 10']
+    end
+    it "should properly justify indexes when the index > 0 " do
+      ExecutableCodeParser::instructions_to_list(KVPS6+KVPS6)[9,11].should == [
+        '  9  QPullup "@q"',
+        ' 10  EnScope',
+        ' 11  Measure "@q" 14 6 10']
+    end
+  end
+  it "prepares an empty map when there are no keys" do
+    ecp = ExecutableCodeParser.new '<Code><map></map></Code>'
+    ecp.parsed_value.should == {}
+  end
+  it "prepares an one element map when there is only one key in the XML" do
+    ecp = ExecutableCodeParser.new('<Code><map><kvpair><key><string>main</string></key>'+
+      '<value><instructions><i>EnScope</i></instructions></value></kvpair></map></Code>')
+    ecp.parsed_value.should == {:main => ["  0  EnScope"]}
+  end
+  it "prepares an two element map when there are two keys in the XML" do
+    ecp = ExecutableCodeParser.new(CMAP_2)
+    ecp.parsed_value.should ==RES_CMAP_2
+  end
+  it "should throw an exception with bad input" do
+    expect {ExecutableCodeParser.new "junk"}.to raise_error ParserError, /junk/
+  end
+end

File GUI/spec/parsers/stack_translation_parser_spec.rb

View file
+require 'spec/spec_helper'
+
+require 'spec/specdata/stack_translation_data'
+
+
+describe StackTranslationParser do
+    describe "class method kv_pairs_to_map" do
+    it "should return the empty map if there are no pairs" do
+      stp = StackTranslationParser.new(EMPTYSTACK)
+      stp.parsed_value.should == [{}]
+    end
+    it "should return a  a key ->value  map of a single entry" do
+      stp = StackTranslationParser.new(P1)
+      stp.parsed_value.should == [{:p => 1}]
+    end
+    it "should return  a key ->value map of all entries " do
+      stp = StackTranslationParser.new(P1WITHREX27)
+      stp.parsed_value.should == [{:p => 1, :rex => 27}]
+    end
+    it "should create the two element list of empty map and one elt map when input empty and then p1" do
+      stp = StackTranslationParser.new(P1ANDEMPTY)
+      stp.parsed_value.should == [{},{:p => 1}]
+    end
+    it "should create a three element list with all map items when input a 3 level translation" do
+      stp = StackTranslationParser.new(L3STACK)
+      stp.parsed_value.should == [{:p => 1},{:p => 2},{:rex => 27,:p => 3}]
+    end
+  end
+end
+

File GUI/spec/specdata/dump_data.rb

View file
 require 'spec/specdata/classical_stack_data'
 
-DCALL="<DumpCall><int>5</int><string>Ret</string><Cstack></Cstack></DumpCall>"
-DCALL2="<DumpCall><int>7</int><string>some_method</string><Cstack><cint>5</cint></Cstack></DumpCall>"
+DCALL="<DumpCall><int>5</int><string>Ret</string><Classical></Classical></DumpCall>"
+DCALL2="<DumpCall><int>7</int><string>some_method</string><Classical><cint>5</cint></Classical></DumpCall>"
 
 DSPLIT= "<DumpSplit>whatever</DumpSplit>"

File GUI/spec/specdata/executable_code_data.rb

View file
+KVPS6='<i>EnScope</i><i>QLoad "@q" 0</i><i>QApply 0 Hadamard "@q"</i>'+
+  '<i>QPullup "@q"</i><i>EnScope</i><i>Measure "@q" 14 6 10</i>'
+
+KVPAIRS_2 = '<kvpair><key><string>main</string></key>'+
+        '<value><instructions><i>EnScope</i></instructions></value></kvpair>'+
+        '<kvpair><key><string>cflip_fcdelbl0</string></key>'+
+        '<value><instructions><i>EnScope</i><i>QLoad "@q" 0</i></instructions></value></kvpair>'
+
+CMAP_SINGLE = '<Code><map><kvpair><key><string>main</string></key>'+
+        '<value><instructions><i>EnScope</i></instructions></value></kvpair>'+
+        '</map></Code>'
+CMAP_6 = '<Code><map><kvpair><key><string>main</string></key>'+
+        '<value><instructions>'+KVPS6+'</instructions></value></kvpair>'+
+        '</map></Code>'
+CMAP_2x6 = '<Code><map><kvpair><key><string>main</string></key>'+
+        '<value><instructions>'+KVPS6+KVPS6+'</instructions></value></kvpair>'+
+        '</map></Code>'
+CMAP_2='<Code><map>'+KVPAIRS_2+'</map></Code>'
+
+RES_CMAP_2 = {:main => ["  0  EnScope"], :cflip_fcdelbl0 => ["  0  EnScope", '  1  QLoad "@q" 0']}

File GUI/spec/specdata/quantum_stack_data.rb

View file
   QSVAL5,4)
 
 QSINT = make_multi_sstacks("<Qstack><int>3</int><bool>True</bool>",
-  "<ClassicalStack><cint>27</cint><cint>5</cint></ClassicalStack></Qstack>",
+  "<Classical><cint>27</cint><cint>5</cint></Classical></Qstack>",
   QSVAL5,2)
 
 

File GUI/spec/specdata/stack_translation_data.rb

View file
 
 P1 = "<MMap><map>"+KVP1+"</map></MMap>"
 P2 = "<MMap><map>"+KVP2+"</map></MMap>"
+P1WITHREX27 = "<MMap><map>"+KVP1+KVREX27+"</map></MMap>"
 P1ANDR1 = "<MMap><map>"+KVP1+"</map><map>"+KVR1+"</map></MMap>"
 P1ANDR1ANDS1 = "<MMap><map>"+KVP1+"</map><map>"+KVR1+"</map><map>"+KVS1+"</map></MMap>"
 

File GUI/spec/view/descriptor_painter_spec.rb

View file
 
 describe ClassicalDescriptorPainter do
   before(:each) do
-   @sd = DescriptorPainterFactory.make_painter(AbstractDescriptorModel.make_instance "<ClassicalStack><cint>1</cint><cbool>True</cbool><cint>14</cint></ClassicalStack>")
+   @sd = DescriptorPainterFactory.make_painter(AbstractDescriptorModel.make_instance "<Classical><cint>1</cint><cbool>True</cbool><cint>14</cint></Classical>")
   end
   after (:all) do
     @sd = nil

File GUI/src/manifest.rb

View file
   require "panels/parsers/"+rf+"_pattern_parser"
 end
 
+
+%w{stack_translation code_pointer executable_code}.each do |rf|
+  require "panels/parsers/"+rf+"_parser"
+end
+
 require 'painting/canvas_size'
 require 'application_model'
 

File GUI/src/panels/classical_stack/classical_stack_model.rb

View file
-class ClassicalStackModel < XmlBasedModel
+class ClassicalStackModel < ApplicationModel
   attr_accessor :classical_stack_text
   attr_accessor :classical_stack
 
   end
 
   def classical_stack=(xml_input)
-    @classical_stack = check_and_return_value(CSTACK_PATTERN,xml_input,
-      lambda { |m| ClassicalStackModel::classical_values_to_list m})
+    cpp = ClassicalPatternParser.new xml_input
+    @classical_stack = cpp.parsed_value
   end
 
-  def self.classical_values_to_list(cvals)
-    values_to_list cvals, CLASSICALVALUES_PATTERN  do | ret, cv|
-      ret << cv[2].to_i if cv[2]
-      ret << (cv[4] == "True" or cv[4] == "true") if cv[4]
-    end
-  end
-
-  CSTACK_PATTERN = Regexp.new /<Cstack>(((<cint>(-?\d*)<\/cint>)|(<cbool>(((t|T)rue)|((F|f)alse))<\/cbool>))*)<\/Cstack>/
-  CLASSICALVALUES_PATTERN = Regexp.new /(<cint>(-?\d*)<\/cint>)|(<cbool>(((t|T)rue)|((F|f)alse))<\/cbool>)/
 end

File GUI/src/panels/dump/dump_call_model.rb

View file
     "Return to #{@ret_label}(#{@ret_offset}). CS=#{@cstack.to_a}"
   end
 
-  DC_PATTERN= Regexp.new /<DumpCall><int>(\d*)<\/int><string>([\w\d_]*)<\/string>(<Cstack>.*?<\/Cstack>)<\/DumpCall>/
+  DC_PATTERN= Regexp.new /<DumpCall><int>(\d*)<\/int><string>([\w\d_]*)<\/string>(<Classical>.*?<\/Classical>)<\/DumpCall>/
 end

File GUI/src/panels/executable_code/code_pointer.rb

View file
   attr_accessor :qpo_method
   attr_accessor :line_number
   def initialize(xml_string)
-    cp_match = CODE_POINTER_PATTERN.match xml_string
-    raise ModelCreateError, "code pointer xml was ill-formed"  if !cp_match
-    @qpo_method = cp_match[1].to_sym
-    @line_number = cp_match[2].to_i
+    cp_match = CodePointerParser.new xml_string
+    @qpo_method = cp_match.parsed_value[0]
+    @line_number = cp_match.parsed_value[1]
   end
 
   def normalize(max_plus_one)
     end
   end
 
-  CODE_POINTER_PATTERN = Regexp.new /^<pair><string>(.*?)<\/string><int>(\d*)<\/int><\/pair>$/
 end

File GUI/src/panels/executable_code/executable_code_model.rb

View file
 require 'panels/executable_code/code_pointer'
 
 class ExecutableCodeModel
-  include XmlDecode
   attr_accessor :the_code
   attr_accessor :the_code_pointer
   attr_accessor :the_code_was_updated
 
   def the_code=(xml_string)
-    @the_code = ExecutableCodeModel::code_xml_to_map(xml_string)
+    ecp = ExecutableCodeParser.new xml_string
+    @the_code = ecp.parsed_value
     raise ModelCreateError, "code xml was ill-formed" if !self.the_code
   end
 
     @the_code_was_updated
   end
 
-
-
-  def self.code_xml_to_map(xml_string)
-    return {} if ! xml_string or "" == xml_string
-    ret = {}
-    map_match = CODE_MAP_PATTERN.match xml_string
-    return nil if !map_match
-    ExecutableCodeModel.kv_pairs_to_map map_match[1]
-
-  end
-
-  def self.kv_pairs_to_map(kvps)
-    return {} if !kvps or kvps == ""
-    ret = {}
-    kvp = KVPAIRS_PATTERN.match kvps
-    return ret if !kvp
-    ret[kvp[1].to_sym] = ExecutableCodeModel::instructions_to_list(kvp[2])
-    matched_len = kvp[0].length
-    while kvp
-      kvp = KVPAIRS_PATTERN.match(kvps[matched_len,kvps.length])
-      return ret if !kvp
-      ret[kvp[1].to_sym] = ExecutableCodeModel::instructions_to_list(kvp[2])
-      matched_len += kvp[0].length
-    end
-  end
-
-  def self.instructions_to_list(instructions)
-    count = 0
-    values_to_list instructions, INSTRUCTIONS_PATTERN  do |ret, ins|
-      ret << sprintf("%3d  %s",count,ins[1])
-      count += 1
-    end
-  end
-
-
-  INSTRUCTIONS_PATTERN = Regexp.new /<i>(.*?)<\/i>/
-
-  CODE_MAP_PATTERN = Regexp.new /^<Code><map>(.*)<\/map><\/Code>$/
-  KVPAIRS_PATTERN = Regexp.new   /^<kvpair><key><string>(.*?)<\/string><\/key><value><instructions>(.*?)<\/instructions><\/value><\/kvpair>/
-
-
-
 end

File GUI/src/panels/parsers/abstract_list_pattern_parser.rb

View file
 class AbstractListPatternParser < AbstractPatternParser
-  include XmlDecode
   
   def initialize(instring)
     super(instring)
     @parsed_list
   end
   
+  def self.values_to_list(input,pattern,return_value=[])
+    #return [] if !input or "" == input
+    match_vals = pattern.match input
+    return return_value if ! match_vals
+    matched_len = match_vals[0].length
+    yield return_value,match_vals
+    while match_vals
+      match_vals = pattern.match input[matched_len, input.length]
+      return return_value if ! match_vals
+      matched_len += match_vals[0].length
+      yield return_value,match_vals
+    end
+  end
 end

File GUI/src/panels/parsers/classical_pattern_parser.rb

View file
 class ClassicalPatternParser < AbstractListPatternParser
   
   def self.top_level_regexp
-    Regexp.new /^<ClassicalStack>(?<classical_values>((<cint>(-?\d+)<\/cint>)|(<cbool>(True|False)<\/cbool>))*)<\/ClassicalStack>$/
+    Regexp.new /^<Classical>(?<classical_values>((<cint>(-?\d+)<\/cint>)|(<cbool>(True|False)<\/cbool>))*)<\/Classical>$/
   end
   
   LIST_PATTERN = Regexp.new /^(<cint>(?<int_value>-?\d+)<\/cint>)|(<cbool>(?<bool_value>True|False)<\/cbool>)/

File GUI/src/panels/parsers/code_pointer_parser.rb

View file
+class CodePointerParser < AbstractPatternParser
+  
+  def self.top_level_regexp
+    Regexp.new /^<pair><string>(?<key>.*?)<\/string><int>(?<value>\d*)<\/int><\/pair>$/
+  end
+  
+  def parsed_value
+    [@md[:key].to_sym,@md[:value].to_i]
+  end
+end

File GUI/src/panels/parsers/executable_code_parser.rb

View file
+class ExecutableCodeParser < AbstractListPatternParser
+  
+  def self.top_level_regexp
+    Regexp.new /^<Code><map>(?<code_map>(<kvpair><key><string>(.*?)<\/string><\/key><value><instructions>(<i>(.*?)<\/i>)*?<\/instructions><\/value><\/kvpair>)*?)<\/map><\/Code>$/
+  end
+  
+  def parse_list
+    ExecutableCodeParser::values_to_list @md[:code_map], KVPAIRS_PATTERN, {} do |retmap, kvpair|
+      retmap[kvpair[:code_key].to_sym] = ExecutableCodeParser::instructions_to_list kvpair[:instructions_list]
+    end
+  end
+    # 
+    # def self.kv_pairs_to_map(kvps)
+    #   return {} if !kvps or kvps == ""
+    #   ret = {}
+    #   kvp = KVPAIRS_PATTERN.match kvps
+    #   return ret if !kvp
+    #   ret[kvp[1].to_sym] = ExecutableCodeModel::instructions_to_list(kvp[2])
+    #   matched_len = kvp[0].length
+    #   while kvp
+    #     kvp = KVPAIRS_PATTERN.match(kvps[matched_len,kvps.length])
+    #     return ret if !kvp
+    #     ret[kvp[1].to_sym] = ExecutableCodeModel::instructions_to_list(kvp[2])
+    #     matched_len += kvp[0].length
+    #   end
+    # end
+
+  def self.instructions_to_list(instructions)
+    count = 0
+    self.values_to_list instructions, INSTRUCTIONS_PATTERN  do |ret, ins|
+      ret << sprintf("%3d  %s",count,ins[1])
+      count += 1
+    end
+  end
+
+
+  INSTRUCTIONS_PATTERN = Regexp.new /<i>(.*?)<\/i>/
+
+  KVPAIRS_PATTERN = Regexp.new   /^<kvpair><key><string>(?<code_key>.*?)<\/string><\/key><value><instructions>(?<instructions_list>(<i>(.*?)<\/i>)*?)<\/instructions><\/value><\/kvpair>/
+
+end

File GUI/src/panels/parsers/stack_translation_parser.rb

View file
+class StackTranslationParser < AbstractListPatternParser
+  
+  def self.top_level_regexp
+    Regexp.new /^<MMap>(?<maps>(<map>(<kvpair><key><string>(.*?)<\/string><\/key><value><int>(\d*)<\/int><\/value><\/kvpair>)*<\/map>)*)<\/MMap>$/
+  end
+  
+  def parse_list
+    values = @md[:maps]
+    StackTranslationParser.values_to_list values, LIST_PATTERN do |ret, mdata|
+      ret << StackTranslationParser::kv_pairs_to_map(mdata[:key_value_pairs])
+    end
+  end
+  
+
+  def self.kv_pairs_to_map(kvps)
+    self.values_to_list kvps, KVPATTERN, {} do |ret, mdkv|
+      ret[mdkv[:key].to_sym] = mdkv[:value].to_i
+    end
+  end
+  
+
+  LIST_PATTERN = Regexp.new /^<map>(?<key_value_pairs>(<kvpair><key><string>(.*?)<\/string><\/key><value><int>(\d*)<\/int><\/value><\/kvpair>)*)<\/map>/
+  KVPATTERN = Regexp.new /^<kvpair><key><string>(?<key>.*?)<\/string><\/key><value><int>(?<value>\d*)<\/int><\/value><\/kvpair>/
+
+end

File GUI/src/panels/quantum_stack/quantum_stack_model.rb

View file
       <int>(?<stackaddress>-?(\d)*)<\/int>  #Stackaddress ([1])
       <bool>(?<on_diagonal>(True)|(False))<\/bool> #on diagonal ([3])
       <substacks>(?<substacks>.*)<\/substacks> # the substacks ([6])
-      (?<descriptor>(<Zero\/>)|(<Value>.*<\/Value>)|(<Qubits>.*<\/Qubits>)|(<ClassicalStack>.*<\/ClassicalStack>)|(<AlgebraicData>.*<\/AlgebraicData>))  # stack descriptor [7]
+      (?<descriptor>(<Zero\/>)|(<Value>.*<\/Value>)|(<Qubits>.*<\/Qubits>)|(<Classical>.*<\/Classical>)|(<AlgebraicData>.*<\/AlgebraicData>))  # stack descriptor [7]
       <\/Qstack>/x
 
 

File GUI/src/panels/stack_translation/stack_translation_model.rb

View file
   attr_accessor :text
 
   def stack_translation=(in_mmap)
-    @stack_translation = StackTranslationModel::decode_mmap(in_mmap)
+    stp = StackTranslationParser.new in_mmap
+    @stack_translation = stp.parsed_value
     @reverse_translation = @stack_translation.reverse.inject({}) do |rev_map,st_map|
       rev_map.merge! st_map.invert
     end
     rmap[val.to_i].id2name
   end
 
-  def self.decode_mmap(in_mmap)
-    return [] if in_mmap == ""
-    ret = []
-    match_list_of_maps = MMAP_PATTERN.match in_mmap
-    raise ModelCreateError, in_mmap if !match_list_of_maps
-    lom = match_list_of_maps[1]
-    list_elem = LIST_ELEMENT_PATTERN.match(lom)
-    return [] if !list_elem
-    list_elems_len = list_elem[0].length
-    while list_elem
-      ret << StackTranslationModel::kv_pairs_to_map(list_elem[1])
-      list_elem = LIST_ELEMENT_PATTERN.match(lom[list_elems_len, lom.length])
-      return ret if !list_elem
-      list_elems_len += list_elem[0].length
-    end
-  end
-
-  def self.kv_pairs_to_map(kvps)
-    return {} if !kvps or kvps == ""
-    ret = {}
-    kvp = KVPATTERN.match kvps
-    return ret if !kvp
-    ret[kvp[1].to_sym] = kvp[2].to_i
-    matched_len = kvp[0].length
-    while kvp
-      kvp = KVPATTERN.match(kvps[matched_len,kvps.length])
-      return ret if !kvp
-      ret[kvp[1].to_sym] = kvp[2].to_i
-      matched_len += kvp[0].length
-    end
-  end
-
-  MMAP_PATTERN = Regexp.new /^<MMap>(.*)<\/MMap>$/
-  LIST_ELEMENT_PATTERN = Regexp.new /^<map>(.*?)<\/map>/
-  KVPATTERN = Regexp.new /^<kvpair><key><string>(.*?)<\/string><\/key><value><int>(\d*)<\/int><\/value><\/kvpair>/
 
 end