def parse(string, filename = '')
scanner = StringScanner.new( string, false )
definitions = {}
in_attrs = false
line_num = 1
current_element = nil
element_name = nil
element_type = nil
term = "(;|\n)"
pos_proc = proc do
"#{filename}:#{line_num}: "
end
while scanner.rest?
if scanner.skip(/(\r)?\n/) then
line_num += 1
next
end
if scanner.skip(/(?:#.*$|[ \r\f\t]+)/) then
next
end
if in_attrs then
if scanner.skip(/([a-zA-Z0-9_]+[\!\?]?)[ \r\f\t]*=[ \r\f\t]*/)
key = scanner[1]
if scanner.skip(/^[^"'](.*)\[/) then
list = nil
object = scanner[1]
if scanner.match?(/^(["'])/) then
close = scanner[1]
if close == '"' and scanner.skip(/"(.*?)"\]/)
elsif close == "'" and scanner.skip(/'(.*?)'\]/)
else
raise CKDParseError, \
pos_proc.call << scanner.peek(60).inspect << \
"\nString literal error. Or, \";\" doesn't exist."
end
list = "\"#{scanner[1]}\""
else
if scanner.skip(/([a-zA-Z0-9_\.\!\^^?]+)\][ \r\t\f]*#{term}/)
list = scanner[1]
else
raise CKDParseError, pos_proc.call << \
scanner.peek(60).inspect << \
"\nArray or Hash literal error. Or, \";\" doesn't exist.\n"
end
end
value = "#{object}[#{list}]"
line_num += value.count("\n")
elsif scanner.match?(/^(["'])/) then
close = scanner[1]
if close == '"' and scanner.skip(/"(.*?)"[ \r\f\t]*#{term}/m)
elsif close == "'" and scanner.skip(/'(.*?)'[ \r\f\t]*#{term}/m)
else
raise CKDParseError, \
pos_proc.call << scanner.peek(60).inspect << \
"\nString literal error. Or, \";\" doesn't exist."
end
value = "\"#{scanner[1]}\""
line_num += value.count("\n")
else
if scanner.skip(/([a-zA-Z0-9_\.\!\^^?]+)[ \r\t\f]*#{term}/)
value = scanner[1]
else
raise CKDParseError, pos_proc.call << \
scanner.peek(60).inspect << \
"\nMethod name error. Or, \";\" doesn't exist." "\n"
end
end
current_element[key] = value
next
end
if scanner.skip(/\s*\}/)
definitions[element_name] = current_element
current_element = nil
in_attrs = false
next
end
if scanner.skip(/[ \r\t\f]*#{term}/)
next
end
else
if scanner.skip(/([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_]+)\s*\{/)
element_name = scanner[1]
element_type = scanner[2]
current_element = {}
current_element['oid'] = element_name
current_element['element'] = element_type
if definitions.key? element_name then
raise CKDParseError, pos_proc.call << \
scanner.peek(60).inspect << \
"\n'#{element_name}' definition is already existed." "\n"
end
in_attrs = true
next
end
end
def_str = _pretty_print(definitions)
raise CKDParseError, pos_proc.call << scanner.peek(60).inspect << \
"\nNot match any rule.\n\n" << def_str << "\n"
end
if in_attrs
raise CKDParseError, pos_proc.call << \
"The last element is not enclosed.\n\n"
end
definitions
end