Skip to content

Commit

Permalink
Added upper bounds for sequences (#149)
Browse files Browse the repository at this point in the history
* Added top-level option shape to well-formedness specifications

* Replaced Option class by extended Sequence class

* Bounds checking for sequences

---------

Co-authored-by: Sylvan Clebsch <[email protected]>
  • Loading branch information
EliasC and sylvanc authored Dec 16, 2024
1 parent 7825421 commit 5858239
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 13 deletions.
73 changes: 61 additions & 12 deletions include/trieste/wf.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,13 @@ namespace trieste
struct Sequence
{
Choice choice;
size_t minlen;
size_t min_len;
size_t max_len;
bool has_minlen = false;
bool has_maxlen = false;

SNMALLOC_SLOW_PATH Sequence(Choice choice_, size_t minlen_) :
choice{choice_}, minlen{minlen_} {}
SNMALLOC_SLOW_PATH Sequence(Choice choice_, size_t minlen_, size_t maxlen_) :
choice{choice_}, min_len{minlen_}, max_len(maxlen_) {}
SNMALLOC_SLOW_PATH Sequence() = default;
SNMALLOC_SLOW_PATH Sequence(const Sequence&) = default;
SNMALLOC_SLOW_PATH Sequence(Sequence&&) = default;
Expand All @@ -262,9 +265,30 @@ namespace trieste
return std::numeric_limits<size_t>::max();
}

Sequence& operator[](size_t new_minlen)
Sequence& operator[](size_t new_len)
{
minlen = new_minlen;
if (has_minlen && has_maxlen)
throw std::runtime_error(
"Too many bounds when building sequence: ["
+ std::to_string(min_len) + "]["
+ std::to_string(max_len) + "]["
+ std::to_string(new_len) + "]");

if (has_minlen && !has_maxlen && new_len < min_len)
throw std::runtime_error(
"Upper bound is below lower bound when building sequence: ["
+ std::to_string(min_len) + "][" + std::to_string(new_len) + "]");

if (!has_minlen)
{
min_len = new_len;
has_minlen = true;
}
else
{
max_len = new_len;
has_maxlen = true;
}
return *this;
}

Expand All @@ -285,10 +309,19 @@ namespace trieste
ok = choice.check(child) && ok;
}

if (!has_err && (node->size() < minlen))
if (!has_err && (node->size() < min_len))
{
logging::Error() << node->location().origin_linecol()
<< ": expected at least " << minlen
<< ": expected at least " << min_len
<< " children, found " << node->size() << std::endl
<< node->location().str() << node << std::endl;
ok = false;
}

if (!has_err && (node->size() > max_len))
{
logging::Error() << node->location().origin_linecol()
<< ": expected at most " << max_len
<< " children, found " << node->size() << std::endl
<< node->location().str() << node << std::endl;
ok = false;
Expand All @@ -305,10 +338,11 @@ namespace trieste

void gen(Gen& g, size_t depth, Node node) const
{
for (size_t i = 0; i < minlen; ++i)
size_t i;
for (i = 0; i < min_len; ++i)
choice.gen(g, depth, node);

while (g.next() % 2)
while (i++ < max_len && g.next() % 2)
choice.gen(g, depth, node);
}
};
Expand Down Expand Up @@ -830,17 +864,32 @@ namespace trieste

inline Sequence operator++(const Token& type, int)
{
return Sequence{Choice{std::vector<Token>{type}}, 0};
return Sequence{Choice{std::vector<Token>{type}}, 0, std::numeric_limits<size_t>::max()};
}

inline Sequence operator++(const Choice& choice, int)
{
return Sequence{choice, 0};
return Sequence{choice, 0, std::numeric_limits<size_t>::max()};
}

inline Sequence operator++(Choice&& choice, int)
{
return Sequence{choice, 0};
return Sequence{choice, 0, std::numeric_limits<size_t>::max()};
}

inline Sequence operator~(const Token& type)
{
return Sequence{Choice{std::vector<Token>{type}}, 0, 1};
}

inline Sequence operator~(const Choice& choice)
{
return Sequence{choice, 0, 1};
}

inline Sequence operator~(Choice&& choice)
{
return Sequence{choice, 0, 1};
}

inline Field operator>>=(const Token& name, const Token& type)
Expand Down
2 changes: 1 addition & 1 deletion parsers/json/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace trieste
// clang-format off
inline const auto wf_parse =
(Top <<= File)
| (File <<= Group++)
| (File <<= ~Group)
| (Value <<= Group)
| (Array <<= Group)
| (Object <<= Group)
Expand Down

0 comments on commit 5858239

Please sign in to comment.