forked from kschiess/parslet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lookahead.rb
45 lines (36 loc) · 1.19 KB
/
lookahead.rb
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
# Either positive or negative lookahead, doesn't consume its input.
#
# Example:
#
# str('foo').present? # matches when the input contains 'foo', but leaves it
#
class Parslet::Atoms::Lookahead < Parslet::Atoms::Base
attr_reader :positive
attr_reader :bound_parslet
def initialize(bound_parslet, positive=true) # :nodoc:
super()
# Model positive and negative lookahead by testing this flag.
@positive = positive
@bound_parslet = bound_parslet
@error_msgs = {
:positive => ["Input should start with ", bound_parslet],
:negative => ["Input should not start with ", bound_parslet]
}
end
def try(source) # :nodoc:
pos = source.pos
value = bound_parslet.apply(source)
return success(nil) if positive ^ value.error?
return error(source, @error_msgs[:positive], pos) if positive
return error(source, @error_msgs[:negative], pos)
# This is probably the only parslet that rewinds its input in #try.
# Lookaheads NEVER consume their input, even on success, that's why.
ensure
source.pos = pos
end
precedence LOOKAHEAD
def to_s_inner(prec) # :nodoc:
char = positive ? '&' : '!'
"#{char}#{bound_parslet.to_s(prec)}"
end
end