Module: SDL4R

Defined in:
lib/sdl4r/sdl4r.rb,
lib/sdl4r/tag.rb,
lib/sdl4r/parser.rb,
lib/sdl4r/sdl_binary.rb,
lib/sdl4r/parser/token.rb,
lib/sdl4r/parser/reader.rb,
lib/sdl4r/sdl_time_span.rb,
lib/sdl4r/sdl_parse_error.rb,
lib/sdl4r/parser/tokenizer.rb,
lib/sdl4r/parser/time_span_with_zone.rb

Overview

– Simple Declarative Language (SDL) for Ruby Copyright 2005 Ikayzo, inc.

This program is free software. You can distribute or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation.

This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND, INCLUDING MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this program; if not, contact the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++

Defined Under Namespace

Classes: Parser, SdlBinary, SdlParseError, SdlTimeSpan, Tag

Constant Summary collapse

MAX_INTEGER_32 =
2**31 - 1
MIN_INTEGER_32 =
-(2**31)
MAX_INTEGER_64 =
2**63 - 1
MIN_INTEGER_64 =
-(2**63)
BASE64_WRAP_LINE_LENGTH =
72
ANONYMOUS_TAG_NAME =
"content"
ROOT_TAG_NAME =
"root"

Class Method Summary collapse

Class Method Details

.coerce_or_fail(o) ⇒ Object

Coerce the type to a standard SDL type or raises an ArgumentError.

Returns o if of the following classes: NilClass, String, Numeric, Float, TrueClass, FalseClass, Date, DateTime, Time, SdlTimeSpan, SdlBinary,

Rationals are turned into Floats using Rational#to_f.

Raises:

  • (ArgumentError)


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/sdl4r/sdl4r.rb', line 156

def self.coerce_or_fail(o)
  case o

  when Rational
    return o.to_f

  when NilClass,
      String,
      Numeric,
      Float,
      TrueClass,
      FalseClass,
      Date,
      DateTime,
      Time,
      SdlTimeSpan,
      SdlBinary
    return o

  end

  raise ArgumentError, "#{o.class.name} is not coercible to an SDL type"
end

.format(o, add_quotes = true, line_prefix = "", indent = "\t") ⇒ Object

Creates an SDL string representation for a given object and returns it.

o

the object to format

add_quotes

indicates whether quotes will be added to Strings and characters (true by default)

line_prefix

the line prefix to use (“” by default)

indent

the indent string to use (“t” by default)



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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
# File 'lib/sdl4r/sdl4r.rb', line 47

def self.format(o, add_quotes = true, line_prefix = "", indent = "\t")
  if o.is_a?(String)
    if add_quotes
      o_length = 0
      o.scan(/./m) { o_length += 1 } # counts the number of chars (as opposed of bytes)
      if o_length == 1
        return "'" + escape(o, "'") + "'"
      else
        return '"' + escape(o, '"') + '"'
      end
    else
      return escape(o)
    end
    
  elsif o.is_a?(Bignum)
    return o.to_s + "BD"
    
  elsif o.is_a?(Integer)
    if MIN_INTEGER_32 <= o and o <= MAX_INTEGER_32
      return o.to_s
    elsif MIN_INTEGER_64 <= o and o <= MAX_INTEGER_64
      return o.to_s + "L"
    else
      return o.to_s + "BD"
    end
    
  elsif o.is_a?(Float)
    return (o.to_s + "F")
    
  elsif o.is_a?(Rational)
    return o.to_f.to_s + "F"

  elsif o.is_a?(BigDecimal)
    s = o.to_s('F')
    s.sub!(/\.0$/, "")
    return "#{s}BD"

  elsif o.nil?
    return "null"

  elsif o.is_a?(SdlBinary)
    encoded_o = Base64.encode64(o.bytes)
    encoded_o.gsub!(/[\r\n]/m, "") # Remove the EOL inserted every 60 chars

    if add_quotes
      if encoded_o.length > BASE64_WRAP_LINE_LENGTH
        # FIXME: we should a constant or some parameter instead of hardcoded spaces
        wrap_lines_in_ascii(encoded_o, BASE64_WRAP_LINE_LENGTH, "#{line_prefix}#{indent}")
        encoded_o.insert(0, "[#{$/}")
        encoded_o << "#{$/}#{line_prefix}]"
      else
        encoded_o.insert(0, "[")
        encoded_o << "]"
      end
    end

    return encoded_o
    
  # Below, we use "#{o.year}" instead of "%Y" because "%Y" always emit 4 chars at least even if
  # the date is before 1000.
  elsif o.is_a?(DateTime) || o.is_a?(Time)
    milliseconds = get_datetime_milliseconds(o)

    if milliseconds == 0
      zone_part = o.strftime("%:z")
      if zone_part and zone_part != "+00:00"
        return o.strftime("#{o.year}/%m/%d %H:%M:%S#{zone_part}")
      else
        return o.strftime("#{o.year}/%m/%d %H:%M:%S")
      end
    else
      ms_part = milliseconds.to_s.ljust(3, '0')
      if zone_part and zone_part != "+00:00"
        return o.strftime("#{o.year}/%m/%d %H:%M:%S." + ms_part + zone_part)
      else
        return o.strftime("#{o.year}/%m/%d %H:%M:%S." + ms_part)
      end
    end

  elsif o.is_a?(Date)
    return o.strftime("#{o.year}/%m/%d")
    
  else
    return o.to_s
  end
end

.new_date_time(year, month, day, hour, min, sec, time_zone_offset) ⇒ Object

Creates and returns the object representing a datetime (DateTime in the default implementation). This method is, by default, called by the Parser class. It could be overriden as follows in order to get Time instances from all the SDL4R parsers.

module SDL4R
  def self.new_date_time(year, month, day, hour, min, sec, time_zone_offset)
    Time.utc(year, month, day, hour, min, sec)
  end
end


144
145
146
# File 'lib/sdl4r/sdl4r.rb', line 144

def self.new_date_time(year, month, day, hour, min, sec, time_zone_offset)
  DateTime.civil(year, month, day, hour, min, sec, time_zone_offset)
end

.read(input) ⇒ Object

Creates and returns a tag named “root” and add all the tags specified in the given input.

input

String, IO, Pathname or URI.

root = SDL4R::read(<<EOF
planets {
  earth area_km2=510900000
  mars
}
EOF
)

root = SDL4R::read(Pathname.new("my_dir/my_file.sdl"))

IO.open("my_dir/my_file.sdl", "r") { |io|
  root = SDL4R::read(io)
}

root = SDL4R::read(URI.new("http://my_site/my_file.sdl"))


237
238
239
# File 'lib/sdl4r/sdl4r.rb', line 237

def self.read(input)
  Tag.new(ROOT_TAG_NAME).read(input)
end

.SdlBinary(o) ⇒ Object

Try to coerce ‘o’ into a SdlBinary. Raise an ArgumentError if it fails.



72
73
74
75
76
77
78
79
80
# File 'lib/sdl4r/sdl_binary.rb', line 72

def self.SdlBinary(o)
  if o.kind_of? SdlBinary
    return o
  elsif o.kind_of? String
    return SdlBinary.new(o)
  else
    raise ArgumentError, "can't coerce argument"
  end
end

.to_attribute_map(s) ⇒ Object

Parse a string representing the attributes portion of an SDL tag and return the results as a map.

Example

hash = SDL4R.to_attribute_hash("value=1 debugging=on time=12:24:01");

# { "value" => 1, "debugging" => true, "time" => SdlTimeSpan.new(12, 24, 01) }

Raises:

  • (ArgumentError)


275
276
277
278
# File 'lib/sdl4r/sdl4r.rb', line 275

def self.to_attribute_map(s)
  raise ArgumentError, "'s' cannot be null" if s.nil?
  return read("atts " + s).child.attributes
end

.to_value(s) ⇒ Object

Parses and returns the value corresponding with the specified SDL literal.

SDL4R.to_value("\"abcd\"") # => "abcd"
SDL4R.to_value("1") # => 1
SDL4R.to_value("null") # => nil

Raises:

  • (ArgumentError)


247
248
249
250
# File 'lib/sdl4r/sdl4r.rb', line 247

def self.to_value(s)
  raise ArgumentError, "'s' cannot be null" if s.nil?
  return read(s).child.value
end

.to_value_array(s) ⇒ Object

Example

array = SDL4R.to_value_array("1 true 12:24:01")

Will return an int, a boolean, and a time span.

Raises:

  • (ArgumentError)


261
262
263
264
# File 'lib/sdl4r/sdl4r.rb', line 261

def self.to_value_array(s)
  raise ArgumentError, "'s' cannot be null" if s.nil?
  return read(s).child.values
end

.validate_identifier(identifier) ⇒ Object

Validates an SDL identifier String. SDL Identifiers must start with a Unicode letter or underscore (_) and contain only unicode letters, digits, underscores (_), dashes(-), periods (.) and dollar signs ($).

Raises

ArgumentError if the identifier is not legal

TODO: support UTF-8 identifiers



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/sdl4r/sdl4r.rb', line 189

def self.validate_identifier(identifier)
  if identifier.nil? or identifier.empty?
    raise ArgumentError, "SDL identifiers cannot be null or empty."
  end

  # in Java, was if(!Character.isJavaIdentifierStart(identifier.charAt(0)))
  unless identifier =~ /^[a-zA-Z_]/
    raise ArgumentError,
      "'" + identifier[0..0] +
      "' is not a legal first character for an SDL identifier. " +
      "SDL Identifiers must start with a unicode letter or " +
      "an underscore (_)."
  end
  
  unless identifier.length == 1 or identifier =~ /^[a-zA-Z_][a-zA-Z_0-9\-\.\$]*$/
    for i in 1..identifier.length
      unless identifier[i..i] =~ /^[a-zA-Z_0-9\-\.\$]$/
        raise ArgumentError,
          "'" + identifier[i..i] + 
          "' is not a legal character for an SDL identifier. " +
          "SDL Identifiers must start with a unicode letter or " +
          "underscore (_) followed by 0 or more unicode " +
          "letters, digits, underscores (_), dashes (-), periodss (.) and dollar signs ($)"
      end
    end
  end
end