Full list of ones I'm using so far:
# Emulation of yyless(X) is done by using $-[0] (aka @LAST_MATCH_START).
sub YYLess {
my ($p, $x) = @_;
return (pos(${$p->input}) = $-[0] + $x);
}
# @LMS is also useful for emulating yytext.
sub YYText {
my ($p) = @_;
return substr(${$p->input}, $-[0], $p->YYLeng);
}
sub YYLeng {
my ($p) = @_;
# use pos instead of $+[0], since the pos might have changed from a
previous YYLess command
return pos(${$p->input}) - $-[0];
}
sub YYLexPrioritize {
my ($p, $re_hash) = (shift, shift);
my $order_array = ref $_[0] ? shift : [ @_ ];
# Reverse the array to an index hash
my $h = 0;
my %order_hash = map { $_ => $h++; } @$order_array;
my $s = $p->input;
# Run through the REs in order, capture the matches and char lengths
my @results;
my $orig_pos = pos($$s);
foreach my $rule (@$order_array) {
my $re = $re_hash->{$rule};
if (${$p->input} =~ /${re}/gc) {
push @results, [ $rule => $p->YYText ];
pos($$s) = $orig_pos; # reset back to orig pos
}
}
return undef unless scalar @results;
# Who wins? Sort by the standard lex prioritization: 1. char length
of result, 2. rule order
@results = sort { length $b->[1] <=> length $a->[1] || $order_hash{
$a->[0] } <=> $order_hash{ $b->[0] } } @results;
# return rule name only; still need to run the RE again in case of
other RE-based YY variables
return $results[0]->[0];
}
# Bison's yylloc is a YYLTYPE of:
# first_line
# first_column
# last_line
# last_column
#
# We can't exactly provide that, but we can provide more
# than enough to get by with an error message.
### FIXME: This is probably too much, and might hurt speed. ###
sub YYLLoc {
my ($p, $val, $i) = @_;
return {
val => $val // $p->YYText,
char_pos => $-[0], # XXX: is this accurate?
token => $p->YYCurtok,
token_val => $p->YYCurval,
first_line => $p->YYFirstline,
left_side => $p->YYLhs,
right_side => $p->YYRightside($i),
rule_name => $p->YYName,
};
}