def _parse_funcs(text, is_output=False): if is_output: text = text[text.index(FUNCTION_START):text.index(FUNCTION_END)] funcs = {} # syntax we don't want to see in the final parse tree LPAR, RPAR, LBRACE, RBRACE, COMMA, SEMICOLON = map(Suppress, "(){},;") const = Keyword("const") static = Keyword("static") inline = Keyword("inline") dtype = Word(alphanums + "_*") identifier = Word(alphanums + "_") argDecl = Group( Optional(const("const")) + dtype("dtype") + Optional(identifier("name")) + Optional(COMMA)) args = Group(ZeroOrMore(argDecl)) if not is_output: func = Optional(Suppress("DVZ_EXPORT")) + \ Optional(Suppress("DVZ_INLINE")) else: func = Empty() signature = Optional(static("static")) + \ Optional(inline("inline")) + \ dtype("out") + \ identifier("name") + \ LPAR + args("args") + RPAR + \ Optional(SEMICOLON) func = cStyleComment("docstring") + func + \ signature("signature") for item, start, stop in func.scanString(text): args = [] # for i, entry in enumerate(item.args): # args.append((entry.const, entry.dtype, entry.name)) funcs[item.name] = item return funcs
def parse(liberty_string): # _p.ParserElement.enablePackrat() <- dont, kills memory - and slower... identifier = _p.Word(_p.alphanums + "._") # a name for.. EOL = _p.LineEnd().suppress() # end of line ws = " \t" _p.ParserElement.setDefaultWhitespaceChars(ws) linebreak = _p.Suppress("\\" + _p.LineEnd()) o_linebreak = _p.Optional(linebreak) library_name = identifier b_left = _p.Suppress("(") b_right = _p.Suppress(")") cb_left = _p.Suppress("{") cb_right = _p.Suppress("}") semicolon = _p.Suppress(";") colon = _p.Suppress(":") quote = _p.Suppress('"') emptyquote = '""' comma = _p.Suppress(",") comment = _p.Suppress(_p.cStyleComment()) valuestring = _p.Word(_p.alphanums + "'=&_-+*/.$:!| ") valuestring_quoted = emptyquote | quote + _p.Word(_p.alphanums + "'=&_-+*/.$:! ()|") + quote valuelist = _p.Group(quote + valuestring + _p.OneOrMore(comma + valuestring) + quote) value = valuestring | valuestring_quoted | valuelist key_value_pair = _p.Group(identifier + colon + value) + semicolon + EOL named_list = ( identifier + b_left + _p.Group(o_linebreak + value + _p.ZeroOrMore(comma + o_linebreak + value)) + o_linebreak + b_right + (semicolon + EOL | EOL) ) group = _p.Forward() group << _p.Group( _p.Group( identifier + b_left + _p.Optional( (identifier + _p.ZeroOrMore(comma + identifier)) | valuestring_quoted + _p.ZeroOrMore(comma + valuestring_quoted) ) ) + b_right + cb_left + EOL + _p.Group(_p.ZeroOrMore(key_value_pair | named_list | group | EOL | comment)) + cb_right + EOL ) library = _p.Suppress(_p.ZeroOrMore(comment | EOL)) + group + _p.Suppress(_p.ZeroOrMore(comment | EOL)) key_value_pair.setParseAction(handle_parameters) named_list.setParseAction(handle_list) group.setParseAction(handle_groups) valuestring.setParseAction(parse_string_if_possible) return library.parseString(liberty_string)[0]["library"]
def _parse_struct(text): structs = {} # syntax we don't want to see in the final parse tree LBRACE, RBRACE, COMMA, SEMICOLON = map(Suppress, "{},;") _struct = Literal("struct") ^ Literal("union") dtype = Word(alphanums + "_*") identifier = Word(alphanums + "_[]") structDecl = Group( dtype("dtype") + identifier("name") + SEMICOLON + Optional(cStyleComment("desc"))) structList = Group(structDecl + ZeroOrMore(structDecl)) struct = _struct('struct') + identifier("struct_name") + LBRACE + \ structList("names") + RBRACE + SEMICOLON for item, start, stop in struct.scanString(text): l = [] for i, entry in enumerate(item.names): l.append((entry.dtype, entry.name, entry.desc)) structs[item.struct_name] = (item.struct, l) return structs
def parse(self, s): ats = [] parser = pyparsing.cStyleComment('lalala') parser.parseWithTabs() for p in parser.scanString(s): c = p[0][0] if c.startswith('/**'): ats.extend(parse_comment(c, s, p[2])) if debug: print 'LIST DUMP' import pprint pprint.pprint(ats) # build tree starting from flat ats self.classes = [] cursor = self.classes # where to append nodes for at in ats: level, _, class_ = command_option[at.name] try: node = class_(at.name, at.lines) except InvalidDocNode as e: print e continue if level == 0: self.classes.append(node) cursor = node elif level == 1: self.classes[-1].append(node) cursor = node else: cursor.append(node) if debug: print 'TREE DUMP' for class_ in self.classes: class_.dump()
def _setup_QASMParser(): """ Routine to initialise and return parsing blocks """ class _Op: """ Class to set up quantum operations """ def __init__(self, name, argParser, version="OPENQASM 2.0", qop=False, keyOverride=None): global cops global qops global _reservedKeys if name in qops or name in cops: raise IOError(dupTokenWarning.format("Operation", name)) self.operation = name if keyOverride is not None: self.parser = (keyOverride + argParser).addParseAction( lambda s, l, t: _override_keyword(t, name)) else: self.parser = CaselessKeyword(name)("keyword") + argParser self.version = parse_version(version) self.parser.addParseAction( lambda s, l, t: _set_version(t, self.version)) _reservedKeys.append(name) if qop: qops[name] = self else: cops[name] = self class _Routine(): """ Class to set up quantum gates, circuits, etc. """ def __init__(self, name, pargs=False, spargs=False, gargs=False, qargs=False, returnables=False, prefixes=None, version="OPENQASM 2.0"): global blocks global _reservedKeys if name in qops or name in cops: raise IOError(dupTokenWarning.format("Routine", name)) self.operation = name self.parser = Keyword(name)("keyword") + validName("gateName") if prefixes: localPrefixParser = Each(map(Optional, map( Keyword, prefixes))).addParseAction(prefix_setter) else: localPrefixParser = prefixParser self.parser = localPrefixParser + self.parser # Handle different args req = [] if pargs: req.append(Optional(pargParser)("pargs")) if spargs: req.append(Optional(spargParser)("spargs")) if gargs: req.append(Optional(gargParser)("gargs")) self.parser = self.parser + Each(req) if qargs: self.parser = self.parser + qargParser("qargs") if returnables: self.parser = self.parser + Optional(returnParser) self.version = parse_version(version) self.parser.addParseAction( lambda s, l, t: _set_version(t, self.version)) _reservedKeys.append(name) blocks[name] = self class _Block(): """ Class to set up blocks such as if, for, etc. """ def __init__(self, name, detParser, version="OPENQASM 2.0"): global blocks global _reservedKeys self.operation = name self.parser = Keyword(name)("keyword") + detParser self.version = parse_version(version) self.parser.addParseAction( lambda s, l, t: _set_version(t, self.version)) _reservedKeys.append(name) blocks[name] = self sign = Word("+-", exact=1) number = Word(nums) expo = Combine(CaselessLiteral("e") + Optional(sign) + number).setResultsName("exponent") pi = CaselessKeyword("pi") bitstring = Combine(OneOrMore(oneOf("0 1")) + Literal("b")) integer = Combine(number + Optional(expo)) real = Combine( Optional(sign) + (("." + number) ^ (number + "." + Optional(number))) + Optional(expo)) validName = Forward() lineEnd = Literal(";") _is_ = Keyword("to").suppress() _in_ = Keyword("in") _to_ = Literal("->").suppress() commentSyntax = "//" commentOpenStr = "/*" commentCloseStr = "*/" commentOpenSyntax = Literal(commentOpenStr) commentCloseSyntax = Literal(commentCloseStr) dirSyntax = "***" dirOpenStr = f"{dirSyntax} begin" dirCloseStr = f"{dirSyntax} end" dirSyntax = Keyword(dirSyntax) dirOpenSyntax = CaselessLiteral(dirOpenStr) dirCloseSyntax = CaselessLiteral(dirCloseStr) intFunc = oneOf("abs powrem countof fllog") realFunc = oneOf("abs powrem arcsin arccos arctan sin cos tan exp ln sqrt") boolFunc = oneOf("andof orof xorof") inL, inS, inR = map(Suppress, "[:]") vBar = Suppress("|") bSlash = Suppress("\\") brL, brR = map(Suppress, "()") intExp = Forward() realExp = Forward() boolExp = Forward() index = intExp.setResultsName("index") interval = Optional(intExp.setResultsName("start"), default=None) + inS \ + Optional(intExp.setResultsName("end"), default=None) \ + Optional(inS + Optional(intExp.setResultsName("step"), default=1)) interRef = Group(inL + interval + inR) loopRef = Group( inL + intExp.setResultsName("start") + inS + intExp.setResultsName("end") + Optional(inS + Optional(intExp.setResultsName("step"), default=1)) + inR) ref = inL + Group(delimitedList(index ^ interval))("ref") + inR regNoRef = validName("var") regRef = Group(validName("var") + Optional(ref)) regMustRef = Group(validName("var") + ref) regListNoRef = Group(delimitedList(regNoRef)) regListRef = Group(delimitedList(regRef)) inPlaceAlias = vBar + regListRef + vBar validQarg = regRef | inPlaceAlias aliasQarg = Group(regRef) | inPlaceAlias inPlaceCreg = bSlash + delimitedList(regRef | bitstring) + bSlash validCreg = (regRef | inPlaceCreg) def set_maths_type(toks, mathsType): """ Set logical or integer or floating point """ toks["type"] = mathsType intVar = integer | regRef realVar = real | integer | pi | regRef boolVar = interRef | regRef | realExp | intExp | validCreg | bitstring intFuncVar = (intFunc + brL + Group(Optional(delimitedList(intVar)))("args") + brR).setParseAction(Function) realFuncVar = ((realFunc ^ intFunc) + brL + Group(Optional(delimitedList(realVar)))("args") + brR).setParseAction(Function) boolFuncVar = (boolFunc + brL + Group(Optional(delimitedList(boolVar)))("args") + brR).setParseAction(Function) mathOp = [(oneOf("- +"), 1, opAssoc.RIGHT, Binary), (oneOf("^"), 2, opAssoc.LEFT, Binary), (oneOf("* / div"), 2, opAssoc.LEFT, Binary), (oneOf("+ -"), 2, opAssoc.LEFT, Binary)] logOp = [(oneOf("! not"), 1, opAssoc.RIGHT, Binary), (oneOf("and or xor"), 2, opAssoc.LEFT, Binary), (oneOf("< <= == != >= >"), 2, opAssoc.LEFT, Binary), (oneOf("in"), 2, opAssoc.LEFT, Binary)] intExp <<= infixNotation( intFuncVar | intVar, mathOp).setParseAction(lambda s, l, t: set_maths_type(t, "int")) realExp <<= infixNotation( realFuncVar | realVar, mathOp).setParseAction(lambda s, l, t: set_maths_type(t, "float")) boolExp <<= infixNotation( boolFuncVar | boolVar, logOp).setParseAction(lambda s, l, t: set_maths_type(t, "bool")) mathExp = intExp ^ realExp ^ boolExp cregExp = bitstring("bit") ^ validCreg("reg") prefixes = ["unitary"] callMods = ["CTRL", "INV"] def prefix_setter(toks): """ Pull out prefixes of gate calls and add them into list """ for prefix in prefixes: toks[prefix] = prefix in toks.asList() prefixParser = Each(map(Optional, map(Keyword, prefixes))).addParseAction(prefix_setter) pargParser = brL + delimitedList(validName)("pargs") + brR spargParser = inL + delimitedList(validName)("spargs") + inR gargParser = ungroup( nestedExpr("<", ">", delimitedList(ungroup(validName)), None)) qargParser = delimitedList(regRef) callQargParser = delimitedList(validQarg) callPargParser = brL + delimitedList(realExp) + brR callSpargParser = inL + delimitedList(intExp) + inR fullArgParser = Each( (Optional(pargParser("pargs")), Optional(spargParser("spargs")), Optional(gargParser("gargs")))) callArgParser = Each( (Optional(callPargParser("pargs")), Optional(callSpargParser("spargs")), Optional(gargParser("gargs")))) returnParser = Optional(_to_ + validCreg("byprod")) modifiers = ZeroOrMore(Combine(oneOf(callMods) + Suppress("-"))) commentLine = Literal(commentSyntax).suppress() + restOfLine("comment") commentBlock = cStyleComment("comment").addParseAction( removeQuotes).addParseAction(removeQuotes) comment = commentLine | commentBlock comment.addParseAction(lambda s, l, t: _set_version(t, (0, 0, 0))) directiveName = Word(alphas).setParseAction(downcaseTokens) directiveArgs = CharsNotIn(";") _Op("directive", directiveName("directive") + Suppress(White() * (1, )) + directiveArgs("args"), version="REQASM 1.0", keyOverride=(~dirOpenSyntax + ~dirCloseSyntax + dirSyntax)) def split_args(toks): """ Split directive arguments out """ toks[0]["keyword"] = "directive" toks[0]["args"] = toks[0]["args"].strip().split(" ") directiveStatement = directiveName("directive") + restOfLine("args") + \ Group(ZeroOrMore(Combine(Optional(White(" ")) + ~dirCloseSyntax + Word(printables+" "))))("block") directiveBlock = ungroup( nestedExpr( dirOpenSyntax, dirCloseSyntax, content=directiveStatement, ignoreExpr=(comment | quotedString )).setWhitespaceChars("\n").setParseAction(split_args)) directiveBlock.addParseAction(lambda s, l, t: _set_version(t, (2, 1, 0))) # Programming lines _Op("version", Empty(), version=(0, 0, 0), keyOverride=Combine( oneOf(versions)("type") + White() + real("versionNumber"))("version")) _Op("include", quotedString("file").addParseAction(removeQuotes)) # Gate-like structures _Op("opaque", validName("name") + fullArgParser + Optional(qargParser("qargs")) + returnParser, keyOverride=prefixParser + "opaque") _Routine("gate", pargs=True, qargs=True) _Routine("circuit", pargs=True, qargs=True, spargs=True, returnables=True, version="REQASM 1.0") # Variable-like structures _Op("creg", regRef("arg")) _Op("qreg", regRef("arg")) _Op("cbit", Group(regNoRef)("arg"), version="REQASM 1.0") _Op("qbit", Group(regNoRef)("arg"), version="REQASM 1.0") _Op("defAlias", regMustRef("alias"), keyOverride="alias", version="REQASM 1.0") # No more on-definition aliases _Op("alias", regRef("alias") + _is_ + aliasQarg("target"), keyOverride="set", version="REQASM 1.0") _Op("val", validName("var") + Literal("=").suppress() + mathExp("val"), version="REQASM 1.0") _Op("set", (Group(regRef)("var") ^ inPlaceCreg("var")) + Literal("=").suppress() + cregExp("val"), version="REQASM 1.0") # Operations-like structures _Op("measure", regRef("qreg") + _to_ + regRef("creg"), qop=True) _Op("barrier", regListNoRef("args")) _Op("output", regRef("value"), qop=True, version="REQASM 1.0") _Op("reset", regRef("qreg")) _Op("exit", Empty(), version="REQASM 1.0") _Op("free", validName("target"), version="REQASM 1.0") _Op("next", validName("loopVar"), qop=True, version="REQASM 1.0") _Op("finish", (Literal("quantum process") | validName)("loopVar"), qop=True, version="REQASM 1.0") _Op("end", validName("process"), qop=True, version="REQASM 1.0") # Special gate call handler callGate = Combine(Group(modifiers)("mods") + \ validName("gate")) + \ callArgParser + \ callQargParser("qargs").addParseAction(lambda s, l, t: _override_keyword(t, "call")) + \ returnParser callGate.addParseAction(lambda s, l, t: _set_version(t, (1, 2, 0))) # Block structures _Block("for", validName("var") + _in_ + loopRef("range"), version="REQASM 1.0") _Block("if", "(" + boolExp("cond") + ")", version="REQASM 1.0") _Block("while", "(" + boolExp("cond") + ")", version="OMEQASM 1.0") qopsParsers = list(map(lambda qop: qop.parser, qops.values())) + [callGate, directiveBlock] blocksParsers = list(map(lambda block: block.parser, blocks.values())) _Op("if", blocks["if"].parser + Group(Group(Group(Or(qopsParsers))))("block"), version="OPENQASM 2.0", keyOverride=Empty()) _Op("for", blocks["for"].parser + Group(Group(Group(Or(qopsParsers))))("block"), version="REQASM 1.0", keyOverride=Empty()) _Op("while", blocks["while"].parser + Group(Group(Group(Or(qopsParsers))))("block"), version="OMEQASM 1.0", keyOverride=Empty()) # Set-up line parsers reservedNames = Or(map(Keyword, _reservedKeys)) validName <<= (~reservedNames) + Word(alphas, alphanums + "_") copsParsers = list(map(lambda cop: cop.parser, cops.values())) operations = (( (Or(copsParsers) ^ Or(qopsParsers)) | # Classical/Quantum Operations callGate | # Gate parsers White() # Blank Line ) + lineEnd.suppress()) ^ directiveBlock # ; or Directives validLine = Forward() codeBlock = nestedExpr("{", "}", Suppress(White()) ^ Group(validLine), (quotedString)) validLine <<= ( ((operations + Optional(comment)) ^ (Or(blocksParsers) + codeBlock("block") + Optional(lineEnd)) ^ comment)) # Whole line comment testLine = Forward() dummyCodeBlock = nestedExpr( "{", "}", testLine, (directiveBlock | quotedString | comment)) + Optional(lineEnd) ignoreSpecialBlocks = (~commentOpenSyntax + ~commentCloseSyntax + ~dirOpenSyntax + ~dirCloseSyntax) testLine <<= ( comment | # Comments directiveBlock | # Directives (ignoreSpecialBlocks + ZeroOrMore(CharsNotIn("{}")) + dummyCodeBlock) | # Block operations (ignoreSpecialBlocks + ZeroOrMore(CharsNotIn("{};")) + lineEnd) ) # QASM Instructions testKeyword = (dirSyntax.setParseAction( lambda s, l, t: _override_keyword(t, "directive")) | Word(alphas)("keyword")) code = (Group(directiveBlock)) | Group(validLine) return code, testLine, testKeyword, reservedNames, mathExp
def addToHeaderDict(headerName, structt): headerList[headerName] = structt.asDict() def addToAnnotationDict(annotateName, annotate): s = annotate[1] # first remove the quotes if s.startswith("'''"): s = s[3:-3] if s.startswith('"'): s = s[1:-1] annotateDict[annotate['name']] = s comment = '## ' + restOfLine #comment = '#' + restOfLine CMNT = Optional(cStyleComment("comment")) CMNT2 = Optional( (Suppress('//') + restOfLine("comment2"))) #Optional(cppStyleComment("comment2")) STRQ3 = QuotedString("'''", multiline=True) ANNOTSTR = (QuotedString("'''", multiline=True) | quotedString) #IDENTIFIER = Regex(r'[a-zA-Z_][a-zA-Z_0-9]*') #INTEGER = Regex(r'([+-]?(([1-9][0-9]*)|0+))') #IDENTIFIER = Word(alphas+"_", alphas+nums+"_" ) INT_DECI = Regex('([+-]?(([1-9][0-9]*)|0+))') INT_OCT = Regex('(0[0-7]*)') INT_HEX = Regex('(0[xX][0-9a-fA-F]*)') INT = INT_HEX | INT_OCT | INT_DECI FLOAT = Regex( '[+-]?(((\d+\.\d*)|(\d*\.\d+))([eE][-+]?\d+)?)|(\d*[eE][+-]?\d+)') SIZE = INT