Class: IniParser::Parser
- Inherits:
-
Object
- Object
- IniParser::Parser
- Defined in:
- lib/iniparser/parser.rb
Constant Summary collapse
- COMMENT_CLASS =
note: for now support # and ; - why? why not?
'[#;]'
- SEP_CLASS =
note: name/value separator - for now only support = (no longer support :) - why? why not?
'[=]'
- IDENT =
note: for now do NOT support dot (.) - keep reserved for hierarchy latter note: for now allow dash (-) only inside identifier (NOT beginning or end) note: yes, allow just numbers as identifiers
'[a-zA-Z0-9_](?:[a-zA-Z0-9_-]*[a-zA-Z0-9_])?'
- STRICT_SECTION_RE =
%r{^ \s* \[ \s* (?<key>#{IDENT}) \s* (?:" ## allow optional subsection (?<sub>[^"]+) " \s* )? \] \s* $}x
- SECTION_RE =
note: yes, allow spaces inside (but only inside) section name note: for now NO quotes (“”) allowed
%r{^ \s* \[ \s* (?<key>[^ "\]] (?:[^"\]]*[^ "\]])? ) \s* \] \s* $}x
- PROP_RE =
%r{^ \s* (?<key>#{IDENT}) \s* (?:#{SEP_CLASS} \s* (?<value>.*?) ## note: use non-greedy (.*?) match \s* )? $}x
Class Method Summary collapse
- .load(text) ⇒ Object
-
.load_file(path) ⇒ Object
returns a nested hash (compatible structure - works like YAML.load_file).
Instance Method Summary collapse
-
#initialize(text) ⇒ Parser
constructor
A new instance of Parser.
- #parse ⇒ Object
Constructor Details
#initialize(text) ⇒ Parser
Returns a new instance of Parser.
37 38 39 |
# File 'lib/iniparser/parser.rb', line 37 def initialize( text ) @text = text end |
Class Method Details
.load(text) ⇒ Object
32 33 34 |
# File 'lib/iniparser/parser.rb', line 32 def self.load( text ) new( text ).parse end |
.load_file(path) ⇒ Object
returns a nested hash
(compatible structure - works like YAML.load_file)
27 28 29 30 |
# File 'lib/iniparser/parser.rb', line 27 def self.load_file( path ) text = File.open( path, 'r:bom|utf-8' ) {|f| f.read } load( text ) end |
Instance Method Details
#parse ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/iniparser/parser.rb', line 93 def parse hash = top_hash = {} text = @text text = text.gsub( "\t", ' ' ) # replace all tabs w/ spaces for now lineno = 0 text.each_line do |line| lineno += 1 ## track line numbers for (parse) error reporting ### skip comments # e.g. # this is a comment line if line =~ /^\s*#{COMMENT_CLASS}/ ## logger.debug 'skipping comment line' next end ### skip blank lines if line =~ /^\s*$/ ## logger.debug 'skipping blank line' next end # pass 1) remove possible trailing eol comment ## e.g -> New York # Sample EOL Comment Here (with or without commas,,,,) ## e.g -> New York ; Sample EOL Comment Here (with or without commas,,,,) ## becomes -> New York ## NOTE: MUST have leading white space for now - keep - why? why not!!!!! ## do any urls use # for fragments? line = line.sub( /\s+#{COMMENT_CLASS}.*$/, '' ) # pass 2) remove leading and trailing whitespace line = line.strip if m=STRICT_SECTION_RE.match( line ) # strict section key = m[ :key ] hash = top_hash[ key ] ||= {} sub_key = m[ :sub ] if sub_key ## check for subsection hash = hash[ sub_key ] ||= {} end elsif m=SECTION_RE.match( line ) # liberal section; allow everything in key key = m[ :key ] hash = top_hash[ key ] ||= {} elsif m=PROP_RE.match( line ) key = m[ :key ] value = m[ :value].to_s # note: use to_s - might return nil ### todo: strip quotes from value??? why? why not? ## todo/check - raise error on duplicate - why? why not? ## for now just warn puts "WARN: line #{lineno} - duplicate key >#{key}< in section; will overwrite existing value" if hash.key?( key ) hash[ key ] = value else raise ParseError.new( "line #{lineno} - unknown line type; cannot parse >#{line}<" ) end end # each lines top_hash end |