class Inversion::Parser::State
Parse state object class. State
objects keep track of where in the parse tree new nodes should be appended, and manages inclusion.
Attributes
The stack of templates that have been loaded for this state; for loop detection.
The stack of containers
The parse options in effect for this parse state
The template object for this parser state
Public Class Methods
Create a new State
object
# File lib/inversion/parser.rb, line 172 def initialize( template, options={} ) @template = template @options = options.dup @tree = [] @node_stack = [ @tree ] @include_stack = [] end
Public Instance Methods
Append operator: add nodes to the correct part of the parse tree.
# File lib/inversion/parser.rb, line 209 def <<( node ) # self.log.debug "Appending %p" % [ node ] node.before_appending( self ) self.node_stack.last << node if node.is_container? # Containers get pushed onto the stack so they get appended to self.node_stack.push( node ) else # Container nodes' #after_appending gets called in #pop node.after_appending( self ) end return self rescue Inversion::ParseError => err raise err, "%s at %s" % [ err.message, node.location ] end
Append another Array of nodes onto this state’s node tree.
# File lib/inversion/parser.rb, line 230 def append_tree( newtree ) newtree.each do |node| self.node_stack.last << node end end
Clear any parsed nodes from the state, leaving the options and include_stack
intact.
# File lib/inversion/parser.rb, line 277 def clear_nodes @tree = [] @node_stack = [ @tree ] end
Return the node that is currently being appended to, or ‘nil` if there aren’t any opened container nodes.
# File lib/inversion/parser.rb, line 271 def current_node return self.node_stack.last end
Copy constructor – duplicate inner structures.
# File lib/inversion/parser.rb, line 182 def initialize_copy( original ) @template = original.template @options = original.options.dup @tree = @tree.map( &:dup ) @node_stack = [ @tree ] @include_stack = original.include_stack.dup end
Check to see if all open tags have been closed.
# File lib/inversion/parser.rb, line 248 def is_well_formed? return self.node_stack.length == 1 end
Load a subtemplate from the specified ‘path`, checking for recursive-dependency.
# File lib/inversion/parser.rb, line 284 def load_subtemplate( path ) if self.include_stack.include?( path ) stack_desc = ( self.include_stack + [path] ).join( ' --> ' ) msg = "Recursive load of %p detected: from %s" % [ path, stack_desc ] self.log.error( msg ) raise Inversion::StackError, msg end # self.log.debug "Include stack is: %p" % [ self.include_stack ] substate = self.dup substate.clear_nodes substate.include_stack.push( path ) return Inversion::Template.load( path, substate, self.options ) end
Pop one level off of the node stack and return it.
# File lib/inversion/parser.rb, line 255 def pop closed_node = self.node_stack.pop # If there's nothing on the node stack, we've popped the top-level # Array, which means there wasn't an opening container. raise Inversion::ParseError, "unbalanced end: no open tag" if self.node_stack.empty? closed_node.after_appending( self ) return closed_node end
Returns the tree if it’s well formed.
# File lib/inversion/parser.rb, line 238 def tree unless self.is_well_formed? raise Inversion::ParseError, "Unclosed container tag: %s, from %s" % [ self.node_stack.last.tagname, self.node_stack.last.location ] end return @tree end