YAML: expose libyaml's errors

db4
Jon Harper 2014-04-18 16:32:14 +02:00 committed by John Benediktsson
parent 559f140a93
commit e6301c4cd2
4 changed files with 120 additions and 44 deletions

View File

@ -4,7 +4,7 @@ USING: accessors alien.c-types alien.data assocs classes.struct
combinators continuations destructors io io.backend combinators continuations destructors io io.backend
io.encodings.ascii io.encodings.string io.encodings.utf8 io.encodings.ascii io.encodings.string io.encodings.utf8
io.launcher kernel libc locals math.parser prettyprint sequences io.launcher kernel libc locals math.parser prettyprint sequences
yaml.ffi ; yaml.ffi yaml.private ;
IN: yaml.dbg IN: yaml.dbg
: event. ( event -- ) : event. ( event -- )
@ -35,7 +35,7 @@ f :> done!
event &yaml_event_delete event. event &yaml_event_delete event.
event type>> YAML_STREAM_END_EVENT = done! event type>> YAML_STREAM_END_EVENT = done!
] with-destructors ] [ ] with-destructors ] [
"error" throw parser (libyaml-parser-error)
] if ] if
] until ] until
] [ . ] recover ] [ . ] recover

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! 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
help.markup help.syntax kernel linked-assocs math sequences sets help.markup help.syntax kernel linked-assocs math sequences sets
strings ; strings yaml.ffi ;
IN: yaml IN: yaml
HELP: >yaml HELP: >yaml
@ -33,6 +33,36 @@ HELP: yaml>
} }
{ $description "Deserializes the YAML formatted string into a Factor object." } ; { $description "Deserializes the YAML formatted string into a Factor object." } ;
HELP: libyaml-emitter-error
{ $values
{ "error" yaml_error_type_t } { "problem" string }
}
{ $description "yaml_emitter_emit returned with status 0. The slots of this error give more information." } ;
HELP: libyaml-initialize-error
{ $description "yaml_*_initialize returned with status 0. This usually means LibYAML failed to allocate memory." } ;
HELP: libyaml-parser-error
{ $values
{ "error" yaml_error_type_t } { "problem" string } { "problem_offset" integer } { "problem_value" integer } { "problem_mark" yaml_mark_t } { "context" string } { "context_mark" yaml_mark_t }
}
{ $description "yaml_parser_parse returned with status 0. The slots of this error give more information." } ;
HELP: yaml-no-document
{ $description "The input of " { $link yaml> } " had no documents." } ;
HELP: yaml-undefined-anchor
{ $values
{ "anchor" string } { "anchors" sequence }
}
{ $description "The document references an undefined anchor " { $snippet "anchor" } ". For information, the list of currently defined anchors in the document is " { $snippet "anchors" } "." } ;
HELP: yaml-unexpected-event
{ $values
{ "actual" yaml_event_type_t } { "expected" sequence }
}
{ $description "LibYAML produced the unexpected event " { $snippet "actual" } ", but the list of expected events is " { $snippet "expected" } "." } ;
ARTICLE: "yaml-mapping" "Mapping between Factor and YAML types" ARTICLE: "yaml-mapping" "Mapping between Factor and YAML types"
{ $heading "Types mapping" } { $heading "Types mapping" }
"The rules in the table below are used to convert between yaml and factor objects." "The rules in the table below are used to convert between yaml and factor objects."
@ -90,6 +120,25 @@ ARTICLE: "yaml-input" "Deserialization control"
"etc." "etc."
} }
; ;
ARTICLE: "yaml-errors" "YAML errors"
{ $heading "libYAML's errors" }
"LibYAML exposes error when parsing/emitting yaml. See " { $url "http://pyyaml.org/wiki/LibYAML" } ". More information is available directly in pyyaml's source code in their C interface. They are groupped in the following errors:"
{ $list
{ $link libyaml-parser-error }
{ $link libyaml-emitter-error }
{ $link libyaml-initialize-error }
}
{ $heading "Conversion errors" }
"Additional errors are thrown when converting to/from factor objects:"
{ $list
{ $link yaml-undefined-anchor }
{ $link yaml-no-document }
"Or many errors thrown by library words (eg unparseable numbers, converting unsupported objects to yaml, etc)"
}
{ $heading "Bugs" }
"The following error probably means that there is a bug in the implementation: " { $link yaml-unexpected-event }
;
ARTICLE: "yaml" "YAML serialization" ARTICLE: "yaml" "YAML serialization"
"The " { $vocab-link "yaml" } " vocabulary implements YAML serialization/deserialization." "The " { $vocab-link "yaml" } " vocabulary implements YAML serialization/deserialization."
{ $heading "Main conversion words" } { $heading "Main conversion words" }
@ -104,6 +153,7 @@ ARTICLE: "yaml" "YAML serialization"
"yaml-mapping" "yaml-mapping"
"yaml-output" "yaml-output"
"yaml-input" "yaml-input"
"yaml-errors"
} }
{ $examples { $examples
{ $example "USING: prettyprint yaml ;" { $example "USING: prettyprint yaml ;"

View File

@ -111,9 +111,6 @@ CONSTANT: fancy-anchors-obj {
${ fancy-anchors-obj } [ $ fancy-anchors yaml> ] unit-test ${ fancy-anchors-obj } [ $ fancy-anchors yaml> ] unit-test
${ fancy-anchors-obj } [ $ fancy-anchors-obj >yaml yaml> ] unit-test ${ fancy-anchors-obj } [ $ fancy-anchors-obj >yaml yaml> ] unit-test
! Missing anchors
[ "*foo" yaml> ] [ "No previous anchor" = ] must-fail-with
! Simple Recursive output ! Simple Recursive output
: simple-recursive-list ( -- obj ) : simple-recursive-list ( -- obj )
{ f } clone [ 0 over set-nth ] keep ; { f } clone [ 0 over set-nth ] keep ;
@ -561,4 +558,8 @@ ${ construct-value-obj } [ $ construct-value-str yaml-docs> ] unit-test
${ construct-value-obj } [ $ construct-value-obj >yaml-docs yaml-docs> ] unit-test ${ construct-value-obj } [ $ construct-value-obj >yaml-docs yaml-docs> ] unit-test
! !!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!
! *.detect ! errors
[ "- foo\n:)" yaml> ] [ libyaml-parser-error? ] must-fail-with
[ "- &foo 1\n- *baz\n" yaml> ] [ yaml-undefined-anchor? ] must-fail-with
[ "" yaml> ] [ yaml-no-document? ] must-fail-with

View File

@ -2,16 +2,43 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.data arrays assocs byte-arrays USING: accessors alien.data arrays assocs byte-arrays
classes.struct combinators combinators.extras classes.struct combinators combinators.extras
combinators.short-circuit destructors fry hashtables combinators.short-circuit destructors fry generalizations
hashtables.identity io.encodings.string io.encodings.utf8 kernel hashtables hashtables.identity io.encodings.string
libc linked-assocs locals make math math.parser namespaces io.encodings.utf8 kernel libc linked-assocs locals make math
sequences sets strings yaml.conversion yaml.ffi ; math.parser namespaces sequences sets strings yaml.conversion
yaml.ffi ;
FROM: sets => set ; FROM: sets => set ;
IN: yaml IN: yaml
ERROR: libyaml-parser-error
error problem problem_offset
problem_value problem_mark context context_mark ;
ERROR: libyaml-initialize-error ;
ERROR: libyaml-emitter-error error problem ;
ERROR: yaml-undefined-anchor anchor anchors ;
ERROR: yaml-unexpected-event actual expected ;
ERROR: yaml-no-document ;
<PRIVATE <PRIVATE
: yaml-assert-ok ( ? -- ) [ "yaml error" throw ] unless ; : yaml-initialize-assert-ok ( ? -- ) [ libyaml-initialize-error ] unless ;
: (libyaml-parser-error) ( parser -- )
{
[ error>> ] [ problem>> ] [ problem_offset>> ] [ problem_value>> ]
[ problem_mark>> ] [ context>> ] [ context_mark>> ]
} cleave [ clone ] 7 napply libyaml-parser-error ;
: (libyaml-emitter-error) ( emitter -- )
[ error>> ] [ problem>> ] bi [ clone ] bi@ libyaml-emitter-error ;
: yaml-parser-assert-ok ( ? parser -- )
swap [ drop ] [ (libyaml-parser-error) ] if ;
: yaml-emitter-assert-ok ( ? emitter -- )
swap [ drop ] [ (libyaml-emitter-error) ] if ;
: yaml_parser_parse_asserted ( parser event -- )
[ yaml_parser_parse ] [ drop yaml-parser-assert-ok ] 2bi ;
: yaml_emitter_emit_asserted ( emitter event -- )
[ yaml_emitter_emit ] [ drop yaml-emitter-assert-ok ] 2bi ;
TUPLE: yaml-alias anchor ; TUPLE: yaml-alias anchor ;
C: <yaml-alias> yaml-alias C: <yaml-alias> yaml-alias
@ -19,8 +46,8 @@ SYMBOL: anchors
: ?register-anchor ( obj event -- obj ) : ?register-anchor ( obj event -- obj )
dupd anchor>> [ anchors get set-at ] [ drop ] if* ; dupd anchor>> [ anchors get set-at ] [ drop ] if* ;
: assert-anchor-exists ( anchor -- ) : assert-anchor-exists ( anchor -- )
anchors get at* nip anchors get 2dup at* nip
[ "No previous anchor" throw ] unless ; [ 2drop ] [ yaml-undefined-anchor ] if ;
: deref-anchor ( event -- obj ) : deref-anchor ( event -- obj )
data>> alias>> anchor>> data>> alias>> anchor>>
@ -47,7 +74,6 @@ TUPLE: factor_yaml_event_t type data start_mark end_mark ;
[ data>> ] [ type>> ] bi { [ data>> ] [ type>> ] bi {
{ YAML_SEQUENCE_START_EVENT [ sequence_start>> deep-copy-seq f ] } { YAML_SEQUENCE_START_EVENT [ sequence_start>> deep-copy-seq f ] }
{ YAML_MAPPING_START_EVENT [ mapping_start>> deep-copy-map f swap ] } { YAML_MAPPING_START_EVENT [ mapping_start>> deep-copy-map f swap ] }
[ throw ]
} case factor_event_data boa ; } case factor_event_data boa ;
: deep-copy-event ( event -- event' ) : deep-copy-event ( event -- event' )
{ [ type>> ] [ deep-copy-data ] [ start_mark>> ] [ end_mark>> ] } cleave { [ type>> ] [ deep-copy-data ] [ start_mark>> ] [ end_mark>> ] } cleave
@ -62,7 +88,7 @@ TUPLE: factor_yaml_event_t type data start_mark end_mark ;
! Must not reuse the event struct before with-destructors scope ends ! Must not reuse the event struct before with-destructors scope ends
: next-event ( parser event -- event ) : next-event ( parser event -- event )
[ yaml_parser_parse yaml-assert-ok ] [ &yaml_event_delete ] bi ; [ yaml_parser_parse_asserted ] [ &yaml_event_delete ] bi ;
DEFER: parse-sequence DEFER: parse-sequence
DEFER: parse-mapping DEFER: parse-mapping
@ -76,7 +102,6 @@ DEFER: parse-mapping
dup type>> { dup type>> {
{ YAML_SEQUENCE_START_EVENT [ (parse-sequence) ] } { YAML_SEQUENCE_START_EVENT [ (parse-sequence) ] }
{ YAML_MAPPING_START_EVENT [ (parse-mapping) ] } { YAML_MAPPING_START_EVENT [ (parse-mapping) ] }
[ throw ]
} case ; } case ;
:: next-value ( parser event -- obj ) :: next-value ( parser event -- obj )
@ -122,8 +147,8 @@ DEFER: parse-mapping
: expect-event ( parser event type -- ) : expect-event ( parser event type -- )
[ [
[ next-event type>> ] dip = [ next-event type>> ] dip 2dup =
[ "wrong event" throw ] unless [ 2drop ] [ 1array yaml-unexpected-event ] if
] with-destructors ; ] with-destructors ;
GENERIC: (deref-aliases) ( anchors obj -- obj' ) GENERIC: (deref-aliases) ( anchors obj -- obj' )
@ -152,7 +177,7 @@ M: assoc (deref-aliases)
parser event next-event type>> { parser event next-event type>> {
{ YAML_DOCUMENT_START_EVENT [ t ] } { YAML_DOCUMENT_START_EVENT [ t ] }
{ YAML_STREAM_END_EVENT [ f ] } { YAML_STREAM_END_EVENT [ f ] }
[ "wrong event" throw ] [ { YAML_DOCUMENT_START_EVENT YAML_STREAM_END_EVENT } yaml-unexpected-event ]
} case } case
] with-destructors ] with-destructors
[ [
@ -163,7 +188,7 @@ M: assoc (deref-aliases)
! registers destructors (use with with-destructors) ! registers destructors (use with with-destructors)
:: init-parser ( str -- parser event ) :: init-parser ( str -- parser event )
yaml_parser_t (malloc-struct) &free :> parser yaml_parser_t (malloc-struct) &free :> parser
parser yaml_parser_initialize yaml-assert-ok parser yaml_parser_initialize yaml-initialize-assert-ok
parser &yaml_parser_delete drop parser &yaml_parser_delete drop
str utf8 encode str utf8 encode
@ -179,7 +204,7 @@ PRIVATE>
[ [
init-parser init-parser
[ YAML_STREAM_START_EVENT expect-event ] [ YAML_STREAM_START_EVENT expect-event ]
[ ?parse-yaml-doc [ "No Document" throw ] unless ] 2bi [ ?parse-yaml-doc [ yaml-no-document ] unless ] 2bi
] with-destructors ; ] with-destructors ;
: yaml-docs> ( str -- arr ) : yaml-docs> ( str -- arr )
@ -262,25 +287,25 @@ GENERIC: emit-value ( emitter event anchor obj -- )
event anchor event anchor
obj [ yaml-tag ] [ represent-scalar ] bi obj [ yaml-tag ] [ represent-scalar ] bi
-1 f f YAML_ANY_SCALAR_STYLE -1 f f YAML_ANY_SCALAR_STYLE
yaml_scalar_event_initialize yaml-assert-ok yaml_scalar_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok ; emitter event yaml_emitter_emit_asserted ;
M: object emit-value ( emitter event anchor obj -- ) emit-scalar ; M: object emit-value ( emitter event anchor obj -- ) emit-scalar ;
M: yaml-anchor emit-value ( emitter event unused obj -- ) M: yaml-anchor emit-value ( emitter event unused obj -- )
nip [ anchor>> ] [ obj>> ] bi emit-value ; nip [ anchor>> ] [ obj>> ] bi emit-value ;
M:: yaml-alias emit-value ( emitter event unused obj -- ) M:: yaml-alias emit-value ( emitter event unused obj -- )
event obj anchor>> yaml_alias_event_initialize yaml-assert-ok event obj anchor>> yaml_alias_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok ; emitter event yaml_emitter_emit_asserted ;
:: emit-sequence-start ( emitter event anchor tag -- ) :: emit-sequence-start ( emitter event anchor tag -- )
event anchor tag f YAML_ANY_SEQUENCE_STYLE event anchor tag f YAML_ANY_SEQUENCE_STYLE
yaml_sequence_start_event_initialize yaml-assert-ok yaml_sequence_start_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok ; emitter event yaml_emitter_emit_asserted ;
: emit-sequence-end ( emitter event -- ) : emit-sequence-end ( emitter event -- )
dup yaml_sequence_end_event_initialize yaml-assert-ok dup yaml_sequence_end_event_initialize yaml-initialize-assert-ok
yaml_emitter_emit yaml-assert-ok ; yaml_emitter_emit_asserted ;
: emit-sequence-body ( emitter event seq -- ) : emit-sequence-body ( emitter event seq -- )
[ emit-object ] with with each ; [ emit-object ] with with each ;
@ -305,12 +330,12 @@ M: linked-assoc emit-value ( emitter event anchor assoc -- )
:: emit-assoc-start ( emitter event anchor tag -- ) :: emit-assoc-start ( emitter event anchor tag -- )
event anchor tag f YAML_ANY_MAPPING_STYLE event anchor tag f YAML_ANY_MAPPING_STYLE
yaml_mapping_start_event_initialize yaml-assert-ok yaml_mapping_start_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok ; emitter event yaml_emitter_emit_asserted ;
: emit-assoc-end ( emitter event -- ) : emit-assoc-end ( emitter event -- )
dup yaml_mapping_end_event_initialize yaml-assert-ok dup yaml_mapping_end_event_initialize yaml-initialize-assert-ok
yaml_emitter_emit yaml-assert-ok ; yaml_emitter_emit_asserted ;
M: assoc emit-value ( emitter event anchor assoc -- ) M: assoc emit-value ( emitter event anchor assoc -- )
[ drop YAML_MAP_TAG emit-assoc-start ] [ drop YAML_MAP_TAG emit-assoc-start ]
@ -324,7 +349,7 @@ M: set emit-value ( emitter event anchor set -- )
! registers destructors (use with with-destructors) ! registers destructors (use with with-destructors)
:: init-emitter ( -- emitter event ) :: init-emitter ( -- emitter event )
yaml_emitter_t (malloc-struct) &free :> emitter yaml_emitter_t (malloc-struct) &free :> emitter
emitter yaml_emitter_initialize yaml-assert-ok emitter yaml_emitter_initialize yaml-initialize-assert-ok
emitter &yaml_emitter_delete drop emitter &yaml_emitter_delete drop
BV{ } clone :> output BV{ } clone :> output
@ -334,26 +359,26 @@ M: set emit-value ( emitter event anchor set -- )
yaml_event_t (malloc-struct) &free :> event yaml_event_t (malloc-struct) &free :> event
event YAML_UTF8_ENCODING event YAML_UTF8_ENCODING
yaml_stream_start_event_initialize yaml-assert-ok yaml_stream_start_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok emitter event yaml_emitter_emit_asserted
emitter event ; emitter event ;
:: emit-doc ( emitter event obj -- ) :: emit-doc ( emitter event obj -- )
event f f f f yaml_document_start_event_initialize yaml-assert-ok event f f f f yaml_document_start_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok emitter event yaml_emitter_emit_asserted
emitter event obj emit-object emitter event obj emit-object
event f yaml_document_end_event_initialize yaml-assert-ok event f yaml_document_end_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok ; emitter event yaml_emitter_emit_asserted ;
! registers destructors (use with with-destructors) ! registers destructors (use with with-destructors)
:: flush-emitter ( emitter event -- str ) :: flush-emitter ( emitter event -- str )
event yaml_stream_end_event_initialize yaml-assert-ok event yaml_stream_end_event_initialize yaml-initialize-assert-ok
emitter event yaml_emitter_emit yaml-assert-ok emitter event yaml_emitter_emit_asserted
emitter yaml_emitter_flush yaml-assert-ok emitter [ yaml_emitter_flush ] [ yaml-emitter-assert-ok ] bi
yaml-write-buffer get utf8 decode ; yaml-write-buffer get utf8 decode ;
PRIVATE> PRIVATE>