Ejemplo n.º 1
0
    def _create_parser() -> ParserElement:
        # operators in the format later used by infixNotation
        operator_list = [
            (None, 2, opAssoc.LEFT, BooleanAndOperation._create_from_implicit_tokens),
            (CaselessKeyword('not') | "~" | "!", 1, opAssoc.RIGHT, BooleanNotOperation._create_from_tokens),
            (CaselessKeyword('and') | "&", 2, opAssoc.LEFT, BooleanAndOperation._create_from_tokens),
            (CaselessKeyword('xor') | "^", 2, opAssoc.LEFT, BooleanXorOperation._create_from_tokens),
            (CaselessKeyword('or') | "|", 2, opAssoc.LEFT, BooleanOrOperation._create_from_tokens),
        ]

        # terms (atoms) that will be combined with the boolean operators
        term_list = [
            (CaselessKeyword('tag'), TagFilterTerm._create_from_tokens),
            (CaselessKeyword('ingr'), IngredientFilterTerm._create_from_tokens),
            (CaselessKeyword('unit'), UnitFilterTerm._create_from_tokens),
            (None, AnyFilterTerm._create_from_tokens),
        ]

        # extract keywords that can
        operator_expressions = [om[0] for om in operator_list if om[0] is not None]
        term_expressions = [tm[0] for tm in term_list if tm[0] is not None]
        reserved_expressions = operator_expressions + term_expressions

        # quoted string indicates exact macthc
        quoted_filter_string = (QuotedString('"', escChar='\\') | QuotedString("'", escChar='\\')).setResultsName('string')
        # quoted_filter_string.setDebug(True)
        quoted_filter_string.setName("quoted_filter_string")
        quoted_filter_string.setParseAction(ExactFilterString._create_from_tokens)

        # not quoted string is inexact match, can't contain whitespace or be an operator
        unquoted_filter_string = ~MatchFirst(reserved_expressions) + Regex(r'[^\s\(\)]+', flags=re.U).setResultsName('string')
        # unquoted_filter_string.setDebug(True)
        unquoted_filter_string.setName("unquoted_filter_string")
        unquoted_filter_string.setParseAction(FuzzyFilterString._create_from_tokens)

        # regular expressions aren't parsed in the grammar but delegated to python re.compile in the parser action
        regex_filter_string = QuotedString('/', escChar='\\')
        regex_filter_string.setName("regex_filter_string")
        regex_filter_string.setParseAction(RegexFilterString._create_from_tokens)

        # unquoted_filter_string must be last, so that initial quotes are handled correctly
        filter_string = regex_filter_string | quoted_filter_string | unquoted_filter_string
        filter_string.setParseAction(lambda toks: toks[0])

        filter_terms = []
        for prefix_expression, term_action in term_list:
            if prefix_expression is not None:
                filter_term = Combine(prefix_expression + ':' + filter_string.setResultsName("filter_string"))
                filter_term.setName("filter_term_"+str(prefix_expression.match))
            else:
                filter_term = filter_string.setResultsName("filter_string")
                filter_term.setName("filter_term_None")
            # filter_term.setDebug(True)
            filter_term.addParseAction(term_action)
            filter_terms.append(filter_term)
        filter_term = MatchFirst(filter_terms)
        filter_expr = infixNotation(filter_term, operator_list)

        return filter_expr
 def _define_grammar(self):
     '''define the grammar to be used, and add actions'''
     self._define_actions()
     eol = LineEnd().suppress()
     white = Optional(White()).suppress()
     begin = Keyword('begin').suppress()
     end = Keyword('end').suppress()
     comment = (Literal('#') + restOfLine).suppress()
     data_value = Combine(OneOrMore(CharsNotIn('#\n\r')))
     data_line = (LineStart() + white + Optional(data_value) +
                  Optional(comment) + eol)
     block_name = Word(alphas, alphanums + '_')
     begin_block = (LineStart() + begin + block_name +
                    Optional(comment) + eol)
     end_block = LineStart() + end + block_name + Optional(comment) + eol
     junk = ZeroOrMore(LineStart() + white + NotAny(begin) +
                       restOfLine + eol).suppress()
     data = Group(ZeroOrMore(NotAny(end) + data_line))
     block_def = begin_block + data + end_block
     block_defs = junk + OneOrMore(block_def + junk)
     self._grammar = block_defs
     begin_block.addParseAction(self._begin_block_action)
     end_block.addParseAction(self._end_block_action)
     data_value.addParseAction(self._data_value_action)
eol = LineEnd().suppress()
begin = Keyword("begin").suppress()
end = Keyword("end").suppress()
comment = (Literal("#") + restOfLine).suppress()
data_value = Combine(OneOrMore(CharsNotIn("#\n\r")))
data = LineStart() + Optional(data_value) + Optional(comment) + eol
block_name = Word(alphas, alphanums + "_")
begin_block = LineStart() + begin + block_name + Optional(comment) + eol
end_block = LineStart() + end + block_name + Optional(comment) + eol
junk = ZeroOrMore(LineStart() + NotAny(begin) + restOfLine + eol).suppress()
block_def = begin_block + Group(ZeroOrMore(NotAny(end) + data)) + end_block
block_defs = junk + OneOrMore(block_def + junk)

begin_block.addParseAction(create_block)
end_block.addParseAction(finish_block)
data_value.addParseAction(handle_data)

test_str = """
bla bla
begin block_1 # bla bla
    0.17  # suspicious value
# comment line
   -7.34
end block_1
# and noe the second block
begin block_2
    17.34
    11.8
end block_2

"""
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
eol = LineEnd().suppress()
begin = Keyword('begin').suppress()
end = Keyword('end').suppress()
comment = (Literal('#') + restOfLine).suppress()
data_value = Combine(OneOrMore(CharsNotIn('#\n\r')))
data = LineStart() + Optional(data_value) + Optional(comment) + eol
block_name = Word(alphas, alphanums + '_')
begin_block = LineStart() + begin + block_name + Optional(comment) + eol
end_block = LineStart() + end + block_name + Optional(comment) + eol
junk = ZeroOrMore(LineStart() + NotAny(begin) + restOfLine + eol).suppress()
block_def = begin_block + Group(ZeroOrMore(NotAny(end) + data)) + end_block
block_defs = junk + OneOrMore(block_def + junk)

begin_block.addParseAction(create_block)
end_block.addParseAction(finish_block)
data_value.addParseAction(handle_data)

test_str = '''
bla bla
begin block_1 # bla bla
    0.17  # suspicious value
# comment line
   -7.34
end block_1
# and noe the second block
begin block_2
    17.34
    11.8
end block_2

'''
Ejemplo n.º 6
0
expr = Forward()

##########
# Number #
##########


def number_parse_action(instring, tokensStart, retTokens):
    parsed_values = retTokens[0]
    return types.Number(float(parsed_values))


number = Combine(Word(nums) + Optional(Literal('.') + Word(nums)))

number.addParseAction(number_parse_action)

##########
# String #
##########

single_quote_string = QuotedString('\'', escChar='\\')
double_quote_string = QuotedString('"', escChar='\\')


def string_parse_action(instring, tokensStart, retTokens):
    parsed_values = retTokens[0]
    return types.String(parsed_values)


string = single_quote_string | double_quote_string