text: """
  
  qasm.py - Functions to parse a set of qasm commands into a Sympy Circuit.
  
  Examples taken from Chuang's page: http://www.media.mit.edu/quanta/qasm2circ/
  
  The code returns a circuit and an associated list of labels.
  >>> from sympy.physics.quantum.qasm import Qasm
  >>> q = Qasm('qubit q0', 'qubit q1', 'h q0', 'cnot q0,q1')
  >>> q.get_circuit()
  CNOT(1,0)*H(1)
  
  >>> q = Qasm('qubit q0', 'qubit q1', 'cnot q0,q1', 'cnot q1,q0', 'cnot q0,q1')
  >>> q.get_circuit()
  CNOT(1,0)*CNOT(0,1)*CNOT(1,0)
  """
  
  __all__ = [
      'Qasm',
      ]
  
  from sympy.physics.quantum.gate import H, CNOT, X, Z, CGate, CGateS, SWAP, S, T,CPHASE
  from sympy.physics.quantum.circuitplot import Mz
  
  def read_qasm(lines):
      return Qasm(*lines.splitlines())
  
  def read_qasm_file(filename):
      return Qasm(*open(filename).readlines())
  
  def prod(c):
      p = 1
      for ci in c:
          p *= ci
      return p
  
  def flip_index(i, n):
      """Reorder qubit indices from largest to smallest.
  
      >>> from sympy.physics.quantum.qasm import flip_index
      >>> flip_index(0, 2)
      1
      >>> flip_index(1, 2)
      0
      """
      return n-i-1
  
  def trim(line):
      """Remove everything following comment # characters in line.
  
      >>> from sympy.physics.quantum.qasm import trim
      >>> trim('nothing happens here')
      'nothing happens here'
      >>> trim('something #happens here')
      'something '
      """
      if not '#' in line:
          return line
      return line.split('#')[0]
  
  def get_index(target, labels):
      """Get qubit labels from the rest of the line,and return indices
  
      >>> from sympy.physics.quantum.qasm import get_index
      >>> get_index('q0', ['q0', 'q1'])
      1
      >>> get_index('q1', ['q0', 'q1'])
      0
      """
      nq = len(labels)
      return flip_index(labels.index(target), nq)
  
  def get_indices(targets, labels):
      return [get_index(t, labels) for t in targets]
  
  def nonblank(args):
      for line in args:
          line = trim(line)
          if line.isspace():
              continue
          yield line
      return
  
  def fullsplit(line):
      words = line.split()
      rest = ' '.join(words[1:])
      return fixcommand(words[0]), [s.strip() for s in rest.split(',')]
  
  def fixcommand(c):
      """Fix Qasm command names.
  
      Remove all of forbidden characters from command c, and
      replace 'def' with 'qdef'.
      """
      forbidden_characters = ['-']
      c = c.lower()
      for char in forbidden_characters:
          c = c.replace(char, '')
      if c == 'def':
          return 'qdef'
      return c
  
  def stripquotes(s):
      """Replace explicit quotes in a string.
  
      >>> from sympy.physics.quantum.qasm import stripquotes
      >>> stripquotes("'S'") == 'S'
      True
      >>> stripquotes('"S"') == 'S'
      True
      >>> stripquotes('S') == 'S'
      True
      """
      s = s.replace('"', '') # Remove second set of quotes?
      s = s.replace("'", '')
      return s
  
  class Qasm(object):
      """Class to form objects from Qasm lines
  
      >>> from sympy.physics.quantum.qasm import Qasm
      >>> q = Qasm('qubit q0', 'qubit q1', 'h q0', 'cnot q0,q1')
      >>> q.get_circuit()
      CNOT(1,0)*H(1)
      >>> q = Qasm('qubit q0', 'qubit q1', 'cnot q0,q1', 'cnot q1,q0', 'cnot q0,q1')
      >>> q.get_circuit()
      CNOT(1,0)*CNOT(0,1)*CNOT(1,0)
      """
      def __init__(self, *args, **kwargs):
          self.defs = {}
          self.circuit = []
          self.labels = []
          self.inits = {}
          self.add(*args)
          self.kwargs = kwargs
  
      def add(self, *lines):
          for line in nonblank(lines):
              command, rest = fullsplit(line)
              if self.defs.get(command): #defs come first, since you can override built-in
                  function = self.defs.get(command)
                  indices = self.indices(rest)
                  if len(indices) == 1:
                      self.circuit.append(function(indices[0]))
                  else:
                      self.circuit.append(function(indices[:-1], indices[-1]))
              elif hasattr(self, command):
                  function = getattr(self, command)
                  function(*rest)
              else:
                  print("Function %s not defined. Skipping" % command)
  
      def get_circuit(self):
          return prod(reversed(self.circuit))
  
      def get_labels(self):
          return list(reversed(self.labels))
  
      def plot(self):
          from sympy.physics.quantum.circuitplot import CircuitPlot
          circuit, labels = self.get_circuit(), self.get_labels()
          CircuitPlot(circuit, len(labels), labels=labels, inits=self.inits)
  
      def qubit(self, arg, init=None):
          self.labels.append(arg)
          if init: self.inits[arg] = init
  
      def indices(self, args):
          return get_indices(args, self.labels)
  
      def index(self, arg):
          return get_index(arg, self.labels)
  
      def nop(self, *args):
          pass
  
      def x(self, arg):
          self.circuit.append(X(self.index(arg)))
  
      def z(self, arg):
          self.circuit.append(Z(self.index(arg)))
  
      def h(self, arg):
          self.circuit.append(H(self.index(arg)))
  
      def s(self, arg):
          self.circuit.append(S(self.index(arg)))
  
      def t(self, arg):
          self.circuit.append(T(self.index(arg)))
  
      def measure(self, arg):
          self.circuit.append(Mz(self.index(arg)))
  
      def cnot(self, a1, a2):
          self.circuit.append(CNOT(*self.indices([a1, a2])))
  
      def swap(self, a1, a2):
          self.circuit.append(SWAP(*self.indices([a1, a2])))
  
      def cphase(self, a1, a2):
          self.circuit.append(CPHASE(*self.indices([a1, a2])))
  
      def toffoli(self, a1, a2, a3):
          i1, i2, i3 = self.indices([a1, a2, a3])
          self.circuit.append(CGateS((i1, i2), X(i3)))
  
      def cx(self, a1, a2):
          fi, fj = self.indices([a1, a2])
          self.circuit.append(CGate(fi, X(fj)))
  
      def cz(self, a1, a2):
          fi, fj = self.indices([a1, a2])
          self.circuit.append(CGate(fi, Z(fj)))
  
      def defbox(self, *args):
          print("defbox not supported yet. Skipping: ", args)
  
      def qdef(self, name, ncontrols, symbol):
          from sympy.physics.quantum.circuitplot import CreateOneQubitGate, CreateCGate
          ncontrols = int(ncontrols)
          command = fixcommand(name)
          symbol = stripquotes(symbol)
          if ncontrols > 0:
              self.defs[command] = CreateCGate(symbol)
          else:
              self.defs[command] = CreateOneQubitGate(symbol)
  