lib/opulent/parser/node.rb in opulent-1.5.5 vs lib/opulent/parser/node.rb in opulent-1.6.0
- old
+ new
@@ -8,87 +8,86 @@
# node [ attributes ] Inline text
#
# @param parent [Node] Parent node to which we append the node
#
def node(parent, indent = nil)
- if (name = lookahead(:node_lookahead) || lookahead(:shorthand_lookahead))
- return nil if KEYWORDS.include? name[0].to_sym
+ return unless (name = lookahead(:node_lookahead) ||
+ lookahead(:shorthand_lookahead))
- # Accept either explicit node_name or implicit :div node_name
- # with shorthand attributes
- if (node_name = accept :node)
- node_name = node_name.to_sym
- shorthand = shorthand_attributes
- elsif (shorthand = shorthand_attributes)
- node_name = :div
- end
+ return nil if KEYWORDS.include? name[0].to_sym
- # Node creation options
- options = {}
+ # Accept either explicit node_name or implicit :div node_name
+ # with shorthand attributes
+ if (node_name = accept :node)
+ node_name = node_name.to_sym
+ shorthand = shorthand_attributes
+ elsif (shorthand = shorthand_attributes)
+ node_name = :div
+ end
- # Get leading and trailing whitespace
- if accept_stripped :leading_whitespace
- options[:leading_whitespace] = true
- if accept :leading_trailing_whitespace
- options[:trailing_whitespace] = true
- end
- elsif accept_stripped :trailing_whitespace
- options[:trailing_whitespace] = true
- end
+ # Node creation options
+ options = {}
- # Get wrapped node attributes
- atts = attributes(shorthand) || {}
+ # Get leading whitespace
+ options[:leading_whitespace] = accept_stripped(:leading_whitespace)
- # Inherit attributes from definition
- options[:extension] = extension = extend_attributes
+ # Get trailing whitespace
+ options[:trailing_whitespace] = accept_stripped(:trailing_whitespace)
- # Get unwrapped node attributes
- options[:attributes] = attributes_assignments atts, false
+ # Get wrapped node attributes
+ atts = attributes(shorthand) || {}
- # Create node
- current_node = [:node, node_name, options, [], indent]
+ # Inherit attributes from definition
+ options[:extension] = extend_attributes
- # Check if the node is explicitly self enclosing
- if(close = accept_stripped :self_enclosing) || (!@definitions.keys.include?(node_name) && Settings::SelfEnclosing.include?(node_name))
- current_node[@options][:self_enclosing] = true
+ # Get unwrapped node attributes
+ options[:attributes] = attributes_assignments atts, false
- unless close.nil? || close.strip.empty?
- undo close; error :self_enclosing
- end
+ # Create node
+ current_node = [:node, node_name, options, [], indent]
- # For self enclosing tag error reporting purposes
- line = @i
- end
+ # Check for self enclosing tags and definitions
+ def_check = !@definitions.keys.include?(node_name) &&
+ Settings::SELF_ENCLOSING.include?(node_name)
- # Check whether we have explicit inline elements and add them
- # with increased base indentation
- if (accept :inline_child)
- # Inline node element
- unless (child_node = node current_node, indent)
- error :inline_child
- end
- else
- # Inline text element
- text_node = text current_node, indent, false
+ # Check if the node is explicitly self enclosing
+ if (close = accept_stripped :self_enclosing) || def_check
+ current_node[@options][:self_enclosing] = true
+
+ unless close.nil? || close.strip.empty?
+ undo close
+ Logger.error :parse, @code, @i, @j, :self_enclosing
end
+ end
- # Add the current node to the root
- root(current_node, indent)
+ # Check whether we have explicit inline elements and add them
+ # with increased base indentation
+ if accept :inline_child
+ # Inline node element
+ Logger.error :parse,
+ @code,
+ @i,
+ @j,
+ :inline_child unless node current_node, indent
+ elsif comment current_node, indent
+ # Accept same line comments
+ else
+ # Accept inline text element
+ text current_node, indent, false
+ end
- # if current_node[@options][:self_enclosing] && current_node[@children].any?
- # error :self_enclosing_children, line
- # end
+ # Add the current node to the root
+ root current_node, indent
- # Create a clone of the definition model. Cloning the options is also
- # necessary because it's a shallow copy
- if @definitions.keys.include?(node_name)
- @definition_stack << node_name
- parent[@children] << process_definition(node_name, current_node)
- @definition_stack.pop
- else
- parent[@children] << current_node
- end
+ # Create a clone of the definition model. Cloning the options is also
+ # necessary because it's a shallow copy
+ if @definitions.keys.include?(node_name)
+ @definition_stack << node_name
+ parent[@children] << process_definition(node_name, current_node)
+ @definition_stack.pop
+ else
+ parent[@children] << current_node
end
end
# When entering a definition model, we replace all the node types with their
# know definitions at definition call time.
@@ -105,17 +104,22 @@
# for the initial call node children and for the model
# children
process_definition_child model[@options][:call]
process_definition_child model
- return model
+ model
end
+ # Process definition children for the current node.
+ #
+ # @param node [Node] Callee node
+ #
def process_definition_child(node)
node[@children].map! do |child|
if child[@type] == :node
- if !@definition_stack.include?(child[@value]) && @definitions.keys.include?(child[@value])
+ if !@definition_stack.include?(child[@value]) &&
+ @definitions.keys.include?(child[@value])
process_definition child[@value], child
else
process_definition_child child if child[@children]
child
end
@@ -152,124 +156,138 @@
#
# @param atts [Hash] Node attributes
#
def shorthand_attributes(atts = {})
while (key = accept :shorthand)
- key = Settings::Shorthand[key.to_sym]
+ key = Settings::SHORTHAND[key.to_sym]
# Check whether the value is escaped or unescaped
escaped = accept(:unescaped_value) ? false : true
# Get the attribute value and process it
if (value = accept(:node))
- value = [:expression, value.inspect, {escaped: escaped}]
+ value = [:expression, value.inspect, { escaped: escaped }]
elsif (value = accept(:exp_string))
- value = [:expression, value, {escaped: escaped}]
+ value = [:expression, value, { escaped: escaped }]
elsif (value = paranthesis)
- value = [:expression, value, {escaped: escaped}]
+ value = [:expression, value, { escaped: escaped }]
else
- error :shorthand
+ Logger.error :parse, @code, @i, @j, :shorthand
end
# IDs are unique, the rest of the attributes turn into arrays in
# order to allow multiple values or identifiers
add_attribute(atts, key, value)
end
- return atts
+ atts
end
+ # Get element attributes
+ #
+ # @atts [Hash] Accumulator for node attributes
+ #
def attributes(atts = {})
wrapped_attributes atts
attributes_assignments atts, false
-
- return atts
+ atts
end
-
# Check if we match node attributes
#
# [ assignments ]
#
# @param as_parameters [Boolean] Accept or reject identifier nodes
#
def wrapped_attributes(list)
if (bracket = accept :brackets)
- attributes_assignments list
- accept bracket.to_sym, :*
+ accept_newline
+ attributes_assignments list, true
+ accept_newline
+
+ accept_stripped bracket.to_sym, :*
end
- return list
+ list
end
# Check if we match an expression node or
# a node node
#
# [ assignments ]
#
- # @param parent [Hash] Parent to which we append nodes
+ # @param list [Hash] Parent to which we append nodes
# @param as_parameters [Boolean] Accept or reject identifier nodes
#
- def attributes_assignments(parent, wrapped = true)
- unless wrapped
- return parent if lookahead(:assignment_lookahead).nil?
+ def attributes_assignments(list, wrapped = true)
+ if wrapped && lookahead(:exp_identifier_stripped_lookahead).nil? ||
+ !wrapped && lookahead(:assignment_lookahead).nil?
+ return list
end
- if (argument = accept_stripped :node)
- argument = argument.to_sym
+ return unless (argument = accept_stripped :node)
- if accept :assignment
- # Check if we have an attribute escape or not
- escaped = if accept :assignment_unescaped
- false
- else
- true
- end
+ argument = argument.to_sym
- # Get the argument value if we have an assignment
- if (value = expression(false, wrapped))
- value[@options][:escaped] = escaped
+ if accept_stripped :assignment
+ # Check if we have an attribute escape or not
+ escaped = if accept :assignment_unescaped
+ false
+ else
+ true
+ end
- # IDs are unique, the rest of the attributes turn into arrays in
- # order to allow multiple values or identifiers
- add_attribute(parent, argument, value)
- else
- error :assignments_colon
- end
+ # Get the argument value if we have an assignment
+ if (value = expression(false, wrapped))
+ value[@options][:escaped] = escaped
+
+ # IDs are unique, the rest of the attributes turn into arrays in
+ # order to allow multiple values or identifiers
+ add_attribute(list, argument, value)
else
- parent[argument] = [:expression, "nil", {escaped: false}] unless parent[argument]
+ Logger.error :parse, @code, @i, @j, :assignments_colon
end
-
- # If our attributes are wrapped, we allow method calls without
- # paranthesis, ruby style, therefore we need a terminator to signify
- # the expression end. If they are not wrapped (inline), we require
- # paranthesis and allow inline calls
- if wrapped && accept_stripped(:assignment_terminator)
- attributes_assignments parent, wrapped
- elsif !wrapped && lookahead(:assignment_lookahead)
- attributes_assignments parent, wrapped
+ else
+ unless list[argument]
+ list[argument] = [:expression, 'true', { escaped: false }]
end
+ end
- return parent
- elsif !parent.empty?
- error :assignments_comma
+ # If our attributes are wrapped, we allow method calls without
+ # paranthesis, ruby style, therefore we need a terminator to signify
+ # the expression end. If they are not wrapped (inline), we require
+ # paranthesis and allow inline calls
+ if wrapped
+ # Accept optional comma between attributes
+ accept_stripped :assignment_terminator
+
+ # Lookahead for attributes on the current line and the next one
+ if lookahead(:exp_identifier_stripped_lookahead)
+ attributes_assignments list, wrapped
+ elsif lookahead_next_line(:exp_identifier_stripped_lookahead)
+ accept_newline
+ attributes_assignments list, wrapped
+ end
+ elsif !wrapped && lookahead(:assignment_lookahead)
+ attributes_assignments list, wrapped
end
+
+ list
end
# Extend node attributes with hash from
#
# +value
# +{hash: "value"}
# +(paranthesis)
#
def extend_attributes
- if (accept :extend_attributes)
- unescaped = accept :unescaped_value
+ return unless accept :extend_attributes
+ unescaped = accept :unescaped_value
- extension = expression(false, false, false)
- extension[@options][:escaped] = false if unescaped
+ extension = expression(false, false, false)
+ extension[@options][:escaped] = !unescaped
- return extension
- end
+ extension
end
end
end