420 lines
9.3 KiB
C++
420 lines
9.3 KiB
C++
|
|
#ifndef TOML11_SYNTAX_FWD_HPP
|
||
|
|
#define TOML11_SYNTAX_FWD_HPP
|
||
|
|
|
||
|
|
#include "../scanner.hpp"
|
||
|
|
#include "../spec.hpp"
|
||
|
|
#include "../version.hpp"
|
||
|
|
|
||
|
|
namespace toml
|
||
|
|
{
|
||
|
|
inline namespace TOML11_INLINE_VERSION_NAMESPACE
|
||
|
|
{
|
||
|
|
namespace detail
|
||
|
|
{
|
||
|
|
namespace syntax
|
||
|
|
{
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// UTF-8
|
||
|
|
|
||
|
|
// avoid redundant representation and out-of-unicode sequence
|
||
|
|
|
||
|
|
character_in_range const& utf8_1byte (const spec&);
|
||
|
|
sequence const& utf8_2bytes(const spec&);
|
||
|
|
sequence const& utf8_3bytes(const spec&);
|
||
|
|
sequence const& utf8_4bytes(const spec&);
|
||
|
|
|
||
|
|
class non_ascii final : public scanner_base
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
explicit non_ascii(const spec& s) noexcept
|
||
|
|
: utf8_2B_(utf8_2bytes(s)),
|
||
|
|
utf8_3B_(utf8_3bytes(s)),
|
||
|
|
utf8_4B_(utf8_4bytes(s))
|
||
|
|
{}
|
||
|
|
~non_ascii() override = default;
|
||
|
|
|
||
|
|
region scan(location& loc) const override
|
||
|
|
{
|
||
|
|
{
|
||
|
|
const auto reg = utf8_2B_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const auto reg = utf8_3B_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const auto reg = utf8_4B_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
return region{};
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string expected_chars(location&) const override
|
||
|
|
{
|
||
|
|
return "non-ascii utf-8 bytes";
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner_base* clone() const override
|
||
|
|
{
|
||
|
|
return new non_ascii(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string name() const override
|
||
|
|
{
|
||
|
|
return "non_ascii";
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
sequence utf8_2B_;
|
||
|
|
sequence utf8_3B_;
|
||
|
|
sequence utf8_4B_;
|
||
|
|
};
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Whitespace
|
||
|
|
|
||
|
|
character_either const& wschar(const spec&);
|
||
|
|
|
||
|
|
repeat_at_least const& ws(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Newline
|
||
|
|
|
||
|
|
either const& newline(const spec&);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Comments
|
||
|
|
|
||
|
|
either const& allowed_comment_char(const spec& s);
|
||
|
|
|
||
|
|
// XXX Note that it does not take newline
|
||
|
|
sequence const& comment(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Boolean
|
||
|
|
|
||
|
|
either const& boolean(const spec&);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Integer
|
||
|
|
|
||
|
|
class digit final : public scanner_base
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
explicit digit(const spec&) noexcept
|
||
|
|
: scanner_(char_type('0'), char_type('9'))
|
||
|
|
{}
|
||
|
|
|
||
|
|
|
||
|
|
~digit() override = default;
|
||
|
|
|
||
|
|
region scan(location& loc) const override
|
||
|
|
{
|
||
|
|
return scanner_.scan(loc);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string expected_chars(location&) const override
|
||
|
|
{
|
||
|
|
return "digit [0-9]";
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner_base* clone() const override
|
||
|
|
{
|
||
|
|
return new digit(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string name() const override
|
||
|
|
{
|
||
|
|
return "digit";
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
character_in_range scanner_;
|
||
|
|
};
|
||
|
|
|
||
|
|
class alpha final : public scanner_base
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
explicit alpha(const spec&) noexcept
|
||
|
|
: lowercase_(char_type('a'), char_type('z')),
|
||
|
|
uppercase_(char_type('A'), char_type('Z'))
|
||
|
|
{}
|
||
|
|
~alpha() override = default;
|
||
|
|
|
||
|
|
region scan(location& loc) const override
|
||
|
|
{
|
||
|
|
{
|
||
|
|
const auto reg = lowercase_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const auto reg = uppercase_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
return region{};
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string expected_chars(location&) const override
|
||
|
|
{
|
||
|
|
return "alpha [a-zA-Z]";
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner_base* clone() const override
|
||
|
|
{
|
||
|
|
return new alpha(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string name() const override
|
||
|
|
{
|
||
|
|
return "alpha";
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
character_in_range lowercase_;
|
||
|
|
character_in_range uppercase_;
|
||
|
|
};
|
||
|
|
|
||
|
|
class hexdig final : public scanner_base
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
explicit hexdig(const spec& s) noexcept
|
||
|
|
: digit_(s),
|
||
|
|
lowercase_(char_type('a'), char_type('f')),
|
||
|
|
uppercase_(char_type('A'), char_type('F'))
|
||
|
|
{}
|
||
|
|
~hexdig() override = default;
|
||
|
|
|
||
|
|
region scan(location& loc) const override
|
||
|
|
{
|
||
|
|
{
|
||
|
|
const auto reg = digit_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const auto reg = lowercase_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const auto reg = uppercase_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
return region{};
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string expected_chars(location&) const override
|
||
|
|
{
|
||
|
|
return "hex [0-9a-fA-F]";
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner_base* clone() const override
|
||
|
|
{
|
||
|
|
return new hexdig(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string name() const override
|
||
|
|
{
|
||
|
|
return "hexdig";
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
digit digit_;
|
||
|
|
character_in_range lowercase_;
|
||
|
|
character_in_range uppercase_;
|
||
|
|
};
|
||
|
|
|
||
|
|
sequence const& num_suffix(const spec& s);
|
||
|
|
|
||
|
|
sequence const& dec_int(const spec& s);
|
||
|
|
sequence const& hex_int(const spec& s);
|
||
|
|
sequence const& oct_int(const spec&);
|
||
|
|
sequence const& bin_int(const spec&);
|
||
|
|
either const& integer(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Floating
|
||
|
|
|
||
|
|
sequence const& zero_prefixable_int(const spec& s);
|
||
|
|
sequence const& fractional_part(const spec& s);
|
||
|
|
sequence const& exponent_part(const spec& s);
|
||
|
|
sequence const& hex_floating(const spec& s);
|
||
|
|
either const& floating(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Datetime
|
||
|
|
|
||
|
|
sequence const& local_date(const spec& s);
|
||
|
|
sequence const& local_time(const spec& s);
|
||
|
|
either const& time_offset(const spec& s);
|
||
|
|
sequence const& full_time(const spec& s);
|
||
|
|
character_either const& time_delim(const spec&);
|
||
|
|
sequence const& local_datetime(const spec& s);
|
||
|
|
sequence const& offset_datetime(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// String
|
||
|
|
|
||
|
|
sequence const& escaped_x2(const spec& s);
|
||
|
|
sequence const& escaped_u4(const spec& s);
|
||
|
|
sequence const& escaped_U8(const spec& s);
|
||
|
|
|
||
|
|
sequence const& escaped (const spec& s);
|
||
|
|
either const& basic_char (const spec& s);
|
||
|
|
sequence const& basic_string(const spec& s);
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// multiline string
|
||
|
|
|
||
|
|
sequence const& escaped_newline(const spec& s);
|
||
|
|
sequence const& ml_basic_string(const spec& s);
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// literal string
|
||
|
|
|
||
|
|
either const& literal_char(const spec& s);
|
||
|
|
sequence const& literal_string(const spec& s);
|
||
|
|
sequence const& ml_literal_string(const spec& s);
|
||
|
|
either const& string(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Keys
|
||
|
|
|
||
|
|
// to keep `expected_chars` simple
|
||
|
|
class non_ascii_key_char final : public scanner_base
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
using in_range = character_in_range; // make definition short
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
explicit non_ascii_key_char(const spec& s) noexcept;
|
||
|
|
~non_ascii_key_char() override = default;
|
||
|
|
|
||
|
|
region scan(location& loc) const override;
|
||
|
|
|
||
|
|
std::string expected_chars(location&) const override
|
||
|
|
{
|
||
|
|
return "bare key non-ASCII script";
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner_base* clone() const override
|
||
|
|
{
|
||
|
|
return new non_ascii_key_char(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string name() const override
|
||
|
|
{
|
||
|
|
return "non-ASCII bare key";
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
std::uint32_t read_utf8(location& loc) const;
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
repeat_at_least const& unquoted_key(const spec& s);
|
||
|
|
either const& quoted_key(const spec& s);
|
||
|
|
either const& simple_key(const spec& s);
|
||
|
|
sequence const& dot_sep(const spec& s);
|
||
|
|
sequence const& dotted_key(const spec& s);
|
||
|
|
|
||
|
|
class key final : public scanner_base
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
|
||
|
|
using char_type = location::char_type;
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
explicit key(const spec& s) noexcept
|
||
|
|
: dotted_(dotted_key(s)),
|
||
|
|
simple_(simple_key(s))
|
||
|
|
{}
|
||
|
|
~key() override = default;
|
||
|
|
|
||
|
|
region scan(location& loc) const override
|
||
|
|
{
|
||
|
|
{
|
||
|
|
const auto reg = dotted_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
{
|
||
|
|
const auto reg = simple_.scan(loc);
|
||
|
|
if(reg.is_ok()) {return reg;}
|
||
|
|
}
|
||
|
|
return region{};
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string expected_chars(location&) const override
|
||
|
|
{
|
||
|
|
return "basic key([a-zA-Z0-9_-]) or quoted key(\" or ')";
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner_base* clone() const override
|
||
|
|
{
|
||
|
|
return new key(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string name() const override
|
||
|
|
{
|
||
|
|
return "key";
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
sequence dotted_;
|
||
|
|
either simple_;
|
||
|
|
};
|
||
|
|
|
||
|
|
sequence const& keyval_sep(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// Table key
|
||
|
|
|
||
|
|
sequence const& std_table(const spec& s);
|
||
|
|
|
||
|
|
sequence const& array_table(const spec& s);
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// extension: null
|
||
|
|
|
||
|
|
literal const& null_value(const spec&);
|
||
|
|
|
||
|
|
} // namespace syntax
|
||
|
|
} // namespace detail
|
||
|
|
} // TOML11_INLINE_VERSION_NAMESPACE
|
||
|
|
} // namespace toml
|
||
|
|
#endif // TOML11_SYNTAX_FWD_HPP
|