grammar TomlRB::Primitive

include TomlRB::Helper

rule primitive
  string | bool | datetime | number
end

##
# String rules
##

rule string
  multiline_string | multiline_literal | basic_string | literal_string
end

rule basic_string
  (/(["])(?:\\?.)*?\1/ space) <TomlRB::BasicString>
end

rule literal_string
  (/(['])(?:\\?.)*?\1/ space) <TomlRB::LiteralString>
end

rule multiline_string
  ('"""' line_break* (text:~('"""' !'"')|'') '"""' space) <TomlRB::MultilineString>
end

rule multiline_literal
  ("'''" line_break* (text:~("'''" !"'")|'') "'''" space) <TomlRB::MultilineLiteral>
end

##
# Date time rules
##

rule datetime
  ( skeleton:(datetime_skeleton | date_skeleton) ("Z" | date_offset | [,\.] frac:(/\d/1*6) date_offset?)? ) {
    skeleton = captures[:skeleton].first
    y,m,d,h,mi,s = skeleton.value
    offset = captures[:date_offset].first || "+00:00"
    sec_frac = captures[:frac].first || 0
    s = "#{s}.#{sec_frac}".to_f

    Time.new(*[y,m,d,h,mi,s,offset.to_s])
  }
end

rule datetime_skeleton
  (y:/\d\d\d\d/ "-" m:/\d\d/ "-" d:/\d\d/ "T" h:/\d\d/ ":" mi:/\d\d/ ":" s:/\d\d/) {
    [:y,:m,:d,:h,:mi,:s].map{ |s| capture(s).value }
  }
end

rule date_offset
  offset:(sign /\d\d/ ":" /\d\d/)
end

rule date_skeleton
  (y:/\d\d\d\d/ "-" m:/\d\d/ "-" d:/\d\d/) {
    [:y,:m,:d].map{ |s| capture(s).value } + [0, 0, 0]
  }
end

##
# Number rules
##

rule number
   exponent | float | integer
end

rule float
  (integer '.' integer) { to_str.to_f }
end

rule exponent
  ( (float | integer) [eE] integer) { to_str.to_f }
end

rule integer
  (sign? [0-9_]+) { to_str.to_i }
end

rule sign
  '+' | '-'
end

##
# Boolean rules
##

rule bool
  true | false
end

rule true
  'true' { true }
end

rule false
  'false' { false }
end

##
# Key rules
##

rule key
  quoted_key | bare_key
end

rule bare_key
  [a-zA-Z0-9_-]+
end

rule quoted_key
  string
end

end