Esempio n. 1
0
    def parse_atoms(self, tokens, command, min_size, max_size=None):
        """
        Parses a sequence of N atoms (min_size <= N <= max_size) consuming
        the tokens
        """
        if max_size is None:
            max_size = min_size

        res = []
        current = None
        for _ in xrange(min_size):
            current = tokens.consume()
            if current == ")":
                raise PysmtSyntaxError("Expected at least %d arguments in "
                                       "%s command." %\
                                  (min_size, command))
            if current == "(":
                raise PysmtSyntaxError("Unexpected token '(' in %s "
                                       "command." % command)
            res.append(current)

        for _ in xrange(min_size, max_size + 1):
            current = tokens.consume()
            if current == ")":
                return res
            if current == "(":
                raise PysmtSyntaxError("Unexpected token '(' in %s "
                                       "command." % command)
            res.append(current)
        raise PysmtSyntaxError("Unexpected token '%s' in %s command. Expected " \
                               "at most %d arguments." % (current, command,
                                                          max_size))
Esempio n. 2
0
    def _enter_annotation(self, stack, tokens, key):
        """Deals with annotations"""
        #pylint: disable=unused-argument

        term = self.get_expression(tokens)

        tk = tokens.consume()
        while tk != ")":
            if not tk.startswith(":"):
                raise PysmtSyntaxError("Annotations keyword should start with"
                                       " colon! Offending token: '%s'" % tk)
            keyword = tk[1:]
            tk = tokens.consume()
            value = None
            if tk == "(":
                counter = 1
                buff = [tk]
                while counter != 0:
                    tk = tokens.raw_read()
                    if tk == "(":
                        counter += 1
                    elif tk == ")":
                        counter -= 1
                    buff.append(tk)
                value = "".join(buff)
            else:
                value = tk
            tk = tokens.consume()
            self.cache.annotations.add(term, keyword, value)

        assert len(stack[-1]) == 0
        # re-add the ")" to the tokenizer because we consumed it, but
        # get_expression needs it
        tokens.add_extra_token(")")
        stack[-1].append(lambda: term)
Esempio n. 3
0
    def _enter_quantifier(self, stack, tokens, key):
        """Handles quantifiers by defining the bound variable in the cache
        before parsing the matrix
        """
        mgr = self.env.formula_manager
        vrs = []
        self.consume_opening(tokens, "expression")
        current = "("
        self.consume_opening(tokens, "expression")
        while current != ")":
            if current != "(":
                raise PysmtSyntaxError("Expected '(' in let binding")
            vname = self.parse_atom(tokens, "expression")
            typename = self.parse_type(tokens, "expression")

            var = self._get_var(vname, typename)
            self.cache.bind(vname, var)
            vrs.append(var)

            self.consume_closing(tokens, "expression")
            current = tokens.consume()

        quant = None
        if key == 'forall':
            quant = mgr.ForAll
        else:
            quant = mgr.Exists

        stack[-1].append(self._exit_quantifier)
        stack[-1].append(quant)
        stack[-1].append(vrs)
Esempio n. 4
0
 def parse_atom(self, tokens, command):
     """Parses a single name from the tokens"""
     var = tokens.consume()
     if var == "(" or var == ")":
         raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                           (var, command))
     return var
Esempio n. 5
0
def parseDefineFun(parser, tokens):
    current = tokens.consume()

    if (current != "define-fun"):
        raise PysmtSyntaxError("'define-fun' expected", tokens.pos_info)
    var = parser.get_expression(tokens)
    if (not var.is_symbol()):
        raise PysmtSyntaxError("Symbol expected", tokens.pos_info)
    namedparams = parser.parse_named_params(tokens, "define-fun")
    if (namedparams):
        raise PysmtSyntaxError("'()' expected", tokens.pos_info)
    rtype = parser.parse_type(tokens, "define-fun")
    ebody = parser.get_expression(tokens)
    if (not ebody.is_constant()):
        raise PysmtSyntaxError("Constant expected", tokens.pos_info)
    current = tokens.consume()
    return (var, ebody)
Esempio n. 6
0
 def expect(self, token_class, token_repr):
     """
     Check that the next token is the specified one or fail with a
     ParserError
     """
     if type(self.token) != token_class:
         raise PysmtSyntaxError("Expected '%s'" % token_repr)
     self.advance()
Esempio n. 7
0
 def _cmd_declare_sort(self, current, tokens):
     """(declare-sort <symbol> <numeral>)"""
     (typename, arity) = self.parse_atoms(tokens, current, 2)
     try:
         type_ = self.env.type_manager.Type(typename, int(arity))
     except ValueError:
         raise PysmtSyntaxError("Expected an integer as arity of type %s" %
                                typename)
     self.cache.bind(typename, type_)
     return SmtLibCommand(current, [type_])
Esempio n. 8
0
 def parse(self, string):
     """Parses the content of the given string"""
     self.token = None
     self.tokenizer = self.lexer.tokenize(string)
     self.token = next(self.tokenizer)
     result = self.expression()
     try:
         bd = next(self.tokenizer)
         raise PysmtSyntaxError("Bogus data after expression: '%s' "
                                "(Partial: %s)" % (bd, result))
     except StopIteration:
         return result
Esempio n. 9
0
    def parse_type(self, tokens, command, additional_token=None):
        """Parses a single type name from the tokens"""
        if additional_token is not None:
            var = additional_token
        else:
            var = tokens.consume()
        if var == "(":
            op = tokens.consume()

            if op == "Array":
                idxtype = self.parse_type(tokens, command)
                elemtype = self.parse_type(tokens, command)
                self.consume_closing(tokens, command)
                return ("Array", idxtype, elemtype)

            if op != "_":
                raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                  (op, command))
            ts = tokens.consume()
            if ts != "BitVec":
                raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                  (ts, command))

            size = 0
            dim = tokens.consume()
            try:
                size = int(dim)
            except ValueError:
                raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                  (dim, command))

            self.consume_closing(tokens, command)
            return "BV%d" % size

        elif var == ")":
            raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                              (var, command))
        return var
Esempio n. 10
0
def readModel(parser, modelFile):
    with open(modelFile) as script:
        model = {}
        symbols = parser.env.formula_manager.symbols
        parser.cache.update(symbols)
        tokens = Tokenizer(script, interactive=parser.interactive)
        res = []
        current = tokens.consume()
        if (current != "sat"):
            raise PysmtSyntaxError("'sat' expected", tokens.pos_info)
        parser.consume_opening(tokens, "<main>")
        current = tokens.consume()
        if (current != "model"):
            raise PysmtSyntaxError("'model' expected", tokens.pos_info)

        current = tokens.consume()
        while current != ")":
            if (current != "("):
                raise PysmtSyntaxError("'(' expected", tokens.pos_info)
            (var, val) = parseDefineFun(parser, tokens)
            model[var] = val
            current = tokens.consume()
        return model
Esempio n. 11
0
def readModel(parser, modelFile, inputFile):
    with open(modelFile) as script:
        lino = 0
        for line in script:
            lino += 1
            read_status = line.strip()
            if read_status != 'success':
                break

        if (read_status == "unknown"):
            print("model_validator_status=UNKNOWN")
            print("model_validator_error=solver_returned_unknown")
            sys.exit(0)
        if (read_status == "unsat"):
            status = None
            with open(inputFile, 'r') as infile:
                for line in infile:
                    if ":status" in line:
                        if "unsat" in line:
                            status = "unsat"
                            print("model_validator_status=UNKNOWN")
                            print(
                                "model_validator_error=the_problem_status_is_unsatisfiable"
                            )
                        elif "sat" in line:
                            status = "sat"
                            print("model_validator_status=INVALID")
                            print(
                                "model_validator_error=the_problem_status_is_satisfiable"
                            )
                        elif "unknown" in line:
                            print("model_validator_status=UNKNOWN")
                            print(
                                "model_validator_error=the_problem_status_is_unknown"
                            )
                            status = "unknown"
                        break
            # the benchmark scrambler removes the status line, in case of a
            # benchmark without status line we assume satisfiability
            if not status:
                print("model_validator_status=INVALID")
                print("model_validator_error=solver_returned_unsat")
            sys.exit(0)
        if (read_status != "sat"):
            raise PysmtSyntaxError("'sat' expected at line %d" % lino)
        # Return UNKNOWN if the output is only "sat" and does not contain a model

        model, interpretation = parser.parse_model(script)
        return model, interpretation
Esempio n. 12
0
    def _enter_smtlib_as(self, stack, tokens, key):
        """Utility function that handles 'as' that is a special function in SMTLIB"""
        #pylint: disable=unused-argument
        const = self.parse_atom(tokens, "expression")
        if const != "const":
            raise PysmtSyntaxError("expected 'const' in expression after 'as'")
        ty = self.parse_type(tokens, "expression")

        def res(expr):
            return self.env.formula_manager.Array(ty.index_type, expr)

        def handler():
            return res

        stack[-1].append(handler)
Esempio n. 13
0
    def get_expression(self, tokens):
        """
        Returns the pysmt representation of the given parsed expression
        """
        mgr = self.env.formula_manager
        stack = []

        while True:
            tk = tokens.consume()

            if tk == "(":
                while tk == "(":
                    stack.append([])
                    tk = tokens.consume()

                if tk in self.interpreted:
                    fun = self.interpreted[tk]
                    fun(stack, tokens, tk)
                else:
                    stack[-1].append(self.atom(tk, mgr))

            elif tk == ")":
                try:
                    lst = stack.pop()
                    fun = lst.pop(0)
                except IndexError:
                    raise PysmtSyntaxError("Unexpected ')'")

                try:
                    res = fun(*lst)
                except TypeError as err:
                    if not callable(fun):
                        raise NotImplementedError("Unknown function '%s'" %
                                                  fun)
                    raise err

                if len(stack) > 0:
                    stack[-1].append(res)
                else:
                    return res

            else:
                try:
                    stack[-1].append(self.atom(tk, mgr))
                except IndexError:
                    return self.atom(tk, mgr)
Esempio n. 14
0
    def atom(self, token, mgr):
        """
        Given a token and a FormulaManager, returns the pysmt representation of
        the token
        """
        res = self.cache.get(token)
        if res is None:
            if token.startswith("#"):
                # it is a BitVector
                value = None
                width = None
                if token[1] == "b":
                    # binary
                    width = len(token) - 2
                    value = int("0" + token[1:], 2)
                else:
                    if token[1] != "x":
                        raise PysmtSyntaxError("Invalid bit-vector constant "
                                               "'%s'" % token)
                    width = (len(token) - 2) * 16
                    value = int("0" + token[1:], 16)
                res = mgr.BV(value, width)
            else:
                # it could be a number or a string
                try:
                    frac = Fraction(token)
                    if frac.denominator == 1:
                        # We found an integer, depending on the logic this can be
                        # an Int or a Real
                        if self.logic is None or \
                           self.logic.theory.integer_arithmetic:
                            if "." in token:
                                res = mgr.Real(frac)
                            else:
                                res = mgr.Int(frac.numerator)
                        else:
                            res = mgr.Real(frac)
                    else:
                        res = mgr.Real(frac)

                except ValueError:
                    # a string constant
                    res = token
            self.cache.bind(token, res)
        return res
Esempio n. 15
0
 def get_assignment_list(self, script):
     """
     Parse an assignment list produced by get-model and get-value
     commands in SmtLib
     """
     symbols = self.env.formula_manager.symbols
     self.cache.update(symbols)
     tokens = Tokenizer(script, interactive=self.interactive)
     res = []
     self.consume_opening(tokens, "<main>")
     current = tokens.consume()
     while current != ")":
         if current != "(":
             raise PysmtSyntaxError("'(' expected")
         vname = self.get_expression(tokens)
         expr = self.get_expression(tokens)
         self.consume_closing(tokens, current)
         res.append((vname, expr))
         current = tokens.consume()
     self.cache.unbind_all(symbols)
     return res
Esempio n. 16
0
    def _enter_let(self, stack, tokens, key):
        """Handles a let expression by recurring on the expression and
        updating the cache
        """
        #pylint: disable=unused-argument
        self.consume_opening(tokens, "expression")
        newvals = {}
        current = "("
        self.consume_opening(tokens, "expression")
        while current != ")":
            if current != "(":
                raise PysmtSyntaxError("Expected '(' in let binding")
            vname = self.parse_atom(tokens, "expression")
            expr = self.get_expression(tokens)
            newvals[vname] = expr
            self.cache.bind(vname, expr)
            self.consume_closing(tokens, "expression")
            current = tokens.consume()

        stack[-1].append(self._exit_let)
        stack[-1].append(newvals.keys())
Esempio n. 17
0
 def led(self, parser, left):
     # BVExtract, Select or Store
     op = left
     e1 = parser.expression()
     if type(parser.token) == ExprElse:
         #BVExtract
         parser.advance()
         end = parser.expression()
         parser.expect(CloseBrak, "]")
         return parser.mgr.BVExtract(op, e1.constant_value(),
                                     end.constant_value())
     elif type(parser.token) == CloseBrak:
         # Select
         parser.advance()
         return parser.mgr.Select(op, e1)
     elif type(parser.token) == ArrStore:
         #Store
         parser.advance()
         e2 = parser.expression()
         parser.expect(CloseBrak, "]")
         return parser.mgr.Store(op, e1, e2)
     else:
         raise PysmtSyntaxError("Unexpected token:" + str(parser.token))
Esempio n. 18
0
 def led(self, parser, left):
     raise PysmtSyntaxError("Syntax error at token '%s' (Read: '%s')." % \
                       (parser.token, left))
Esempio n. 19
0
 def nud(self, parser):
     raise PysmtSyntaxError("Syntax error at token '%s'." % parser.token)
Esempio n. 20
0
 def lexing_error(self, read):
     raise PysmtSyntaxError("Unexpected input: %s" % read)
Esempio n. 21
0
    def parse_type(self,
                   tokens,
                   command,
                   type_params=None,
                   additional_token=None):
        """Parses a single type name from the tokens"""
        if additional_token is not None:
            var = additional_token
        else:
            var = tokens.consume()

        res = None
        if type_params and var in type_params:
            return (var,
                    )  # This is a type parameter, it is handled recursively
        elif var == "(":
            op = tokens.consume()

            if op == "Array":
                idxtype = self.parse_type(tokens, command)
                elemtype = self.parse_type(tokens, command)
                self.consume_closing(tokens, command)
                res = self.env.type_manager.ArrayType(idxtype, elemtype)

            elif op == "_":
                ts = tokens.consume()
                if ts != "BitVec":
                    raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                      (ts, command))

                size = 0
                dim = tokens.consume()
                try:
                    size = int(dim)
                except ValueError:
                    raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                      (dim, command))

                self.consume_closing(tokens, command)
                res = self.env.type_manager.BVType(size)
            else:
                # It must be a custom-defined type
                base_type = self.cache.get(op)
                if base_type is None or not isinstance(base_type, _TypeDecl):
                    raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                           (op, command))
                pparams = []
                has_free_params = False
                for _ in range(base_type.arity):
                    ty = self.parse_type(tokens,
                                         command,
                                         type_params=type_params)
                    pparams.append(ty)
                    if isinstance(ty, tuple):
                        has_free_params = True
                if has_free_params:

                    def definition(*args):
                        params = []
                        for x in pparams:
                            if isinstance(x, tuple):
                                params.append(args[type_params.index(x[0])])
                            else:
                                params.append(x)
                        return self.env.type_manager.get_type_instance(
                            base_type, *params)

                    res = PartialType("tmp", definition)
                else:
                    res = self.env.type_manager.get_type_instance(
                        base_type, *pparams)
                self.consume_closing(tokens, command)
        elif var == "Bool":
            res = self.env.type_manager.BOOL()
        elif var == "Int":
            res = self.env.type_manager.INT()
        elif var == "Real":
            res = self.env.type_manager.REAL()
        else:
            cached = self.cache.get(var)
            if cached is not None:
                res = self.cache.get(var)
            else:
                raise PysmtSyntaxError("Unexpected token '%s' in %s command." % \
                                       (var, command))

        if isinstance(res, _TypeDecl):
            return res()
        else:
            return res
Esempio n. 22
0
    def _smtlib_underscore(self, stack, tokens, key):
        #pylint: disable=unused-argument
        """Utility function that handles _ special function in SMTLIB"""
        mgr = self.env.formula_manager

        op = self.parse_atom(tokens, "expression")

        fun = None
        if op == "extract":
            send = self.parse_atom(tokens, "expression")
            sstart = self.parse_atom(tokens, "expression")
            try:
                start = int(sstart)
                end = int(send)
            except ValueError:
                raise PysmtSyntaxError("Expected number in '_ extract' "
                                       "expression")
            fun = lambda x: mgr.BVExtract(x, start, end)

        elif op == "zero_extend":
            swidth = self.parse_atom(tokens, "expression")
            try:
                width = int(swidth)
            except ValueError:
                raise PysmtSyntaxError("Expected number in '_ zero_extend' "
                                       "expression")
            fun = lambda x: mgr.BVZExt(x, width)

        elif op == "repeat":
            scount = self.parse_atom(tokens, "expression")
            try:
                count = int(scount)
            except ValueError:
                raise PysmtSyntaxError("Expected number in '_ repeat' "
                                       "expression")
            fun = lambda x: mgr.BVRepeat(x, count)

        elif op == "rotate_left":
            sstep = self.parse_atom(tokens, "expression")
            try:
                step = int(sstep)
            except ValueError:
                raise PysmtSyntaxError("Expected number in '_ rotate_left' "
                                       "expression")
            fun = lambda x: mgr.BVRol(x, step)

        elif op == "rotate_right":
            sstep = self.parse_atom(tokens, "expression")
            try:
                step = int(sstep)
            except ValueError:
                raise PysmtSyntaxError("Expected number in '_ rotate_left' "
                                       "expression")
            fun = lambda x: mgr.BVRor(x, step)

        elif op == "sign_extend":
            swidth = self.parse_atom(tokens, "expression")
            try:
                width = int(swidth)
            except ValueError:
                raise PysmtSyntaxError("Expected number in '(_ sign_extend) "
                                       "expression'")
            fun = lambda x: mgr.BVSExt(x, width)

        elif op.startswith("bv"):
            try:
                v = int(op[2:])
                width = int(self.parse_atom(tokens, "expression"))
            except ValueError:
                raise PysmtSyntaxError("Expected number in '_ bv' expression: "
                                       "'%s'" % op)
            fun = mgr.BV(v, width)

        else:
            raise PysmtSyntaxError("Unexpected '_' expression '%s'" % op)

        stack[-1].append(lambda: fun)
Esempio n. 23
0
 def _res(a, b):
     if b.is_constant():
         return op(a, b.constant_value())
     else:
         raise PysmtSyntaxError("Constant expected, got '%s'" % b)
Esempio n. 24
0
    def create_generator(reader):
        """Takes a file-like object and produces a stream of tokens following
        the LISP rules.

        This is the method doing the heavy-lifting of tokenization.
        """
        spaces = set([" ", "\n", "\t"])
        separators = set(["(", ")", "|", "\""])
        specials = spaces | separators | set([";", ""])

        c = next(reader)

        eof = False
        while not eof:
            if c in specials:
                # consume the spaces
                if c in spaces:
                    c = next(reader)

                elif c in separators:
                    if c == "|":
                        s = []
                        c = next(reader)
                        while c and c != "|":
                            if c == "\\":  # This is a single '\'
                                c = next(reader)
                                if c != "|" and c != "\\":
                                    # Only \| and \\ are supported escapings
                                    raise PysmtSyntaxError("Unknown escaping in " \
                                                           "quoted symbol: "
                                                           "'\\%s'" % c)
                            s.append(c)
                            c = next(reader)
                        if not c:
                            raise PysmtSyntaxError("Expected '|'")
                        yield "".join(s)
                        c = next(reader)

                    elif c == "\"":
                        # String literals
                        s = []
                        c = next(reader)
                        while c:
                            if c == "\"":
                                c = next(reader)
                                if c == "\"":
                                    s.append(c)
                                    c = next(reader)
                                else:
                                    break
                            else:
                                s.append(c)
                                c = next(reader)
                        if not c:
                            raise PysmtSyntaxError("Expected '|'")
                        yield '"%s"' % (
                            "".join(s)
                        )  # string literals maintain their quoting

                    else:
                        yield c
                        c = next(reader)

                elif c == ";":
                    while c and c != "\n":
                        c = next(reader)
                    c = next(reader)

                else:
                    # EOF
                    eof = True
                    assert len(c) == 0
            else:
                tk = []
                while c not in specials:
                    tk.append(c)
                    c = next(reader)
                yield "".join(tk)
Esempio n. 25
0
 def test_pysmt_syntax_error(self):
     from pysmt.exceptions import PysmtSyntaxError
     try:
         raise PysmtSyntaxError("'define-fun' expected", (5,5))
     except PysmtSyntaxError as ex:
         self.assertEqual(str(ex), "Line 5, Col 5: 'define-fun' expected")
Esempio n. 26
0
 def consume_closing(self, tokens, command):
     """ Consumes a single ')' """
     p = tokens.consume()
     if p != ")":
         raise PysmtSyntaxError("Unexpected token '%s' in %s command. " \
                           "Expected ')'" % (p, command))
Esempio n. 27
0
def readModel(parser, modelFile, inputFile):
    with open(modelFile) as script:
        model = {}
        symbols = parser.env.formula_manager.symbols
        parser.cache.update(symbols)
        tokens = Tokenizer(script, interactive=parser.interactive)
        res = []
        current = tokens.consume()

        if (current == "unknown"):
            print ("model_validator_status=UNKNOWN")
            print ("model_validator_error=solver_returned_unknown")
            sys.exit(0)
        if (current == "unsat"):
            status = None
            with open(inputFile, 'r') as infile:
                for line in infile:
                    if ":status" in line:
                        if "unsat" in line:
                            status = "unsat"
                            print ("model_validator_status=UNKNOWN")
                            print ("model_validator_error=the_problem_status_is_unsatisfiable")
                        elif "sat" in line:
                            status = "sat"
                            print ("model_validator_status=INVALID")
                            print ("model_validator_error=the_problem_status_is_satisfiable")
                        elif "unknown" in line:
                            print ("model_validator_status=UNKNOWN")
                            print ("model_validator_error=the_problem_status_is_unknown")
                            status = "unknown"
                        break
            # the benchmark scrambler removes the status line, in case of a
            # benchmark without status line we assume satisfiability
            if not status:
                print ("model_validator_status=INVALID")
                print ("model_validator_error=solver_returned_unsat")
            sys.exit(0)
        if (current != "sat"):
            raise PysmtSyntaxError("'sat' expected", tokens.pos_info)
        # Return UNKNOWN if the output is only "sat" and does not contain a model
        try:
            current = tokens.consume_maybe()
        except StopIteration:
            print ("model_validator_status=UNKNOWN")
            print ("model_validator_error=no_output")
            sys.exit(0)

        if (current != "("):
            raise PysmtSyntaxError("'(' expected", tokens.pos_info)
        current = tokens.consume()

        # Backwards compatibility: skip optional model keyword
        if (current == "model"):
            current = tokens.consume()

        while current != ")":
            if (current != "("):
                raise PysmtSyntaxError("'(' expected", tokens.pos_info)
            (var, val) = parseDefineFun(parser, tokens)
            model[var] = val
            current = tokens.consume()
        return model