mame/src/lib/netlist/plib/pparser.h
2019-09-28 12:51:42 +02:00

282 lines
6.4 KiB
C++

// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* pparser.h
*
*/
#ifndef PPARSER_H_
#define PPARSER_H_
#include "plists.h"
#include "pstream.h"
#include "pstring.h"
//#include <cstdint>
#include <unordered_map>
namespace plib {
class ptokenizer
{
public:
template <typename T>
ptokenizer(T &&strm) // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
: m_strm(std::forward<T>(strm))
, m_lineno(0)
, m_cur_line("")
, m_px(m_cur_line.begin())
, m_unget(0)
, m_string('"')
{
}
COPYASSIGNMOVE(ptokenizer, delete)
virtual ~ptokenizer() = default;
enum token_type
{
IDENTIFIER,
NUMBER,
TOKEN,
STRING,
COMMENT,
UNKNOWN,
ENDOFFILE
};
struct token_id_t
{
public:
static constexpr std::size_t npos = static_cast<std::size_t>(-1);
token_id_t() : m_id(npos) {}
explicit token_id_t(const std::size_t id) : m_id(id) {}
std::size_t id() const { return m_id; }
private:
std::size_t m_id;
};
struct token_t
{
explicit token_t(token_type type)
: m_type(type), m_id(), m_token("")
{
}
token_t(token_type type, const pstring &str)
: m_type(type), m_id(), m_token(str)
{
}
token_t(const token_id_t &id, const pstring &str)
: m_type(TOKEN), m_id(id), m_token(str)
{
}
bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
bool is_type(const token_type type) const { return m_type == type; }
pstring str() const { return m_token; }
private:
token_type m_type;
token_id_t m_id;
pstring m_token;
};
int currentline_no() { return m_lineno; }
pstring currentline_str();
/* tokenizer stuff follows ... */
token_t get_token();
pstring get_string();
pstring get_identifier();
pstring get_identifier_or_number();
double get_number_double();
long get_number_long();
void require_token(const token_id_t &token_num);
void require_token(const token_t &tok, const token_id_t &token_num);
token_id_t register_token(const pstring &token)
{
token_id_t ret(m_tokens.size());
m_tokens.emplace(token, ret);
return ret;
}
ptokenizer & identifier_chars(const pstring &s) { m_identifier_chars = s; return *this; }
ptokenizer & number_chars(const pstring &st, const pstring & rem) { m_number_chars_start = st; m_number_chars = rem; return *this; }
ptokenizer & string_char(pstring::value_type c) { m_string = c; return *this; }
ptokenizer & whitespace(const pstring & s) { m_whitespace = s; return *this; }
ptokenizer & comment(const pstring &start, const pstring &end, const pstring &line)
{
m_tok_comment_start = register_token(start);
m_tok_comment_end = register_token(end);
m_tok_line_comment = register_token(line);
return *this;
}
token_t get_token_internal();
void error(const pstring &errs) { verror(errs, currentline_no(), currentline_str()); }
putf8_reader &stream() { return m_strm; }
protected:
virtual void verror(const pstring &msg, int line_num, const pstring &line) = 0;
private:
void skipeol();
pstring::value_type getc();
void ungetc(pstring::value_type c);
bool eof() { return m_strm.eof(); }
putf8_reader m_strm;
int m_lineno;
pstring m_cur_line;
pstring::const_iterator m_px;
pstring::value_type m_unget;
/* tokenizer stuff follows ... */
pstring m_identifier_chars;
pstring m_number_chars;
pstring m_number_chars_start;
std::unordered_map<pstring, token_id_t> m_tokens;
pstring m_whitespace;
pstring::value_type m_string;
token_id_t m_tok_comment_start;
token_id_t m_tok_comment_end;
token_id_t m_tok_line_comment;
};
class ppreprocessor : public std::istream
{
public:
struct define_t
{
define_t(const pstring &name, const pstring &replace)
: m_name(name), m_replace(replace)
{}
pstring m_name;
pstring m_replace;
};
using defines_map_type = std::unordered_map<pstring, define_t>;
explicit ppreprocessor(defines_map_type *defines = nullptr);
~ppreprocessor() override
{
delete rdbuf();
}
template <typename T>
ppreprocessor & process(T &&istrm)
{
putf8_reader reader(std::forward<T>(istrm));
pstring line;
while (reader.readline(line))
{
m_lineno++;
line = process_line(line);
m_buf += decltype(m_buf)(line.c_str()) + static_cast<char>(10);
}
return *this;
}
COPYASSIGN(ppreprocessor, delete)
ppreprocessor &operator=(ppreprocessor &&src) = delete;
ppreprocessor(ppreprocessor &&s) noexcept
: std::istream(new readbuffer(this))
, m_defines(std::move(s.m_defines))
, m_expr_sep(std::move(s.m_expr_sep))
, m_ifflag(s.m_ifflag)
, m_level(s.m_level)
, m_lineno(s.m_lineno)
, m_buf(std::move(s.m_buf))
, m_pos(s.m_pos)
, m_state(s.m_state)
, m_comment(s.m_comment)
{
}
protected:
class readbuffer : public std::streambuf
{
public:
readbuffer(ppreprocessor *strm) : m_strm(strm), m_buf() { setg(nullptr, nullptr, nullptr); }
readbuffer(readbuffer &&rhs) noexcept : m_strm(rhs.m_strm), m_buf() {}
COPYASSIGN(readbuffer, delete)
readbuffer &operator=(readbuffer &&src) = delete;
int_type underflow() override
{
//printf("here\n");
if (this->gptr() == this->egptr())
{
/* clang reports sign error - weird */
std::size_t bytes = pstring_mem_t_size(m_strm->m_buf) - static_cast<std::size_t>(m_strm->m_pos);
if (bytes > m_buf.size())
bytes = m_buf.size();
std::copy(m_strm->m_buf.c_str() + m_strm->m_pos, m_strm->m_buf.c_str() + m_strm->m_pos + bytes, m_buf.data());
//printf("%ld\n", (long int)bytes);
this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
m_strm->m_pos += static_cast</*pos_type*/long>(bytes);
}
return this->gptr() == this->egptr()
? std::char_traits<char>::eof()
: std::char_traits<char>::to_int_type(*this->gptr());
}
private:
ppreprocessor *m_strm;
std::array<char_type, 1024> m_buf;
};
//friend class st;
int expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio);
define_t *get_define(const pstring &name);
pstring replace_macros(const pstring &line);
virtual void error(const pstring &err);
private:
enum state_e
{
PROCESS,
LINE_CONTINUATION
};
pstring process_line(pstring line);
pstring process_comments(pstring line);
defines_map_type m_defines;
std::vector<pstring> m_expr_sep;
std::uint_least64_t m_ifflag; // 31 if levels
int m_level;
int m_lineno;
pstring_t<pu8_traits> m_buf;
std::istream::pos_type m_pos;
state_e m_state;
pstring m_line;
bool m_comment;
};
} // namespace plib
#endif /* PPARSER_H_ */