Skip to content

Commit

Permalink
RakuAST handling of regex sigspace
Browse files Browse the repository at this point in the history
There were a few ways this might have been designed, but modeling it as
a node wrapping the piece of regex that is followed by sigspace seems
the least error-prone. A flag on every regex node that it's followed by
sigspace is more memory intensive in the common case, and not always
meaningful anyway, plus it would be a nuisance to apply it everywhere.
It does force all of the decision-making into whatever is constructing
the AST nodes, but so will force some whitespace insertion onto any
pretty printers too (as well as making sure they already think they are
emitting sigspace code, if they want to properly handle synthetic
constructions).
  • Loading branch information
jnthn committed Jun 3, 2021
1 parent 700c71f commit d5cfc1a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
26 changes: 19 additions & 7 deletions src/Raku/Actions.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -1676,17 +1676,19 @@ class Raku::RegexActions is HLL::Actions does Raku::CommonActions {
}

method quantified_atom($/) {
my $atom := $<atom>.ast;
my $atom := self.wrap-sigspace: $<sigmaybe>, $<atom>.ast;
if $<quantifier> {
my $quantifier := $<quantifier>.ast;
if $<separator> {
my $separator := $<separator>.ast;
my $trailing-separator := $<separator><septype> eq '%%';
self.attach: $/, self.r('Regex', 'QuantifiedAtom').new(:$atom, :$quantifier,
:$separator, :$trailing-separator);
self.attach: $/, self.wrap-sigspace: $<sigfinal>,
self.r('Regex', 'QuantifiedAtom').new(:$atom, :$quantifier,
:$separator, :$trailing-separator);
}
else {
self.attach: $/, self.r('Regex', 'QuantifiedAtom').new(:$atom, :$quantifier);
self.attach: $/, self.wrap-sigspace: $<sigfinal>,
self.r('Regex', 'QuantifiedAtom').new(:$atom, :$quantifier);
}
}
else {
Expand All @@ -1695,15 +1697,25 @@ class Raku::RegexActions is HLL::Actions does Raku::CommonActions {
"' may only be used immediately following a quantifier");
}
if $<backmod> {
self.attach: $/, self.r('Regex', 'BacktrackModifiedAtom').new:
:$atom, :backtrack($<backmod>.ast);
self.attach: $/, self.wrap-sigspace: $<sigfinal>,
self.r('Regex', 'BacktrackModifiedAtom').new:
:$atom, :backtrack($<backmod>.ast);
}
else {
self.attach: $/, $atom;
self.attach: $/, self.wrap-sigspace: $<sigfinal>, $atom;
}
}
}

method wrap-sigspace($cond, $ast) {
$cond && $cond.ast
?? self.r('Regex', 'WithSigspace').new($ast)
!! $ast
}

method sigmaybe:sym<normspace>($/) { make 0; }
method sigmaybe:sym<sigwhite>($/) { make 1; }

method atom($/) {
if $<metachar> {
self.attach: $/, $<metachar>.ast;
Expand Down
23 changes: 23 additions & 0 deletions src/Raku/ast/regex.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -1722,3 +1722,26 @@ class RakuAST::Regex::Backtrack::Ratchet is RakuAST::Regex::Backtrack {
$quant-qast
}
}

# A regex atom or term followed by sigspace.
class RakuAST::Regex::WithSigspace is RakuAST::Regex::Atom {
has RakuAST::Regex::Term $.regex;

method new(RakuAST::Regex::Term $regex) {
my $obj := nqp::create(self);
nqp::bindattr($obj, RakuAST::Regex::WithSigspace, '$!regex', $regex);
$obj
}

method IMPL-REGEX-QAST(RakuAST::IMPL::QASTContext $context, %mods) {
QAST::Regex.new: :rxtype<concat>,
$!regex.IMPL-REGEX-QAST($context, %mods),
QAST::Regex.new:
:rxtype<subrule>, :subtype<method>, :name<ws>,
QAST::NodeList.new(QAST::SVal.new( :value('ws') ))
}

method visit-children(Code $visitor) {
$visitor($!regex);
}
}

0 comments on commit d5cfc1a

Please sign in to comment.