mirror of https://github.com/Qiskit/qiskit.git
refactor parser
This commit is contained in:
parent
0581d8e719
commit
739e4c1416
|
@ -1,58 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# Author: Jim Challenger
|
||||
import os
|
||||
import sys
|
||||
from . import _qasm_yy as qasm
|
||||
import traceback
|
||||
|
||||
|
||||
class Qasm(object):
|
||||
|
||||
def __init__(self, filename = None, data = None):
|
||||
if ( filename == None and data == None ):
|
||||
raise qasm.QasmException("Missing input file and/or data")
|
||||
if ( filename != None and data != None ):
|
||||
raise qasm.QasmException("File and data must not both be specified initializing qasm")
|
||||
|
||||
self._filename = filename
|
||||
self._data = data
|
||||
|
||||
def print_tokens(self):
|
||||
if ( self._filename ):
|
||||
self._data = open(self._filename).read()
|
||||
|
||||
qasm_p = qasm.QasmParser(self._filename)
|
||||
return qasm_p.print_tokens()
|
||||
|
||||
def parse(self):
|
||||
if ( self._filename ):
|
||||
self._data = open(self._filename).read()
|
||||
|
||||
qasm_p = qasm.QasmParser(self._filename)
|
||||
qasm_p.parse_debug(False)
|
||||
return qasm_p.parse(self._data)
|
||||
|
||||
def main(args):
|
||||
|
||||
try:
|
||||
q = Qasm(filename=args[0])
|
||||
ast = q.parse()
|
||||
print('---------------------------------------- PARSE TREE ----------------------------------------')
|
||||
ast.to_string(0)
|
||||
print('-------------------------------------- END PARSE TREE --------------------------------------')
|
||||
|
||||
|
||||
except qasm.QasmException as e:
|
||||
print('--------------------------------------------------------------------------------')
|
||||
print(e.msg)
|
||||
print('--------------------------------------------------------------------------------')
|
||||
|
||||
except Exception as e:
|
||||
print('--------------------------------------------------------------------------------')
|
||||
print(sys.exc_info()[0], 'Exception parsing qasm file')
|
||||
traceback.print_exc()
|
||||
print('--------------------------------------------------------------------------------')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
|
@ -1,2 +0,0 @@
|
|||
from ._Qasm import Qasm
|
||||
from . import _qasm_yy as qasm
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
from ._qasm import Qasm
|
|
@ -0,0 +1,24 @@
|
|||
from ._barrier import Barrier
|
||||
from ._binaryop import BinaryOp
|
||||
from ._cnot import Cnot
|
||||
from ._creg import Creg
|
||||
from ._customunitary import CustomUnitary
|
||||
from ._expressionlist import ExpressionList
|
||||
from ._external import External
|
||||
from ._gate import Gate
|
||||
from ._gatebody import GateBody
|
||||
from ._id import Id
|
||||
from ._idlist import IdList
|
||||
from ._if import If
|
||||
from ._indexedid import IndexedId
|
||||
from ._intnode import Int
|
||||
from ._magic import Magic
|
||||
from ._measure import Measure
|
||||
from ._opaque import Opaque
|
||||
from ._prefix import Prefix
|
||||
from ._primarylist import PrimaryList
|
||||
from ._program import Program
|
||||
from ._qreg import Qreg
|
||||
from ._real import Real
|
||||
from ._reset import Reset
|
||||
from ._universalunitary import UniversalUnitary
|
|
@ -0,0 +1,21 @@
|
|||
"""
|
||||
Node for an OPENQASM barrier statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Barrier(Node):
|
||||
"""Node for an OPENQASM barrier statement.
|
||||
|
||||
children[0] is a primarylist node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the barrier node."""
|
||||
Node.__init__(self, 'barrier', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "barrier " + self.children[0].qasm() + ";"
|
|
@ -0,0 +1,24 @@
|
|||
"""
|
||||
Node for an OPENQASM binary operation expression.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class BinaryOp(Node):
|
||||
"""Node for an OPENQASM binary operation exprssion.
|
||||
|
||||
children[0] is the operation, as a character.
|
||||
children[1] is the left expression.
|
||||
children[2] is the right expression.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the binaryop node."""
|
||||
Node.__init__(self, 'binop', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "(" + self.children[1].qasm() + self.children[0] + \
|
||||
self.children[2].qasm() + ")"
|
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
Node for an OPENQASM CNOT statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Cnot(Node):
|
||||
"""Node for an OPENQASM CNOT statement.
|
||||
|
||||
children[0], children[1] are id nodes if CX is inside a gate body,
|
||||
otherwise they are primary nodes.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the cnot node."""
|
||||
Node.__init__(self, 'cnot', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "CX " + self.children[0].qasm() + "," + \
|
||||
self.children[1].qasm() + ";"
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Node for an OPENQASM creg statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Creg(Node):
|
||||
"""Node for an OPENQASM creg statement.
|
||||
|
||||
children[0] is an indexedid node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the creg node."""
|
||||
Node.__init__(self, 'creg', children, None)
|
||||
# This is the indexed id, the full "id[n]" object
|
||||
self.id = children[0]
|
||||
# Name of the creg
|
||||
self.name = self.id.name
|
||||
# Source line number
|
||||
self.line = self.id.line
|
||||
# Source file name
|
||||
self.file = self.id.file
|
||||
# Size of the register
|
||||
self.index = self.id.index
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print the node data, with indent."""
|
||||
ind = indent * ' '
|
||||
print(ind, 'creg')
|
||||
self.children[0].to_string(indent + 3)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "creg " + self.id.qasm() + ";"
|
|
@ -0,0 +1,41 @@
|
|||
"""
|
||||
Node for an OPENQASM custom gate statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class CustomUnitary(Node):
|
||||
"""Node for an OPENQASM custom gate statement.
|
||||
|
||||
children[0] is an id node.
|
||||
children[1] is an exp_list (if len==3) or primary_list.
|
||||
children[2], if present, is a primary_list.
|
||||
|
||||
Has properties:
|
||||
.id = id node
|
||||
.name = gate name string
|
||||
.arguments = None or exp_list node
|
||||
.bitlist = primary_list node
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the custom gate node."""
|
||||
Node.__init__(self, 'custom_unitary', children, None)
|
||||
self.id = children[0]
|
||||
self.name = self.id.name
|
||||
if len(children) == 3:
|
||||
self.arguments = children[1]
|
||||
self.bitlist = children[2]
|
||||
else:
|
||||
self.arguments = None
|
||||
self.bitlist = children[1]
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
s = self.name
|
||||
if self.arguments is not None:
|
||||
s += "(" + self.arguments.qasm() + ")"
|
||||
s += " " + self.bitlist.qasm() + ";"
|
||||
return s
|
|
@ -0,0 +1,25 @@
|
|||
"""
|
||||
Node for an OPENQASM expression list.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class ExpressionList(Node):
|
||||
"""Node for an OPENQASM expression list.
|
||||
|
||||
children are expression nodes.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the expression list node."""
|
||||
Node.__init__(self, 'expression_list', children, None)
|
||||
|
||||
def size(self):
|
||||
"""Return the number of expressions."""
|
||||
return len(self.children)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return ",".join([self.children[j].qasm() for j in range(self.size())])
|
|
@ -0,0 +1,18 @@
|
|||
"""
|
||||
Node for an OPENQASM external function.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class External(Node):
|
||||
"""Node for an OPENQASM external function.
|
||||
|
||||
children[0] is an id node with the name of the function.
|
||||
children[1] is an expression node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the external node."""
|
||||
Node.__init__(self, 'external', children, None)
|
|
@ -0,0 +1,54 @@
|
|||
"""
|
||||
Node for an OPENQASM gate definition.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Gate(Node):
|
||||
"""Node for an OPENQASM gate definition.
|
||||
|
||||
children[0] is an id node.
|
||||
If len(children) is 3, children[1] is an idlist node,
|
||||
and children[2] is a gatebody node.
|
||||
Otherwise, children[1] is an expressionlist node,
|
||||
children[2] is an idlist node, and children[3] is a gatebody node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the gate node."""
|
||||
Node.__init__(self, 'gate', children, None)
|
||||
self.id = children[0]
|
||||
# The next three fields are required by the symbtab
|
||||
self.name = self.id.name
|
||||
self.line = self.id.line
|
||||
self.file = self.id.file
|
||||
|
||||
if len(children) == 3:
|
||||
self.arguments = None
|
||||
self.bitlist = children[1]
|
||||
self.body = children[2]
|
||||
else:
|
||||
self.arguments = children[1]
|
||||
self.bitlist = children[2]
|
||||
self.body = children[3]
|
||||
|
||||
def n_args(self):
|
||||
"""Return the number of parameter expressions."""
|
||||
if self.arguments:
|
||||
return self.arguments.size()
|
||||
return 0
|
||||
|
||||
def n_bits(self):
|
||||
"""Return the number of qubit arguments."""
|
||||
return self.bitlist.size()
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
s = "gate " + self.name
|
||||
if self.arguments is not None:
|
||||
s += "(" + self.arguments.qasm() + ")"
|
||||
s += " " + self.bitlist.qasm() + "\n"
|
||||
s += "{\n" + self.body.qasm() + "}"
|
||||
return s
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Node for an OPENQASM custom gate body.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class GateBody(Node):
|
||||
"""Node for an OPENQASM custom gate body.
|
||||
|
||||
children is a list of gate operation nodes.
|
||||
These are one of barrier, custom_unitary, U, or CX.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the gatebody node."""
|
||||
Node.__init__(self, 'gate_body', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
s = ""
|
||||
for c in self.children:
|
||||
s += " " + c.qasm() + "\n"
|
||||
return s
|
||||
|
||||
def calls(self):
|
||||
"""Return a list of custom gate names in this gate body."""
|
||||
lst = []
|
||||
for c in self.children:
|
||||
if c.type == "custom_unitary":
|
||||
lst.append(c.name)
|
||||
return lst
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Node for an OPENQASM id.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Id(Node):
|
||||
"""Node for an OPENQASM id.
|
||||
|
||||
The node has no children but has fields name, line, and file.
|
||||
There is a flag is_bit that is set when XXXXX to help with scoping.
|
||||
"""
|
||||
|
||||
def __init__(self, id, line, file):
|
||||
"""Create the id node."""
|
||||
Node.__init__(self, "id", None, None)
|
||||
self.name = id
|
||||
self.line = line
|
||||
self.file = file
|
||||
# To help with scoping rules, so we know the id is a bit,
|
||||
# this flag is set to True when the id appears in a gate declaration
|
||||
self.is_bit = False
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print the node with indent."""
|
||||
ind = indent * ' '
|
||||
print(ind, 'id', self.name)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return self.name
|
|
@ -0,0 +1,25 @@
|
|||
"""
|
||||
Node for an OPENQASM idlist.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class IdList(Node):
|
||||
"""Node for an OPENQASM idlist.
|
||||
|
||||
children is a list of id nodes.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the idlist node."""
|
||||
Node.__init__(self, 'id_list', children, None)
|
||||
|
||||
def size(self):
|
||||
"""Return the length of the list."""
|
||||
return len(self.children)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return ",".join([self.children[j].qasm() for j in range(self.size())])
|
|
@ -0,0 +1,25 @@
|
|||
"""
|
||||
Node for an OPENQASM if statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class If(Node):
|
||||
"""Node for an OPENQASM if statement.
|
||||
|
||||
children[0] is an id node.
|
||||
children[1] is an integer node.
|
||||
children[2] is quantum operation node, including U, CX, custom_unitary,
|
||||
measure, reset, (and BUG: barrier, if).
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the if node."""
|
||||
Node.__init__(self, 'if', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "if(" + self.children[0].qasm() + "==" \
|
||||
+ self.children[1].qasm() + ") " + self.children[2].qasm()
|
|
@ -0,0 +1,32 @@
|
|||
"""
|
||||
Node for an OPENQASM indexed id.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class IndexedId(Node):
|
||||
"""Node for an OPENQASM indexed id.
|
||||
|
||||
children[0] is an id node.
|
||||
children[1] is an integer (not a node).
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the indexed id node."""
|
||||
Node.__init__(self, 'indexed_id', children, None)
|
||||
self.id = children[0]
|
||||
self.name = self.id.name
|
||||
self.line = self.id.line
|
||||
self.file = self.id.file
|
||||
self.index = children[1]
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print with indent."""
|
||||
ind = indent * ' '
|
||||
print(ind, 'indexed_id', self.name, self.index)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return self.name + "[%d]" % self.index
|
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
Node for an OPENQASM integer.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Int(Node):
|
||||
"""Node for an OPENQASM integer.
|
||||
|
||||
This node has no children. The data is in the value field.
|
||||
"""
|
||||
|
||||
def __init__(self, id):
|
||||
"""Create the integer node."""
|
||||
Node.__init__(self, "int", None, None)
|
||||
self.value = id
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print with indent."""
|
||||
ind = indent * ' '
|
||||
print(ind, 'int', self.value)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "%d" % self.value
|
|
@ -0,0 +1,21 @@
|
|||
"""
|
||||
Node for an OPENQASM file identifier/version statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Magic(Node):
|
||||
"""Node for an OPENQASM file identifier/version statement ("magic number").
|
||||
|
||||
children[0] is a floating point number (not a node).
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the version node."""
|
||||
Node.__init__(self, 'magic', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "OPENQASM %.1f;" % self.children[0]
|
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
Node for an OPENQASM measure statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Measure(Node):
|
||||
"""Node for an OPENQASM measure statement.
|
||||
|
||||
children[0] is a primary node (id or indexedid)
|
||||
children[1] is a primary node (id or indexedid)
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the measure node."""
|
||||
Node.__init__(self, 'measure', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "measure " + self.children[0].qasm() + " -> " + \
|
||||
self.children[1].qasm() + ";"
|
|
@ -0,0 +1,50 @@
|
|||
"""
|
||||
Base node object for the OPENQASM syntax tree.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
|
||||
|
||||
class Node(object):
|
||||
"""Base node object for the OPENQASM syntax tree."""
|
||||
|
||||
def __init__(self, type, children=None, root=None):
|
||||
"""Construct a new node object."""
|
||||
self.type = type
|
||||
if children:
|
||||
self.children = children
|
||||
else:
|
||||
self.children = []
|
||||
self.root = root
|
||||
# True if this node is an expression node, False otherwise
|
||||
self.expression = False
|
||||
|
||||
def is_expression(self):
|
||||
"""Return True if this is an expression node."""
|
||||
return self.expression
|
||||
|
||||
def add_child(self, n):
|
||||
"""Add a child node."""
|
||||
self.children.append(n)
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print with indent."""
|
||||
ind = indent * ' '
|
||||
if self.root:
|
||||
print(ind, self.type, '---', self.root)
|
||||
else:
|
||||
print(ind, self.type)
|
||||
indent = indent + 3
|
||||
ind = indent * ' '
|
||||
for c in self.children:
|
||||
if c is None:
|
||||
print("OOPS! type of parent is", type(self))
|
||||
print(self.children)
|
||||
if type(c) is str:
|
||||
print(ind, c)
|
||||
elif type(c) is int:
|
||||
print(ind, str(c))
|
||||
elif type(c) is float:
|
||||
print(ind, str(c))
|
||||
else:
|
||||
c.to_string(indent)
|
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
Node for an OPENQASM opaque gate declaration.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Opaque(Node):
|
||||
"""Node for an OPENQASM opaque gate declaration.
|
||||
|
||||
children[0] is an id node.
|
||||
If len(children) is 3, children[1] is an expressionlist node,
|
||||
and children[2] is an idlist node.
|
||||
Otherwise, children[1] is an idlist node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the opaque gate node."""
|
||||
Node.__init__(self, 'opaque', children, None)
|
||||
self.id = children[0]
|
||||
# The next three fields are required by the symbtab
|
||||
self.name = self.id.name
|
||||
self.line = self.id.line
|
||||
self.file = self.id.file
|
||||
if len(children) == 3:
|
||||
self.arguments = children[1]
|
||||
self.bitlist = children[2]
|
||||
else:
|
||||
self.arguments = None
|
||||
self.bitlist = children[1]
|
||||
|
||||
def n_args(self):
|
||||
"""Return the number of parameter expressions."""
|
||||
if self.arguments:
|
||||
return self.arguments.size()
|
||||
return 0
|
||||
|
||||
def n_bits(self):
|
||||
"""Return the number of qubit arguments."""
|
||||
return self.bitlist.size()
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
s = "opaque %s" % self.name
|
||||
if self.arguments is not None:
|
||||
s += "(" + self.arguments.qasm() + ")"
|
||||
s += self.bitlist.qasm() + ";"
|
||||
return s
|
|
@ -0,0 +1,22 @@
|
|||
"""
|
||||
Node for an OPENQASM prefix expression.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Prefix(Node):
|
||||
"""Node for an OPENQASM prefix expression.
|
||||
|
||||
children[0] is a prefix string such as '-'.
|
||||
children[1] is an expression node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the prefix node."""
|
||||
Node.__init__(self, 'prefix', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return self.children[0] + "(" + self.children[1].qasm() + ")"
|
|
@ -0,0 +1,25 @@
|
|||
"""
|
||||
Node for an OPENQASM primarylist.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class PrimaryList(Node):
|
||||
"""Node for an OPENQASM primarylist.
|
||||
|
||||
children is a list of primary nodes. Primary nodes are indexedid or id.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the primarylist node."""
|
||||
Node.__init__(self, 'primary_list', children, None)
|
||||
|
||||
def size(self):
|
||||
"""Return the size of the list."""
|
||||
return len(self.children)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return ",".join([self.children[j].qasm() for j in range(self.size())])
|
|
@ -0,0 +1,24 @@
|
|||
"""
|
||||
Node for an OPENQASM program.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Program(Node):
|
||||
"""Node for an OPENQASM program.
|
||||
|
||||
children is a list of nodes (statements).
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the program node."""
|
||||
Node.__init__(self, 'program', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
s = ""
|
||||
for c in self.children:
|
||||
s += c.qasm() + "\n"
|
||||
return s
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Node for an OPENQASM qreg statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Qreg(Node):
|
||||
"""Node for an OPENQASM qreg statement.
|
||||
|
||||
children[0] is an indexedid node.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the qreg node."""
|
||||
Node.__init__(self, 'qreg', children, None)
|
||||
# This is the indexed id, the full "id[n]" object
|
||||
self.id = children[0]
|
||||
# Name of the qreg
|
||||
self.name = self.id.name
|
||||
# Source line number
|
||||
self.line = self.id.line
|
||||
# Source file name
|
||||
self.file = self.id.file
|
||||
# Size of the register
|
||||
self.index = self.id.index
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print the node data, with indent."""
|
||||
ind = indent * ' '
|
||||
print(ind, 'qreg')
|
||||
self.children[0].to_string(indent + 3)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "qreg " + self.id.qasm() + ";"
|
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
Node for an OPENQASM real number.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Real(Node):
|
||||
"""Node for an OPENQASM real number.
|
||||
|
||||
This node has no children. The data is in the value field.
|
||||
"""
|
||||
|
||||
def __init__(self, id):
|
||||
"""Create the real node."""
|
||||
Node.__init__(self, "real", None, None)
|
||||
self.value = id
|
||||
|
||||
def to_string(self, indent):
|
||||
"""Print with indent."""
|
||||
ind = indent * ' '
|
||||
print(ind, 'real', self.value)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "%0.15f" % self.value # TODO: control the precision
|
|
@ -0,0 +1,21 @@
|
|||
"""
|
||||
Node for an OPENQASM reset statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Reset(Node):
|
||||
"""Node for an OPENQASM reset statement.
|
||||
|
||||
children[0] is a primary node (id or indexedid)
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the reset node."""
|
||||
Node.__init__(self, 'reset', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "reset " + self.children[0].qasm() + ";"
|
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
Node for an OPENQASM U statement.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class UniversalUnitary(Node):
|
||||
"""Node for an OPENQASM U statement.
|
||||
|
||||
children[0] is an expressionlist node.
|
||||
children[1] is a primary node (id or indexedid).
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
"""Create the U node."""
|
||||
Node.__init__(self, 'universal_unitary', children, None)
|
||||
|
||||
def qasm(self):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
return "U(" + self.children[0].qasm() + ") " + \
|
||||
self.children[1].qasm() + ";"
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
OPENQASM circuit object.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
from ._qasmexception import QasmException
|
||||
from ._qasmparser import QasmParser
|
||||
|
||||
|
||||
class Qasm(object):
|
||||
"""OPENQASM circuit object."""
|
||||
|
||||
def __init__(self, filename=None, data=None):
|
||||
"""Create an OPENQASM circuit object."""
|
||||
if filename is None and data is None:
|
||||
raise QasmException("Missing input file and/or data")
|
||||
if filename is not None and data is not None:
|
||||
raise QasmException("File and data must not both be"
|
||||
+ " specified initializing qasm")
|
||||
self._filename = filename
|
||||
self._data = data
|
||||
|
||||
def print_tokens(self):
|
||||
"""Parse and print tokens."""
|
||||
if self._filename:
|
||||
self._data = open(self._filename).read()
|
||||
|
||||
qasm_p = QasmParser(self._filename)
|
||||
return qasm_p.print_tokens()
|
||||
|
||||
def parse(self):
|
||||
"""Parse the data."""
|
||||
if self._filename:
|
||||
self._data = open(self._filename).read()
|
||||
qasm_p = QasmParser(self._filename)
|
||||
qasm_p.parse_debug(False)
|
||||
return qasm_p.parse(self._data)
|
|
@ -0,0 +1,17 @@
|
|||
"""
|
||||
Exception for errors raised while parsing OPENQASM.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
|
||||
|
||||
class QasmException(Exception):
|
||||
"""Base class for errors raised while parsing OPENQASM."""
|
||||
|
||||
def __init__(self, *msg):
|
||||
"""Set the error message."""
|
||||
self.msg = ' '.join(msg)
|
||||
|
||||
def __str__(self):
|
||||
"""Return the message."""
|
||||
return repr(self.msg)
|
|
@ -0,0 +1,213 @@
|
|||
"""
|
||||
OPENQASM Lexer.
|
||||
|
||||
This is a wrapper around the PLY lexer to support the "include" statement
|
||||
by creating a stack of lexers.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
import os
|
||||
import ply.lex as lex
|
||||
from ._qasmexception import QasmException
|
||||
from . import _node as Node
|
||||
|
||||
|
||||
class QasmLexer(object):
|
||||
"""OPENQASM Lexer.
|
||||
|
||||
This is a wrapper around the PLY lexer to support the "include" statement
|
||||
by creating a stack of lexers.
|
||||
"""
|
||||
|
||||
def __mklexer__(self, filename):
|
||||
"""Create a PLY lexer."""
|
||||
self.lexer = lex.lex(module=self, debug=False)
|
||||
self.filename = filename
|
||||
self.lineno = 1
|
||||
|
||||
def __init__(self, filename):
|
||||
"""Create the OPENQASM lexer."""
|
||||
self.__mklexer__(filename)
|
||||
self.stack = []
|
||||
|
||||
def input(self, data):
|
||||
"""Set the input text data."""
|
||||
self.data = data
|
||||
self.lexer.input(data)
|
||||
|
||||
def token(self):
|
||||
"""Return the next token."""
|
||||
ret = self.lexer.token()
|
||||
return ret
|
||||
|
||||
def pop(self):
|
||||
"""Pop a PLY lexer off the stack."""
|
||||
self.lexer = self.stack.pop()
|
||||
self.filename = self.lexer.qasm_file
|
||||
self.lineno = self.lexer.qasm_line
|
||||
|
||||
def push(self, filename):
|
||||
"""Push a PLY lexer on the stack to parse filename."""
|
||||
self.lexer.qasm_file = self.filename
|
||||
self.lexer.qasm_line = self.lineno
|
||||
self.stack.append(self.lexer)
|
||||
self.__mklexer__(filename)
|
||||
self.data = open(filename).read()
|
||||
self.lexer.input(self.data)
|
||||
|
||||
# ---- Beginning of the PLY lexer ----
|
||||
literals = r'=()[]{};<>,.+-/*"'
|
||||
tokens = (
|
||||
'NNINTEGER',
|
||||
'BARRIER',
|
||||
'OPAQUE',
|
||||
'RESET',
|
||||
'IF',
|
||||
'REAL',
|
||||
'QREG',
|
||||
'CREG',
|
||||
'GATE',
|
||||
'PI',
|
||||
'CX',
|
||||
'U',
|
||||
'MEASURE',
|
||||
'MAGIC',
|
||||
'ASSIGN',
|
||||
'MATCHES',
|
||||
'ID',
|
||||
'STRING',
|
||||
)
|
||||
|
||||
def t_REAL(self, t):
|
||||
r'(([0-9]+|([0-9]+)?\.[0-9]+|[0-9]+\.)[eE][+-]?[0-9]+)|(([0-9]+)?\.[0-9]+|[0-9]+\.)'
|
||||
t.value = float(t.value)
|
||||
# tad nasty, see mkfloat.py to see how this is derived from python spec
|
||||
return t
|
||||
|
||||
def t_NNINTEGER(self, t):
|
||||
r'\d+'
|
||||
t.value = int(t.value)
|
||||
return t
|
||||
|
||||
def t_QREG(self, t):
|
||||
'qreg'
|
||||
return t
|
||||
|
||||
def t_CREG(self, t):
|
||||
'creg'
|
||||
return t
|
||||
|
||||
def t_GATE(self, t):
|
||||
'gate'
|
||||
return t
|
||||
|
||||
def t_MEASURE(self, t):
|
||||
'measure'
|
||||
return t
|
||||
|
||||
def t_IF(self, t):
|
||||
'if'
|
||||
return t
|
||||
|
||||
def t_RESET(self, t):
|
||||
'reset'
|
||||
return t
|
||||
|
||||
def t_ASSIGN(self, t):
|
||||
'->'
|
||||
return t
|
||||
|
||||
def t_MATCHES(self, t):
|
||||
'=='
|
||||
return t
|
||||
|
||||
def t_BARRIER(self, t):
|
||||
'barrier'
|
||||
return t
|
||||
|
||||
def t_OPAQUE(self, t):
|
||||
'opaque'
|
||||
return t
|
||||
|
||||
def t_STRING(self, t):
|
||||
r'\"([^\\\"]|\\.)*\"'
|
||||
return t
|
||||
|
||||
def t_INCLUDE(self, t):
|
||||
'include'
|
||||
|
||||
'''
|
||||
Now eat up the next two tokens which must be
|
||||
1 - the name of the include file, and
|
||||
2 - a terminating semocolon
|
||||
|
||||
Then push the current lexer onto the stack, create a new one from
|
||||
the include file, and push it onto the stack.
|
||||
|
||||
When we hit eof (the t_eof) rule, we pop.
|
||||
'''
|
||||
next = self.lexer.token()
|
||||
lineno = next.lineno
|
||||
# print('NEXT', next, "next.value", next.value, type(next))
|
||||
if type(next.value) == str:
|
||||
incfile = next.value.strip('"')
|
||||
else:
|
||||
raise QasmException("Invalid include: must be a quoted string.")
|
||||
|
||||
next = self.lexer.token()
|
||||
if next is None or next.value != ';':
|
||||
raise QasmException('Invalid syntax, missing ";" at line',
|
||||
str(lineno))
|
||||
|
||||
if not os.path.exists(incfile):
|
||||
raise QasmException('Include file', incfile,
|
||||
'cannot be found, line', str(next.lineno),
|
||||
', file', self.filename)
|
||||
|
||||
self.push(incfile)
|
||||
return self.lexer.token()
|
||||
|
||||
|
||||
def t_MAGIC(self, t):
|
||||
'OPENQASM'
|
||||
return t
|
||||
|
||||
def t_COMMENT(self, t):
|
||||
r'//.*'
|
||||
pass
|
||||
|
||||
def t_ID(self, t):
|
||||
r'[a-zA-Z_][a-zA-Z0-9_]*'
|
||||
|
||||
if t.value == 'U':
|
||||
t.type = 'U'
|
||||
return t
|
||||
|
||||
if t.value == 'CX':
|
||||
t.type = 'CX'
|
||||
return t
|
||||
|
||||
if t.value == 'pi':
|
||||
t.type = 'PI'
|
||||
return t
|
||||
|
||||
t.value = Node.Id(t.value, self.lineno, self.filename)
|
||||
return t
|
||||
|
||||
def t_newline(self, t):
|
||||
r'\n+'
|
||||
self.lineno += len(t.value)
|
||||
t.lexer.lineno = self.lineno
|
||||
|
||||
def t_eof(self, t):
|
||||
if len(self.stack) > 0:
|
||||
self.pop()
|
||||
return self.lexer.token()
|
||||
else:
|
||||
return None
|
||||
|
||||
t_ignore = ' \t\r'
|
||||
|
||||
def t_error(self, t):
|
||||
print("Junk in the line -->%s<--" % t.value[0])
|
||||
# t.lexer.skip(1)
|
|
@ -0,0 +1,978 @@
|
|||
"""
|
||||
OPENQASM parser.
|
||||
|
||||
Author: Jim Challenger
|
||||
"""
|
||||
import math
|
||||
from ._qasmlexer import QasmLexer
|
||||
import ply.yacc as yacc
|
||||
from ._qasmexception import QasmException
|
||||
from . import _node as node
|
||||
|
||||
|
||||
class QasmParser(object):
|
||||
"""OPENQASM Parser."""
|
||||
|
||||
def __init__(self, filename):
|
||||
"""Create the parser."""
|
||||
self.lexer = QasmLexer(filename)
|
||||
self.tokens = self.lexer.tokens
|
||||
self.parser = yacc.yacc(module=self, debug=True)
|
||||
self.qasm = None
|
||||
self.parseDeb = False
|
||||
self.global_symtab = {} # global symtab
|
||||
self.current_symtab = self.global_symtab # top of symbol stack
|
||||
self.symbols = [] # symbol stack
|
||||
|
||||
def update_symtab(self, obj):
|
||||
"""Update a node in the symbol table.
|
||||
|
||||
Everything in the symtab must be a node with these attributes:
|
||||
name - the string name of the object
|
||||
type - the string type of the object
|
||||
line - the source line where the type was first found
|
||||
file - the source file where the type was first found
|
||||
"""
|
||||
if obj.name in self.current_symtab:
|
||||
prev = self.current_symtab[obj.name]
|
||||
raise QasmException("Duplicate declaretion for", obj.type + " '"
|
||||
+ obj.name + "' at line", str(obj.line)
|
||||
+ ', file', obj.file
|
||||
+ '.\nPrevious occurance at line',
|
||||
str(prev.line) + ', file', prev.file)
|
||||
self.current_symtab[obj.name] = obj
|
||||
|
||||
def verify_declared_bit(self, obj):
|
||||
"""Verify a qubit id against the gate prototype."""
|
||||
# We are verifying gate args against the formal parameters of a
|
||||
# gate prototype.
|
||||
if obj.name not in self.current_symtab:
|
||||
raise QasmException("Cannot find symbol '" + obj.name
|
||||
+ "' in argument list for gate, line",
|
||||
str(obj.line), 'file', obj.file)
|
||||
|
||||
# This insures the thing is from the bitlist and not from the
|
||||
# argument list.
|
||||
sym = self.current_symtab[obj.name]
|
||||
if not (sym.type == 'id' and sym.is_bit):
|
||||
raise QasmException("Bit", obj.name,
|
||||
'is not declared as a bit in the gate.')
|
||||
|
||||
def verify_bit_list(self, obj):
|
||||
"""Verify each qubit in a list of ids."""
|
||||
# We expect the object to be a bitlist or an idlist, we don't care.
|
||||
# We will iterate it and insure everything in it is declared as a bit,
|
||||
# and throw if not.
|
||||
for b in obj.children:
|
||||
self.verify_declared_bit(b)
|
||||
|
||||
def verify_exp_list(self, obj):
|
||||
"""Verify each expression in a list."""
|
||||
# A tad harder. This is a list of expressions each of which could be
|
||||
# the head of a tree. We need to recursively walk each of these and
|
||||
# ensure that any Id elements resolve to the current stack.
|
||||
#
|
||||
# I believe we only have to look at the current symtab.
|
||||
if obj.children is not None:
|
||||
for child in obj.children:
|
||||
if isinstance(child, node.Id):
|
||||
if child.name in ['sin', 'cos', 'tan', 'exp',
|
||||
'ln', 'sqrt']:
|
||||
continue
|
||||
|
||||
if child.name not in self.current_symtab:
|
||||
raise QasmException("Argument '" + child.name
|
||||
+ "' in expression cannot be "
|
||||
+ "found, line", str(child.line),
|
||||
"file", child.file)
|
||||
else:
|
||||
if hasattr(child, "children"):
|
||||
self.verify_exp_list(child)
|
||||
|
||||
def verify_as_gate(self, obj, bitlist, arglist=None):
|
||||
"""Verify a user defined gate call."""
|
||||
if obj.name not in self.global_symtab:
|
||||
raise QasmException("Cannot find gate definition for '" + obj.name
|
||||
+ "', line", str(obj.line), 'file', obj.file)
|
||||
g = self.global_symtab[obj.name]
|
||||
if not (g.type == 'gate' or g.type == 'opaque'):
|
||||
raise QasmException("'" + obj.name + "' is used as a gate "
|
||||
+ "or opaque call but the symbol is neither;"
|
||||
+ " it is a '" + g.type + "' line",
|
||||
str(obj.line), 'file', obj.file)
|
||||
|
||||
if g.n_bits() != bitlist.size():
|
||||
raise QasmException("Gate or opaque call to '" + obj.name
|
||||
+ "' uses", str(bitlist.size()),
|
||||
"qubits but is declared for",
|
||||
str(g.n_bits()), "qubits", "line",
|
||||
str(obj.line), 'file', obj.file)
|
||||
|
||||
if arglist:
|
||||
if g.n_args() != arglist.size():
|
||||
raise QasmException("Gate or opaque call to '" + obj.name
|
||||
+ "' uses", str(arglist.size()),
|
||||
"qubits but is declared for",
|
||||
str(g.n_args()), "qubits", "line",
|
||||
str(obj.line), 'file', obj.file)
|
||||
else:
|
||||
if g.n_args() > 0:
|
||||
raise QasmException("Gate or opaque call to '" + obj.name
|
||||
+ "' has no arguments but is declared for",
|
||||
str(g.n_args()), "qubits", "line",
|
||||
str(obj.line), 'file', obj.file)
|
||||
|
||||
def verify_reg(self, obj, typ):
|
||||
"""Verify a register."""
|
||||
# How to verify:
|
||||
# types must match
|
||||
# indexes must be checked
|
||||
if obj.name not in self.global_symtab:
|
||||
raise QasmException('Cannot find definition for', typ, "'"
|
||||
+ obj.name + "'", 'at line', str(obj.line),
|
||||
'file', obj.file)
|
||||
|
||||
sym = self.global_symtab[obj.name]
|
||||
|
||||
if sym.type != typ:
|
||||
raise QasmException("Type for '" + sym.name + "' should be '"
|
||||
+ typ + "' but was found to be '" + sym.type
|
||||
+ "'", "line", str(obj.line), "file", obj.file)
|
||||
|
||||
if obj.type == 'indexed_id':
|
||||
bound = sym.index
|
||||
ndx = obj.index
|
||||
if ndx < 0 or ndx >= bound:
|
||||
raise QasmException("Register index for '" + sym.name
|
||||
+ "' out of bounds. Index is", str(ndx),
|
||||
"bound is 0 <= index <", str(bound),
|
||||
"at line", str(obj.line), "file", obj.file)
|
||||
|
||||
def verify_reg_list(self, obj, typ):
|
||||
"""Verify a list of registers."""
|
||||
# We expect the object to be a bitlist or an idlist, we don't care.
|
||||
# We will iterate it and ensure everything in it is declared as a bit,
|
||||
# and throw if not.
|
||||
for b in obj.children:
|
||||
self.verify_reg(b, typ)
|
||||
|
||||
def pop_scope(self):
|
||||
"""Return to the previous scope."""
|
||||
self.current_symtab = self.symbols.pop()
|
||||
|
||||
def push_scope(self):
|
||||
"""Enter a new scope."""
|
||||
self.symbols.append(self.current_symtab)
|
||||
self.current_symtab = {}
|
||||
|
||||
# ---- Begin the PLY parser ----
|
||||
start = 'main'
|
||||
|
||||
def p_main(self, p):
|
||||
'''
|
||||
main : program
|
||||
'''
|
||||
self.qasm = p[1]
|
||||
|
||||
# ----------------------------------------
|
||||
# program : statement
|
||||
# | program statement
|
||||
# ----------------------------------------
|
||||
def p_program_0(self, p):
|
||||
'''
|
||||
program : statement
|
||||
'''
|
||||
p[0] = node.Program([p[1]])
|
||||
|
||||
def p_program_1(self, p):
|
||||
'''
|
||||
program : program statement
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[0].add_child(p[2])
|
||||
|
||||
# ----------------------------------------
|
||||
# statement : decl
|
||||
# | quantum_op ';'
|
||||
# | magic ';'
|
||||
# ----------------------------------------
|
||||
def p_statement(self, p):
|
||||
'''
|
||||
statement : decl
|
||||
| quantum_op ';'
|
||||
| magic ';'
|
||||
| ignore
|
||||
| quantum_op error
|
||||
| magic error
|
||||
'''
|
||||
if len(p) > 2:
|
||||
if p[2] != ';':
|
||||
raise QasmException("Missing ';' at end of statement; "
|
||||
+ "received", str(p[2].value))
|
||||
p[0] = p[1]
|
||||
|
||||
def p_magic(self, p):
|
||||
'''
|
||||
magic : MAGIC REAL
|
||||
'''
|
||||
p[0] = node.Magic([p[2]])
|
||||
|
||||
def p_magic_0(self, p):
|
||||
'''
|
||||
magic : MAGIC error
|
||||
'''
|
||||
magic = "2.0;"
|
||||
raise QasmException("Invalid magic string. Expected '" + magic
|
||||
+ "'. Is the semicolon missing?")
|
||||
|
||||
# ----------------------------------------
|
||||
# id : ID
|
||||
# ----------------------------------------
|
||||
def p_id(self, p):
|
||||
'''
|
||||
id : ID
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_id_e(self, p):
|
||||
'''
|
||||
id : error
|
||||
'''
|
||||
raise QasmException("Expected an ID, received '"
|
||||
+ str(p[1].value) + "'")
|
||||
|
||||
# ----------------------------------------
|
||||
# indexed_id : ID [ int ]
|
||||
# ----------------------------------------
|
||||
def p_indexed_id(self, p):
|
||||
'''
|
||||
indexed_id : id '[' NNINTEGER ']'
|
||||
| id '[' NNINTEGER error
|
||||
| id '[' error
|
||||
'''
|
||||
if len(p) == 4:
|
||||
raise QasmException("Expecting an integer index; received",
|
||||
str(p[3].value))
|
||||
if p[4] != ']':
|
||||
raise QasmException("Missing ']' in indexed ID; received",
|
||||
str(p[4].value))
|
||||
p[0] = node.IndexedId([p[1], p[3]])
|
||||
|
||||
# ----------------------------------------
|
||||
# primary : id
|
||||
# | indexed_id
|
||||
# ----------------------------------------
|
||||
def p_primary(self, p):
|
||||
'''
|
||||
primary : id
|
||||
| indexed_id
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
# ----------------------------------------
|
||||
# id_list : id
|
||||
# | id_list ',' id
|
||||
# ----------------------------------------
|
||||
def p_id_list_0(self, p):
|
||||
'''
|
||||
id_list : id
|
||||
'''
|
||||
p[0] = node.IdList([p[1]])
|
||||
|
||||
def p_id_list_1(self, p):
|
||||
'''
|
||||
id_list : id_list ',' id
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[0].add_child(p[3])
|
||||
|
||||
# ----------------------------------------
|
||||
# gate_id_list : id
|
||||
# | gate_id_list ',' id
|
||||
# ----------------------------------------
|
||||
def p_gate_id_list_0(self, p):
|
||||
'''
|
||||
gate_id_list : id
|
||||
'''
|
||||
p[0] = node.IdList([p[1]])
|
||||
self.update_symtab(p[1])
|
||||
|
||||
def p_gate_id_list_1(self, p):
|
||||
'''
|
||||
gate_id_list : gate_id_list ',' id
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[0].add_child(p[3])
|
||||
self.update_symtab(p[3])
|
||||
|
||||
# ----------------------------------------
|
||||
# bit_list : bit
|
||||
# | bit_list ',' bit
|
||||
# ----------------------------------------
|
||||
def p_bit_list_0(self, p):
|
||||
'''
|
||||
bit_list : id
|
||||
'''
|
||||
p[0] = node.IdList([p[1]])
|
||||
p[1].is_bit = True
|
||||
self.update_symtab(p[1])
|
||||
|
||||
def p_bit_list_1(self, p):
|
||||
'''
|
||||
bit_list : bit_list ',' id
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[0].add_child(p[3])
|
||||
p[3].is_bit = True
|
||||
self.update_symtab(p[3])
|
||||
|
||||
# ----------------------------------------
|
||||
# primary_list : primary
|
||||
# | primary_list ',' primary
|
||||
# ----------------------------------------
|
||||
def p_primary_list_0(self, p):
|
||||
'''
|
||||
primary_list : primary
|
||||
'''
|
||||
p[0] = node.PrimaryList([p[1]])
|
||||
|
||||
def p_primary_list_1(self, p):
|
||||
'''
|
||||
primary_list : primary_list ',' primary
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[1].add_child(p[3])
|
||||
|
||||
# ----------------------------------------
|
||||
# decl : qreg_decl
|
||||
# | creg_decl
|
||||
# | gate_decl
|
||||
# ----------------------------------------
|
||||
def p_decl(self, p):
|
||||
'''
|
||||
decl : qreg_decl ';'
|
||||
| creg_decl ';'
|
||||
| qreg_decl error
|
||||
| creg_decl error
|
||||
| gate_decl
|
||||
'''
|
||||
if len(p) > 2:
|
||||
if p[2] != ';':
|
||||
raise QasmException("Missing ';' in qreg or creg declaraton."
|
||||
+ " Instead received '" + p[2].value + "'")
|
||||
p[0] = p[1]
|
||||
|
||||
# ----------------------------------------
|
||||
# qreg_decl : QREG indexed_id
|
||||
# ----------------------------------------
|
||||
def p_qreg_decl(self, p):
|
||||
'''
|
||||
qreg_decl : QREG indexed_id
|
||||
'''
|
||||
p[0] = node.Qreg([p[2]])
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_qreg_decl_e(self, p):
|
||||
'''
|
||||
qreg_decl : QREG error
|
||||
'''
|
||||
raise QasmException("Expecting indexed id (ID[int]) in QREG"
|
||||
+ " declaration; received", p[2].value)
|
||||
|
||||
# ----------------------------------------
|
||||
# creg_decl : QREG indexed_id
|
||||
# ----------------------------------------
|
||||
def p_creg_decl(self, p):
|
||||
'''
|
||||
creg_decl : CREG indexed_id
|
||||
'''
|
||||
p[0] = node.Creg([p[2]])
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_creg_decl_e(self, p):
|
||||
'''
|
||||
creg_decl : CREG error
|
||||
'''
|
||||
raise QasmException("Expecting indexed id (ID[int]) in CREG"
|
||||
+ " declaration; received", p[2].value)
|
||||
|
||||
# Gate_body will throw if there are errors, so we don't need to cover
|
||||
# that here. Same with the id_lists - if they are not legal, we die
|
||||
# before we get here
|
||||
#
|
||||
# ----------------------------------------
|
||||
# gate_decl : GATE id gate_scope bit_list gate_body
|
||||
# | GATE id gate_scope '(' ')' bit_list gate_body
|
||||
# | GATE id gate_scope '(' gate_id_list ')' bit_list gate_body
|
||||
#
|
||||
# ----------------------------------------
|
||||
def p_gate_decl_0(self, p):
|
||||
'''
|
||||
gate_decl : GATE id gate_scope bit_list gate_body
|
||||
'''
|
||||
p[0] = node.Gate([p[2], p[4], p[5]])
|
||||
self.pop_scope()
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_gate_decl_1(self, p):
|
||||
'''
|
||||
gate_decl : GATE id gate_scope '(' ')' bit_list gate_body
|
||||
'''
|
||||
p[0] = node.Gate([p[2], p[6], p[7]])
|
||||
self.pop_scope()
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_gate_decl_2(self, p):
|
||||
'''
|
||||
gate_decl : GATE id gate_scope '(' gate_id_list ')' bit_list gate_body
|
||||
'''
|
||||
p[0] = node.Gate([p[2], p[5], p[7], p[8]])
|
||||
self.pop_scope()
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_gate_scope(self, p):
|
||||
'''
|
||||
gate_scope :
|
||||
'''
|
||||
self.push_scope()
|
||||
|
||||
# ----------------------------------------
|
||||
# gate_body : '{' gate_op_list '}'
|
||||
# | '{' '}'
|
||||
#
|
||||
# | '{' gate_op_list error
|
||||
# | '{' error
|
||||
#
|
||||
# Error handling: gete_op will throw if there's a problem so we won't
|
||||
# get here with in the gate_op_list
|
||||
# ----------------------------------------
|
||||
def p_gate_body_0(self, p):
|
||||
'''
|
||||
gate_body : '{' '}'
|
||||
'''
|
||||
if p[2] != '}':
|
||||
raise QasmException("Missing '}' in gate definition; received'"
|
||||
+ str(p[2].value) + "'")
|
||||
p[0] = node.GateBody(None)
|
||||
|
||||
def p_gate_body_1(self, p):
|
||||
'''
|
||||
gate_body : '{' gate_op_list '}'
|
||||
'''
|
||||
p[0] = node.GateBody(p[2])
|
||||
|
||||
# ----------------------------------------
|
||||
# gate_op_list : gate_op
|
||||
# | gate_op_ist gate_op
|
||||
#
|
||||
# Error handling: gete_op will throw if there's a problem so we won't
|
||||
# get here with errors
|
||||
# ----------------------------------------
|
||||
def p_gate_op_list_0(self, p):
|
||||
'''
|
||||
gate_op_list : gate_op
|
||||
'''
|
||||
p[0] = [p[1]]
|
||||
|
||||
def p_gate_op_list_1(self, p):
|
||||
'''
|
||||
gate_op_list : gate_op_list gate_op
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[0].append(p[2])
|
||||
|
||||
# ----------------------------------------
|
||||
# These are for use outside of gate_bodies and allow
|
||||
# indexed ids everywhere.
|
||||
#
|
||||
# unitary_op : U '(' exp_list ')' primary
|
||||
# | CX primary ',' primary
|
||||
# | id pirmary_list
|
||||
# | id '(' ')' primary_list
|
||||
# | id '(' exp_list ')' primary_list
|
||||
#
|
||||
# Note that it might not be unitary - this is the mechanism that
|
||||
# is also used to invoke calls to 'opaque'
|
||||
# ----------------------------------------
|
||||
def p_unitary_op_0(self, p):
|
||||
'''
|
||||
unitary_op : U '(' exp_list ')' primary
|
||||
'''
|
||||
p[0] = node.UniversalUnitary([p[3], p[5]])
|
||||
self.verify_reg(p[5], 'qreg')
|
||||
self.verify_exp_list(p[3])
|
||||
|
||||
def p_unitary_op_1(self, p):
|
||||
'''
|
||||
unitary_op : CX primary ',' primary
|
||||
'''
|
||||
p[0] = node.Cnot([p[2], p[4]])
|
||||
self.verify_reg(p[2], 'qreg')
|
||||
self.verify_reg(p[4], 'qreg')
|
||||
|
||||
def p_unitary_op_2(self, p):
|
||||
'''
|
||||
unitary_op : id primary_list
|
||||
'''
|
||||
p[0] = node.CustomUnitary([p[1], p[2]])
|
||||
self.verify_as_gate(p[1], p[2])
|
||||
self.verify_reg_list(p[2], 'qreg')
|
||||
|
||||
def p_unitary_op_3(self, p):
|
||||
'''
|
||||
unitary_op : id '(' ')' primary_list
|
||||
'''
|
||||
p[0] = node.CustomUnitary([p[1], p[4]])
|
||||
self.verify_as_gate(p[1], p[4])
|
||||
self.verify_reg_list(p[4], 'qreg')
|
||||
|
||||
def p_unitary_op_4(self, p):
|
||||
'''
|
||||
unitary_op : id '(' exp_list ')' primary_list
|
||||
'''
|
||||
p[0] = node.CustomUnitary([p[1], p[3], p[5]])
|
||||
self.verify_as_gate(p[1], p[5], arglist=p[3])
|
||||
self.verify_reg_list(p[5], 'qreg')
|
||||
self.verify_exp_list(p[3])
|
||||
|
||||
# ----------------------------------------
|
||||
# This is a restricted set of "quantum_op" which also
|
||||
# prohibits indexed ids, for use in a gate_body
|
||||
#
|
||||
# gate_op : U '(' exp_list ')' id ';'
|
||||
# | CX id ',' id ';'
|
||||
# | id id_list ';'
|
||||
# | id '(' ')' id_list ';'
|
||||
# | id '(' exp_list ')' id_list ';'
|
||||
# | BARRIER id_list ';'
|
||||
# ----------------------------------------
|
||||
def p_gate_op_0(self, p):
|
||||
'''
|
||||
gate_op : U '(' exp_list ')' id ';'
|
||||
'''
|
||||
p[0] = node.UniversalUnitary([p[3], p[5]])
|
||||
self.verify_declared_bit(p[5])
|
||||
self.verify_exp_list(p[3])
|
||||
|
||||
def p_gate_op_0e1(self, p):
|
||||
'''
|
||||
gate_op : U '(' exp_list ')' error
|
||||
'''
|
||||
raise QasmException("Invalid U inside gate definition. "
|
||||
+ "Missing bit id or ';'")
|
||||
|
||||
def p_gate_op_0e2(self, p):
|
||||
'''
|
||||
gate_op : U '(' exp_list error
|
||||
'''
|
||||
raise QasmException("Missing ')' in U invocation in gate definition.")
|
||||
|
||||
def p_gate_op_1(self, p):
|
||||
'''
|
||||
gate_op : CX id ',' id ';'
|
||||
'''
|
||||
p[0] = node.Cnot([p[2], p[4]])
|
||||
self.verify_declared_bit(p[2])
|
||||
self.verify_declared_bit(p[4])
|
||||
|
||||
def p_gate_op_1e1(self, p):
|
||||
'''
|
||||
gate_op : CX error
|
||||
'''
|
||||
raise QasmException("Invalid CX inside gate definition. "
|
||||
+ "Expected an ID or '.', received '"
|
||||
+ str(p[2].value) + "'")
|
||||
|
||||
def p_gate_op_1e2(self, p):
|
||||
'''
|
||||
gate_op : CX id ',' error
|
||||
'''
|
||||
raise QasmException("Invalid CX inside gate definition. "
|
||||
+ "Expected an ID or ';', received '"
|
||||
+ str(p[4].value) + "'")
|
||||
|
||||
def p_gate_op_2(self, p):
|
||||
'''
|
||||
gate_op : id id_list ';'
|
||||
'''
|
||||
p[0] = node.CustomUnitary([p[1], p[2]])
|
||||
# To verify:
|
||||
# 1. id is declared as a gate in global scope
|
||||
# 2. everything in the id_list is declared as a bit in local scope
|
||||
self.verify_as_gate(p[1], p[2])
|
||||
self.verify_bit_list(p[2])
|
||||
|
||||
def p_gate_op_2e(self, p):
|
||||
'''
|
||||
gate_op : id id_list error
|
||||
'''
|
||||
raise QasmException("Invalid gate invocation inside gate definition.")
|
||||
|
||||
def p_gate_op_3(self, p):
|
||||
'''
|
||||
gate_op : id '(' ')' id_list ';'
|
||||
'''
|
||||
p[0] = node.CustomUnitary([p[1], p[4]])
|
||||
self.verify_as_gate(p[1], p[4])
|
||||
self.verify_bit_list(p[4])
|
||||
|
||||
def p_gate_op_4(self, p):
|
||||
'''
|
||||
gate_op : id '(' exp_list ')' id_list ';'
|
||||
'''
|
||||
p[0] = node.CustomUnitary([p[1], p[3], p[5]])
|
||||
self.verify_as_gate(p[1], p[5], arglist=p[3])
|
||||
self.verify_bit_list(p[5])
|
||||
self.verify_exp_list(p[3])
|
||||
|
||||
def p_gate_op_4e0(self, p):
|
||||
'''
|
||||
gate_op : id '(' ')' error
|
||||
'''
|
||||
raise QasmException("Invalid bit list inside gate definition or"
|
||||
+ " missing ';'")
|
||||
|
||||
def p_gate_op_4e1(self, p):
|
||||
'''
|
||||
gate_op : id '(' error
|
||||
'''
|
||||
raise QasmException("Unmatched () for gate invocation inside gate"
|
||||
+ " invocation.")
|
||||
|
||||
def p_gate_op_5(self, p):
|
||||
'''
|
||||
gate_op : BARRIER id_list ';'
|
||||
'''
|
||||
p[0] = node.Barrier([p[2]])
|
||||
self.verify_bit_list(p[2])
|
||||
|
||||
def p_gate_op_5e(self, p):
|
||||
'''
|
||||
gate_op : BARRIER error
|
||||
'''
|
||||
raise QasmException("Invalid barrier inside gate definition.")
|
||||
|
||||
# ----------------------------------------
|
||||
# opaque : OPAQUE id gate_scope bit_list
|
||||
# | OPAQUE id gate_scope '(' ')' bit_list
|
||||
# | OPAQUE id gate_scope '(' gate_id_list ')' bit_list
|
||||
#
|
||||
# These are like gate declaratons only wihtout a body.
|
||||
# ----------------------------------------
|
||||
def p_opaque_0(self, p):
|
||||
'''
|
||||
opaque : OPAQUE id gate_scope bit_list
|
||||
'''
|
||||
p[0] = Opaque([p[2], p[4]])
|
||||
self.pop_scope()
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_opaque_1(self, p):
|
||||
'''
|
||||
opaque : OPAQUE id gate_scope '(' ')' bit_list
|
||||
'''
|
||||
p[0] = node.Opaque([p[2], p[6]])
|
||||
self.pop_scope()
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_opaque_2(self, p):
|
||||
'''
|
||||
opaque : OPAQUE id gate_scope '(' gate_id_list ')' bit_list
|
||||
'''
|
||||
p[0] = node.Opaque([p[2], p[5], p[7]])
|
||||
self.pop_scope()
|
||||
self.update_symtab(p[0])
|
||||
|
||||
def p_opaque_1e(self, p):
|
||||
'''
|
||||
opaque : OPAQUE id gate_scope '(' error
|
||||
'''
|
||||
raise QasmException("Poorly formed OPAQUE statement.")
|
||||
|
||||
# ----------------------------------------
|
||||
# measure : MEASURE primary ASSIGN primary
|
||||
# ----------------------------------------
|
||||
def p_measure(self, p):
|
||||
'''
|
||||
measure : MEASURE primary ASSIGN primary
|
||||
'''
|
||||
p[0] = node.Measure([p[2], p[4]])
|
||||
self.verify_reg(p[2], 'qreg')
|
||||
self.verify_reg(p[4], 'creg')
|
||||
|
||||
def p_measure_e(self, p):
|
||||
|
||||
'''
|
||||
measure : MEASURE primary error
|
||||
'''
|
||||
raise QasmException("Illegal measure statement." + str(p[3].value))
|
||||
|
||||
# ----------------------------------------
|
||||
# barrier : BARRIER primary_list
|
||||
#
|
||||
# Errors are covered by handling erros in primary_list
|
||||
# ----------------------------------------
|
||||
def p_barrier(self, p):
|
||||
'''
|
||||
barrier : BARRIER primary_list
|
||||
'''
|
||||
p[0] = node.Barrier([p[2]])
|
||||
self.verify_reg_list(p[2], 'qreg')
|
||||
|
||||
# ----------------------------------------
|
||||
# reset : RESET primary
|
||||
# ----------------------------------------
|
||||
def p_reset(self, p):
|
||||
'''
|
||||
reset : RESET primary
|
||||
'''
|
||||
p[0] = node.Reset([p[2]])
|
||||
self.verify_reg(p[2], 'qreg')
|
||||
|
||||
# ----------------------------------------
|
||||
# IF '(' ID MATCHES NNINTEGER ')' quantum_op
|
||||
# ----------------------------------------
|
||||
def p_if(self, p):
|
||||
'''
|
||||
if : IF '(' id MATCHES NNINTEGER ')' quantum_op
|
||||
if : IF '(' id error
|
||||
if : IF '(' id MATCHES error
|
||||
if : IF '(' id MATCHES NNINTEGER error
|
||||
if : IF error
|
||||
'''
|
||||
if len(p) == 3:
|
||||
raise QasmException("Ill-formed IF statement. Perhaps a"
|
||||
+ " missing '('?")
|
||||
if len(p) == 5:
|
||||
raise QasmException("Ill-formed IF statement. Expected '==', "
|
||||
+ "received '" + str(p[4].value))
|
||||
if len(p) == 6:
|
||||
raise QasmException("Ill-formed IF statement. Expected a number, "
|
||||
+ "received '" + str(p[5].value))
|
||||
if len(p) == 7:
|
||||
raise QasmException("Ill-formed IF statement, unmatched '('")
|
||||
|
||||
p[0] = node.If([p[3], p[5], p[7]])
|
||||
|
||||
# ----------------------------------------
|
||||
# These are all the things you can have outside of a gate declaration
|
||||
# quantum_op : unitary_op
|
||||
# | opaque
|
||||
# | measure
|
||||
# | reset
|
||||
# | barrier
|
||||
# | if
|
||||
#
|
||||
# ----------------------------------------
|
||||
def p_quantum_op(self, p):
|
||||
'''
|
||||
quantum_op : unitary_op
|
||||
| opaque
|
||||
| measure
|
||||
| barrier
|
||||
| reset
|
||||
| if
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
# ----------------------------------------
|
||||
# unary : NNINTEGER
|
||||
# | REAL
|
||||
# | PI
|
||||
# | ID
|
||||
# | '(' expression ')'
|
||||
# | id '(' expression ')'
|
||||
#
|
||||
# We will trust 'expression' to throw before we have to handle it here
|
||||
# ----------------------------------------
|
||||
def p_unary_0(self, p):
|
||||
'''
|
||||
unary : NNINTEGER
|
||||
'''
|
||||
p[0] = node.Int(p[1])
|
||||
|
||||
def p_unary_1(self, p):
|
||||
'''
|
||||
unary : REAL
|
||||
'''
|
||||
p[0] = node.Real(p[1])
|
||||
|
||||
def p_unary_2(self, p):
|
||||
'''
|
||||
unary : PI
|
||||
'''
|
||||
p[0] = node.Real(math.pi)
|
||||
|
||||
def p_unary_3(self, p):
|
||||
'''
|
||||
unary : id
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_unary_4(self, p):
|
||||
'''
|
||||
unary : '(' expression ')'
|
||||
'''
|
||||
p[0] = p[2]
|
||||
|
||||
def p_unary_6(self, p):
|
||||
'''
|
||||
unary : id '(' expression ')'
|
||||
'''
|
||||
# note this is a semantic check, not syntactic
|
||||
if p[1].name not in ['sin', 'cos', 'tan', 'exp', 'ln', 'sqrt']:
|
||||
raise QasmException("Illegal external function call: ",
|
||||
str(p[1].name))
|
||||
p[0] = node.External([p[1], p[3]])
|
||||
|
||||
# ----------------------------------------
|
||||
# Prefix
|
||||
# ----------------------------------------
|
||||
def p_prefix_expression_0(self, p):
|
||||
'''
|
||||
prefix_expression : unary
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_prefix_expression_1(self, p):
|
||||
'''
|
||||
prefix_expression : '+' prefix_expression
|
||||
| '-' prefix_expression
|
||||
'''
|
||||
p[0] = node.Prefix([p[1], p[2]])
|
||||
|
||||
def p_additive_expression_0(self, p):
|
||||
'''
|
||||
additive_expression : prefix_expression
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_additive_expression_1(self, p):
|
||||
'''
|
||||
additive_expression : additive_expression '+' prefix_expression
|
||||
| additive_expression '-' prefix_expression
|
||||
'''
|
||||
p[0] = node.BinaryOp([p[2], p[1], p[3]])
|
||||
|
||||
def p_multiplicative_expression_0(self, p):
|
||||
'''
|
||||
multiplicative_expression : additive_expression
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_multiplicative_expression_1(self, p):
|
||||
'''
|
||||
multiplicative_expression : multiplicative_expression '*' additive_expression
|
||||
| multiplicative_expression '/' additive_expression
|
||||
'''
|
||||
p[0] = node.BinaryOp([p[2], p[1], p[3]])
|
||||
|
||||
def p_expression_0(self, p):
|
||||
'''
|
||||
expression : multiplicative_expression
|
||||
'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_expression_1(self, p):
|
||||
'''
|
||||
expression : expression '^' multiplicative_expression
|
||||
'''
|
||||
p[0] = node.BinaryOp([p[2], p[1], p[3]])
|
||||
|
||||
# ----------------------------------------
|
||||
# exp_list : exp
|
||||
# | exp_list ',' exp
|
||||
# ----------------------------------------
|
||||
def p_exp_list_0(self, p):
|
||||
'''
|
||||
exp_list : expression
|
||||
'''
|
||||
p[0] = node.ExpressionList([p[1]])
|
||||
|
||||
def p_exp_list_1(self, p):
|
||||
'''
|
||||
exp_list : exp_list ',' expression
|
||||
'''
|
||||
p[0] = p[1]
|
||||
p[0].add_child(p[3])
|
||||
|
||||
def p_ignore(self, p):
|
||||
'''
|
||||
ignore : STRING
|
||||
'''
|
||||
# this should never hit but it keeps the unsupressable warnings at bay
|
||||
pass
|
||||
|
||||
def p_error(self, p):
|
||||
# EOF is a special case because the stupid error token isn't placed
|
||||
# on the stack
|
||||
if not p:
|
||||
raise QasmException("Error at end of file. "
|
||||
+ "Perhaps there is a missing ';'")
|
||||
|
||||
col = self.find_column(self.lexer.data, p)
|
||||
print("Error near line", str(self.lexer.lineno), 'Column', col)
|
||||
|
||||
def find_column(self, input, token):
|
||||
"""Compute the column.
|
||||
|
||||
Input is the input text string.
|
||||
token is a token instance.
|
||||
"""
|
||||
if token is None:
|
||||
return 0
|
||||
last_cr = input.rfind('\n', 0, token.lexpos)
|
||||
if last_cr < 0:
|
||||
last_cr = 0
|
||||
column = (token.lexpos - last_cr) + 1
|
||||
return column
|
||||
|
||||
def print_tokens(self):
|
||||
'''Test method to verify tokenizer.'''
|
||||
try:
|
||||
while True:
|
||||
tok = self.lexer.token()
|
||||
if not tok:
|
||||
break
|
||||
# TODO: This isn't really the column, it's the character
|
||||
# position. Need to do backtrack to the nearest \n to get
|
||||
# the actual column.
|
||||
print('TOKEN:' + str(tok) + ":ENDTOKEN", 'at line',
|
||||
tok.lineno, 'column', tok.lexpos, 'file',
|
||||
self.lexer.filename)
|
||||
except QasmException as e:
|
||||
print('Exception tokenizing qasm file:', e.msg)
|
||||
|
||||
def parse_debug(self, val):
|
||||
"""Set the parseDeb field."""
|
||||
if val is True:
|
||||
self.parseDeb = True
|
||||
elif val is False:
|
||||
self.parseDeb = False
|
||||
else:
|
||||
raise QasmException("Illegal debug value '" + str(val)
|
||||
+ "' must be True or False.")
|
||||
|
||||
def parse(self, data):
|
||||
"""Parse some data."""
|
||||
self.parser.parse(data, lexer=self.lexer, debug=self.parseDeb)
|
||||
if self.qasm is None:
|
||||
raise QasmException("Uncaught exception in parser; "
|
||||
+ "see previous messages for details.")
|
||||
return self.qasm
|
||||
|
||||
def print_tree(self):
|
||||
"""Print parsed OPENQASM."""
|
||||
if self.qasm is not None:
|
||||
self.qasm.to_string(0)
|
||||
else:
|
||||
print("No parsed qasm to print")
|
||||
|
||||
def run(self, data):
|
||||
"""Parser runner.
|
||||
|
||||
To use this module stand-alone.
|
||||
"""
|
||||
ast = self.parser.parse(data, debug=True)
|
||||
self.parser.parse(data, debug=True)
|
||||
ast.to_string(0)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue