-
-
Notifications
You must be signed in to change notification settings - Fork 373
/
Cursor.pm
87 lines (77 loc) · 2.88 KB
/
Cursor.pm
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
my class Cursor does NQPCursorRole {
has $!ast; # Need it to survive re-creations of the match object.
# Some bits to support <prior>
my $last_match;
method MATCH() {
my $match := nqp::getattr(self, Cursor, '$!match');
return $match if nqp::istype($match, Match) && nqp::isconcrete($match);
$match := nqp::create(Match);
nqp::bindattr($match, Match, '$!orig', nqp::findmethod(self, 'orig')(self));
nqp::bindattr_i($match, Match, '$!from', nqp::getattr_i(self, Cursor, '$!from'));
nqp::bindattr_i($match, Match, '$!to', nqp::getattr_i(self, Cursor, '$!pos'));
nqp::bindattr($match, Match, '$!ast', nqp::getattr(self, Cursor, '$!ast'));
nqp::bindattr($match, Match, '$!CURSOR', self);
my Mu $list := nqp::list();
my Mu $hash := nqp::hash();
if $match.Bool {
my Mu $caphash := nqp::findmethod(Cursor, 'CAPHASH')(self);
my Mu $capiter := nqp::iterator($caphash);
while $capiter {
my str $key = nqp::shift_s($capiter);
my Mu $value := nqp::p6type(nqp::atkey($caphash, $key));
if $key eq '$!from' || $key eq '$!to' {
nqp::bindattr_i($match, Match, $key, $value.from);
}
else {
$value := nqp::p6list($value, List, Mu)
if nqp::islist($value);
nqp::iscclass(pir::const::CCLASS_NUMERIC, $key, 0)
?? nqp::bindpos($list, $key, $value)
!! nqp::bindkey($hash, $key, $value);
}
}
}
nqp::bindattr($match, Capture, '$!list', $list);
nqp::bindattr($match, Capture, '$!hash', $hash);
nqp::bindattr(self, Cursor, '$!match', $match);
$match;
}
method MATCH_SAVE() {
my $match := self.MATCH();
$last_match := $match if $match;
$match;
}
method INTERPOLATE($var, $i = 0) {
nqp::isconcrete($var) ??
($var ~~ Callable ?? $var(self) !! self."!LITERAL"(nqp::unbox_s($var.Str), $i)) !!
self."!cursor_start"()
}
method OTHERGRAMMAR($grammar, $name, |) {
my $lang_cursor := $grammar.'!cursor_init'(self.target(), :p(self.pos()));
$lang_cursor."$name"();
}
method RECURSE() {
pir::find_dynamic_lex__Ps('$?REGEX')(self)
}
method prior() {
nqp::isconcrete($last_match) ??
self."!LITERAL"(nqp::unbox_s(~$last_match)) !!
self."!cursor_start"()
}
}
sub MAKE_REGEX($arg) {
my role CachedCompiledRegex {
has $.regex;
}
if $arg ~~ Regex {
$arg
}
elsif nqp::istype($arg, CachedCompiledRegex) {
$arg.regex
}
else {
my $rx := eval("my \$x = anon regex \{ $arg \}");
$arg does CachedCompiledRegex($rx);
$rx
}
}