class Eggshell::ParseTree

Holds a hierarchical collection of blocks and macros. The tree follows this structure:

pre. [ String*, [:block, 'block_name', [], line_start]* # last entry is array of Eggshell::Line, [:macro, 'macro_name', {}, [

        __repeat_of_parse_tree
        ]
], line_start*

]

Constants

BH

A block handler handles one or more lines as a unit as long as all the lines conform to the block's expectations.

Blocks are either identified explicitly:

pre. block_name. some content \ block_name({}). some content

Or, through some non-alphanumeric character:

pre. |table|start|inferred |another|row|here

When a handler can handle a line, it sets an internal block type (retrieved with {{current_type()}}). Subsequent lines are passed to {{continue_with()}} which returns `true` if the line conforms to the current type or `false` to close the block.

The line or lines are finally passed to {{process()}} to generate the output.

h2. Block Standards

When explicitly calling a block and passing a parameter, always expect the first argument to be a hash of various attributes:

pre. p({'class': '', 'id': '', 'attributes': {}}, other, arguments, …). paragraph start

IDX_ARGS
IDX_LINES
IDX_LINES_END
IDX_LINES_START
IDX_NAME
IDX_TYPE
MH

Macros are extensible functions that can do a lot of things:

  • include other Eggshell documents into current document

  • process part of a document into a variable

  • do conditional processing

  • do loop processing

  • etc.

A typical macro call looks like this: `@macro(param, param, …)` and must be the first item on the line (excluding whitespace).

If a macro encloses a chunk of document, it would generally look like this:

pre. @block_macro(param, …) misc content misc content @end_block_macro

Public Class Methods

condense(processor, units) click to toggle source

Groups together chained macros. This ensures proper block-chain flow. Note that a related sequence is grouped within a {{pipe}} macro.

# File lib/eggshell/parse-tree.rb, line 163
def self.condense(processor, units)
        condensed  = []

        last_macro = nil
        units.each do |unit|
                if !unit.is_a?(Array) || unit[0] == :block
                        condensed << unit
                else
                        mhandler = processor.get_macro_handler(unit[1])
                        chain_type = nil
                        chain_macro = nil
                        chain_type, chain_macro = mhandler.chain_type(unit[1]) if mhandler
                        if chain_type != MH::CHAIN_NONE
                                if chain_type == MH::CHAIN_START
                                        unit[3] = condense(processor, unit[3])
                                        condensed << [:macro, 'pipe', [{'chained'=>chain_macro}], [unit], unit[4], -1]
                                        last_macro = unit[1]
                                elsif chain_type == MH::CHAIN_CONTINUE && chain_macro == last_macro
                                        unit[3] = condense(processor, unit[3])
                                        condensed[-1][3] << unit
                                elsif chain_type == MH::CHAIN_END && chain_macro == last_macro
                                        unit[3] = condense(processor, unit[3])
                                        condensed[-1][3] << unit
                                        condensed[-1][5] = unit[5]
                                        last_macro = nil
                                else
                                        condensed << unit
                                        last_macro = nil
                                end
                        else
                                condensed << unit
                        end
                end
        end

        condensed
end
new() click to toggle source
# File lib/eggshell/parse-tree.rb, line 23
def initialize
        #@eggshell = eggshell
        @modes = [:nil]
        @tree = []
        @lines = []
        @macro_delims = []
        @macro_open = []
        @macro_ptr = []
        @ptr = @tree
end
walk(struct = nil, indent = 0, out = nil) click to toggle source

Does basic output of parse tree structure to visually inspect parsed info.

# File lib/eggshell/parse-tree.rb, line 142
def self.walk(struct = nil, indent = 0, out = nil)
        out = $stdout if !out
        struct.each do |row|
                if row.is_a?(Eggshell::Line)
                        out.write "#{'  '*indent}#{row.to_s.inspect} ##{row.line_num}\n"
                elsif row.is_a?(Array)
                        if row[0] == :macro
                                out.write "#{'  '*indent}@#{row[1]}(#{row[2].inspect}) | end=#{row[-1]}\n"
                                walk(row[3], indent + 1, out)
                        elsif row[0] == :block
                                out.write "#{'  '*indent}#{row[1]}(#{row[2].inspect}) | end=#{row[-1]}\n"
                                walk(row[3], indent + 1, out)
                        end
                else
                        out.write "#{'  '*indent}#{row.inspect} ?\n"
                end
        end
end

Public Instance Methods

collect(line_obj) click to toggle source
# File lib/eggshell/parse-tree.rb, line 106
def collect(line_obj)
        more = @cur_block[0].continue_with(line_obj.line)
        if more != BH::RETRY
                @lines << line_obj
                if more == BH::DONE
                        push_block
                end
        else
                push_block
        end
        more
end
collect_macro_raw(line_obj) click to toggle source
# File lib/eggshell/parse-tree.rb, line 119
def collect_macro_raw(line_obj)
        @ptr << line_obj
end
collect_mode() click to toggle source
# File lib/eggshell/parse-tree.rb, line 137
def collect_mode
        @collect_modes[-1]
end
macro_delim_match(line_obj, line_num) click to toggle source
# File lib/eggshell/parse-tree.rb, line 54
def macro_delim_match(line_obj, line_num)
        if @macro_delims[-1] == line_obj.line
                if @modes[-1] == :block
                        push_block
                end
                @macro_delims.pop
                @macro_open.pop
                @ptr = @macro_ptr.pop
                @ptr[-1][-1] = line_num
                last_mode = @modes.pop
                return true
        end
        return false
end
mode() click to toggle source

@todo return macro_open

# File lib/eggshell/parse-tree.rb, line 133
def mode
        @modes[-1]
end
new_block(handler, type, line_obj, consume_mode, line_start, eggshell) click to toggle source
# File lib/eggshell/parse-tree.rb, line 69
def new_block(handler, type, line_obj, consume_mode, line_start, eggshell)
        block_type, args, line = eggshell.parse_block_start(line_obj.line)
        nline = Eggshell::Line.new(line, line_obj.tab_str, line_obj.indent_lvl, line_obj.line_num)

        if consume_mode != BH::DONE
                #@modes << :block
                if line != ''
                        @lines << nline
                        line_start -= 1
                end
                @cur_block = [handler, type, args, line_start]
                if consume_mode == BH::COLLECT_RAW
                        #mode = :raw
                        @modes << :raw
                else consume_mode == BH::COLLECT
                        #mode = :block
                        @modes << :block
                end
        else
                @ptr << [:block, type, args, [nline], line_start, line_start]
        end
end
new_macro(line_obj, line_start, macro, args, delim, mode) click to toggle source
# File lib/eggshell/parse-tree.rb, line 34
def new_macro(line_obj, line_start, macro, args, delim, mode)
        line = line_obj.line
        #macro, args, delim = Eggshell::Processor.parse_macro_start(line)

        push_block

        if delim
                @modes << (mode == MH::COLLECT_RAW_MACRO ? :macro_raw : macro)
                @macro_delims << delim #delim.reverse.gsub('[', ']').gsub('(', ')').gsub('{', '}')
                @macro_open << line
                @macro_ptr << @ptr
                # set ptr to entry's tree
                entry = [:macro, macro, args, [], line_start, line_start]
                @ptr << entry
                @ptr = entry[IDX_LINES]
        else
                @ptr << [:macro, macro, args, [], line_start, line_start]
        end
end
push_block() click to toggle source
# File lib/eggshell/parse-tree.rb, line 92
def push_block
        if @modes[-1] == :block || @modes[-1] == :raw
                if @cur_block
                        line_end = @cur_block[3]
                        line_end = @lines[-1].line_num if @lines[-1]
                        @ptr << [:block, @cur_block[1], @cur_block[2], @lines, @cur_block[3], line_end]
                        @lines = []
                        @cur_block[0].reset
                        @cur_block = nil
                end
                @modes.pop
        end
end
raw_line(line_obj) click to toggle source
# File lib/eggshell/parse-tree.rb, line 123
def raw_line(line_obj)
        @ptr << line_obj
end
tree() click to toggle source
# File lib/eggshell/parse-tree.rb, line 127
def tree
        @tree.clone
end