-
-
Notifications
You must be signed in to change notification settings - Fork 372
/
regex.rakumod
123 lines (102 loc) · 3.29 KB
/
regex.rakumod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Base marker for all things that may appear as top-level regex syntax.
class RakuAST::Regex is RakuAST::Node {
method IMPL-REGEX-TOP-LEVEL-QAST(RakuAST::IMPL::QASTContext $context, Mu $code-object, %mods) {
# Compile the regex.
my $regex-qast := self.IMPL-REGEX-QAST($context, %mods);
# Store its captures and NFA.
# TODO
QRegex::P6Regex::Actions.store_regex_caps($code-object, nqp::null, nqp::hash());
# Wrap in scan/pass
QAST::Regex.new(
:rxtype('concat'),
QAST::Regex.new( :rxtype('scan') ),
$regex-qast,
QAST::Regex.new( :rxtype('pass') )
)
}
}
# Common role done by all branching regex constructs (alternations and conjunctions).
class RakuAST::Regex::Branching is RakuAST::Regex {
has Mu $!branches;
method new(*@branches) {
my $obj := nqp::create(self);
nqp::bindattr($obj, RakuAST::Regex::Branching, '$!branches',
@branches);
$obj
}
method branches() {
self.IMPL-WRAP-LIST($!branches)
}
method IMPL-REGEX-QAST(RakuAST::IMPL::QASTContext $context, %mods) {
my $qast := QAST::Regex.new(:rxtype(self.IMPL-QAST-REGEX-TYPE));
for $!branches {
$qast.push($_.IMPL-REGEX-QAST($context, $_));
}
$qast
}
method visit-children(Code $visitor) {
for $!branches {
$visitor($_);
}
}
}
# Sequential alternation (||).
class RakuAST::Regex::SequentialAlternation is RakuAST::Regex::Branching {
method IMPL-QAST-REGEX-TYPE() { 'altseq' }
}
# Sequential conjunction (&&).
class RakuAST::Regex::SequentialConjunction is RakuAST::Regex::Branching {
method IMPL-QAST-REGEX-TYPE() { 'conjseq' }
}
# Alternation (|).
class RakuAST::Regex::Alternation is RakuAST::Regex::Branching {
method IMPL-QAST-REGEX-TYPE() { 'alt' }
}
# Conjunction (|).
class RakuAST::Regex::Conjunction is RakuAST::Regex::Branching {
method IMPL-QAST-REGEX-TYPE() { 'conj' }
}
# A sequence of terms to match, one after the other.
class RakuAST::Regex::Sequence is RakuAST::Regex {
has Mu $!terms;
method new(*@terms) {
my $obj := nqp::create(self);
nqp::bindattr($obj, RakuAST::Regex::Sequence, '$!terms',
@terms);
$obj
}
method terms() {
self.IMPL-WRAP-LIST($!terms)
}
method IMPL-REGEX-QAST(RakuAST::IMPL::QASTContext $context, %mods) {
my $concat := QAST::Regex.new(:rxtype<concat>);
for $!terms {
$concat.push($_.IMPL-REGEX-QAST($context, $_));
}
$concat
}
method visit-children(Code $visitor) {
for $!terms {
$visitor($_);
}
}
}
# Marker for all regex terms.
class RakuAST::Regex::Term is RakuAST::Regex {
}
# Marker for all regex atoms.
class RakuAST::Regex::Atom is RakuAST::Regex::Term {
}
# A literal, unquoted, piece of text appearing in the regex.
class RakuAST::Regex::Literal is RakuAST::Regex::Atom {
has str $.text;
method new(str $text) {
my $obj := nqp::create(self);
nqp::bindattr_s($obj, RakuAST::Regex::Literal, '$!text', $text);
$obj
}
method IMPL-REGEX-QAST(RakuAST::IMPL::QASTContext $context, %mods) {
# TODO modifiers
QAST::Regex.new( :rxtype<literal>, $!text )
}
}