Skip to main content

I writedwrote a simple parser for using it in input-output operators. What is wrong with this code and how could it be better?

Here is an example of using my parser:Example:

I writed a simple parser for using it in input-output operators.

Here is an example of using my parser:

I wrote a simple parser for input-output operators. What is wrong with this code and how could it be better?

Example:

Tweeted twitter.com/#!/StackCodeReview/status/351568284782563328
Source Link
user21974
user21974

Simple Parser, C++

I writed a simple parser for using it in input-output operators.

#ifndef PARSER_H_
#define PARSER_H_

#include <string>

class parser {
public:
    typedef std::string::const_iterator const_iterator;
private:
    static const_iterator start_position(bool b, const std::string& str);
    static const_iterator begin_it(const parser& p);
    static const_iterator end_it(const parser& p);
    static const_iterator current_it(const parser& p);
    const_iterator begin;
    const_iterator end;
    const_iterator it;
public:

    parser(): begin(NULL), end(NULL), it(NULL) {};

    parser
    (
        const std::string& str_to_parse,
        bool start_from_the_end
    ):
        begin(str_to_parse.begin()),
        end  (str_to_parse.end()),
        it   (start_position(start_from_the_end, str_to_parse)) {};

    //Give another string to parser:
    void str(const std::string&);

    void set_to_begin();
    void set_to_end();

    parser& operator = (const parser&);

    bool eof_str() const;

    char get();         //move forward
    char rget();        //move backward
    char peek() const;  //watch current symbol

    //pass an all symbols beginning from current:
    void pass(char);     //moving forward
    void rpass(char);    //moving backward
    //pass an all symbols beginning from
    //current which satisfy to condition:
    void pass(bool (*)(char));  //moving forward
    void rpass(bool (*)(char)); //moving backward

    //return iterator:
    const_iterator current_it() const;

};

//This function is used in constructor:
//it helps to set iterator of parser
//to beginning or to the end of string.
inline
parser::const_iterator parser::start_position(bool b, const std::string& str) {

    if (b)
        return str.end();

    return str.begin();
}

//This functions are used in operator=.
//I decided to do not writing analogous
//const-functions for better encapsulation.
inline
parser::const_iterator parser::begin_it(const parser& p) {return p.begin;}
inline
parser::const_iterator parser::end_it(const parser& p) {return p.end;}
inline
parser::const_iterator parser::current_it(const parser& p) {return p.it;}

inline
void parser::str(const std::string& str_to_parse) {
    begin = str_to_parse.begin();
    end   = str_to_parse.end();
    it    = str_to_parse.begin();
}

inline
void parser::set_to_begin() {it = begin;}

inline
void parser::set_to_end() {it = end;}

inline
parser& parser::operator = (const parser& p) {
    begin = begin_it(p);
    end   = end_it(p);
    it    = current_it(p);
    return *this;
}

inline
bool parser::eof_str() const {return it >= end;}

inline
char parser::get() {return *(it++);}

inline
char parser::rget() {return *(it--);}

inline
char parser::peek() const {return *it;}

inline
void parser::pass(char chr) {
    while (*it == chr) ++it;
}

inline
void parser::rpass(char chr) {
    while (*it == chr) --it;
}

inline
void parser::pass(bool (*cond)(char)) {
    while (cond(*it)) ++it;
}

inline
void parser::rpass(bool (*cond)(char)) {
    while (cond(*it)) --it;
}

inline
parser::const_iterator parser::current_it() const {return it;}

#endif /* PARSER_H_ */

Here is an example of using my parser:

#include "parser.h"
#include <string>

bool digit(char chr) {
    return (chr >= '0' && chr <= '9');
}

std::string cut_number(parser& p, bool& error) {
    error = false;
    //Check on that the first
    //symbol is a digit:
    if (!digit(p.peek())) {
        error = true;
        return "";
    }
    parser::const_iterator begin = p.current_it();
    //Check on that it is
    //correct number:
    if (p.get() == '0') {
        if (digit(p.peek())) {
            error = true;
            return "";
        }
    }
    p.pass(digit);
    //In the code below could not be
    //if (p.get() == '.')
    //because next char after *p.it
    //must be checked only if *p.it == '.'
    if (p.peek() == '.') {
        p.get();
        //Check on that it is
        //correct float pointing number:
        if (!digit(p.peek())) {
            error = true;
            return "";
        }
        else p.pass(digit);
    }
    parser::const_iterator end = p.current_it();
    return std::string(begin, end);
}