module Zenithal::ZenithalParserMethod
Constants
- ATTRIBUTE_END
- ATTRIBUTE_EQUAL
- ATTRIBUTE_SEPARATOR
- ATTRIBUTE_START
- COMMENT_DELIMITER
- CONTENT_DELIMITER
- CONTENT_END
- CONTENT_START
- ELEMENT_START
- ESCAPE_CHARS
- ESCAPE_START
- MACRO_START
- MARK_CHARS
- SPACE_CHARS
- SPECIAL_ELEMENT_ENDS
- SPECIAL_ELEMENT_STARTS
- STRING_END
- STRING_START
- SYSTEM_INSTRUCTION_NAME
- VALID_FIRST_IDENTIFIER_CHARS
- VALID_MIDDLE_IDENTIFIER_CHARS
Private Instance Methods
check_version()
click to toggle source
# File source/zenml/parser.rb, line 449 def check_version string = @source.string if match = string.match(/\\zml\?\s*\|.*version\s*=\s*"(\d+\.\d+)".*\|/) @version = match[1] end end
create_comment(kind, content, options)
click to toggle source
# File source/zenml/parser.rb, line 422 def create_comment(kind, content, options) comment = REXML::Comment.new(" " + content.strip + " ") return comment end
create_element(name, marks, attributes, children_list, options)
click to toggle source
# File source/zenml/parser.rb, line 343 def create_element(name, marks, attributes, children_list, options) nodes = REXML::Nodes[] if marks.include?(:trim) children_list.each do |children| children.trim_indents end end if marks.include?(:instruction) unless children_list.size <= 1 throw_custom("Processing instruction cannot have more than one argument") end nodes = create_instruction(name, attributes, children_list.first, options) else unless marks.include?(:multiple) || children_list.size <= 1 throw_custom("Normal element cannot have more than one argument") end nodes = create_normal_element(name, attributes, children_list, options) end return nodes end
create_escape(place, char, options)
click to toggle source
# File source/zenml/parser.rb, line 427 def create_escape(place, char, options) unless ESCAPE_CHARS.include?(char) throw_custom("Invalid escape") end return char end
create_instruction(target, attributes, children, options)
click to toggle source
# File source/zenml/parser.rb, line 364 def create_instruction(target, attributes, children, options) nodes = REXML::Nodes[] if target == SYSTEM_INSTRUCTION_NAME @version = attributes["version"] if attributes["version"] @special_element_names[:brace] = attributes["brace"] if attributes["brace"] @special_element_names[:bracket] = attributes["bracket"] if attributes["bracket"] @special_element_names[:slash] = attributes["slash"] if attributes["slash"] elsif target == "xml" instruction = REXML::XMLDecl.new instruction.version = attributes["version"] || REXML::XMLDecl::DEFAULT_VERSION instruction.encoding = attributes["encoding"] instruction.standalone = attributes["standalone"] nodes << instruction else instruction = REXML::Instruction.new(target) actual_contents = [] attributes.each do |key, value| actual_contents << "#{key}=\"#{value}\"" end if children.first && !children.first.empty? actual_contents << children.first end instruction.content = actual_contents.join(" ") nodes << instruction end return nodes end
create_normal_element(name, attributes, children_list, options)
click to toggle source
# File source/zenml/parser.rb, line 392 def create_normal_element(name, attributes, children_list, options) nodes = REXML::Nodes[] children_list.each do |children| element = REXML::Element.new(name) attributes.each do |key, value| element.add_attribute(key, value) end children.each do |child| element.add(child) end nodes << element end return nodes end
create_special_element(kind, children, options)
click to toggle source
# File source/zenml/parser.rb, line 407 def create_special_element(kind, children, options) name = @special_element_names[kind] if name nodes = create_element(name, [], {}, [children], options) else throw_custom("No name specified for #{kind} elements") end return nodes end
create_text(raw_text, options)
click to toggle source
# File source/zenml/parser.rb, line 417 def create_text(raw_text, options) text = REXML::Text.new(raw_text, true, nil, false) return text end
determine_options(name, marks, attributes, macro, options)
click to toggle source
# File source/zenml/parser.rb, line 331 def determine_options(name, marks, attributes, macro, options) if marks.include?(:verbal) options = options.clone options[:verbal] = true end if macro && @plugins.key?(name) options = options.clone options[:plugin] = @plugins[name].call(attributes) end return options end
parse()
click to toggle source
# File source/zenml/parser.rb, line 45 def parse if @whole parse_document else parse_nodes({}) end end
parse_attribute(first, options)
click to toggle source
# File source/zenml/parser.rb, line 155 def parse_attribute(first, options) unless first parse_char(ATTRIBUTE_SEPARATOR) end parse_space name = parse_identifier(options) parse_space value = maybe(->{parse_attribute_value(options)}) || name parse_space attribute = {name => value} return attribute end
parse_attribute_value(options)
click to toggle source
# File source/zenml/parser.rb, line 168 def parse_attribute_value(options) parse_char(ATTRIBUTE_EQUAL) parse_space value = parse_string(options) return value end
parse_attributes(options)
click to toggle source
# File source/zenml/parser.rb, line 146 def parse_attributes(options) parse_char(ATTRIBUTE_START) first_attribute = parse_attribute(true, options) rest_attribtues = many(->{parse_attribute(false, options)}) attributes = first_attribute.merge(*rest_attribtues) parse_char(ATTRIBUTE_END) return attributes end
parse_block_comment(options)
click to toggle source
# File source/zenml/parser.rb, line 285 def parse_block_comment(options) parse_char(CONTENT_START) content = parse_block_comment_content(options) parse_char(CONTENT_END) if @version == "1.0" parse_char(COMMENT_DELIMITER) end comment = create_comment(:block, content, options) return comment end
parse_block_comment_content(options)
click to toggle source
# File source/zenml/parser.rb, line 296 def parse_block_comment_content(options) chars = many(->{parse_char_out([CONTENT_END])}) content = chars.join return content end
parse_children(options)
click to toggle source
# File source/zenml/parser.rb, line 220 def parse_children(options) parse_char(CONTENT_START) children = parse_nodes(options) parse_char(CONTENT_END) return children end
parse_children_chain(options)
click to toggle source
# File source/zenml/parser.rb, line 203 def parse_children_chain(options) if @version == "1.0" first_children = choose(->{parse_empty_children(options)}, ->{parse_children(options)}) rest_children_list = many(->{parse_children(options)}) children_list = [first_children] + rest_children_list else children_list = many(->{parse_children(options)}, 1..) end return children_list end
parse_children_list(options)
click to toggle source
# File source/zenml/parser.rb, line 194 def parse_children_list(options) if @version == "1.0" children_list = parse_children_chain(options) else children_list = choose(->{parse_empty_children_chain(options)}, ->{parse_children_chain(options)}) end return children_list end
parse_comment(options)
click to toggle source
# File source/zenml/parser.rb, line 265 def parse_comment(options) parse_char(COMMENT_DELIMITER) comment = choose(->{parse_line_comment(options)}, ->{parse_block_comment(options)}) return comment end
parse_document()
click to toggle source
# File source/zenml/parser.rb, line 53 def parse_document document = REXML::Document.new check_version children = parse_nodes({}) if @exact parse_eof end children.each do |child| document.add(child) end return document end
parse_element(options)
click to toggle source
# File source/zenml/parser.rb, line 95 def parse_element(options) name, marks, attributes, macro = parse_tag(options) next_options = determine_options(name, marks, attributes, macro, options) children_list = parse_children_list(next_options) if name == SYSTEM_INSTRUCTION_NAME parse_space end if macro element = process_macro(name, marks, attributes, children_list, options) else element = create_element(name, marks, attributes, children_list, options) end return element end
parse_empty_children(options)
click to toggle source
# File source/zenml/parser.rb, line 227 def parse_empty_children(options) if @version == "1.0" parse_char(CONTENT_END) children = REXML::Nodes[] else parse_char(CONTENT_DELIMITER) children = REXML::Nodes[] end return children end
parse_empty_children_chain(options)
click to toggle source
# File source/zenml/parser.rb, line 214 def parse_empty_children_chain(options) children = parse_empty_children(options) children_list = [children] return children_list end
parse_escape(place, options)
click to toggle source
# File source/zenml/parser.rb, line 302 def parse_escape(place, options) parse_char(ESCAPE_START) char = parse_char escape = create_escape(place, char, options) return escape end
parse_first_identifier_char(options)
click to toggle source
# File source/zenml/parser.rb, line 316 def parse_first_identifier_char(options) char = parse_char_any(VALID_FIRST_IDENTIFIER_CHARS) return char end
parse_identifier(options)
click to toggle source
# File source/zenml/parser.rb, line 309 def parse_identifier(options) first_char = parse_first_identifier_char(options) rest_chars = many(->{parse_middle_identifier_char(options)}) identifier = first_char + rest_chars.join return identifier end
parse_line_comment(options)
click to toggle source
# File source/zenml/parser.rb, line 271 def parse_line_comment(options) parse_char(COMMENT_DELIMITER) content = parse_line_comment_content(options) parse_char("\n") comment = create_comment(:line, content, options) return comment end
parse_line_comment_content(options)
click to toggle source
# File source/zenml/parser.rb, line 279 def parse_line_comment_content(options) chars = many(->{parse_char_out(["\n"])}) content = chars.join return content end
parse_mark(options)
click to toggle source
# File source/zenml/parser.rb, line 138 def parse_mark(options) parsers = MARK_CHARS.map do |mark, query| next ->{parse_char(query).yield_self{|_| mark}} end mark = choose(*parsers) return mark end
parse_marks(options)
click to toggle source
# File source/zenml/parser.rb, line 133 def parse_marks(options) marks = many(->{parse_mark(options)}) return marks end
parse_middle_identifier_char(options)
click to toggle source
# File source/zenml/parser.rb, line 321 def parse_middle_identifier_char(options) char = parse_char_any(VALID_MIDDLE_IDENTIFIER_CHARS) return char end
parse_nodes(options)
click to toggle source
# File source/zenml/parser.rb, line 66 def parse_nodes(options) nodes = nil if options[:plugin] nodes = options[:plugin].send(:parse) elsif options[:verbal] raw_nodes = many(->{parse_text(options)}) nodes = raw_nodes.inject(REXML::Nodes[], :<<) else parsers = [] parsers << ->{parse_element(options)} if options[:in_slash] next_options = options.clone next_options.delete(:in_slash) else next_options = options end @special_element_names.each do |kind, name| unless kind == :slash && options[:in_slash] parsers << ->{parse_special_element(kind, next_options)} end end parsers << ->{parse_comment(options)} parsers << ->{parse_text(options)} raw_nodes = many(->{choose(*parsers)}) nodes = raw_nodes.inject(REXML::Nodes[], :<<) end return nodes end
parse_space()
click to toggle source
# File source/zenml/parser.rb, line 326 def parse_space space = many(->{parse_char_any(SPACE_CHARS)}) return space end
parse_special_element(kind, options)
click to toggle source
# File source/zenml/parser.rb, line 110 def parse_special_element(kind, options) parse_char(SPECIAL_ELEMENT_STARTS[kind]) if kind == :slash next_options = options.clone next_options[:in_slash] = true else next_options = options end children = parse_nodes(next_options) parse_char(SPECIAL_ELEMENT_ENDS[kind]) element = create_special_element(kind, children, options) return element end
parse_string(options)
click to toggle source
# File source/zenml/parser.rb, line 175 def parse_string(options) parse_char(STRING_START) strings = many(->{parse_string_plain_or_escape(options)}) parse_char(STRING_END) string = strings.join return string end
parse_string_plain(options)
click to toggle source
# File source/zenml/parser.rb, line 183 def parse_string_plain(options) chars = many(->{parse_char_out([STRING_END, ESCAPE_START])}, 1..) string = chars.join return string end
parse_string_plain_or_escape(options)
click to toggle source
# File source/zenml/parser.rb, line 189 def parse_string_plain_or_escape(options) string = choose(->{parse_escape(:string, options)}, ->{parse_string_plain(options)}) return string end
parse_tag(options)
click to toggle source
# File source/zenml/parser.rb, line 124 def parse_tag(options) start_char = parse_char_any([ELEMENT_START, MACRO_START]) name = parse_identifier(options) marks = parse_marks(options) attributes = maybe(->{parse_attributes(options)}) || {} macro = start_char == MACRO_START return name, marks, attributes, macro end
parse_text(options)
click to toggle source
# File source/zenml/parser.rb, line 238 def parse_text(options) raw_texts = many(->{parse_text_plain_or_escape(options)}, 1..) text = create_text(raw_texts.join, options) return text end
parse_text_plain(options)
click to toggle source
# File source/zenml/parser.rb, line 244 def parse_text_plain(options) out_chars = [ESCAPE_START, CONTENT_END] unless options[:verbal] out_chars.push(ELEMENT_START, MACRO_START, CONTENT_START, COMMENT_DELIMITER) if @version == "1.1" out_chars.push(CONTENT_DELIMITER) end @special_element_names.each do |kind, name| out_chars.push(SPECIAL_ELEMENT_STARTS[kind], SPECIAL_ELEMENT_ENDS[kind]) end end chars = many(->{parse_char_out(out_chars)}, 1..) string = chars.join return string end
parse_text_plain_or_escape(options)
click to toggle source
# File source/zenml/parser.rb, line 260 def parse_text_plain_or_escape(options) string = choose(->{parse_escape(:text, options)}, ->{parse_text_plain(options)}) return string end
process_macro(name, marks, attributes, children_list, options)
click to toggle source
# File source/zenml/parser.rb, line 434 def process_macro(name, marks, attributes, children_list, options) elements = REXML::Nodes[] if @macros.key?(name) raw_elements = @macros[name].call(attributes, children_list) raw_elements.each do |raw_element| elements << raw_element end elsif @plugins.key?(name) elements = children_list.first else throw_custom("No such macro '#{name}'") end return elements end