${ YAML_INT_TAG } { "0" "0o7" "0x3A" "-19" } resolve-tests
${ YAML_FLOAT_TAG } { "0." "-0.0" ".5" "+12e03" "-2E+05" } resolve-tests
${ YAML_FLOAT_TAG } { ".inf" "-.Inf" "+.INF" ".NAN" } resolve-tests
+${ YAML_TIMESTAMP_TAG } {
+ "2001-12-15T02:59:43.1Z"
+ "2001-12-14t21:59:43.10-05:00"
+ "2001-12-14 21:59:43.10 -5"
+ "2001-12-15 2:59:43.10"
+ "2002-12-14"
+ "2001-2-4 \t\t 1:59:43.10 \t\t -5:00"
+} resolve-tests
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs base64 byte-arrays combinators
combinators.extras hash-sets kernel linked-assocs math
-math.parser regexp sequences strings yaml.ffi ;
+math.parser regexp sequences strings yaml.ffi
+calendar calendar.format ;
IN: yaml.conversion
! !!!!!!!!!!!!!!
CONSTANT: re-number R/ [-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?/
CONSTANT: re-infinity R/ [-+]?\.(inf|Inf|INF)/
CONSTANT: re-nan R/ \.(nan|NaN|NAN)/
+CONSTANT: re-timestamp R/ [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?([Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](\.[0-9]*)?([ \t]*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?))?/
: resolve-plain-scalar ( str -- tag )
{
{ [ re-number matches? ] [ YAML_FLOAT_TAG ] }
{ [ re-infinity matches? ] [ YAML_FLOAT_TAG ] }
{ [ re-nan matches? ] [ YAML_FLOAT_TAG ] }
+ { [ re-timestamp matches? ] [ YAML_TIMESTAMP_TAG ] }
[ drop YAML_STR_TAG ]
} cond-case ;
[ string>number ]
} cond ;
+! YAML allows
+! - multiple whitespaces between date and time
+! - multiple whitespaces between time and offset
+! - months, days and hours on 1 digit
+! preprocess to fix this mess...
+: yaml>rfc3339 ( str -- str' )
+ R/ -[0-9][^0-9]/ [ [ CHAR: 0 1 ] dip insert-nth ] re-replace-with
+ R/ -[0-9][^0-9]/ [ [ CHAR: 0 1 ] dip insert-nth ] re-replace-with
+ R/ [^0-9][0-9]:/ [ [ CHAR: 0 1 ] dip insert-nth ] re-replace-with
+ R/ [ \t]+/ " " re-replace
+ CHAR: : over index cut CHAR: space swap remove append ;
+
+: construct-timestamp ( obj -- obj' )
+ dup R/ [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/ matches?
+ [ ymd>timestamp ] [ yaml>rfc3339 rfc3339>timestamp ] if ;
+
: construct-scalar ( scalar-event -- scalar )
[ value>> ] [ resolve-scalar ] bi {
{ YAML_NULL_TAG [ drop f ] }
{ YAML_INT_TAG [ construct-int ] }
{ YAML_FLOAT_TAG [ construct-float ] }
{ YAML_BINARY_TAG [ base64> ] }
+ { YAML_TIMESTAMP_TAG [ construct-timestamp ] }
{ YAML_STR_TAG [ ] }
} case ;
M: byte-array represent-scalar ( obj -- str ) >base64 "" like ;
M: byte-array yaml-tag ( obj -- tag ) drop YAML_BINARY_TAG ;
+
+M: timestamp represent-scalar ( obj -- str ) timestamp>rfc3339 ;
+M: timestamp yaml-tag ( obj -- str ) drop YAML_TIMESTAMP_TAG ;
! Copyright (C) 2014 Jon Harper.
! See http://factorcode.org/license.txt for BSD license.
-USING: arrays assocs byte-arrays hash-sets hashtables
+USING: arrays assocs byte-arrays hash-sets hashtables calendar
help.markup help.syntax kernel linked-assocs math sequences sets
strings yaml.ffi yaml.config ;
IN: yaml
{ "!!float" { $link float } }
{ "!!str" { $link string } }
{ "!!binary" { $link byte-array } }
- { "!!timestamp" "Not supported yet" }
+ { "!!timestamp" { $link timestamp } }
{ { $snippet "sequences" } "" }
{ "!!seq" { $link array } }
{ "!!omap" { $link linked-assoc } }
! See http://factorcode.org/license.txt for BSD license.
USING: assocs grouping kernel linked-assocs literals locals
namespaces sequences tools.test yaml yaml.config yaml.ffi
-yaml.private ;
+yaml.private calendar ;
IN: yaml.tests
! TODO real conformance tests here
! !!!!!!!!!!!!!!!
! construct-timestamp
-! TODO what to do with timestamp ?
-! CONSTANT: construct-timestamp-obj f
-!
-! CONSTANT: construct-timestamp-str """canonical: 2001-12-15T02:59:43.1Z
-! valid iso8601: 2001-12-14t21:59:43.10-05:00
-! space separated: 2001-12-14 21:59:43.10 -5
-! no time zone (Z): 2001-12-15 2:59:43.10
-! date (00:00:00Z): 2002-12-14
-! """
-!
-! ${ construct-timestamp-obj } [ $ construct-timestamp-str yaml> ] unit-test
-! ${ construct-timestamp-obj } [ $ construct-timestamp-obj >yaml yaml> ] unit-test
+CONSTANT: construct-timestamp-obj H{
+ {
+ "space separated"
+ T{ timestamp
+ { year 2001 }
+ { month 12 }
+ { day 14 }
+ { hour 21 }
+ { minute 59 }
+ { second 43+1/10 }
+ { gmt-offset T{ duration { hour -5 } } }
+ }
+ }
+ {
+ "canonical"
+ T{ timestamp
+ { year 2001 }
+ { month 12 }
+ { day 15 }
+ { hour 2 }
+ { minute 59 }
+ { second 43+1/10 }
+ }
+ }
+ {
+ "date (00:00:00Z)"
+ T{ timestamp { year 2002 } { month 12 } { day 14 } }
+ }
+ {
+ "no time zone (Z)"
+ T{ timestamp
+ { year 2001 }
+ { month 12 }
+ { day 15 }
+ { hour 2 }
+ { minute 59 }
+ { second 43+1/10 }
+ }
+ }
+ {
+ "valid iso8601"
+ T{ timestamp
+ { year 2001 }
+ { month 12 }
+ { day 14 }
+ { hour 21 }
+ { minute 59 }
+ { second 43+1/10 }
+ { gmt-offset T{ duration { hour -5 } } }
+ }
+ }
+ {
+ "crazy"
+ T{ timestamp
+ { year 2002 }
+ { month 2 }
+ { day 4 }
+ { hour 1 }
+ { minute 2 }
+ { second 59+123/1000 }
+ { gmt-offset
+ T{ duration { hour 10 } { minute 23 } }
+ }
+ }
+ }
+}
+CONSTANT: construct-timestamp-str """canonical: 2001-12-15T02:59:43.1Z
+valid iso8601: 2001-12-14t21:59:43.10-05:00
+space separated: 2001-12-14 21:59:43.10 -5
+no time zone (Z): 2001-12-15 2:59:43.10
+date (00:00:00Z): 2002-12-14
+crazy: 2002-2-4 \t\t \t 1:02:59.123 \t\t +10:23
+"""
+
+${ construct-timestamp-obj } [ $ construct-timestamp-str yaml> ] unit-test
+${ construct-timestamp-obj } [ $ construct-timestamp-obj >yaml yaml> ] unit-test
! !!!!!!!!!!!!!!!
! construct-value