OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace-storage / opencog / persist / file / fast_load.cc

147 lines · cc ref:
/*
 * fast_load.cc
 * Fast load of Atomese in s-expression format.
 *
 * Copyright (C) 2020 Alexey Potapov, Anatoly Belikov
 *
 * Authors: Alexey Potapov
 *          Anatoly Belikov
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/persist/sexcom/Dispatcher.h>
#include <opencog/persist/sexpr/Sexpr.h>

#include "fast_load.h"

using namespace opencog;

Handle opencog::parseStream(std::istream& in, AtomSpacePtr asp)
{
    Dispatcher cmd;
    cmd.set_base_space(asp);
    static std::unordered_map<std::string, Handle> ascache; // empty, not currently used.
    Handle h;
    size_t expr_cnt = 0;
    size_t line_cnt = 0;
    int pcount = 0;
    size_t r = 0;

    std::string expr;
    while (!in.eof())
    {
        std::string line;
        std::getline(in, line);
        line_cnt++;
        expr += line;
        while (true)
        {
            size_t l = 0;
            r = expr.length();

            // Zippy the Pinhead says: Are we having fun yet?
            pcount = Sexpr::get_next_expr(expr, l, r, line_cnt);

            // Trim away comments at end of line
            if (0 < pcount)
            {
                expr = expr.substr(l, r - l);
                break;
            }

            // Nothing to do.
            if (l == r)
                break;

            expr_cnt++;

            // At this point, we expect to either have a declaration
            // of an Atom e.g. `(ConceptNode "foo")` or we have a
            // command e.g. `(cog-set-value! (Concept "foo") ...`.
            // If its a command, the `Sexpr::decode_atom()` will throw
            // a SyntaxException, and so we try again, hoping for a
            // command.
            try
            {
                h = asp->add_atom(Sexpr::decode_atom(expr, l, r, line_cnt, ascache));
            }
            catch (const SyntaxException& ex)
            {
                cmd.interpret_command(expr.substr(l));
            }

            expr = expr.substr(r + 1);
        }
    }

    if (0 < pcount)
        throw std::runtime_error(
            "Unbalanced parenthesis >>" + expr.substr(r) + "<<");

    return h;
}

/// load_file -- load the given file into the given AtomSpace.
void opencog::load_file(const std::string& fname, AtomSpacePtr asp)
{
    std::ifstream f(fname);
    if (not f.is_open())
        throw std::runtime_error("Cannot find file >>" + fname + "<<");

    parseStream(f, asp);
    
    f.close();
}

// Parse an Atomese string expression and return a Handle to the parsed atom
// The expression is assumed not to contain any newlines!
Handle opencog::parseExpression(const std::string& expr, AtomSpacePtr asp)
{
    static std::unordered_map<std::string, Handle> ascache; // empty, not currently used.
    size_t l = 0;
    size_t r = expr.length();
    size_t rr = r;

    Handle h;

    while (true)
    {
        // Zippy the Pinhead says: Are we having fun yet?
        int pcount = Sexpr::get_next_expr(expr, l, r, 0);

        // Finished.
        if (l == r)
            break;

        if (0 < pcount)
            throw std::runtime_error(
                "Unbalanced parenthesis >>" + expr.substr(r) + "<<");
        h = asp->add_atom(Sexpr::decode_atom(expr, l, r, 0, ascache));

        l = r + 1;
        r = rr;
    }

    return h;
}