Commits

Brett Giles committed 6f20428

descriptor pattern parsers all separated from actual model.

Comments (0)

Files changed (48)

GUI/spec/controller/classical_stack_controller_spec.rb

     @c.set_classical_stack_data("<Cstack>"+cint(-27)+CIBT+cint(40)+CIBF+"</Cstack>")
     @c.get_classical_stack_data.should == "<html>-27<br />true<br />40<br />false</html>"
   end
-
-  it "should set the server_connection when given an sc" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    @c.lqpl_emulator_server_connection=sc
-  end
-  it "should ask the sc for the classical stack when given a depth and recursion" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    sc.should_receive(:get_classical_stack).and_return("<Cstack>"+CIBT+"</Cstack>")
-
-    @c.lqpl_emulator_server_connection=sc
-    @c.set_classical_stack("5","4")
-    @c.get_classical_stack_data.should == "<html>true</html>"
-  end
+  # it "should ask the sc for the classical stack when given a depth and recursion" do
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     sc.should_receive(:get_classical_stack).and_return("<Cstack>"+CIBT+"</Cstack>")
+  # 
+  #     @c.lqpl_emulator_server_connection=sc
+  #     @c.set_classical_stack("5","4")
+  #     @c.get_classical_stack_data.should == "<html>true</html>"
+  #   end
 end

GUI/spec/controller/dump_controller_spec.rb

     @c.get_dump_data.should == "<html><ol><li>Return to Ret(5). CS=[]</li></ol></html>"
   end
 
-  it "should set the server_connection when given an sc" do
-
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    @c.lqpl_emulator_server_connection=sc
-  end
-  it "should ask the sc for the dump when given a depth and recursion" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    sc.should_receive(:get_dump).and_return("<Dump></Dump>")
-
-    @c.lqpl_emulator_server_connection=sc
-    @c.set_dump("5","4")
-  end
+  # it "should ask the sc for the dump when given a depth and recursion" do
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     sc.should_receive(:get_dump).and_return("<Dump></Dump>")
+  # 
+  #     @c.lqpl_emulator_server_connection=sc
+  #     @c.set_dump("5","4")
+  #   end
 end

GUI/spec/controller/quantum_stack_controller.rb

-require 'spec/spec_helper'
-
-require 'spec/specdata/quantum_stack_data'
-require 'src/panels/quantum_stack/quantum_stack_controller'
-require 'src/panels/quantum_stack/quantum_stack_model'
-
-describe QuantumStackController do
-  before(:each) do
-    @d = QuantumStackController.instance
-  end
-
-  it "should set the server_connection when given an sc" do
-
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    @d.lqpl_emulator_server_connection=sc
-  end
-  it "should ask the sc for the quantum stack and the st model for a num when given a depth and recursion and st" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    sc.should_receive(:get_qstack).and_return(QB2WITHBOTTOM)
-
-    st = double("StackTranslation", :nil? => false)
-    st.should_receive(:reverse_lookup).and_return("p")
-
-    @d.lqpl_emulator_server_connection=sc
-    @d.set_quantum_stack("5","4",st)
-
-  end
-end

GUI/spec/controller/quantum_stack_controller_spec.rb

+require 'spec/spec_helper'
+
+require 'spec/specdata/quantum_stack_data'
+require 'src/panels/quantum_stack/quantum_stack_controller'
+require 'src/panels/quantum_stack/quantum_stack_model'
+
+describe QuantumStackController do
+  before(:each) do
+    @d = QuantumStackController.instance
+  end
+
+  # it "should set the server_connection when given an sc" do
+  # 
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     @d.lqpl_emulator_server_connection=sc
+  #   end
+  #   it "should ask the sc for the quantum stack and the st model for a num when given a depth and recursion and st" do
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     sc.should_receive(:get_qstack).and_return(QB2WITHBOTTOM)
+  # 
+  #     st = double("StackTranslation", :nil? => false)
+  #     st.should_receive(:reverse_lookup).and_return("p")
+  # 
+  #     @d.lqpl_emulator_server_connection=sc
+  #     @d.set_quantum_stack("5","4",st)
+  # 
+  #   end
+end

GUI/spec/controller/simulate_results_controller_spec.rb

 
   end
   it "should raise an error when created with junk" do
-    expect { @c.set_simulate_data("junk",@st)}. to raise_error   QuantumStackModelInvalidCreate, /junk/
+    expect { @c.set_simulate_data("junk",@st)}. to raise_error   ModelCreateError, /junk/
   end
 
   it "should create a results set when given the correct input" do
     @c.get_simulate_data.should == "<html>@p(Coin) = Heads<br />@q(qubit) = 0</html>"
   end
 
-  it "should set the server_connection when given an sc" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    @c.lqpl_emulator_server_connection=sc
-  end
-  it "should ask the sc for the classical stack when given a depth and recursion" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    sc.should_receive(:get_simulate_results).and_return(TWOELTS)
-
-    @c.lqpl_emulator_server_connection=sc
-    @c.set_simulate_results("5",@st)
-    @c.get_simulate_data.should == "<html>@p(Coin) = Heads<br />@q(qubit) = 0</html>"
-  end
+  # it "should set the server_connection when given an sc" do
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     @c.lqpl_emulator_server_connection=sc
+  #   end
+  #   it "should ask the sc for the classical stack when given a depth and recursion" do
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     sc.should_receive(:get_simulate_results).and_return(TWOELTS)
+  # 
+  #     @c.lqpl_emulator_server_connection=sc
+  #     @c.set_simulate_results("5",@st)
+  #     @c.get_simulate_data.should == "<html>@p(Coin) = Heads<br />@q(qubit) = 0</html>"
+  #   end
 end

GUI/spec/controller/stack_translation_controller_spec.rb

     @d.get_stack_translation_text.should == "<html><ol><li>p=>1</li></ol></html>"
   end
 
-  it "should set the server_connection when given an sc" do
-
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    @d.lqpl_emulator_server_connection=sc
-  end
-  it "should ask the sc for the stack translation when given a depth and recursion" do
-    sc = double('server_connection')
-    sc.should_receive(:connected?).and_return(true)
-    sc.should_receive(:get_stack_translation).and_return(P1)
-
-    @d.lqpl_emulator_server_connection=sc
-    @d.set_stack_translation("5","4")
-  end
+  # it "should set the server_connection when given an sc" do
+  # 
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     @d.lqpl_emulator_server_connection=sc
+  #   end
+  #   it "should ask the sc for the stack translation when given a depth and recursion" do
+  #     sc = double('server_connection')
+  #     sc.should_receive(:connected?).and_return(true)
+  #     sc.should_receive(:get_stack_translation).and_return(P1)
+  # 
+  #     @d.lqpl_emulator_server_connection=sc
+  #     @d.set_stack_translation("5","4")
+  #   end
   it "should return a stack translation model" do
     @d.set_stack_translation_data(P1)
     @d.get_stack_translation.stack_translation.should == [{:p=>1}]

GUI/spec/model/descriptor_model_spec.rb

   it  "should raise an error if constructed with something other than <ClassicalStack>list of ints or bools</ClassicalStack>" do
     expect {
       sc = AbstractDescriptorModel.make_instance "<ClassicalStack>err</ClassicalStack>"
-    }.to raise_error(ModelCreateError, /<ClassicalStack>err<\/ClassicalStack>/)
+    }.to raise_error(ParserError, /<ClassicalStack>err<\/ClassicalStack>/)
   end
   it  "should have a length equal to the number of elements of the passed in list" do
     sd = AbstractDescriptorModel.make_instance "<ClassicalStack><cint>14</cint></ClassicalStack>"
     sd = AbstractDescriptorModel.make_instance "<ClassicalStack><cint>1</cint><cbool>True</cbool><cint>14</cint></ClassicalStack>"
     sd.substack_labels.should == ["1","true","14"]
   end
-
-  context "list matching" do
-    it "should raise an error when the list is invalid" do
-      expect {
-        ClassicalDescriptorModel::parse_list("invalid")
-      }.to raise_error(ModelCreateError, "invalid")
-    end
-    it "should prepare a list of length 0 when there is no list" do
-      ClassicalDescriptorModel::parse_list("").should == []
-    end
-    it "should result in a one element int list when that is the only input" do
-      ClassicalDescriptorModel::parse_list("<cint>1</cint>").should == [1]
-      ClassicalDescriptorModel::parse_list("<cint>-3491</cint>").should == [-3491]
-    end
-    it "should result in a one element bool list when that is the only input" do
-      ClassicalDescriptorModel::parse_list("<cbool>True</cbool>").should == [true]
-      ClassicalDescriptorModel::parse_list("<cbool>False</cbool>").should == [false]
-    end
-    it "should result in a mixed list when that is the same input" do
-      ClassicalDescriptorModel::parse_list("<cint>1</cint><cbool>True</cbool><cint>14</cint>").should == [1,true,14]
+  context "class methods" do
+    context "validation" do
+      it "should not raise an error if passed an array with elements" do
+         ClassicalDescriptorModel.validate_substacks_count([1,2]).should be_nil
+      end
+      it "should raise an error if passed an empty array" do
+        expect {
+          ClassicalDescriptorModel.validate_substacks_count([])
+        }.to raise_error ModelCreateError, /Classical.*should have/
+      end
+      it "should raise an error if passed a nil array" do
+        expect {
+          ClassicalDescriptorModel.validate_substacks_count(nil)
+        }.to raise_error ModelCreateError, /Classical.*should have/
+      end
     end
   end
 end
 
 
 describe DataDescriptorModel do
-  it  "should raise an error if constructed with something other than <AlgebraicData>list of z,o pairs</AlgebraicData>" do
+  it  "should raise an error if constructed with something other than <AlgebraicData>list of pairs</AlgebraicData>" do
     expect {
       sc = AbstractDescriptorModel.make_instance "<AlgebraicData>err</AlgebraicData>"
-    }.to raise_error(ModelCreateError, /<AlgebraicData>err<\/AlgebraicData>/)
+    }.to raise_error(ParserError, /<AlgebraicData>err<\/AlgebraicData>/)
   end
   it  "should have a length equal to the number of elements of the passed in list" do
     sd = AbstractDescriptorModel.make_instance "<AlgebraicData><string>Nil</string><StackAddresses></StackAddresses></AlgebraicData>"
     sd = AbstractDescriptorModel.make_instance "<AlgebraicData><string>Nil</string><StackAddresses></StackAddresses><string>C</string><StackAddresses><int>3</int><int>4</int></StackAddresses></AlgebraicData>"
     sd.substack_labels.should == ["Nil", "C[3, 4]"]
   end
-  context "constructor matching" do
-    it "should raise an error when the constructor map is invalid" do
-      expect {
-        DataDescriptorModel::parse_pairs("invalid")
-      }.to raise_error(InvalidInput, "invalid")
-    end
-    it "should raise an error when there is no constructor" do
-      expect {
-        DataDescriptorModel::parse_pairs("")
-      }.to raise_error(InvalidInput, "Must have at least one constructor")
-    end
-    it "should result in a one element array of pairs when that is the only input" do
-      DataDescriptorModel::parse_pairs("<string>C</string><StackAddresses><int>3</int><int>4</int></StackAddresses>").should == [["C",[3,4]]]
-    end
-    it "should result in a mixed map when that is the input" do
-      DataDescriptorModel::parse_pairs("<string>Nil</string><StackAddresses></StackAddresses><string>C</string><StackAddresses><int>3</int><int>4</int></StackAddresses>").should ==
-       [["Nil",[]], ["C" , [3,4]]]
-    end
-    it "should raise an error when the map has duplicated constructors" do
-      expect {
-        DataDescriptorModel::parse_pairs("<string>Nil</string><StackAddresses></StackAddresses><string>Nil</string><StackAddresses></StackAddresses>")
-      }.to raise_error(InvalidInput, "Constructor 'Nil' duplicated in algebraic data")
-    end
-  end
-  context "address list matching" do
-    it "should raise an error when the list is invalid" do
-      expect {
-        DataDescriptorModel::parse_address_list("invalid")
-      }.to raise_error(InvalidInput, "invalid")
-    end
-    it "should result in an empty list when there is no input" do
-      DataDescriptorModel::parse_address_list("").should ==  []
-    end
-    it "should result in a one element list when that is the only input" do
-      DataDescriptorModel::parse_address_list("<int>3</int>").should ==  [3]
-    end
-    it "should result in a many element list when that is the input" do
-      DataDescriptorModel::parse_address_list("<int>3</int><int>4</int><int>5</int><int>6</int><int>7</int>").should ==  [3,4,5,6,7]
-    end
-    it "should raise an error when the list has duplicated elements" do
-      expect {
-        DataDescriptorModel::parse_address_list("<int>3</int><int>3</int>")
-      }.to raise_error(InvalidInput, "StackAddress '3' duplicated for single constructor")
+  
+  context "class methods" do
+    context "validation" do
+      it "should not raise an error if passed an array with elements" do
+          DataDescriptorModel.validate_substacks_count([1,2]).should be_nil
+      end
+      it "should raise an error if passed an empty array" do
+        expect {
+          DataDescriptorModel.validate_substacks_count([])
+        }.to raise_error ModelCreateError, /Data.*should have/
+      end
+      it "should raise an error if passed a nil array" do
+        expect {
+          DataDescriptorModel.validate_substacks_count(nil)
+        }.to raise_error ModelCreateError, /Data.*should have/
+      end
     end
   end
+  
+  
 end
 
 
   it  "should raise an error if constructed with something other than <Qubits>list of z,o pairs</Qubits>" do
     expect {
       sc = AbstractDescriptorModel.make_instance "<Qubits>err</Qubits>"
-    }.to raise_error(ModelCreateError, /<Qubits>err<\/Qubits>/)
+    }.to raise_error(ParserError, /<Qubits>err<\/Qubits>/)
   end
   it  "should have a length equal to the number of elements of the passed in list" do
     sd = AbstractDescriptorModel.make_instance "<Qubits><pair><qz/><qz/></pair></Qubits>"
     sd = AbstractDescriptorModel.make_instance "<Qubits><pair><qz/><qz/></pair><pair><qz/><qo/></pair><pair><qo/><qz/></pair><pair><qo/><qo/></pair></Qubits>"
     sd.substack_labels.should == ["00","01","10","11"]
   end
-  context "list matching" do
-    it "should raise an error when the list is invalid" do
-      expect {
-        QubitDescriptorModel::parse_list("invalid")
-      }.to raise_error(InvalidInput, "invalid")
-    end
-    it "should raise and error when there is no list" do
-      expect {
-        QubitDescriptorModel::parse_list("")
-      }.to raise_error(InvalidInput, "Must have qubit indicators")
-    end
-    it "should result in a one element pair list when that is the only input" do
-      QubitDescriptorModel::parse_list("<pair><qz/><qz/></pair>").should == [[0,0]]
-    end
-    it "should result in a mixed list when that is the same input" do
-      QubitDescriptorModel::parse_list("<pair><qz/><qz/></pair><pair><qz/><qo/></pair>").should == [[0,0],[0,1]]
-    end
-    it "should raise an error when the list has duplicated pairs" do
-      expect {
-        QubitDescriptorModel::parse_list("<pair><qz/><qz/></pair><pair><qz/><qz/></pair>")
-      }.to raise_error(InvalidInput, "[0, 0] duplicated in qubit")
-    end
-  end
-  context "translate qubit" do
-    it "should return 1 for <qo/>" do
-      QubitDescriptorModel::translate_qubit("<qo/>").should == 1
-    end
-    it "should return 0 for <qz/>" do
-      QubitDescriptorModel::translate_qubit("<qz/>").should == 0
-    end
-    it "should raise an exception for any other input" do
-      expect {
-        QubitDescriptorModel::translate_qubit("err")
-      }.to raise_error InvalidInput, /err/
+  context "class methods" do
+    context "validation" do
+      it "should not raise an error if passed an array with 1 element" do
+          QubitDescriptorModel.validate_substacks_count([1]).should be_nil
+      end
+      it "should not raise an error if passed an array with 2 elements" do
+          QubitDescriptorModel.validate_substacks_count([1,2]).should be_nil
+      end
+      it "should not raise an error if passed an array with 3 elements" do
+          QubitDescriptorModel.validate_substacks_count([1,2,3]).should be_nil
+      end
+      it "should not raise an error if passed an array with 4 elements" do
+          QubitDescriptorModel.validate_substacks_count([1,2,3,4]).should be_nil
+      end
+      it "should raise an error if passed an empty array" do
+        expect {
+          QubitDescriptorModel.validate_substacks_count([])
+        }.to raise_error ModelCreateError, /Qubit.*should have/
+      end
+      it "should raise an error if passed a nil array" do
+        expect {
+          QubitDescriptorModel.validate_substacks_count(nil)
+        }.to raise_error ModelCreateError, /Qubit.*should have/
+      end
+      it "should raise an error if passed an array with > 4 elements" do
+        expect {
+          QubitDescriptorModel.validate_substacks_count([1,2,3,4,5])
+        }.to raise_error ModelCreateError, /Qubit.*should have/
+      end
     end
   end
 end
 
 
 describe ValueDescriptorModel do
-  it "should always have a length of 0" do
-    sd = AbstractDescriptorModel.make_instance "<Value>0.5</Value>"
-    sd.length.should == 0
+  it "should successfully be created with input '<Value>0.5</Value>'" do
+    z = ValueDescriptorModel.new '<Value>0.5</Value>'
+    z.should_not be_nil
   end
-
-  it "should have the value in the construction string" do
-    sd = AbstractDescriptorModel.make_instance "<Value>6.25e-2</Value>"
-    sd.value.should == "6.25e-2"
-  end
-  it "should allow a number tag to surround the data" do
-    sd = AbstractDescriptorModel.make_instance "<Value><number>0.32</number></Value>"
-    sd.value.should == "0.32"
-  end
-  it "should have no name" do
-    sd = AbstractDescriptorModel.make_instance "<Value>0.5</Value>"
-    sd.name.should be_nil
+  it "should raise an error on other input" do
+    expect {
+      ValueDescriptorModel.new "<Value><Cint>4</Cint></Value>"
+    }.to raise_error ParserError, /Value/
+    expect {
+      ValueDescriptorModel.new "whatever"
+    }.to raise_error ParserError, /whatever/
+  end
+  context "class methods" do
+    context "validation" do
+      it "should raise an error if passed an array with elements" do
+        expect {
+          ValueDescriptorModel.validate_substacks_count([1,2])
+        }.to raise_error ModelCreateError, /Value.*should not have/
+      end
+      it "should not raise an error if passed an empty array" do
+          ValueDescriptorModel.validate_substacks_count([]).should be_nil
+      end
+      it "should not raise an error if passed an array with no elements" do
+          ValueDescriptorModel.validate_substacks_count(nil).should be_nil
+      end
+    end
   end
-
-
-  it "should return 'nil' when asked for substack labels" do
-    sd = AbstractDescriptorModel.make_instance "<Value><number>0.32</number></Value>"
-    sd.substack_labels.should be_nil
+  context 'attributes' do
+    it "should always have a length of 0" do
+      sd = AbstractDescriptorModel.make_instance "<Value>0.5</Value>"
+      sd.length.should == 0
+    end
+    it "should have the value in the construction string" do
+      sd = AbstractDescriptorModel.make_instance "<Value>6.25e-2</Value>"
+      sd.value.should == 6.25e-2
+    end
+    it "should allow a number tag to surround the data" do
+      sd = AbstractDescriptorModel.make_instance "<Value><number>0.32</number></Value>"
+      sd.value.should == 0.32
+    end
+    it "should have no name" do
+      sd = AbstractDescriptorModel.make_instance "<Value>0.5</Value>"
+      sd.name.should be_nil
+    end
+    it "should return 'nil' when asked for substack labels" do
+      sd = AbstractDescriptorModel.make_instance "<Value><number>0.32</number></Value>"
+      sd.substack_labels.should be_nil
+    end
   end
 end
 
 
 describe ZeroDescriptorModel do
-  it "should always have a length of 0" do
-    sd = AbstractDescriptorModel.make_instance "<Zero/>"
-    sd.length.should == 0
+  it "Should create when given no input" do
+    z = ZeroDescriptorModel.new
+    z.should_not be_nil
+  end
+  it "should successfully be created with input '<Zero/>'" do
+    z = ZeroDescriptorModel.new '<Zero/>'
+    z.should_not be_nil
   end
-  it "should raise an error if constructed with something other than <Zero/>" do
+  it "should raise an error on other input" do
     expect {
-      sd = AbstractDescriptorModel.make_instance "<Zero>"
-    }.to raise_error(ModelCreateError, /<Zero>/)
+      ZeroDescriptorModel.new "<Value><Cint>4</Cint></Value>"
+    }.to raise_error ParserError, /Value/
     expect {
-      sd = ZeroDescriptorModel.new "wrong"
-    }.to raise_error(ModelCreateError, /wrong/)
-  end
-  it "should have no name" do
-    sd = AbstractDescriptorModel.make_instance "<Zero/>"
-    sd.name.should be_nil
-  end
-
-  it "should return 'nil' when asked for substack labels" do
-    sd = AbstractDescriptorModel.make_instance "<Zero/>"
-    sd.substack_labels.should be_nil
+      ZeroDescriptorModel.new "whatever"
+    }.to raise_error ParserError, /whatever/
+  end
+  context "class methods" do
+    context "validation" do
+      it "should raise an error if passed an array with elements" do
+        expect {
+          ZeroDescriptorModel.validate_substacks_count([1,2])
+        }.to raise_error ModelCreateError, /Zero.*should not have/
+      end
+      it "should not raise an error if passed an empty array" do
+          ZeroDescriptorModel.validate_substacks_count([]).should be_nil
+      end
+      it "should not raise an error if passed an array with no elements" do
+          ZeroDescriptorModel.validate_substacks_count(nil).should be_nil
+      end
+    end
   end
-
+  context "attributes" do
+    before(:each) do
+      @z = ZeroDescriptorModel.new
+    end
+    it "should have a value of '0'" do
+      @z.value.should == "0"
+    end
+    it "should have a length of 0" do
+      @z.length.should == 0
+    end
+    it "should have no name" do
+      @z.name.should be_nil
+    end
+    it "should return 'nil' when asked for substack labels" do
+      @z.substack_labels.should be_nil
+    end
+ end
 end
 

GUI/spec/model/executable_code_model_spec.rb

 require 'spec/spec_helper'
 require 'src/panels/executable_code/executable_code_model'
-require 'src/exceptions/quantum_stack_model_invalid_create'
 
 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>'
         @ecm = ExecutableCodeModel.new
       end
       it "should throw an exception with bad input" do
-        expect {@ecm.the_code="junk"}.to raise_error QuantumStackModelInvalidCreate, /code xml/
+        expect {@ecm.the_code="junk"}.to raise_error ModelCreateError, /code xml/
       end
       it "should return the created code map when given correct input" do
         @ecm.the_code=CMAP_2
         @ecm = ExecutableCodeModel.new
       end
       it "should throw an exception with bad input" do
-        expect {@ecm.the_code_pointer="junk"}.to raise_error QuantumStackModelInvalidCreate, /code pointer xml/
+        expect {@ecm.the_code_pointer="junk"}.to raise_error ModelCreateError, /code pointer xml/
       end
       it "should return the created code map when given correct input when there is code" do
         @ecm.the_code=CMAP_2
 describe CodePointer do
   describe "creation" do
     it "should throw an exception with bad input" do
-      expect {CodePointer.new("junk")}.to raise_error QuantumStackModelInvalidCreate, /code pointer xml/
+      expect {CodePointer.new("junk")}.to raise_error ModelCreateError, /code pointer xml/
     end
     it "should throw an exception with nil input" do
-      expect {CodePointer.new(nil)}.to raise_error QuantumStackModelInvalidCreate, /code pointer xml/
+      expect {CodePointer.new(nil)}.to raise_error ModelCreateError, /code pointer xml/
     end
     it "should throw an exception with blank input" do
-      expect {CodePointer.new("")}.to raise_error QuantumStackModelInvalidCreate, /code pointer xml/
+      expect {CodePointer.new("")}.to raise_error ModelCreateError, /code pointer xml/
     end
     it "should create a CodePointer instance with correct input " do
       @cp = CodePointer.new("<pair><string>main</string><int>0</int></pair>")

GUI/spec/model/quantum_stack_model_spec.rb

     it "should give an invalid create error when created with incorrect data" do
       expect {
         @qs.quantum_stack = "err"
-      }.to raise_error QuantumStackModelInvalidCreate, /err/
+      }.to raise_error ModelCreateError, /err/
     end
     it "should give an error when stackzero has substacks" do
       expect {
         @qs.quantum_stack = "<Qstack><int>1</int><bool>True</bool><substacks><bottom/></substacks><Zero/></Qstack>"
-      }.to raise_error QuantumStackModelInvalidCreate, /not have/
+      }.to raise_error ModelCreateError, /not have/
     end
     it "should give an error when stackvalue has substacks" do
       expect {
         @qs.quantum_stack = "<Qstack><int>1</int><bool>True</bool><substacks><bottom/></substacks><Value>0.5</Value></Qstack>"
-      }.to raise_error QuantumStackModelInvalidCreate, /not have/
+      }.to raise_error ModelCreateError, /not have/
     end
     it "should give an error when stackqubit does not have substacks" do
       expect {
         @qs.quantum_stack = "<Qstack><int>1</int><bool>True</bool><substacks></substacks><Qubits><pair><qz/><qz/></pair></Qubits></Qstack>"
-      }.to raise_error QuantumStackModelInvalidCreate, /should have/
+      }.to raise_error ModelCreateError, /should have/
     end
     it "should give an error when stackclassical does not have substacks"  do
       expect {
         @qs.quantum_stack = "<Qstack><int>1</int><bool>True</bool><substacks></substacks><ClassicalStack><cint>14</cint></ClassicalStack></Qstack>"
-      }.to raise_error QuantumStackModelInvalidCreate, /should have/
+      }.to raise_error ModelCreateError, /should have/
     end
     it "should give an error when stackdata does not have substacks" do
       expect {
         @qs.quantum_stack = "<Qstack><int>1</int><bool>True</bool><substacks></substacks><AlgebraicData><string>Nil</string><StackAddresses></StackAddresses></AlgebraicData></Qstack>"
-      }.to raise_error QuantumStackModelInvalidCreate, /should have/
+      }.to raise_error ModelCreateError, /should have/
     end
     it "should successfully create the start qstack" do
       @qs.quantum_stack = "<Qstack><int>-1</int><bool>True</bool><substacks></substacks><Value><number>1.0</number></Value></Qstack>"
     expect {
         qs = QuantumStackModel.new
         qs.quantum_stack = "<Qstack><int>1</int><bool>True</bool><substacks><bottom/></substacks><Zero/></Qstack>"
-      }.to raise_error QuantumStackModelInvalidCreate, /Missing/
+      }.to raise_error ModelCreateError, /Missing/
   end
   it "should assign a name for a quantum descriptor" do
     qs = QuantumStackModel.new

GUI/spec/model/simulate_results_model_spec.rb

     it "should throw an error if given invalid input" do
       expect {
         @m.simulate_results = "junk"
-      }.to raise_error  QuantumStackModelInvalidCreate, /junk/
+      }.to raise_error  ModelCreateError, /junk/
     end
     it "should set the text or the random value to 'Random Value: rv" do
       @m.simulate_results =ONEELT

GUI/spec/model/stack_translation_model_spec.rb

     expect {
       s = StackTranslationModel.new
       s.stack_translation= "err"
-    }.to raise_error QuantumStackModelInvalidCreate, /err/
+    }.to raise_error ModelCreateError, /err/
   end
   it "should create a text representation in its text attribute" do
     s = StackTranslationModel.new

GUI/spec/parsers/abstract_pattern_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe AbstractPatternParser do
+  it "should parse only an empty string" do
+    p = AbstractPatternParser.new ""
+    p.parsed?.should be_true
+  end
+  it "should raise an error for other string" do
+    expect {
+      AbstractPatternParser.new "<Zero/>"
+    }.to raise_error ParserError, /Zero/
+    expect {
+      AbstractPatternParser.new "whatever"
+    }.to raise_error ParserError, /whatever/
+  end
+end

GUI/spec/parsers/classical_pattern_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe ClassicalPatternParser do
+  it  "should raise an error if constructed with something other than <ClassicalStack>list of ints or bools</ClassicalStack>" do
+    expect {
+      ClassicalPatternParser.new "<ClassicalStack>err</ClassicalStack>"
+    }.to raise_error(ParserError, /<ClassicalStack>err<\/ClassicalStack>/)
+  end
+  
+  context "list matching" do
+    it "should raise an error when the list is invalid" do
+      expect {
+        ClassicalPatternParser.new("<ClassicalStack>invalid<\/ClassicalStack>")
+      }.to raise_error(ParserError, /invalid/)
+    end
+    it "should result in a one element int list [1] when that is the only input" do
+      cpp= ClassicalPatternParser.new("<ClassicalStack><cint>1</cint><\/ClassicalStack>")
+      cpp.parsed_value.should == [1]
+    end
+    it "should result in a one element int list [-3491] when that is the only input" do
+      cpp= ClassicalPatternParser.new("<ClassicalStack><cint>-3491</cint><\/ClassicalStack>")
+      cpp.parsed_value.should == [-3491]
+    end
+    it "should result in a one element bool list [true] when that is the only input" do
+      cpp= ClassicalPatternParser.new("<ClassicalStack><cbool>True</cbool><\/ClassicalStack>")
+      cpp.parsed_value.should == [true]
+    end
+    it "should result in a one element int list [false] when that is the only input" do
+      cpp= ClassicalPatternParser.new("<ClassicalStack><cbool>False</cbool><\/ClassicalStack>")
+      cpp.parsed_value.should == [false]
+    end
+    it "should result in a mixed list [1,true,14] when that is the input" do
+      cpp= ClassicalPatternParser.new("<ClassicalStack><cint>1</cint><cbool>True</cbool><cint>14</cint><\/ClassicalStack>")
+      cpp.parsed_value.should == [1,true,14]
+    end
+  end
+end

GUI/spec/parsers/data_pattern_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe DataPatternParser do
+  it  "should raise an error if constructed with something other than <AlgebraicData>list of pairs</AlgebraicData>" do
+    expect {
+      DataPatternParser.new "<AlgebraicData>err</AlgebraicData>"
+    }.to raise_error(ParserError, /<AlgebraicData>err<\/AlgebraicData>/)
+  end
+  context "constructor matching" do
+    it "should raise an error when the constructor map is invalid" do
+      expect {
+        DataPatternParser.new("<AlgebraicData>invalid<\/AlgebraicData>")
+      }.to raise_error(ParserError, /invalid/)
+    end
+    it "should raise an error when there is no constructor" do
+      expect {
+        DataPatternParser.new("<AlgebraicData><\/AlgebraicData>")
+      }.to raise_error(ParserError, /No match/)
+    end
+    it "should result in a one element array of pairs when that is the only input" do
+      dpp = DataPatternParser.new("<AlgebraicData><string>C</string><StackAddresses><int>3</int><int>4</int></StackAddresses><\/AlgebraicData>")
+      dpp.parsed_value.should == [["C",[3,4]]]
+    end
+    it "should result in a mixed map when that is the input" do
+      dpp = DataPatternParser.new("<AlgebraicData><string>Nil</string><StackAddresses></StackAddresses><string>C</string><StackAddresses><int>3</int><int>4</int></StackAddresses><\/AlgebraicData>")
+      dpp.parsed_value.should == [["Nil",[]], ["C" , [3,4]]]
+    end
+    it "should raise an error when the map has duplicated constructors" do
+      expect {
+        DataPatternParser.new("<AlgebraicData><string>Nil</string><StackAddresses></StackAddresses><string>Nil</string><StackAddresses></StackAddresses><\/AlgebraicData>")
+      }.to raise_error(InvalidInput, "Constructor 'Nil' duplicated in algebraic data")
+    end
+  end
+  context "address list matching" do
+    it "should result in an empty list when there is no input" do
+      DataPatternParser::parse_address_list("").should ==  []
+    end
+    it "should result in a one element list when that is the only input" do
+      DataPatternParser::parse_address_list("<int>3</int>").should ==  [3]
+    end
+    it "should result in a many element list when that is the input" do
+      DataPatternParser::parse_address_list("<int>3</int><int>4</int><int>5</int><int>6</int><int>7</int>").should ==  [3,4,5,6,7]
+    end
+    it "should raise an error when the list has duplicated elements" do
+      expect {
+        DataPatternParser::parse_address_list("<int>3</int><int>3</int>")
+      }.to raise_error(InvalidInput, "StackAddress '3' duplicated for single constructor")
+    end
+  end
+end

GUI/spec/parsers/qubit_pattern_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe QubitPatternParser do
+  it  "should raise an error if constructed with something other than <Qubits>list of z,o pairs</Qubits>" do
+    expect {
+      QubitPatternParser.new "<Qubits>err</Qubits>"
+    }.to raise_error(ParserError, /<Qubits>err<\/Qubits>/)
+  end
+  it "should have the value being the list of qubit indicators in the string" do
+    qpp = QubitPatternParser.new "<Qubits><pair><qz/><qz/></pair><pair><qz/><qo/></pair><pair><qo/><qz/></pair><pair><qo/><qo/></pair></Qubits>"
+    qpp.parsed_value.should == [[0,0],[0,1],[1,0],[1,1]]
+  end
+  context "list matching" do
+    it "should result in a one element pair list when that is the only input" do
+      qpp = QubitPatternParser.new "<Qubits><pair><qz/><qz/></pair></Qubits>"
+      qpp.parse_list.should == [[0,0]]
+    end
+    it "should result in a mixed list when that is the same input" do
+      qpp = QubitPatternParser.new "<Qubits><pair><qz/><qz/></pair><pair><qz/><qo/></pair></Qubits>"
+      qpp.parse_list.should == [[0,0],[0,1]]
+    end
+    it "should raise an error when the list has duplicated pairs" do
+      expect {
+        QubitPatternParser.new "<Qubits><pair><qz/><qz/></pair><pair><qz/><qz/></pair></Qubits>"
+       # qpp.parse_list("<pair><qz/><qz/></pair><pair><qz/><qz/></pair>")
+      }.to raise_error(InvalidInput, "[0, 0] duplicated in qubit")
+    end
+  end
+  context "translate qubit" do
+    it "should return 1 for <qo/>" do
+      QubitPatternParser::translate_qubit("<qo/>").should == 1
+    end
+    it "should return 0 for <qz/>" do
+      QubitPatternParser::translate_qubit("<qz/>").should == 0
+    end
+    it "should raise an exception for any other input" do
+      expect {
+        QubitPatternParser::translate_qubit("err")
+      }.to raise_error InvalidInput, /err/
+    end
+  end
+end

GUI/spec/parsers/value_pattern_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe ValuePatternParser do
+  it "should successfully parse VALUE-number-VALUE '<Value>1.0</Value>'" do
+    p = ValuePatternParser.new "<Value>1.0</Value>"
+    p.parsed?.should be_true
+  end
+  it "should successfully parse VALUE-NUMBER-number-NUMBER-VALUE '<Value><number>0.3846298001</number></Value>'" do
+    p = ValuePatternParser.new "<Value>0.3846298001</Value>"
+    p.parsed?.should be_true
+  end
+  it "should successfully parse VALUE-NUMBER-enumber-NUMBER-VALUE '<Value>6.25e-2</Value>'" do
+    p = ValuePatternParser.new "<Value>6.25e-2</Value>"
+    p.parsed?.should be_true
+  end
+  it "should raise an error if the value is > 1" do
+    expect {
+      ValuePatternParser.new "<Value>1.1</Value>"
+    }.to raise_error ParserError, /1.1/
+  end
+  it "should raise an error if the value is < 0" do
+    expect {
+      ValuePatternParser.new "<Value>-0.5</Value>"
+    }.to raise_error ParserError, /-0.5/
+  end
+  it "should raise an error for any other string" do
+    expect {
+      ValuePatternParser.new "<Value><Cint>4</Cint></Value>"
+    }.to raise_error ParserError, /Value/
+    expect {
+      ValuePatternParser.new "whatever"
+    }.to raise_error ParserError, /whatever/
+  end
+  context "parsed value" do
+    it "should return the 1 for input <Value>1.0</Value>" do
+      p = ValuePatternParser.new "<Value>1.0</Value>"
+      p.parsed_value.should == 1.0
+    end
+    it "should return the value 0.3846298001  for input '<Value><number>0.3846298001</number></Value>'" do
+      p = ValuePatternParser.new '<Value><number>0.3846298001</number></Value>'
+      p.parsed_value.should == 0.3846298001
+    end
+    it "should return the value 6.25e-2  for input '<Value><number>6.25e-2</number></Value>'" do
+      p = ValuePatternParser.new '<Value><number>6.25e-2</number></Value>'
+      p.parsed_value.should == 6.25e-2
+    end
+  end
+end

GUI/spec/parsers/zero_pattern_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe ZeroPatternParser do
+  it "should successfully parse only '<Zero/>'" do
+    p = ZeroPatternParser.new "<Zero/>"
+    p.parsed?.should be_true
+  end
+  it "should raise an error for any other string" do
+    expect {
+      ZeroPatternParser.new "<Value><Cint>4</Cint></Value>"
+    }.to raise_error ParserError, /Value/
+    expect {
+      ZeroPatternParser.new "whatever"
+    }.to raise_error ParserError, /whatever/
+  end
+end

GUI/spec/spec_helper.rb

 
 TEST_QP_PATH = where_am_i+"/../testdata/qplprograms/"
 
+require 'config/platform'
 require 'manifest'
 

GUI/src/config/platform.rb

+#===============================================================================
+# Platform specific operations, feel free to remove or override any of these
+# that don't work for your platform/application
+
+def on_mac
+ yield if RbConfig::CONFIG["host_os"] =~ /darwin/i
+end
+
+def on_win
+  yield if  RbConfig::CONFIG["host_os"] =~ /^win|mswin/i 
+end
+
+def on_linux
+  yield if  RbConfig::CONFIG["host_os"] =~ /^win|mswin/i 
+end
+
+
+def not_on_mac
+  yield if  !(RbConfig::CONFIG["host_os"] =~ /darwin/i)
+end
+  
+on_mac do
+  testing = java.lang.System.get_property("com.drogar.testing.fest")
+  if !testing or testing != "true"
+    java.lang.System.set_property("apple.laf.useScreenMenuBar", "true")
+  end
+end

GUI/src/dialogs/simulate_results/simulate_results_model.rb

 
   java_signature "void simulate_results(Object)"
   def simulate_results=(xml_data)
-    raise QuantumStackModelInvalidCreate, "Missing Stack Translation" if @stack_translation.nil?
+    raise ModelCreateError, "Missing Stack Translation" if @stack_translation.nil?
     sr = SIMULATE_PATTERN.match xml_data
 
-    raise QuantumStackModelInvalidCreate, "Invalid Simulate Results: #{xml_data}" if !sr
+    raise ModelCreateError, "Invalid Simulate Results: #{xml_data}" if !sr
     @random_value_text = "Random Value: "+sr[1]
     @simulate_results = SimulateResultsModel.result_values_to_list(sr[2],@stack_translation)
   end

GUI/src/exceptions/quantum_stack_model_invalid_create.rb

-class QuantumStackModelInvalidCreate < RuntimeError
-end

GUI/src/lqpl/lqpl_controller.rb

   end
       
   def all_controllers_dispose
-    @dialogs.each {|d| d.dispose}
-    @sub_controllers.each{|sc| sc.dispose}
+    @dialogs.each {|d| d.dispose} if @dialogs
+    @sub_controllers.each{|sc| sc.dispose} if @sub_controllers
   end
   
   def file_simulate_action_performed
 # The useScreenMenuBar is an example of this.
 require 'rbconfig'
 require 'java'
+require 'config/platform'
 
 
-#===============================================================================
-# Platform specific operations, feel free to remove or override any of these
-# that don't work for your platform/application
-
-def on_mac
- yield if RbConfig::CONFIG["host_os"] =~ /darwin/i
-end
-
-def on_win
-  yield if  RbConfig::CONFIG["host_os"] =~ /^win|mswin/i 
-end
-
-def on_linux
-  yield if  RbConfig::CONFIG["host_os"] =~ /^win|mswin/i 
-end
-
-
-def not_on_mac
-  yield if  !(RbConfig::CONFIG["host_os"] =~ /darwin/i)
-end
-  
-on_mac do
-  testing = java.lang.System.get_property("com.drogar.testing.fest")
-  if !testing or testing != "true"
-    java.lang.System.set_property("apple.laf.useScreenMenuBar", "true")
-  end
-end
 
 # End of platform specific code
 #===============================================================================

GUI/src/manifest.rb

   # Files to be added only when run from inside a jar file
 end
 
+
+%w{JOptionPane JFileChooser filechooser.FileNameExtensionFilter JTextArea JScrollPane}.each do |cfile|
+  java_import "javax.swing."+cfile
+end
+
+java_import com.drogar.lqpl.qstack.Painter
+
+java_import java.lang.System
+
+java_import java.awt.Point
+
+%w{point jfile_chooser array}.each do |rfile|
+  require 'utility/monkey/'+rfile
+end
+
+
+%w{translate_line_ends xml_decode drawing}.each do |f|
+  require "utility/"+f
+end
+
+%w{abstract zero value abstract_list qubit data classical}.each do |rf|
+  require "panels/parsers/"+rf+"_pattern_parser"
+end
+
 require 'painting/canvas_size'
 require 'application_model'
-require 'utility/monkey/array'
-require 'utility/xml_decode'
+
 require 'xml_based_model'
-["server_process_not_found", "invalid_input"].each do |f|
+
+%w{server_process_not_found invalid_input}.each do |f|
   require "exceptions/"+f
 end
 
-["translate_line_ends","xml_decode"].each do |f|
-  require "utility/"+f
-end
 
-["lqpl_emulator_server_connection","compiler_server_connection"].each do |f|
+%w{lqpl_emulator_server_connection compiler_server_connection}.each do |f|
   require "communications/"+f
 end
-
-{ ""=>["lqpl"], 
-  "panels/" => ["quantum_stack", "classical_stack","dump","executable_code", "stack_translation"],
-  "dialogs/" =>["simulate_results", "about"]}.each do |k,v|
-    v.each {|f|   require k+f+"/"+f+"_controller" }
+%w{abstract classical data qubit value zero}.each do |rf|
+  require "panels/quantum_stack/descriptor/#{rf}_descriptor_model"
+  require "panels/quantum_stack/descriptor/#{rf}_descriptor_painter"
 end
 
-require "exit_handler"
+require 'panels/quantum_stack/descriptor/descriptor_painter_factory'
+require 'panels/quantum_stack/quantum_stack_painter'
 
-%w{JOptionPane JFileChooser filechooser.FileNameExtensionFilter}.each do |cfile|
-  java_import "javax.swing."+cfile
+{ ""=>%w{lqpl}, 
+  "panels/" => %w{quantum_stack classical_stack dump executable_code stack_translation},
+  "dialogs/" =>%w{simulate_results about}}.each do |k,v|
+    v.each do |f|   
+      require k+f+"/"+f+"_view" 
+      require k+f+"/"+f+"_model" 
+      require k+f+"/"+f+"_controller" 
+    end
 end
 
-java_import java.lang.System
-
-java_import java.awt.Point
+require "exit_handler"
 
 
-require 'utility/monkey/point'
-require 'utility/monkey/jfile_chooser'
 
 

GUI/src/panels/classical_stack/classical_stack_model.rb

-require 'exceptions/quantum_stack_model_invalid_create'
-
 class ClassicalStackModel < XmlBasedModel
   attr_accessor :classical_stack_text
   attr_accessor :classical_stack

GUI/src/panels/dump/dump_call_model.rb

-require "panels/classical_stack/classical_stack_model"
-
 class DumpCallModel
 
   def initialize(inx)
 
   def dumpcall=(in_xml)
     m = DC_PATTERN.match in_xml
-    raise QuantumStackModelInvalidCreate, "Invalid dump_call: #{in_xml}" if !m
+    raise ModelCreateError, "Invalid dump_call: #{in_xml}" if !m
     @ret_offset=m[1]
     @ret_label=m[2]
     @cstack = ClassicalStackModel.new

GUI/src/panels/executable_code/code_pointer.rb

   attr_accessor :line_number
   def initialize(xml_string)
     cp_match = CODE_POINTER_PATTERN.match xml_string
-    raise QuantumStackModelInvalidCreate, "code pointer xml was ill-formed"  if !cp_match
+    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
   end

GUI/src/panels/executable_code/executable_code_model.rb

 
   def the_code=(xml_string)
     @the_code = ExecutableCodeModel::code_xml_to_map(xml_string)
-    raise QuantumStackModelInvalidCreate, "code xml was ill-formed" if !self.the_code
+    raise ModelCreateError, "code xml was ill-formed" if !self.the_code
   end
 
   def the_code_pointer=(xml_string)

GUI/src/panels/executable_code/executable_code_view.rb

-java_import javax.swing.JTextArea
-java_import javax.swing.JScrollPane
-
 WIDTH_OF_TEXT_PANE = 60
+
 class ExecutableCodeView < ApplicationView
   set_java_class com.drogar.lqpl.screens.ExecutingCode
 

GUI/src/panels/parsers/abstract_list_pattern_parser.rb

+class AbstractListPatternParser < AbstractPatternParser
+  include XmlDecode
+  
+  def initialize(instring)
+    super(instring)
+    @parsed_list=parse_list 
+  end
+  
+  def parsed_value
+    @parsed_list
+  end
+  
+end

GUI/src/panels/parsers/abstract_pattern_parser.rb

+class ParserError < RuntimeError 
+end
+
+class AbstractPatternParser
+  def initialize(in_string)
+    @md = self.class.top_level_regexp.match in_string
+    raise ParserError, "No match -#{self.class.top_level_regexp}- to -#{in_string}-" unless @md
+  end
+  
+  def parsed?
+    @md
+  end
+  
+  def self.top_level_regexp
+    Regexp.new /^$/
+  end
+  
+end

GUI/src/panels/parsers/classical_pattern_parser.rb

+class ClassicalPatternParser < AbstractListPatternParser
+  
+  def self.top_level_regexp
+    Regexp.new /^<ClassicalStack>(?<classical_values>((<cint>(-?\d+)<\/cint>)|(<cbool>(True|False)<\/cbool>))*)<\/ClassicalStack>$/
+  end
+  
+  LIST_PATTERN = Regexp.new /^(<cint>(?<int_value>-?\d+)<\/cint>)|(<cbool>(?<bool_value>True|False)<\/cbool>)/
+
+  def parse_list
+    values =   @md[:classical_values]  
+    ClassicalPatternParser::values_to_list values, LIST_PATTERN do |ret, md|
+      ret << md[:int_value].to_i if md[:int_value]
+      ret << (md[:bool_value] == 'True') if md[:bool_value]
+    end
+  end
+end

GUI/src/panels/parsers/data_pattern_parser.rb

+class DataPatternParser < AbstractListPatternParser
+  
+  CONS_PATTERN = Regexp.new /^(<string>(?<constructor_name>[\w\d_]*)<\/string><StackAddresses>(?<addresses>(<int>(\d*)<\/int>)*)<\/StackAddresses>)/
+
+  LIST_PATTERN = Regexp.new /^(<int>(?<address>\d*)<\/int>)/
+
+
+  def self.top_level_regexp
+    Regexp.new /^<AlgebraicData>(?<constructors>(<string>([\w\d_]*)<\/string><StackAddresses>((<int>(\d*)<\/int>)*)<\/StackAddresses>)+)<\/AlgebraicData>$/
+  end
+
+  def parse_list
+    constructors_string = @md[:constructors]
+    DataPatternParser::values_to_list constructors_string, CONS_PATTERN do |rval, mdata|
+      cons_name = mdata[:constructor_name]
+      raise InvalidInput, "Constructor '#{cons_name}' duplicated in algebraic data" if rval.assoc(cons_name)
+      rval << [cons_name,DataPatternParser::parse_address_list(mdata[:addresses])]
+    end
+  end
+
+
+  def self.parse_address_list(addresses_string)
+    DataPatternParser::values_to_list addresses_string, LIST_PATTERN do |rval, md|
+      elem = md[:address].to_i
+      raise InvalidInput, "StackAddress '#{elem}' duplicated for single constructor" if rval.include? elem
+      rval << elem
+    end
+  end
+  
+  
+end

GUI/src/panels/parsers/qubit_pattern_parser.rb

+class QubitPatternParser < AbstractListPatternParser
+  
+  LIST_PATTERN = Regexp.new /^(<pair>(?<first_qubit>(<qz\/>)|(<qo\/>))(?<second_qubit>(<qz\/>)|(<qo\/>))<\/pair>)/
+  # match 2 and 5
+  
+  def self.top_level_regexp
+    Regexp.new /^<Qubits>(?<qubits>(<pair>((<qz\/>)|(<qo\/>))((<qz\/>)|(<qo\/>))<\/pair>){1,4})<\/Qubits>$/
+  end
+    
+  
+  def parse_list
+    qubit_string = @md[:qubits]
+    QubitPatternParser::values_to_list qubit_string, LIST_PATTERN  do |rval,md|
+      elem = [md[:first_qubit], md[:second_qubit]].collect {|qb| QubitPatternParser::translate_qubit qb}
+      raise InvalidInput, "#{elem} duplicated in qubit" if rval.include? elem
+      rval << elem
+    end
+  end
+  
+  def self.translate_qubit(single_qubit)
+   return 0 if single_qubit =~/^<qz\/>$/
+   return 1 if single_qubit =~/^<qo\/>$/
+   raise InvalidInput, "Got #{single_qubit}, expecting one of '<qz/>' or '<qo/>'"
+  end
+end

GUI/src/panels/parsers/value_pattern_parser.rb

+class ValuePatternParser < AbstractPatternParser
+  
+  def self.top_level_regexp
+    Regexp.new /^<Value>(<number>)?(1|1\.|1\.0|0?\.\d*|\d\.\d*e-\d\d?)(<\/number>)?<\/Value>$/
+  end
+  
+  def parsed_value
+    @md[2].to_f
+  end
+end

GUI/src/panels/parsers/zero_pattern_parser.rb

+class ZeroPatternParser < AbstractPatternParser
+  
+  def self.top_level_regexp
+    Regexp.new /^<Zero\/>$/
+  end
+  
+  def parsed_value
+    "0" if @md
+  end
+end

GUI/src/panels/quantum_stack/descriptor/abstract_descriptor_model.rb

-class AbstractDescriptorModel <XmlBasedModel
+class AbstractDescriptorModel <ApplicationModel
   attr_accessor :value
   attr_accessor :name
 

GUI/src/panels/quantum_stack/descriptor/abstract_descriptor_painter.rb

-require 'utility/drawing'
-
-java_import "com.drogar.lqpl.qstack.Painter"
-
-
 class AbstractDescriptorPainter
   include Painter
   include Drawing

GUI/src/panels/quantum_stack/descriptor/classical_descriptor_model.rb

 class ClassicalDescriptorModel< AbstractDescriptorModel
-  include XmlDecode
-  PATTERN=Regexp.new /^<ClassicalStack>(((<cint>(-?\d+)<\/cint>)|(<cbool>(True|False)<\/cbool>))*)<\/ClassicalStack>$/
-
-  LIST_PATTERN = Regexp.new /^(<cint>(-?\d+)<\/cint>)|(<cbool>(True|False)<\/cbool>)/
-
-  def initialize(in_string)
-    @value = check_and_return_value(PATTERN,in_string,
-      lambda { |m| ClassicalDescriptorModel::parse_list m})
+  
+  def self.validate_substacks_count(substacks)
+    raise ModelCreateError, "Classical element on stack should have substacks" if !substacks || substacks.size == 0
   end
 
-  def self.parse_list(sub_string)
-    r = values_to_list sub_string, LIST_PATTERN do |ret, md|
-      ret << md[2].to_i if md[2]
-      ret << (md[4] == 'True') if md[4]
-    end
-    raise ModelCreateError, sub_string if sub_string and sub_string.length > 0 and r.length == 0
-    r
+  def initialize(in_string)
+    cpp = ClassicalPatternParser.new in_string
+    @value = cpp.parsed_value
   end
 
   def length

GUI/src/panels/quantum_stack/descriptor/data_descriptor_model.rb

 class DataDescriptorModel < AbstractDescriptorModel
 
-  PATTERN=Regexp.new /^<AlgebraicData>((<string>([\w\d_]*)<\/string><StackAddresses>((<int>(\d*)<\/int>)*)<\/StackAddresses>)+)<\/AlgebraicData>$/
-
-  CONS_PATTERN = Regexp.new /^(<string>([\w\d_]*)<\/string><StackAddresses>((<int>(\d*)<\/int>)*)<\/StackAddresses>)/
+  def self.validate_substacks_count(substacks)
+    raise ModelCreateError, "Data element on stack should have substacks" if !substacks || substacks.size == 0
+  end
 
-  LIST_PATTERN = Regexp.new /^(<int>(\d*)<\/int>)/
-  # match 2
 
   def initialize(in_string)
-    @value = check_and_return_value(PATTERN,in_string,
-      lambda { |m| DataDescriptorModel::parse_pairs m})
+    dpp = DataPatternParser.new(in_string)
+    
+    @value = dpp.parsed_value
   end
 
 
   def substack_labels
     @value.collect {|v| "#{v[0]}#{v[1] if [] != v[1]}"}
   end
-
-
-  def self.parse_pairs(constructors_string)
-    raise InvalidInput, "Must have at least one constructor" if !constructors_string or constructors_string.length == 0
-    md = CONS_PATTERN.match constructors_string
-    raise InvalidInput, constructors_string if !md
-    rval = [[md[2], self.parse_address_list(md[3])]]
-    num_found = 1
-    while md
-      md = CONS_PATTERN.match(constructors_string[md[1].length*num_found, constructors_string.length])
-      return rval if !md
-      raise InvalidInput, "Constructor '#{md[2]}' duplicated in algebraic data" if rval.assoc(md[2])
-      rval << [md[2],self.parse_address_list(md[3])]
-      num_found += 1
-    end
-    rval
-  end
-
-
-  def self.parse_address_list(addresses_string)
-    r = values_to_list addresses_string, LIST_PATTERN do |rval, md|
-      elem = md[2].to_i
-      raise InvalidInput, "StackAddress '#{elem}' duplicated for single constructor" if rval.include? elem
-      rval << elem
-    end
-    raise InvalidInput, addresses_string if r.length == 0 and addresses_string and addresses_string.length > 0
-    r
-  end
 end

GUI/src/panels/quantum_stack/descriptor/descriptor_painter_factory.rb

 
-require "panels/quantum_stack/descriptor/abstract_descriptor_painter"
-require "panels/quantum_stack/descriptor/zero_descriptor_painter"
-require "panels/quantum_stack/descriptor/value_descriptor_painter"
-require "panels/quantum_stack/descriptor/classical_descriptor_painter"
-require "panels/quantum_stack/descriptor/qubit_descriptor_painter"
-require "panels/quantum_stack/descriptor/data_descriptor_painter"
-
 class DescriptorPainterFactory
   def self.make_painter(model)
     case model

GUI/src/panels/quantum_stack/descriptor/qubit_descriptor_model.rb

 class QubitDescriptorModel < AbstractDescriptorModel
 
-  PATTERN=Regexp.new /^<Qubits>((<pair>((<qz\/>)|(<qo\/>))((<qz\/>)|(<qo\/>))<\/pair>){1,4})<\/Qubits>$/
-
-  LIST_PATTERN = Regexp.new /^(<pair>((<qz\/>)|(<qo\/>))((<qz\/>)|(<qo\/>))<\/pair>)/
-  # match 2 and 5
-
+  def self.validate_substacks_count(substacks)
+    raise ModelCreateError, "Qubit on stack should have 1 - 4 substacks, not #{!substacks ? "be nil" : substacks.size}" if !substacks || substacks.size == 0 or substacks.size > 4
+  end
+ 
   def initialize(in_string)
-    @value = check_and_return_value(PATTERN,in_string,
-      lambda { |m| QubitDescriptorModel::parse_list m})
+    qpp = QubitPatternParser.new in_string
+    @value = qpp.parsed_value
   end
 
   def length
   def substack_labels
     @value.collect {|v| "#{v[0]}#{v[1]}"}
   end
-
-
-  def self.parse_list(qubit_string)
-    raise InvalidInput, "Must have qubit indicators" if !qubit_string or qubit_string.length == 0
-    r = values_to_list qubit_string, LIST_PATTERN  do |rval,md|
-      elem = [self.translate_qubit(md[2]), self.translate_qubit(md[5])]
-      raise InvalidInput, "#{elem} duplicated in qubit" if rval.include? elem
-      rval << elem
-    end
-
-    raise InvalidInput, qubit_string if r.length > 4
-
-    raise InvalidInput, qubit_string if r.length == 0 and qubit_string and qubit_string.length > 0
-    r
-  end
-
-  def self.translate_qubit(single_qubit)
-   case single_qubit
-   when "<qz/>" then 0
-   when "<qo/>" then 1
-   else raise InvalidInput, "Got #{single_qubit}, expecting one of '<qz/>' or '<qo/>'"
-   end
- end
 end

GUI/src/panels/quantum_stack/descriptor/value_descriptor_model.rb

 
 class ValueDescriptorModel < AbstractDescriptorModel
 
-  PATTERN=Regexp.new /^<Value>(<number>)?(.*?)(<\/number>)?<\/Value>$/
-
+  def self.validate_substacks_count(substacks)
+    return unless substacks
+    raise ModelCreateError, "Value element should not have substacks" if substacks.size > 0
+  end
+  
   def initialize(in_string)
-    matc = PATTERN.match in_string
-    raise ModelCreateError, in_string if ! matc
-    @value = matc[2]
+    @value = @value = (ValuePatternParser.new in_string).parsed_value
     @name = nil
   end
 

GUI/src/panels/quantum_stack/descriptor/zero_descriptor_model.rb

 class ZeroDescriptorModel <AbstractDescriptorModel
 
+  def self.validate_substacks_count(substacks)
+    return unless substacks
+    raise ModelCreateError, "Zero stack should not have substacks" if substacks.size > 0
+  end
+  
   def initialize(in_string="<Zero/>")
-    raise ModelCreateError, in_string if in_string != "<Zero/>"
-    @value = "0"
+    @value = (ZeroPatternParser.new in_string).parsed_value
   end
 
   def length
     0
   end
 
-
-
 end

GUI/src/panels/quantum_stack/quantum_stack_model.rb

-require 'exceptions/quantum_stack_model_invalid_create'
-require 'exceptions/stack_descriptor_model_invalid_create'
-require "panels/quantum_stack/descriptor/abstract_descriptor_model"
-require "panels/quantum_stack/descriptor/zero_descriptor_model"
-require "panels/quantum_stack/descriptor/value_descriptor_model"
-require "panels/quantum_stack/descriptor/classical_descriptor_model"
-require "panels/quantum_stack/descriptor/qubit_descriptor_model"
-require "panels/quantum_stack/descriptor/data_descriptor_model"
-
 class QuantumStackModel < XmlBasedModel
 
   attr_accessor :substacks
   end
 
   def quantum_stack=(in_qstack)
-    raise QuantumStackModelInvalidCreate, "Missing Stack Translation" if @stack_translation.nil?
+    raise ModelCreateError, "QuantumStack: Missing Stack Translation" if @stack_translation.nil?
     return if !in_qstack
     @preferred_size = nil
     @bottom = in_qstack == "<bottom/>"
     if !bottom?
-      md = SINGLE_QS_PATTERN.match in_qstack
-      raise QuantumStackModelInvalidCreate, in_qstack if !md
-      @stackaddress = md[1].to_i
-      @on_diagonal = md[3] == "True"
-      @substacks = QuantumStackModel::make_multiple_stacks(md[6], @stack_translation)
-      @descriptor = AbstractDescriptorModel.make_instance md[7]
-      case @descriptor
-      when ZeroDescriptorModel then  raise QuantumStackModelInvalidCreate, "Zero stack should not have substacks" if @substacks.size > 0
-      when ValueDescriptorModel then raise QuantumStackModelInvalidCreate, "Value element should not have substacks" if @substacks.size > 0
-      when QubitDescriptorModel then raise QuantumStackModelInvalidCreate, "Qubit on stack should have substacks '#{in_qstack}" if @substacks.size == 0
-      when ClassicalDescriptorModel then raise QuantumStackModelInvalidCreate, "Classical element on stack should have substacks" if @substacks.size == 0
-      when DataDescriptorModel then raise QuantumStackModelInvalidCreate, "Data element on stack should have substacks" if @substacks.size == 0
-      end
+      decode_stack_data_from_xml in_qstack
 
       @descriptor.name = make_name(:use_stack_address)
     else
       @substacks = []
     end
-
   end
+  
+  def decode_stack_data_from_xml(in_qstack)
+    matched = SingleQSMatcher.new  in_qstack
+    @stackaddress = matched.stackaddress
+    @on_diagonal = matched.on_diagonal?
+    @substacks = QuantumStackModel::make_multiple_stacks(matched.substacks, @stack_translation)
+    @descriptor = AbstractDescriptorModel.make_instance matched.descriptor
+    @descriptor.class.validate_substacks_count(@substacks)
+  end
+  
   def make_name(formatting)
     nm = (@stack_translation.reverse_lookup(@stackaddress)).to_s
 
   def self.get_next_qstack(multi_stacks)
     return nil if !multi_stacks or multi_stacks == ""
     if multi_stacks =~ /^<bottom\/>/
-      return ["<bottom/>",multi_stacks[9,multi_stacks.length]]
+      len = 9
+    else
+      len = QuantumStackModel::find_end_index_for_start_in_data(multi_stacks,"<Qstack>","</Qstack>")
     end
-    if multi_stacks =~ /<Qstack/
-      len = 8 # length of "<Qstack>"
-      in_count = 1
-      while in_count > 0
-        len += 1
-        in_count += 1 if multi_stacks[len,8] == "<Qstack>"
-        in_count -= 1 if multi_stacks[len,9] == "</Qstack>"
-      end
-      len += 9
-      return [multi_stacks[0,len], multi_stacks[len, multi_stacks.length - len + 1]]
+    
+    # len = 8 # length of "<Qstack>"
+    # in_count = 1
+    # while in_count > 0
+    #   len += 1
+    #   in_count += 1 if multi_stacks[len,8] == "<Qstack>"
+    #   in_count -= 1 if multi_stacks[len,9] == "</Qstack>"
+    # end
+    # len += 9
+    return [multi_stacks[0,len], multi_stacks[len, multi_stacks.length - len + 1]]
+  end
+
+  def self.find_end_index_for_start_in_data(data,start_string,end_string)
+    len=start_len = start_string.size
+    end_len = end_string.size
+    in_count = 1
+    while in_count > 0
+      len +=1
+      in_count += 1 if data[len,start_len] == start_string
+      in_count -= 1 if data[len,end_len] == end_string
     end
+    len+ end_len
   end
 
+  class SingleQSMatcher
+    def initialize(in_data)
+      @md = SINGLE_QS_PATTERN.match in_data
+      raise ModelCreateError, in_data if !@md
+    end
+    
+    def stackaddress
+      @md[:stackaddress].to_i
+    end
+    
+    def descriptor
+      @md[:descriptor]
+    end
+    
+    def on_diagonal?
+      @md[:on_diagonal] == "True"
+    end
+    
+    def substacks
+      @md[:substacks]
+    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>/
 
 
   SINGLE_QS_PATTERN = Regexp.new /^<Qstack>
-      <int>(-?(\d)*)<\/int>  #Stackaddress ([1])
-      <bool>((True)|(False))<\/bool> #on diagonal ([3])
-      <substacks>(.*)<\/substacks> # the substacks ([6])
-      ((<Zero\/>)|(<Value>.*<\/Value>)|(<Qubits>.*<\/Qubits>)|(<ClassicalStack>.*<\/ClassicalStack>)|(<AlgebraicData>.*<\/AlgebraicData>))  # stack descriptor [7]
+      <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]
       <\/Qstack>/x
 
 

GUI/src/panels/quantum_stack/quantum_stack_painter.rb

-require "utility/drawing"
-require "panels/quantum_stack/descriptor/descriptor_painter_factory"
-
-java_import "com.drogar.lqpl.qstack.Painter"
-
-
 LINE_LABEL_FONT_SIZE = 8.0
 PLACEMENTS={-1 => :left, 0 => :right, 1 => :right}
 

GUI/src/panels/quantum_stack/quantum_stack_view.rb

-require 'panels/quantum_stack/quantum_stack_painter'
 
 class QuantumStackView < ApplicationView
   set_java_class com.drogar.lqpl.screens.QuantumStackFrame

GUI/src/panels/stack_translation/stack_translation_model.rb

-require 'exceptions/quantum_stack_model_invalid_create'
-
 class StackTranslationModel < XmlBasedModel
   attr_accessor :stack_translation
   attr_accessor :text
     return [] if in_mmap == ""
     ret = []
     match_list_of_maps = MMAP_PATTERN.match in_mmap
-    raise QuantumStackModelInvalidCreate, in_mmap if !match_list_of_maps
+    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