<commit_before>class Regex::P6Regex::Actions;

## this will eventually be handled using contextuals
our @MODIFIERS := Q:PIR { 
        %r = new ['ResizablePMCArray'] 
        $P0 = new ['Hash']
        push %r, $P0
    };

method TOP($/) {
    make buildsub( $<nibbler>.ast );
}

method nibbler($/, $key?) {
    if $key eq 'open' {
        my %old := @MODIFIERS[0];
        my %new := Q:PIR {
                       $P0 = find_lex '%old'
                       %r = clone $P0
                   };
        @MODIFIERS.unshift(%new);
        return 1;
    }

    @MODIFIERS.shift;
    my $past;
    if +$<termish> > 1 {
        $past := PAST::Regex.new( :pasttype('alt') );
        for $<termish> { 
            $past.push($_.ast); 
        }
    }
    else {
        $past := $<termish>[0].ast;
    }
    make $past;
}

method termish($/) {
    my $past := PAST::Regex.new( :pasttype('concat') );
    my $lastlit := 0;
    for $<noun> {
        my $ast := $_.ast;
        if !$ast { }
        elsif $lastlit && $ast.pasttype eq 'literal' {
            $lastlit[0] := $lastlit[0] ~ $ast[0];
        }
        else {
            $past.push($ast);
            $lastlit := $ast.pasttype eq 'literal' ?? $ast !! 0;
        }
    }
    make $past;
}

method quantified_atom($/) {
    my $past := $<atom>.ast;
    if $<quantifier> {
        if !$past { $/.panic("Can't quantify zero-width atom"); }
        my $qast := $<quantifier>[0].ast;
        $qast.unshift($past);
        $past := $qast;
    }
    elsif $<backmod>[0] { backmod($past, $<backmod>[0]); }
    if $past && !$past.backtrack && @MODIFIERS[0]<r> {
        $past.backtrack('r');
    }
    make $past;
}

method atom($/) {
    my $past;
    if $<metachar> { $past := $<metachar>.ast }
    else {
        $past := PAST::Regex.new( ~$/ , :pasttype('literal') );
        if @MODIFIERS[0]<i> { $past.subtype('ignorecase'); }
    }
    make $past;
}

method quantifier:sym<*>($/) {
    my $past := PAST::Regex.new( :pasttype('quant') );
    make backmod($past, $<backmod>);
}

method quantifier:sym<+>($/) {
    my $past := PAST::Regex.new( :pasttype('quant'), :min(1) );
    make backmod($past, $<backmod>);
}

method quantifier:sym<?>($/) {
    my $past := PAST::Regex.new( :pasttype('quant'), :min(0), :max(1) );
    make backmod($past, $<backmod>);
    make $past;
}

method quantifier:sym<**>($/) {
    my $past;
    if $<quantified_atom> {
        $past := PAST::Regex.new( :pasttype('quant'), :min(1),
                                  :sep( $<quantified_atom>.ast ) );
    }
    else {
        $past := PAST::Regex.new( :pasttype('quant'), :min(+$<min>) );
        if ! $<max> { $past.max(+$<min>); }
        elsif $<max>[0] ne '*' { $past.max(+$<max>[0]); }
    }
    make backmod($past, $<backmod>);
}

method metachar:sym<ws>($/) { 
    my $past := @MODIFIERS[0]<s>
                ?? PAST::Regex.new( 'ws', :pasttype('subrule'), 
                                    :subtype('method') )
                !! 0;
    make $past; 
}


method metachar:sym<[ ]>($/) {
    make $<nibbler>.ast;
}

method metachar:sym<( )>($/) {
    my $subpast := buildsub($<nibbler>.ast);
    my $past := PAST::Regex.new( $subpast, :pasttype('subrule'),
                                 :subtype('capture') );
    make $past;
}

method metachar:sym<.>($/) {
    my $past := PAST::Regex.new( :pasttype('charclass'), :subtype('.') );
    make $past;
}

method metachar:sym<^>($/) {
    my $past := PAST::Regex.new( :pasttype('anchor'), :subtype('bos') );
    make $past;
}

method metachar:sym<^^>($/) {
    my $past := PAST::Regex.new( :pasttype('anchor'), :subtype('bol') );
    make $past;
}<commit_msg>Add quoted literals to regexes.<commit_after>class Regex::P6Regex::Actions;

## this will eventually be handled using contextuals
our @MODIFIERS := Q:PIR { 
        %r = new ['ResizablePMCArray'] 
        $P0 = new ['Hash']
        push %r, $P0
    };

method TOP($/) {
    make buildsub( $<nibbler>.ast );
}

method nibbler($/, $key?) {
    if $key eq 'open' {
        my %old := @MODIFIERS[0];
        my %new := Q:PIR {
                       $P0 = find_lex '%old'
                       %r = clone $P0
                   };
        @MODIFIERS.unshift(%new);
        return 1;
    }

    @MODIFIERS.shift;
    my $past;
    if +$<termish> > 1 {
        $past := PAST::Regex.new( :pasttype('alt') );
        for $<termish> { 
            $past.push($_.ast); 
        }
    }
    else {
        $past := $<termish>[0].ast;
    }
    make $past;
}

method termish($/) {
    my $past := PAST::Regex.new( :pasttype('concat') );
    my $lastlit := 0;
    for $<noun> {
        my $ast := $_.ast;
        if !$ast { }
        elsif $lastlit && $ast.pasttype eq 'literal' {
            $lastlit[0] := $lastlit[0] ~ $ast[0];
        }
        else {
            $past.push($ast);
            $lastlit := $ast.pasttype eq 'literal' ?? $ast !! 0;
        }
    }
    make $past;
}

method quantified_atom($/) {
    my $past := $<atom>.ast;
    if $<quantifier> {
        if !$past { $/.panic("Can't quantify zero-width atom"); }
        my $qast := $<quantifier>[0].ast;
        $qast.unshift($past);
        $past := $qast;
    }
    elsif $<backmod>[0] { backmod($past, $<backmod>[0]); }
    if $past && !$past.backtrack && @MODIFIERS[0]<r> {
        $past.backtrack('r');
    }
    make $past;
}

method atom($/) {
    my $past;
    if $<metachar> { $past := $<metachar>.ast }
    else {
        $past := PAST::Regex.new( ~$/ , :pasttype('literal') );
        if @MODIFIERS[0]<i> { $past.subtype('ignorecase'); }
    }
    make $past;
}

method quantifier:sym<*>($/) {
    my $past := PAST::Regex.new( :pasttype('quant') );
    make backmod($past, $<backmod>);
}

method quantifier:sym<+>($/) {
    my $past := PAST::Regex.new( :pasttype('quant'), :min(1) );
    make backmod($past, $<backmod>);
}

method quantifier:sym<?>($/) {
    my $past := PAST::Regex.new( :pasttype('quant'), :min(0), :max(1) );
    make backmod($past, $<backmod>);
    make $past;
}

method quantifier:sym<**>($/) {
    my $past;
    if $<quantified_atom> {
        $past := PAST::Regex.new( :pasttype('quant'), :min(1),
                                  :sep( $<quantified_atom>.ast ) );
    }
    else {
        $past := PAST::Regex.new( :pasttype('quant'), :min(+$<min>) );
        if ! $<max> { $past.max(+$<min>); }
        elsif $<max>[0] ne '*' { $past.max(+$<max>[0]); }
    }
    make backmod($past, $<backmod>);
}

method metachar:sym<ws>($/) { 
    my $past := @MODIFIERS[0]<s>
                ?? PAST::Regex.new( 'ws', :pasttype('subrule'), 
                                    :subtype('method') )
                !! 0;
    make $past; 
}


method metachar:sym<[ ]>($/) {
    make $<nibbler>.ast;
}

method metachar:sym<( )>($/) {
    my $subpast := buildsub($<nibbler>.ast);
    my $past := PAST::Regex.new( $subpast, :pasttype('subrule'),
                                 :subtype('capture') );
    make $past;
}

method metachar:sym<'>($/) {
    my $past := PAST::Regex.new( ~$<quote><val>, :pasttype('literal') );
    make $past;
}

method metachar:sym<.>($/) {
    my $past := PAST::Regex.new( :pasttype('charclass'), :subtype('.') );
    make $past;
}

method metachar:sym<^>($/) {
    my $past := PAST::Regex.new( :pasttype('anchor'), :subtype('bos') );
    make $past;
}

method metachar:sym<^^>($/) {
    my $past := PAST::Regex.new( :pasttype('anchor'), :subtype('bol') );
    make $past;
}
{'fraction_non_alphanumeric': 0.2197387908980746, 'fraction_numerical': 0.00727076881648041, 'mean_word_length': 2.166240409207161, 'pattern_counts': {'":': 0, '<': 82, '<?xml version=': 0, '>': 84, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6860261', 'n_tokens_mistral': 2946, 'n_tokens_neox': 2721, 'n_words': 535}