Skip to content

Commit

Permalink
Add support for unit switch &parse-at and &parse-from attributes.
Browse files Browse the repository at this point in the history
Closes #913.
  • Loading branch information
bbannier committed May 28, 2021
1 parent 9ffdf6a commit 57f2e12
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 2 deletions.
36 changes: 35 additions & 1 deletion spicy/toolchain/src/compiler/codegen/parser-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -981,8 +981,39 @@ struct ProductionVisitor
void operator()(const production::Switch& p) {
builder()->addCall("hilti::debugIndent", {builder::string("spicy")});

if ( const auto& a = AttributeSet::find(p.attributes(), "&parse-from") ) {
// Redirect input to a bytes value.
auto pstate = state();
pstate.trim = builder::bool_(false);
pstate.lahead = builder()->addTmp("parse_lah", look_ahead::Type, look_ahead::None);
pstate.lahead_end = builder()->addTmp("parse_lahe", type::stream::Iterator());
auto expr = a->valueAs<Expression>();

auto tmp = builder()->addTmp("parse_from", type::ValueReference(type::Stream()), *expr);
pstate.data = tmp;
pstate.cur = builder()->addTmp("parse_cur", type::stream::View(), builder::deref(tmp));
pstate.ncur = {};
builder()->addMemberCall(tmp, "freeze", {});

pushState(std::move(pstate));
}

if ( auto a = AttributeSet::find(p.attributes(), "&parse-at") ) {
// Redirect input to a stream position.
auto pstate = state();
pstate.trim = builder::bool_(false);
pstate.lahead = builder()->addTmp("parse_lah", look_ahead::Type, look_ahead::None);
pstate.lahead_end = builder()->addTmp("parse_lahe", type::stream::Iterator());
auto expr = a->valueAs<Expression>();

auto cur = builder::memberCall(state().cur, "advance", {*expr});
pstate.cur = builder()->addTmp("parse_cur", cur);
pstate.ncur = {};
pushState(std::move(pstate));
}

std::optional<Expression> ncur;
if ( auto a = AttributeSet::find(p.attributes(), "&size") ) {
if ( const auto& a = AttributeSet::find(p.attributes(), "&size") ) {
// Limit input to the specified length.
auto length = builder::coerceTo(*a->valueAs<Expression>(), type::UnsignedInteger(64));
auto limited = builder()->addTmp("limited", builder::memberCall(state().cur, "limit", {length}));
Expand Down Expand Up @@ -1023,6 +1054,9 @@ struct ProductionVisitor
builder()->addAssign(state().cur, *ncur);
}

if ( AttributeSet::find(p.attributes(), "&parse-from") || AttributeSet::find(p.attributes(), "&parse-at") )
popState();

builder()->addCall("hilti::debugDedent", {builder::string("spicy")});
}

Expand Down
2 changes: 1 addition & 1 deletion spicy/toolchain/src/compiler/visitors/validator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ struct PreTransformVisitor : public hilti::visitor::PreOrder<void, PreTransformV
for ( const auto& attr : attrs->attributes() ) {
const auto& tag = attr.tag();

if ( tag != "&size" )
if ( tag != "&size" && tag != "&parse-at" && tag != "&parse-from" )
error(fmt("attribute '%s' is not supported here", tag), p);
}
}
Expand Down
9 changes: 9 additions & 0 deletions tests/Baseline/spicy.types.unit.switch-parse-from/output
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
Mini::X {
a: \x01
b: \x01
}
Mini::Y {
a: \x01
b: \x01\x02\x03
}
22 changes: 22 additions & 0 deletions tests/spicy/types/unit/switch-parse-from.spicy
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# @TEST-EXEC: ${SPICYC} %INPUT -j -o %INPUT.hlto
# @TEST-EXEC: ${SCRIPTS}/printf '\01\02\03' | spicy-dump -p Mini::X %INPUT.hlto >>output
# @TEST-EXEC: ${SCRIPTS}/printf '\01\02\03' | spicy-dump -p Mini::Y %INPUT.hlto >>output
# @TEST-EXEC: btest-diff output

module Mini;

public type X = unit {
a: bytes &size=1;
switch ( self.a ) {
* -> b: bytes &eod;
} &parse-from=self.a;
};

public type Y = unit {
%random-access;

a: bytes &size=1;
switch ( self.a ) {
* -> b: bytes &eod;
} &parse-at=self.input();
};

0 comments on commit 57f2e12

Please sign in to comment.