// (C) Copyright 2008-2009 SDML (www.sdml.info) // // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Copyright Andrew Sutton 2007 // // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_FCA_READ_CONCEPTS_HPP #define BOOST_FCA_READ_CONCEPTS_HPP #include #include #include #include #include #include namespace boost { namespace fca { // This file reads input from a concepts file. A concepts file is specified // in a ws-delimited format as: // // o: a1 a2 ... an // // This is actually a bad name for the and function. I should be able to // think of something better. template void read_concepts(std::istream& is, Context& cxt, Relation& rel) { using namespace std; typedef vector string_vector; typedef set string_set; typedef map mapping_type; typedef pair mapping_result; // Declare a map that declares objects and associates them with // attributes. mapping_type mapping; string_set objs; string_set atts; // Parse the file and populate the objs mapping type. This is basically // a collection of objects, each associated with a vector of attributes. for(string line; getline(is, line); ) { if(line.empty()) continue; if(line[0] == '%') continue; if(line[0] == '#') continue; // Parse out the object and the attributes between the : and ; size_t x = line.find_first_of(':'); size_t y = line.find_last_of(';'); string str_obj(line, 0, x); string str_atts(line, x + 1, y - x - 1); // Insert this into the mapping so we can build the relation. mapping_result result = mapping.insert(make_pair(str_obj, string_vector())); string_vector& mapped = result.first->second; // Remember the unique name of the object. objs.insert(str_obj); // Tokenize the attribute string on white space. tokenizer<> tok(str_atts); typename tokenizer<>::iterator i, end = tok.end(); for(i = tok.begin(); i != end; ++i) { // Presever the mapping for the relation. mapped.push_back(*i); // Remember the unique name of the attribute. atts.insert(*i); } } // Re-construct the context and relation. Note that this forces a // "reload" of the relation, ensuring that it is actually aligned with // the newly reassigned context. cxt = Context(objs, atts); rel = Relation(cxt); // Constructing the relation is fairly simple. We just need to set // all of the objects and attributes. typename mapping_type::iterator i, i_end = mapping.end(); for(i = mapping.begin(); i != i_end; ++i) { string_vector& mapped = i->second; // For each mapped attribute... typename string_vector::iterator j, j_end = mapped.end(); for(j = mapped.begin(); j != j_end; ++j) { rel.set(i->first, *j); } } } } /* namespace fca */ } /* namespace boost */ #endif