Program Listing for File Stringreader.h

Return to documentation for file (/tmp/ws/src/ros2_planning_system/plansys2_pddl_parser/include/plansys2_pddl_parser/Stringreader.h)

#pragma once

#include <sstream>
#include <stdexcept>
#include <vector>

#include "plansys2_pddl_parser/TokenStruct.h"
#include "plansys2_pddl_parser/Type.h"

namespace parser { namespace pddl {



class Domain;

class ExpectedToken : public std::runtime_error {
public:
    ExpectedToken(const std::string& token) : std::runtime_error(token + " expected") {}
};

class UnknownToken : public std::runtime_error {
public:
    UnknownToken(const std::string& token) : std::runtime_error(token +  " does not name a known token") {}
};

class UnexpectedEOF : public std::runtime_error {
public:
    UnexpectedEOF() : std::runtime_error("Unexpected EOF found") {}
};

class Stringreader {

public:

    std::vector<std::string> lines;
    int current_line;      // current line of file
    std::string s;
    unsigned r, c;      // current row and column of file

    Stringreader( const std::string & domain ) : current_line( 0 ), r( 1 ), c( 0 ) {

        lines = getLines(domain);

        s = lines[current_line++];
        std::transform(s.begin(), s.end(),s.begin(), ::tolower);
        next();
    }

    ~Stringreader() {
    }

    std::vector<std::string> getLines(const std::string & text)
    {
    std::vector<std::string> ret;
    size_t start = 0, end = 0;

    while (end != std::string::npos) {
      end = text.find("\n", start);
      ret.push_back(text.substr(start, (end == std::string::npos) ? std::string::npos : end - start));
      start = ((end > (std::string::npos - 1)) ? std::string::npos : end + 1);
    }

    return ret;
    }


    // characters to be ignored
    bool ignore( char c ) {
        return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f';
    }

    // parenthesis
    bool paren( char c ) {
        return c == '(' || c == ')' || c == '{' || c == '}';
    }

    // current character
    char getChar() {
        return s[c];
    }

    // print line and column
    void printLine() {
        std::cout << "Line " << r << ", column " << c+1 << ": ";
    }

    void tokenExit( const std::string & t ) {
        c -= t.size();
        printLine();
        throw UnknownToken(t);
    }

    // get next non-ignored character
    void next() {
        for ( ; c < s.size() && ignore( s[c] ); ++c );
        while ( c == s.size() || s[c] == ';' ) {


            ++r;
            c = 0;

            s = lines[current_line++];
            std::transform(s.begin(), s.end(),s.begin(), ::tolower);

            for ( ; c < s.size() && ignore( s[c] ); ++c );
        }
    }

    // get token converted to lowercase
    std::string getToken() {
        std::ostringstream os;
        while ( c < s.size() && !ignore( s[c] ) && !paren( s[c] ) && s[c] != ',' )
            os << ( 65 <= s[c] && s[c] <= 90 ? (char)( s[c++] + 32 ) : s[c++] );

        return os.str();
    }

    // get token converted to lowercase
    // check that the token exists
    template < typename T >
    std::string getToken( const TokenStruct< T > & ts ) {
        std::string t = getToken();
        if ( ts.index( t ) < 0 )
            tokenExit( t );
        return t;
    }

    // assert syntax
    void assert_token( const std::string & t ) {
        unsigned b = 0;
        for ( unsigned k = 0; c + k < s.size() && k < t.size(); ++k )
            b += s[c + k] == t[k] ||
                 ( 65 <= s[c + k] && s[c + k] <= 90 && s[c + k] == t[k] - 32 );

        if ( b < t.size() ) {
            printLine();
            throw ExpectedToken(t);
        }
        c += t.size();
        next();
    }

    // parse the name of a domain or instance
    std::string parseName( const std::string & u ) {
        std::string out;
        std::string t[5] = { "(", "define", "(", u, ")" };
        for ( unsigned i = 0; i < 5; ++i ) {
            assert_token( t[i] );
            if ( i == 3 ) {
                out = getToken();
                next();
            }
        }
        return out;
    }


    // parse a typed list
    // if check is true, checks that types exist
    TokenStruct< std::string > parseTypedList( bool check, const TokenStruct< Type * > & ts = TokenStruct< Type * >(), const std::string & lt = "" ) {
        unsigned k = 0;
        TokenStruct< std::string > out;
        for ( next(); getChar() != ')' && lt.find( getChar() ) == std::string::npos; next() ) {
            if ( getChar() == '-' ) {
                assert_token( "-" );

                std::string t;
                // check if the type is "either"
                if ( getChar() == '(' ) {
                    assert_token( "(" );
                    assert_token( "either" );

                    t = "( either";
                    for ( ; getChar() != ')'; next() ) {
                        if ( check ) t += " " + getToken( ts );
                        else t += " " + getToken();
                    }
                    t += " )";
                    ++c;
                }
                else if ( check ) t = getToken( ts );
                else t = getToken();

                out.types.insert( out.types.end(), out.size() - k, t );
                k = out.size();
            }
            else if ( getChar() == '(' ) {
                assert_token( "(" );
                assert_token( ":private" );
                getToken();
                out.append( parseTypedList( check, ts ) );
            }
            else out.insert( getToken() );
        }
        if ( k < out.size() ) out.types.insert( out.types.end(), out.size() - k, check ? "object" : "" );
        ++c;

        return out;
    }

};

} } // namespaces