Class: Spectre::Node
- Inherits:
-
Object
- Object
- Spectre::Node
- Defined in:
- lib/spectre/base/node.rb
Overview
A Node in the parse tree. Nodes keep the parsing tree consistent by applying some control mechanisms to the parsing process and taking away responsibility from the Parsers. They keep the Closures and parent-child relations between the Parsers as well as the symbol-identified Parsers of the Grammars.
Instance Attribute Summary collapse
-
#actions ⇒ Object
The semantic actions that are associated with this Node - Array.
-
#backtrace ⇒ Object
The location the InputIterator was at, before the Parser started matching.
-
#left ⇒ Object
The left child Node of this Node or nil if none.
-
#parent ⇒ Object
The parent Node of this Node.
-
#parser ⇒ Object
The Parser that resides in this Node.
-
#policy ⇒ Object
Recursively ascends to the top of the parsing chain and returns the first policy it finds or the default policy.
-
#right ⇒ Object
The right child Node of this Node or nil if none.
-
#symbols ⇒ Object
The symbol-identified Parsers for this Node - Hash.
Instance Method Summary collapse
-
#%(right) ⇒ Object
See Operators::List.
-
#&(right) ⇒ Object
See Operators::Intersection.
-
#* ⇒ Object
See Operators::KleeneStar.
-
#**(right) ⇒ Object
See Operators::SequentialOr.
-
#+ ⇒ Object
See Operators::Positive.
-
#-(right) ⇒ Object
See Operators::Difference.
-
#-@ ⇒ Object
See Operators::Optional.
-
#>>(right) ⇒ Object
See Operators::Sequence.
-
#[](action) ⇒ Object
Adds a semantic action to the Node.
-
#^(right) ⇒ Object
See Operators::Xor.
-
#backtrack(iter) ⇒ Object
If parsing fails, the parent of the Node will instruct it to backtrack.
-
#chain ⇒ Object
Returns a multy-line String representing the parse-chain the current Parser is in.
-
#closure ⇒ Object
Recursively ascends to the top of the parsing chain and returns the first closure it finds or nil if none.
-
#closure=(clos) ⇒ Object
Sets the closure and registers the Node and it’s Parser with it.
-
#closure? ⇒ Boolean
Returns true if this Node has a closure set, i.e.
-
#find(sym) ⇒ Object
Tries to find the Parser referenced by the symbol
sym
by walking up the parse tree. -
#initialize(parser, left = nil, right = nil) ⇒ Node
constructor
Initializes the Node’s
parser
property and registers the Node with the given Parser, as well as theleft
andright
child. -
#initialize_copy(other) ⇒ Object
Initializes a new Node by dupping the
other
Node’s Parser, as well as its Closure and actions and the whole parse tree under it. - #inspect ⇒ Object
-
#leaf? ⇒ Boolean
Returns true, if this Node is a leaf Node, else false.
-
#parse(iter, pre_skip = true) ⇒ Object
Saves the backtrace and calls
#scan
on the Parser to do the actual parsing of the InputIteratoriter
. -
#replace_with(rep) ⇒ Object
Replaces this Node with
rep
and returns the modified replacement Node. -
#root? ⇒ Boolean
Returns true, if this Node is the root Node, else false.
-
#shallow_copy(other) ⇒ Object
Unlike
#initialize_copy
this method does notdup
the elments contained in theother
Node, but rather only copies references. -
#to_p ⇒ Object
Converts this Node to a Node, i.e.
-
#|(right) ⇒ Object
See Operators::Union.
-
#~@ ⇒ Object
See Operators::Negation.
Constructor Details
#initialize(parser, left = nil, right = nil) ⇒ Node
Initializes the Node’s parser
property and registers the Node with the given Parser, as well as the left
and right
child.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/spectre/base/node.rb', line 77 def initialize parser, left = nil, right = nil if left @left = left.to_p @left.parent = self end if right @right = right.to_p @right.parent = self end @parser, @symbols, @actions = parser, {}, [] parser.node = self end |
Instance Attribute Details
#actions ⇒ Object
The semantic actions that are associated with this Node - Array.
33 34 35 |
# File 'lib/spectre/base/node.rb', line 33 def actions @actions end |
#backtrace ⇒ Object
The location the InputIterator was at, before the Parser started matching.
37 38 39 |
# File 'lib/spectre/base/node.rb', line 37 def backtrace @backtrace end |
#left ⇒ Object
The left child Node of this Node or nil if none.
41 42 43 |
# File 'lib/spectre/base/node.rb', line 41 def left @left end |
#parent ⇒ Object
The parent Node of this Node.
49 50 51 |
# File 'lib/spectre/base/node.rb', line 49 def parent @parent end |
#parser ⇒ Object
The Parser that resides in this Node.
57 58 59 |
# File 'lib/spectre/base/node.rb', line 57 def parser @parser end |
#policy ⇒ Object
Recursively ascends to the top of the parsing chain and returns the first policy it finds or the default policy.
71 72 73 |
# File 'lib/spectre/base/node.rb', line 71 def policy @policy end |
#right ⇒ Object
The right child Node of this Node or nil if none.
45 46 47 |
# File 'lib/spectre/base/node.rb', line 45 def right @right end |
#symbols ⇒ Object
The symbol-identified Parsers for this Node - Hash.
53 54 55 |
# File 'lib/spectre/base/node.rb', line 53 def symbols @symbols end |
Instance Method Details
#%(right) ⇒ Object
See Operators::List.
348 349 350 |
# File 'lib/spectre/base/node.rb', line 348 def % right Node.new Operators::List.new, self, right.to_p end |
#&(right) ⇒ Object
See Operators::Intersection.
327 328 329 |
# File 'lib/spectre/base/node.rb', line 327 def & right Node.new Operators::Intersection.new, self, right.to_p end |
#* ⇒ Object
See Operators::KleeneStar.
362 363 364 |
# File 'lib/spectre/base/node.rb', line 362 def * Node.new Operators::KleeneStar.new, self end |
#**(right) ⇒ Object
See Operators::SequentialOr.
355 356 357 |
# File 'lib/spectre/base/node.rb', line 355 def ** right Node.new Operators::SequentialOr.new, self, right.to_p end |
#+ ⇒ Object
See Operators::Positive.
369 370 371 |
# File 'lib/spectre/base/node.rb', line 369 def + Node.new Operators::Positive.new, self end |
#-(right) ⇒ Object
See Operators::Difference.
334 335 336 |
# File 'lib/spectre/base/node.rb', line 334 def - right Node.new Operators::Difference.new, self, right.to_p end |
#-@ ⇒ Object
See Operators::Optional.
376 377 378 |
# File 'lib/spectre/base/node.rb', line 376 def -@ Node.new Operators::Optional.new, self end |
#>>(right) ⇒ Object
See Operators::Sequence.
313 314 315 |
# File 'lib/spectre/base/node.rb', line 313 def >> right Node.new Operators::Sequence.new, self, right.to_p end |
#[](action) ⇒ Object
Adds a semantic action to the Node. A semantic action is nothing but an object that implements the call
method (most simple example being a lambda
block), which will accept two parameters: The match made by the Parser and the Closure associated with the Parser.
300 301 302 303 304 305 306 307 308 |
# File 'lib/spectre/base/node.rb', line 300 def [] action @actions ||= [] if action.is_a? Symbol then @actions << ClosureAction.new(action) else @actions << action end self end |
#^(right) ⇒ Object
See Operators::Xor.
341 342 343 |
# File 'lib/spectre/base/node.rb', line 341 def ^ right Node.new Operators::Difference.new, self, right.to_p end |
#backtrack(iter) ⇒ Object
If parsing fails, the parent of the Node will instruct it to backtrack. I.e. it will return the InputIterator to the position before the failed parsing attempt. If no backtrace has been saved, nothing is done. Returns the modified InputIterator.
203 204 205 |
# File 'lib/spectre/base/node.rb', line 203 def backtrack iter iter.to @backtrace.pos if @backtrace end |
#chain ⇒ Object
Returns a multy-line String representing the parse-chain the current Parser is in.
278 279 280 281 |
# File 'lib/spectre/base/node.rb', line 278 def chain ( @parent ? @parent.inspect + "\n " : '' ) + self.inspect end |
#closure ⇒ Object
Recursively ascends to the top of the parsing chain and returns the first closure it finds or nil if none.
151 152 153 |
# File 'lib/spectre/base/node.rb', line 151 def closure @closure || ( @parent ? @parent.closure : nil ) end |
#closure=(clos) ⇒ Object
Sets the closure and registers the Node and it’s Parser with it.
166 167 168 169 170 |
# File 'lib/spectre/base/node.rb', line 166 def closure= clos @closure = clos clos.parser = @parser clos.node = self end |
#closure? ⇒ Boolean
Returns true if this Node has a closure set, i.e. unlike #closure
it will not query the parent for it’s closure.
159 160 161 |
# File 'lib/spectre/base/node.rb', line 159 def closure? @closure ? true : false end |
#find(sym) ⇒ Object
Tries to find the Parser referenced by the symbol sym
by walking up the parse tree. If a Parser is found, it is #dupped and returned, nil otherwise.
288 289 290 291 292 |
# File 'lib/spectre/base/node.rb', line 288 def find sym ret = @symbols[sym] || ( @parent ? @parent.find(sym) : nil ) ret = ret.dup if ret ret end |
#initialize_copy(other) ⇒ Object
Initializes a new Node by dupping the other
Node’s Parser, as well as its Closure and actions and the whole parse tree under it. The backtrace will not be copied.
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 |
# File 'lib/spectre/base/node.rb', line 97 def initialize_copy other if other.parser @parser = other.parser.dup @parser.node = self end if other.closure? @closure = other.closure.dup @closure.node = self @closure.parser = @parser end if other.symbols @symbols = other.symbols.dup end if other.actions @actions = other.actions.dup end if other.left @left = other.left.dup @left.parent = self end if other.right @right = other.right.dup @right.parent = self end end |
#inspect ⇒ Object
387 388 389 |
# File 'lib/spectre/base/node.rb', line 387 def inspect @parser.inspect end |
#leaf? ⇒ Boolean
Returns true, if this Node is a leaf Node, else false.
143 144 145 |
# File 'lib/spectre/base/node.rb', line 143 def leaf? @left.nil? and @right.nil? end |
#parse(iter, pre_skip = true) ⇒ Object
Saves the backtrace and calls #scan
on the Parser to do the actual parsing of the InputIterator iter
. This method will backtrack
automatically when the result of the Parser is nil
.
If pre_skip
is false
, InputIterator#skip! will not be called before the Parser invocation. Please note: pre_skip
being true
does not mean that pre-skipping is done. Other factors may prohibit that, e.g. a LexemeDirective
.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/spectre/base/node.rb', line 217 def parse iter, pre_skip = true @backtrace = iter.dup iter.skip! if @parser.pre_skip? and pre_skip ret = @parser.scan iter backtrack iter unless ret pol = policy ##TODO: simplify this? # test on min and or max if ret and ret.value # min if pol[:min] ret = nil if pol[:min] > ret.value end # max if not reset if ret and pol[:max] ret = nil if pol[:max] < ret.value end # reset if value == nil and min or max specified elsif ret ret = nil if pol[:min] or pol[:max] end @actions ||= [] @actions.each { |action| action.call ret, self.closure } if ret and pol[:actions] ret end |
#replace_with(rep) ⇒ Object
Replaces this Node with rep
and returns the modified replacement Node. If this is called during parsing process, the calling function should #backtrack
and call #parse
for the replacement Node.
263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/spectre/base/node.rb', line 263 def replace_with rep rep.parent = @parent if @parent if self == @parent.left then @parent.left = rep else @parent.right = rep end end rep end |
#root? ⇒ Boolean
Returns true, if this Node is the root Node, else false.
136 137 138 |
# File 'lib/spectre/base/node.rb', line 136 def root? @parent.nil? end |
#shallow_copy(other) ⇒ Object
Unlike #initialize_copy
this method does not dup
the elments contained in the other
Node, but rather only copies references. The backtrace will not be copied.
128 129 130 131 |
# File 'lib/spectre/base/node.rb', line 128 def shallow_copy other @parser, @closure, @symbols, @actions, @left, @right = other.parser, other.closure, other.symbols, other.actions, other.left, other.right end |
#to_p ⇒ Object
Converts this Node to a Node, i.e. returns self
.
254 255 256 |
# File 'lib/spectre/base/node.rb', line 254 def to_p self end |