Class: KPeg::Parser
- Inherits:
-
StringScanner
- Object
- StringScanner
- KPeg::Parser
show all
- Includes:
- Position
- Defined in:
- lib/kpeg/parser.rb
Defined Under Namespace
Classes: LeftRecursive, MemoEntry
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from Position
#current_character, #current_column, #current_line, #current_pos_info, #get_line, #lines, #position_line_offsets
Constructor Details
#initialize(str, grammar, log = false) ⇒ Parser
5
6
7
8
9
10
11
12
13
14
15
|
# File 'lib/kpeg/parser.rb', line 5
def initialize(str, grammar, log=false)
super str
@grammar = grammar
@memoizations = Hash.new { |h,k| h[k] = {} }
@failing_offset = nil
@failing_op = nil
@log = log
end
|
Instance Attribute Details
#failing_offset ⇒ Object
Returns the value of attribute failing_offset.
17
18
19
|
# File 'lib/kpeg/parser.rb', line 17
def failing_offset
@failing_offset
end
|
#failing_op ⇒ Object
Returns the value of attribute failing_op.
18
19
20
|
# File 'lib/kpeg/parser.rb', line 18
def failing_op
@failing_op
end
|
#grammar ⇒ Object
Returns the value of attribute grammar.
17
18
19
|
# File 'lib/kpeg/parser.rb', line 17
def grammar
@grammar
end
|
#memoizations ⇒ Object
Returns the value of attribute memoizations.
17
18
19
|
# File 'lib/kpeg/parser.rb', line 17
def memoizations
@memoizations
end
|
Instance Method Details
#apply(rule) ⇒ Object
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
124
125
|
# File 'lib/kpeg/parser.rb', line 81
def apply(rule)
ans = nil
if m = @memoizations[rule][pos]
m.inc!
self.pos = m.pos
if m.ans.kind_of? LeftRecursive
m.ans.detected = true
if @log
puts "LR #{rule.name} @ #{self.inspect}"
end
return nil
end
ans = m.ans
else
lr = LeftRecursive.new(false)
m = MemoEntry.new(lr, pos)
@memoizations[rule][pos] = m
start_pos = pos
if @log
puts "START #{rule.name} @ #{self.inspect}"
end
ans = rule.op.match(self)
m.move! ans, pos
if ans and lr.detected
ans = grow_lr(rule, start_pos, m)
end
end
if @log
if ans
puts " OK #{rule.name} @ #{self.inspect}"
else
puts " FAIL #{rule.name} @ #{self.inspect}"
end
end
return ans
end
|
#expectation ⇒ Object
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/kpeg/parser.rb', line 165
def expectation
error_pos = @failing_offset
line_no = current_line(error_pos)
col_no = current_column(error_pos)
expected = expected_string()
prefix = nil
case expected
when String
prefix = expected.inspect
when Range
prefix = "to be between #{expected.begin} and #{expected.end}"
when Array
prefix = "to be one of #{expected.inspect}"
when nil
prefix = "anything (no more input)"
else
prefix = "unknown"
end
return "Expected #{prefix} at line #{line_no}, column #{col_no} (offset #{error_pos})"
end
|
#expected_string ⇒ Object
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/kpeg/parser.rb', line 38
def expected_string
case @failing_op
when Choice
return Range.new(@failing_op.start, @failing_op.fin)
when Dot
return nil
else
@failing_op.string
end
end
|
#fail(op) ⇒ Object
32
33
34
35
36
|
# File 'lib/kpeg/parser.rb', line 32
def fail(op)
@failing_offset = pos
@failing_op = op
return nil
end
|
#failed? ⇒ Boolean
142
143
144
|
# File 'lib/kpeg/parser.rb', line 142
def failed?
!!@failing_op
end
|
#grow_lr(rule, start_pos, m) ⇒ Object
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
# File 'lib/kpeg/parser.rb', line 127
def grow_lr(rule, start_pos, m)
while true
self.pos = start_pos
ans = rule.op.match(self)
return nil unless ans
break if pos <= m.pos
m.move! ans, pos
end
self.pos = m.pos
return m.ans
end
|
#invoke(rule) ⇒ Object
Call a rule without memoization
77
78
79
|
# File 'lib/kpeg/parser.rb', line 77
def invoke(rule)
rule.op.match(self)
end
|
#parse(name = nil) ⇒ Object
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
# File 'lib/kpeg/parser.rb', line 146
def parse(name=nil)
if name
rule = @grammar.find(name)
unless rule
raise "Unknown rule - #{name}"
end
else
rule = @grammar.root
end
match = apply rule
if pos == string.size
@failing_op = nil
end
return match
end
|
#switch_grammar(gram) ⇒ Object
22
23
24
25
26
27
28
29
30
|
# File 'lib/kpeg/parser.rb', line 22
def switch_grammar(gram)
begin
old = @grammar
@grammar = gram
yield
ensure
@grammar = old
end
end
|