class DMark::Parser
Attributes
pos[R]
Public Class Methods
new(input)
click to toggle source
# File lib/d-mark/parser.rb, line 53 def initialize(input) @input = input @input_chars = @input.chars @pos = 0 @col_nr = 0 @line_nr = 0 end
Public Instance Methods
advance()
click to toggle source
# File lib/d-mark/parser.rb, line 87 def advance if !eof? && @input_chars[@pos] == "\n" @line_nr += 1 @col_nr = 0 end @pos += 1 @col_nr += 1 end
detect_indentation()
click to toggle source
# File lib/d-mark/parser.rb, line 207 def detect_indentation indentation_chars = 0 pos = @pos loop do case peek_char(pos) when ' ' pos += 1 indentation_chars += 1 else break end end indentation_chars / 2 end
eof?(pos = @pos)
click to toggle source
# File lib/d-mark/parser.rb, line 83 def eof?(pos = @pos) pos >= @input_chars.size end
parse()
click to toggle source
# File lib/d-mark/parser.rb, line 62 def parse res = [] loop do break if eof? res << read_block_with_children end res end
peek_char(pos = @pos)
click to toggle source
# File lib/d-mark/parser.rb, line 75 def peek_char(pos = @pos) if eof? nil else @input_chars[pos] end end
raise_parse_error(msg)
click to toggle source
# File lib/d-mark/parser.rb, line 456 def raise_parse_error(msg) raise ParserError.new(@line_nr, @col_nr, msg) end
read_attribute_key()
click to toggle source
# File lib/d-mark/parser.rb, line 353 def read_attribute_key read_identifier end
read_attribute_value()
click to toggle source
# File lib/d-mark/parser.rb, line 357 def read_attribute_value res = '' is_escaping = false loop do char = peek_char if is_escaping case char when nil, "\n" break else advance res << char is_escaping = false end else case char when nil, "\n", ']', ',' break when '%' advance is_escaping = true else advance res << char end end end res.to_s end
read_attributes()
click to toggle source
# File lib/d-mark/parser.rb, line 321 def read_attributes read_char('[') res = {} at_start = true loop do char = peek_char case char when ']' advance break else read_char(',') unless at_start key = read_attribute_key if peek_char == '=' read_char('=') value = read_attribute_value else value = key end res[key] = value at_start = false end end res end
read_block_with_children(indentation = 0)
click to toggle source
# File lib/d-mark/parser.rb, line 109 def read_block_with_children(indentation = 0) res = read_single_block pending_blanks = 0 until eof? blank_pos = try_read_blank_line if blank_pos @pos = blank_pos @line_nr += 1 @col_nr = 0 pending_blanks += 1 else sub_indentation = detect_indentation break if sub_indentation < indentation + 1 read_indentation(indentation + 1) if try_read_block_start res.children << read_block_with_children(indentation + 1) else res.children << "\n" unless res.children.empty? pending_blanks.times { res.children << "\n" } pending_blanks = 0 res.children.concat(read_inline_content) read_end_of_inline_content end end end res end
read_char(c)
click to toggle source
# File lib/d-mark/parser.rb, line 97 def read_char(c) char = peek_char if char != c raise_parse_error("expected #{c.inspect}, but got #{char.nil? ? 'EOF' : char.inspect}") else advance char end end
read_end_of_inline_content()
click to toggle source
# File lib/d-mark/parser.rb, line 275 def read_end_of_inline_content char = peek_char case char when "\n", nil advance when '}' raise_parse_error('unexpected } -- try escaping it as "%}"') else raise_parse_error('unexpected content') end end
read_identifier()
click to toggle source
# File lib/d-mark/parser.rb, line 287 def read_identifier a = read_identifier_head b = read_identifier_tail "#{a}#{b}" end
read_identifier_head()
click to toggle source
# File lib/d-mark/parser.rb, line 293 def read_identifier_head char = peek_char case char when 'a'..'z' advance char else raise_parse_error("expected an identifier, but got #{char.inspect}") end end
read_identifier_tail()
click to toggle source
# File lib/d-mark/parser.rb, line 304 def read_identifier_tail res = '' loop do char = peek_char case char when 'a'..'z', '-', '0'..'9' advance res << char else break end end res.to_s end
read_indentation(indentation)
click to toggle source
# File lib/d-mark/parser.rb, line 244 def read_indentation(indentation) indentation.times do read_char(' ') read_char(' ') end end
read_inline_content()
click to toggle source
# File lib/d-mark/parser.rb, line 390 def read_inline_content res = [] loop do char = peek_char case char when "\n", nil break when '}' break when '%' advance res << read_percent_body else res << read_string end end res end
read_inline_element()
click to toggle source
# File lib/d-mark/parser.rb, line 441 def read_inline_element name = read_identifier attributes = if peek_char == '[' read_attributes else {} end read_char('{') contents = read_inline_content read_char('}') ElementNode.new(name, attributes, contents) end
read_percent_body()
click to toggle source
# File lib/d-mark/parser.rb, line 428 def read_percent_body char = peek_char case char when '%', '}' advance char.to_s when nil, "\n" raise_parse_error("expected something after %") else read_inline_element end end
read_single_block()
click to toggle source
# File lib/d-mark/parser.rb, line 251 def read_single_block identifier = read_identifier attributes = if peek_char == '[' read_attributes else {} end read_char('.') case peek_char when nil, "\n" advance ElementNode.new(identifier, attributes, []) else read_char(' ') content = read_inline_content read_end_of_inline_content ElementNode.new(identifier, attributes, content) end end
read_string()
click to toggle source
# File lib/d-mark/parser.rb, line 411 def read_string res = '' loop do char = peek_char case char when nil, "\n", '%', '}' break else advance res << char end end res.to_s end
read_until_eol_or_eof()
click to toggle source
# File lib/d-mark/parser.rb, line 224 def read_until_eol_or_eof res = '' loop do char = peek_char case char when "\n" advance break when nil break else advance res << char end end res.to_s end
try_read_blank_line()
click to toggle source
# File lib/d-mark/parser.rb, line 141 def try_read_blank_line pos = @pos loop do case peek_char(pos) when ' ' pos += 1 when nil break pos + 1 when "\n" break pos + 1 else break nil end end end
try_read_block_start()
click to toggle source
FIXME: ugly and duplicated
# File lib/d-mark/parser.rb, line 159 def try_read_block_start old_pos = @pos success = if try_read_identifier_head if try_read_identifier_tail case peek_char when '[' true when '.' advance [' ', "\n", nil].include?(peek_char) end end end @pos = old_pos success end
try_read_identifier_head()
click to toggle source
FIXME: ugly and duplicated
# File lib/d-mark/parser.rb, line 180 def try_read_identifier_head char = peek_char case char when 'a'..'z' advance char end end
try_read_identifier_tail()
click to toggle source
FIXME: ugly and duplicated
# File lib/d-mark/parser.rb, line 190 def try_read_identifier_tail res = '' loop do char = peek_char case char when 'a'..'z', '-', '0'..'9' advance res << char else break end end res.to_s end