class MessageFormat::Parser
Public Class Methods
new()
click to toggle source
# File lib/message_format/parser.rb, line 21 def initialize () @pattern = nil @length = 0 @index = 0 end
parse( pattern )
click to toggle source
# File lib/message_format/parser.rb, line 353 def self.parse ( pattern ) Parser.new().parse(pattern) end
Public Instance Methods
error_message( expected=nil, found )
click to toggle source
# File lib/message_format/parser.rb, line 347 def error_message ( expected=nil, found ) expected ? "Expected \"#{ expected }\" but found \"#{ found }\"" : "Unexpected \"#{ found }\" found" end
is_digit( char )
click to toggle source
# File lib/message_format/parser.rb, line 38 def is_digit ( char ) char == '0' or char == '1' or char == '2' or char == '3' or char == '4' or char == '5' or char == '6' or char == '7' or char == '8' or char == '9' end
is_whitespace( char )
click to toggle source
# File lib/message_format/parser.rb, line 51 def is_whitespace ( char ) char == "\s" or char == "\t" or char == "\n" or char == "\r" or char == "\f" or char == "\v" or char == "\u00A0" or char == "\u2028" or char == "\u2029" end
parse( pattern )
click to toggle source
# File lib/message_format/parser.rb, line 27 def parse ( pattern ) if !pattern.is_a?(String) raise_expected('String pattern', pattern.class.to_s) end @pattern = pattern @length = pattern.length @index = 0 parse_message("message") end
parse_arg_id()
click to toggle source
# File lib/message_format/parser.rb, line 179 def parse_arg_id () skip_whitespace() id = '' while @index < @length char = @pattern[@index] if char == '{' or char == '#' raise_expected('argument id') end if char == '}' or char == ',' or is_whitespace(char) break end id += char @index += 1 end if id.empty? raise_expected('argument id') end skip_whitespace() id end
parse_arg_type()
click to toggle source
# File lib/message_format/parser.rb, line 200 def parse_arg_type () skip_whitespace() arg_type = nil types = [ 'number', 'date', 'time', 'ordinal', 'duration', 'spellout', 'plural', 'selectordinal', 'select' ] types.each do |type| if @pattern.slice(@index, type.length) == type arg_type = type @index += type.length break end end if !arg_type raise_expected(types.join(', ')) end skip_whitespace() arg_type end
parse_argument()
click to toggle source
# File lib/message_format/parser.rb, line 122 def parse_argument () if @pattern[@index] == '#' @index += 1 # move passed # return [ '#' ] end @index += 1 # move passed { id = parse_arg_id() char = @pattern[@index] if char == '}' # end argument @index += 1 # move passed } return [ id ] end if char != ',' raise_expected(',') end @index += 1 # move passed , type = parse_arg_type() char = @pattern[@index] if char == '}' # end argument if ( type == 'plural' or type == 'selectordinal' or type == 'select' ) raise_expected(type + ' message options') end @index += 1 # move passed } return [ id, type ] end if char != ',' raise_expected(',') end @index += 1 # move passed , format = nil offset = nil if type == 'plural' or type == 'selectordinal' offset = parse_plural_offset() format = parse_sub_messages(type) elsif type == 'select' format = parse_sub_messages(type) else format = parse_simple_format() end char = @pattern[@index] if char != '}' # not ended argument raise_expected('}') end @index += 1 # move passed (type == 'plural' or type == 'selectordinal') ? [ id, type, offset, format ] : [ id, type, format ] end
parse_message( parent_type )
click to toggle source
# File lib/message_format/parser.rb, line 310 def parse_message ( parent_type ) elements = [] text = parse_text(parent_type) if !text.empty? elements.push(text) end while @index < @length if @pattern[@index] == '}' if parent_type == 'message' raise_expected() end break end elements.push(parse_argument()) text = parse_text(parent_type) if !text.empty? elements.push(text) end end elements end
parse_plural_offset()
click to toggle source
# File lib/message_format/parser.rb, line 230 def parse_plural_offset () skip_whitespace() offset = 0 if @pattern.slice(@index, 7) == 'offset:' @index += 7 # move passed offset: skip_whitespace() start = @index while ( @index < @length and is_digit(@pattern[@index]) ) @index += 1 end if start == @index raise_expected('offset number') end offset = @pattern[start..@index].to_i skip_whitespace() end offset end
parse_selector()
click to toggle source
# File lib/message_format/parser.rb, line 275 def parse_selector () selector = '' while @index < @length char = @pattern[@index] if char == '}' or char == ',' raise_expected('{') end if char == '{' or is_whitespace(char) break end selector += char @index += 1 end if selector.empty? raise_expected('selector') end skip_whitespace() selector end
parse_simple_format()
click to toggle source
# File lib/message_format/parser.rb, line 220 def parse_simple_format () skip_whitespace() style = parse_text('style') if style.empty? raise_expected('argument style name') end skip_whitespace() style end
parse_sub_message( parent_type )
click to toggle source
# File lib/message_format/parser.rb, line 295 def parse_sub_message ( parent_type ) char = @pattern[@index] if char != '{' raise_expected('{') end @index += 1 # move passed { message = parse_message(parent_type) char = @pattern[@index] if char != '}' raise_expected('}') end @index += 1 # move passed } message end
parse_sub_messages( parent_type )
click to toggle source
# File lib/message_format/parser.rb, line 252 def parse_sub_messages ( parent_type ) skip_whitespace() options = {} has_subs = false while ( @index < @length and @pattern[@index] != '}' ) selector = parse_selector() skip_whitespace() options[selector] = parse_sub_message(parent_type) has_subs = true skip_whitespace() end if !has_subs raise_expected(parent_type + ' message options') end if !options.has_key?('other') # does not have an other selector raise_expected(nil, nil, '"other" option must be specified in ' + parent_type) end options end
parse_text( parent_type )
click to toggle source
# File lib/message_format/parser.rb, line 69 def parse_text ( parent_type ) is_hash_special = (parent_type == 'plural' or parent_type == 'selectordinal') is_arg_style = (parent_type == 'style') text = '' while @index < @length char = @pattern[@index] if ( char == '{' or char == '}' or (is_hash_special and char == '#') or (is_arg_style and is_whitespace(char)) ) break elsif char == '\'' @index += 1 char = @pattern[@index] if char == '\'' # double is always 1 ' text += char @index += 1 elsif ( # only when necessary char == '{' or char == '}' or (is_hash_special and char == '#') or (is_arg_style and is_whitespace(char)) ) text += char while @index + 1 < @length @index += 1 char = @pattern[@index] if @pattern.slice(@index, 2) == '\'\'' # double is always 1 ' text += char @index += 1 elsif char == '\'' # end of quoted @index += 1 break else text += char end end else # lone ' is just a ' text += '\'' # already incremented end else text += char @index += 1 end end text end
raise_expected( expected=nil, found=nil, message=nil )
click to toggle source
# File lib/message_format/parser.rb, line 332 def raise_expected ( expected=nil, found=nil, message=nil ) lines = @pattern[0..@index].split(/\r?\n/) line = lines.length column = lines.last.length if !found found = @index < @length ? @pattern[@index] : 'end of input' end if !message message = error_message(expected, found) end message += ' in "' + @pattern.gsub(/\r?\n/, "\n") + '"' raise SyntaxError.new(message, expected, found, @index, line, column) end
skip_whitespace()
click to toggle source
# File lib/message_format/parser.rb, line 63 def skip_whitespace () while @index < @length and is_whitespace(@pattern[@index]) @index += 1 end end