類別 Psych::Parser

YAML 事件剖析器類別。此類別會剖析 YAML 文件,並對傳遞給建構函式的處理常式呼叫事件。這些事件可用於建構 YAML AST 或反序列化 YAML 文件等用途。甚至可以將其回饋給 Psych::Emitter 以發出與剖析文件相同的內容。

請參閱 Psych::Handler 以取得 Psych::Parser 發出的事件文件。

以下是一個範例,會印出在 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。會從 STDIN 讀取 YAML 文件,並寫回至 STDERR

parser = Psych::Parser.new(Psych::Emitter.new($stderr))
parser.parse($stdin)

Psych 使用 Psych::Parser 搭配 Psych::TreeBuilder 來建構剖析 YAML 文件的 AST。

常數

ANY

讓剖析器選擇編碼

UTF16BE

UTF-16-BE 編碼 含 BOM

UTF16LE

UTF-16-LE 編碼 含 BOM

UTF8

UTF-8 編碼

屬性

external_encoding[W]

設定 此剖析器的編碼為 編碼

handler[RW]

會在其中呼叫事件的處理常式

公開類別方法

new(handler = Handler.new) 按一下以切換來源

使用 handler 建立新的 Psych::Parser 執行個體。會在 handler 上呼叫 YAML 事件。請參閱 Psych::Parser 以取得更多詳細資料。

# File ext/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::ParserPsych::Parser#handler

# File ext/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;
}