grammar Primitive include 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) end rule literal_string (/(['])(?:\\?.)*?\1/ space) end rule multiline_string ('"""' line_break* text:~'"""' '"""' space) end rule multiline_literal ("'''" line_break* text:~"'''" "'''" space) end ## # Date time rules ## rule datetime (date_skeleton ("Z" | date_offset | [,\.] frac:(/\d/1*6) date_offset)) { skeleton = captures[:date_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 date_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 ## # 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-Z_] [a-zA-Z0-9_-]* end rule quoted_key string end end