类 Psych::Parser
YAML 事件解析器类。此类解析 YAML 文档并在传递给构造函数的处理程序上调用事件。这些事件可用于构建 YAML AST 或反序列化 YAML 文档。它甚至可以被馈送到 Psych::Emitter
以发出与解析的文档相同的文档。
有关 Psych::Parser
发出的事件的文档,请参阅 Psych::Handler
。
以下示例打印出 YAML 文档中找到的每个标量
# Handler for detecting scalar values class ScalarHandler < Psych::Handler def scalar value, anchor, tag, plain, quoted, style puts value end end parser = Psych::Parser.new(ScalarHandler.new) parser.parse(yaml_document)
以下示例将解析器馈送到 Psych::Emitter
。YAML 文档从 STDIN 读取并写入 STDERR
parser = Psych::Parser.new(Psych::Emitter.new($stderr)) parser.parse($stdin)
Psych
使用 Psych::Parser
与 Psych::TreeBuilder
结合构建解析的 YAML 文档的 AST。
常量
- ANY
让解析器选择编码
- UTF16BE
带 BOM 的 UTF-16-BE 编码
- UTF16LE
带 BOM 的 UTF-16-LE 编码
- UTF8
UTF-8 编码
属性
external_encoding[W]
将此解析器的编码设置为 encoding
handler[RW]
将调用事件的处理程序
公共类方法
new(handler = Handler.new) 点击以切换源代码
使用 handler
创建一个新的 Psych::Parser
实例。YAML 事件将在 handler
上调用。有关更多详细信息,请参阅 Psych::Parser
。
# File psych/lib/psych/parser.rb, line 47 def initialize handler = Handler.new @handler = handler @external_encoding = ANY end
公共实例方法
mark # → #<Psych::Parser::Mark> 点击以切换源代码
返回一个 Psych::Parser::Mark
对象,其中包含行、列和索引信息。
static VALUE mark(VALUE self) { VALUE mark_klass; VALUE args[3]; yaml_parser_t * parser; TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser); mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark")); args[0] = SIZET2NUM(parser->mark.index); args[1] = SIZET2NUM(parser->mark.line); args[2] = SIZET2NUM(parser->mark.column); return rb_class_new_instance(3, args, mark_klass); }
parse(yaml) 点击以切换源代码
解析包含在yaml
中的 YAML 文档。事件将被调用到解析器实例上设置的处理程序上。
参见 Psych::Parser
和 Psych::Parser#handler
# File psych/lib/psych/parser.rb, line 61 def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>" _native_parse @handler, yaml, path end
私有实例方法
_native_parse(p1, p2, p3) 点击切换源代码
static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path) { yaml_parser_t * parser; yaml_event_t event; int done = 0; int state = 0; int parser_encoding = YAML_ANY_ENCODING; int encoding = rb_utf8_encindex(); rb_encoding * internal_enc = rb_default_internal_encoding(); TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser); yaml_parser_delete(parser); yaml_parser_initialize(parser); if (rb_respond_to(yaml, id_read)) { yaml = transcode_io(yaml, &parser_encoding); yaml_parser_set_encoding(parser, parser_encoding); yaml_parser_set_input(parser, io_reader, (void *)yaml); } else { StringValue(yaml); yaml = transcode_string(yaml, &parser_encoding); yaml_parser_set_encoding(parser, parser_encoding); yaml_parser_set_input_string( parser, (const unsigned char *)RSTRING_PTR(yaml), (size_t)RSTRING_LEN(yaml) ); } while(!done) { VALUE event_args[5]; VALUE start_line, start_column, end_line, end_column; if(parser->error || !yaml_parser_parse(parser, &event)) { VALUE exception; exception = make_exception(parser, path); yaml_parser_delete(parser); yaml_parser_initialize(parser); rb_exc_raise(exception); } start_line = SIZET2NUM(event.start_mark.line); start_column = SIZET2NUM(event.start_mark.column); end_line = SIZET2NUM(event.end_mark.line); end_column = SIZET2NUM(event.end_mark.column); event_args[0] = handler; event_args[1] = start_line; event_args[2] = start_column; event_args[3] = end_line; event_args[4] = end_column; rb_protect(protected_event_location, (VALUE)event_args, &state); switch(event.type) { case YAML_STREAM_START_EVENT: { VALUE args[2]; args[0] = handler; args[1] = INT2NUM(event.data.stream_start.encoding); rb_protect(protected_start_stream, (VALUE)args, &state); } break; case YAML_DOCUMENT_START_EVENT: { VALUE args[4]; /* Get a list of tag directives (if any) */ VALUE tag_directives = rb_ary_new(); /* Grab the document version */ VALUE version = event.data.document_start.version_directive ? rb_ary_new3( (long)2, INT2NUM(event.data.document_start.version_directive->major), INT2NUM(event.data.document_start.version_directive->minor) ) : rb_ary_new(); if(event.data.document_start.tag_directives.start) { yaml_tag_directive_t *start = event.data.document_start.tag_directives.start; yaml_tag_directive_t *end = event.data.document_start.tag_directives.end; for(; start != end; start++) { VALUE handle = Qnil; VALUE prefix = Qnil; if(start->handle) { handle = rb_str_new2((const char *)start->handle); PSYCH_TRANSCODE(handle, encoding, internal_enc); } if(start->prefix) { prefix = rb_str_new2((const char *)start->prefix); PSYCH_TRANSCODE(prefix, encoding, internal_enc); } rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix)); } } args[0] = handler; args[1] = version; args[2] = tag_directives; args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse; rb_protect(protected_start_document, (VALUE)args, &state); } break; case YAML_DOCUMENT_END_EVENT: { VALUE args[2]; args[0] = handler; args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse; rb_protect(protected_end_document, (VALUE)args, &state); } break; case YAML_ALIAS_EVENT: { VALUE args[2]; VALUE alias = Qnil; if(event.data.alias.anchor) { alias = rb_str_new2((const char *)event.data.alias.anchor); PSYCH_TRANSCODE(alias, encoding, internal_enc); } args[0] = handler; args[1] = alias; rb_protect(protected_alias, (VALUE)args, &state); } break; case YAML_SCALAR_EVENT: { VALUE args[7]; VALUE anchor = Qnil; VALUE tag = Qnil; VALUE plain_implicit, quoted_implicit, style; VALUE val = rb_str_new( (const char *)event.data.scalar.value, (long)event.data.scalar.length ); PSYCH_TRANSCODE(val, encoding, internal_enc); if(event.data.scalar.anchor) { anchor = rb_str_new2((const char *)event.data.scalar.anchor); PSYCH_TRANSCODE(anchor, encoding, internal_enc); } if(event.data.scalar.tag) { tag = rb_str_new2((const char *)event.data.scalar.tag); PSYCH_TRANSCODE(tag, encoding, internal_enc); } plain_implicit = event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue; quoted_implicit = event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue; style = INT2NUM(event.data.scalar.style); args[0] = handler; args[1] = val; args[2] = anchor; args[3] = tag; args[4] = plain_implicit; args[5] = quoted_implicit; args[6] = style; rb_protect(protected_scalar, (VALUE)args, &state); } break; case YAML_SEQUENCE_START_EVENT: { VALUE args[5]; VALUE anchor = Qnil; VALUE tag = Qnil; VALUE implicit, style; if(event.data.sequence_start.anchor) { anchor = rb_str_new2((const char *)event.data.sequence_start.anchor); PSYCH_TRANSCODE(anchor, encoding, internal_enc); } tag = Qnil; if(event.data.sequence_start.tag) { tag = rb_str_new2((const char *)event.data.sequence_start.tag); PSYCH_TRANSCODE(tag, encoding, internal_enc); } implicit = event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue; style = INT2NUM(event.data.sequence_start.style); args[0] = handler; args[1] = anchor; args[2] = tag; args[3] = implicit; args[4] = style; rb_protect(protected_start_sequence, (VALUE)args, &state); } break; case YAML_SEQUENCE_END_EVENT: rb_protect(protected_end_sequence, handler, &state); break; case YAML_MAPPING_START_EVENT: { VALUE args[5]; VALUE anchor = Qnil; VALUE tag = Qnil; VALUE implicit, style; if(event.data.mapping_start.anchor) { anchor = rb_str_new2((const char *)event.data.mapping_start.anchor); PSYCH_TRANSCODE(anchor, encoding, internal_enc); } if(event.data.mapping_start.tag) { tag = rb_str_new2((const char *)event.data.mapping_start.tag); PSYCH_TRANSCODE(tag, encoding, internal_enc); } implicit = event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue; style = INT2NUM(event.data.mapping_start.style); args[0] = handler; args[1] = anchor; args[2] = tag; args[3] = implicit; args[4] = style; rb_protect(protected_start_mapping, (VALUE)args, &state); } break; case YAML_MAPPING_END_EVENT: rb_protect(protected_end_mapping, handler, &state); break; case YAML_NO_EVENT: rb_protect(protected_empty, handler, &state); break; case YAML_STREAM_END_EVENT: rb_protect(protected_end_stream, handler, &state); done = 1; break; } yaml_event_delete(&event); if (state) rb_jump_tag(state); } return self; }