Exemple #1
0
def parse_db(mln, content, ignore_unknown_preds=False, db=None, dirs=['.'], projectpath=None):
    '''
    Reads one or more databases in a string representation and returns
    the respective Database objects.
    
    :param mln:                      the MLN object which should be used to load the database.
    :param content:                  the string representation of one or multiple ('---'-separated)
                                     databases
    :param ignore_unknown_preds:     by default this function raises an Exception when it encounters
                                     a predicate in the DB that has not been declared in the associated
                                     MLN. ignore_unknown_preds=True simply ignores such predicates.
    :param db:                       the Database object that shall receive the facts stored in the new DB.
                                     If None, a new `Database` object will be created.
    '''
    log = logging.getLogger('db')
    content = stripComments(content)
    allow_multiple = True
    if db is None:
        allow_multiple = True
        db = Database(mln, ignore_unknown_preds=ignore_unknown_preds)
    dbs = []
    # expand domains with dbtext constants and save evidence
    for line, l in enumerate(content.split("\n")):
        l = l.strip()
        if l == '':
            continue
        # separator between independent databases
        elif l == '---' and not db.isempty():
            dbs.append(db)
            db = Database(mln)
            continue
        # domain declaration
        elif "{" in l:
            domname, constants = db.mln.logic.parse_domain(l)
            domnames = [domname for _ in constants]
        # include
        elif l.startswith('#include'):
            filename = l[len("#include "):].strip()
            m = re.match(r'"(?P<filename>.+)"', filename)
            if m is not None:
                filename = m.group('filename')
                # if the path is relative, look for the respective file 
                # relatively to all paths specified. Take the first file matching.
                if not mlnpath(filename).exists:
                    includefilename = None
                    for d in dirs:
                        mlnp = '/'.join([d, filename])
                        if mlnpath(mlnp).exists:
                            includefilename = mlnp
                            break
                    if includefilename is None:
                        raise Exception('File not found: %s' % filename)
                else:
                    includefilename = filename
            else:
                m = re.match(r'<(?P<filename>.+)>', filename)
                if m is not None:
                    filename = m.group('filename')
                else:
                    raise MLNParsingError('Malformed #include statement: %s' % line)
                if projectpath is None:
                    raise MLNParsingError('No project specified: Cannot locate import from project: %s' % filename)
                includefilename = ':'.join([projectpath, filename])
            logger.debug('Including file: "%s"' % includefilename)
            p = mlnpath(includefilename)
            dbs.extend(parse_db(content=mlnpath(includefilename).content, ignore_unknown_preds=ignore_unknown_preds, dirs=[p.resolve_path()]+dirs, 
                      projectpath=ifNone(p.project, projectpath, lambda x: '/'.join(p.path+[x])), mln=mln)) 
            continue
        # valued evidence
        elif l[0] in "0123456789":
            s = l.find(" ")
            gndatom = l[s + 1:].replace(" ", "")
            value = float(l[:s])
            if value < 0 or value > 1:
                raise Exception('Valued evidence must be in [0,1]') 
            if gndatom  in db.evidence:
                raise Exception("Duplicate soft evidence for '%s'" % gndatom)
            try:
                positive, predname, constants =   mln.logic.parse_literal(gndatom) # TODO Should we allow soft evidence on non-atoms here? (This assumes atoms)
            except NoSuchPredicateError, e:
                if ignore_unknown_preds: continue
                else: raise e
            domnames = mln.predicate(predname).argdoms
            db << (gndatom, value)
        # literal
        else:
            if l[0] == "?":
                raise Exception("Unknown literals not supported (%s)" % l) # this is an Alchemy feature
            try:
                true, predname, constants = mln.logic.parse_literal(l)
            except NoSuchPredicateError, e:
                if ignore_unknown_preds: continue
                else: raise e
            except Exception, e:
                traceback.print_exc()
                raise MLNParsingError('Error parsing line %d: %s (%s)' % (line+1, l, e.message))
Exemple #2
0
	def apply(self, line, state):
		result = OperationResult(line, False)

		trimmed = stripComments(line)
		output = line
		expanded_line = line

		# find the directive
		dirsearch = regex['directive'].search(trimmed)
		if dirsearch:
			directive = dirsearch.group(1)
			identifier = dirsearch.group(2)

			output = commentLine(line)

			if directive == "#macro":
				if self.macro:
					warnings.add("Trying to define multiline macro %s inside other macro %s" % (identifier, self.macro.name))					
					return result

				self.macro = Macro(dirsearch, trimmed)
				self.payload = ""
			elif directive == "#endmacro":
				#print ("macro %s ends") % (self.macro.name)
				self.macro.payload = self.macro.payload.rstrip('\n')
				self.multimacros[self.macro.name] = self.macro
				self.macro = None
				
			# TODO this is basically duplicate of the above functionality, clean it up
			elif directive == "#lambda":
				if self.macro:
					warnings.add("Trying to define multiline lambda %s inside other macro %s" % (identifier, self.macro.name))					
					return result

				self.macro = Macro(dirsearch, trimmed)
				self.macro.oneliner = True
				self.payload = ""
				
			elif directive == "#endlambda":
				#print ("macro %s ends") % (self.macro.name)
				self.macro.payload = self.macro.payload.rstrip('\n')
				self.macro.payload = re.sub("\n+", r':', self.macro.payload)
				self.multimacros[self.macro.name] = self.macro
				self.macro = None
			elif directive == "#undef":
				temp_macro = Macro(dirsearch, trimmed)
				if temp_macro.name in self.multimacros:
					del self.multimacros[temp_macro.name]	

			else:
				output = output

		else:
			if state.args.nomacros:
				return result

			# Expand collected macros only if not inside a multiline macro.
			if self.macro:
				line_trimmed = line
				
				if self.macro.oneliner:
					line_trimmed = line.lstrip(" ").lstrip("\t")
				
				self.macro.payload += line_trimmed
				output = commentLine(output)
			else:
				output = expandAll(line, self.multimacros, Stack(), state)

		result.line = output
		return result
Exemple #3
0
def parse_db(mln, content, ignore_unknown_preds=False, db=None, dirs=['.'], projectpath=None):
    '''
    Reads one or more databases in a string representation and returns
    the respective Database objects.
    
    :param mln:                      the MLN object which should be used to load the database.
    :param content:                  the string representation of one or multiple ('---'-separated)
                                     databases
    :param ignore_unknown_preds:     by default this function raises an Exception when it encounters
                                     a predicate in the DB that has not been declared in the associated
                                     MLN. ignore_unknown_preds=True simply ignores such predicates.
    :param db:                       the Database object that shall receive the facts stored in the new DB.
                                     If None, a new `Database` object will be created.
    '''
    log = logs.getlogger('db')
    content = stripComments(content)
    allow_multiple = True
    if db is None:
        allow_multiple = True
        db = Database(mln, ignore_unknown_preds=ignore_unknown_preds)
    dbs = []
    # expand domains with dbtext constants and save evidence
    for line, l in enumerate(content.split("\n")):
        l = l.strip()
        if l == '':
            continue
        # separator between independent databases
        elif l == '---' and not db.isempty():
            dbs.append(db)
            db = Database(mln)
            continue
        # domain declaration
        elif "{" in l:
            domname, constants = db.mln.logic.parse_domain(l)
            domnames = [domname for _ in constants]
        # include
        elif l.startswith('#include'):
            filename = l[len("#include "):].strip()
            m = re.match(r'"(?P<filename>.+)"', filename)
            if m is not None:
                filename = m.group('filename')
                # if the path is relative, look for the respective file 
                # relatively to all paths specified. Take the first file matching.
                if not mlnpath(filename).exists:
                    includefilename = None
                    for d in dirs:
                        mlnp = '/'.join([d, filename])
                        if mlnpath(mlnp).exists:
                            includefilename = mlnp
                            break
                    if includefilename is None:
                        raise Exception('File not found: %s' % filename)
                else:
                    includefilename = filename
            else:
                m = re.match(r'<(?P<filename>.+)>', filename)
                if m is not None:
                    filename = m.group('filename')
                else:
                    raise MLNParsingError('Malformed #include statement: %s' % line)
                if projectpath is None:
                    raise MLNParsingError('No project specified: Cannot locate import from project: %s' % filename)
                includefilename = ':'.join([projectpath, filename])
            logger.debug('Including file: "%s"' % includefilename)
            p = mlnpath(includefilename)
            dbs.extend(parse_db(content=mlnpath(includefilename).content, ignore_unknown_preds=ignore_unknown_preds, dirs=[p.resolve_path()]+dirs, 
                      projectpath=ifnone(p.project, projectpath, lambda x: '/'.join(p.path+[x])), mln=mln)) 
            continue
        # valued evidence
        elif l[0] in "0123456789":
            s = l.find(" ")
            gndatom = l[s + 1:].replace(" ", "")
            value = float(l[:s])
            if value < 0 or value > 1:
                raise Exception('Valued evidence must be in [0,1]') 
            if gndatom  in db.evidence:
                raise Exception("Duplicate soft evidence for '%s'" % gndatom)
            try:
                _, predname, constants =   mln.logic.parse_literal(gndatom) # TODO Should we allow soft evidence on non-atoms here? (This assumes atoms)
            except NoSuchPredicateError, e:
                if ignore_unknown_preds: continue
                else: raise e
            domnames = mln.predicate(predname).argdoms
            db << (gndatom, value)
        # literal
        else:
            if l[0] == "?":
                raise Exception("Unknown literals not supported (%s)" % l) # this is an Alchemy feature
            try:
                true, predname, constants = mln.logic.parse_literal(l)
            except NoSuchPredicateError, e:
                if ignore_unknown_preds: continue
                else: raise e
            except Exception, e:
                traceback.print_exc()
                raise MLNParsingError('Error parsing line %d: %s (%s)' % (line+1, l, e.message))
Exemple #4
0
    def apply(self, line, state):
        result = OperationResult(line, False)

        trimmed = stripComments(line)
        output = line
        expanded_line = line

        # find the directive
        dirsearch = regex['directive'].search(trimmed)
        if dirsearch:
            directive = dirsearch.group(1)
            identifier = dirsearch.group(2)

            output = commentLine(line)

            if directive == "#macro":
                if self.macro:
                    warnings.add(
                        "Trying to define multiline macro %s inside other macro %s"
                        % (identifier, self.macro.name))
                    return result

                self.macro = Macro(dirsearch, trimmed)
                self.payload = ""
            elif directive == "#endmacro":
                #print ("macro %s ends") % (self.macro.name)
                self.macro.payload = self.macro.payload.rstrip('\n')
                self.multimacros[self.macro.name] = self.macro
                self.macro = None

            # TODO this is basically duplicate of the above functionality, clean it up
            elif directive == "#lambda":
                if self.macro:
                    warnings.add(
                        "Trying to define multiline lambda %s inside other macro %s"
                        % (identifier, self.macro.name))
                    return result

                self.macro = Macro(dirsearch, trimmed)
                self.macro.oneliner = True
                self.payload = ""

            elif directive == "#endlambda":
                #print ("macro %s ends") % (self.macro.name)
                self.macro.payload = self.macro.payload.rstrip('\n')
                self.macro.payload = re.sub("\n+", r':', self.macro.payload)
                self.multimacros[self.macro.name] = self.macro
                self.macro = None
            elif directive == "#undef":
                temp_macro = Macro(dirsearch, trimmed)
                if temp_macro.name in self.multimacros:
                    del self.multimacros[temp_macro.name]

            else:
                output = output

        else:
            if state.args.nomacros:
                return result

            # Expand collected macros only if not inside a multiline macro.
            if self.macro:
                line_trimmed = line

                if self.macro.oneliner:
                    line_trimmed = line.lstrip(" ").lstrip("\t")

                self.macro.payload += line_trimmed
                output = commentLine(output)
            else:
                output = expandAll(line, self.multimacros, Stack(), state)

        result.line = output
        return result